├── Assets ├── Plugins │ ├── SkinnedMeshTools │ │ ├── Editor │ │ │ ├── SkinnedMeshToolsEditorMenu.cs.meta │ │ │ ├── Resources │ │ │ │ ├── Circle_Icon.png │ │ │ │ └── Circle_Icon.png.meta │ │ │ ├── Resources.meta │ │ │ ├── Shaders.meta │ │ │ ├── Shaders │ │ │ │ ├── VertexColorShader.shader.meta │ │ │ │ └── VertexColorShader.shader │ │ │ ├── SkinnedMeshToolsEditorCore.cs.meta │ │ │ ├── SkinnedMeshToolsEditorConfig.cs.meta │ │ │ ├── SkinnedMeshToolsEditorConfig.cs │ │ │ ├── SkinnedMeshToolsEditorMenu.cs │ │ │ └── SkinnedMeshToolsEditorCore.cs │ │ ├── package.json.meta │ │ ├── Editor.meta │ │ ├── SkinnedMeshTools.asmdef.meta │ │ ├── package.json │ │ └── SkinnedMeshTools.asmdef │ └── SkinnedMeshTools.meta └── Plugins.meta ├── README.md ├── LICENSE └── .gitignore /Assets/Plugins/SkinnedMeshTools/Editor/SkinnedMeshToolsEditorMenu.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 124e18ad5c6c4179b132c8c5b164b273 3 | timeCreated: 1613779184 -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/Editor/Resources/Circle_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pshtif/SkinnedMeshTools/HEAD/Assets/Plugins/SkinnedMeshTools/Editor/Resources/Circle_Icon.png -------------------------------------------------------------------------------- /Assets/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c7ea10f53488bf34db75fc0bdfd221cf 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 16e610b498f1839468acd40fd6a37641 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3cec49e85b1c9164db08885b72fbd5f2 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9bd1ee2f5a22a8040b7ff4232053830d 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/Editor/Resources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b01311e47ccce1648bbf855aa833362e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/Editor/Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 93f01870a0c77934193065c3e4db0c40 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/SkinnedMeshTools.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: caeb109c0c745ef448c3569fba831354 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SkinnedMeshTools 2 | Editor extension for Unity with various tools to help working with skinned meshes. 3 | 4 | Check video here: https://www.youtube.com/watch?v=4i4aDyRUZkM 5 | 6 | [![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/4i4aDyRUZkM/0.jpg)](https://www.youtube.com/watch?v=4i4aDyRUZkM) 7 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/Editor/Shaders/VertexColorShader.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f6775e936155ef64c9765b9a687ee6a0 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/Editor/SkinnedMeshToolsEditorCore.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bcfcd024b7a8de94787fa2ee26e867b1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/Editor/SkinnedMeshToolsEditorConfig.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 90ee4a28e7d48154f8b4fee05f40300e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.shtif.skinnedmeshtools", 3 | "displayName": "Skinned Mesh Tools", 4 | "version": "0.1.0", 5 | "unity": "2019.4", 6 | "description": "Tools for skinned meshes.", 7 | "author": { 8 | "name": "Peter @sHTiF Stefcek", 9 | "email": "psthif@gmail.com" 10 | }, 11 | "keywords": [ 12 | "package", 13 | "unity", 14 | "skinnedmesh" 15 | ], 16 | "dependencies": { 17 | } 18 | } -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/SkinnedMeshTools.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "SkinnedMeshTools", 3 | "rootNamespace": "", 4 | "references": [], 5 | "includePlatforms": [ 6 | "Editor" 7 | ], 8 | "excludePlatforms": [], 9 | "allowUnsafeCode": false, 10 | "overrideReferences": false, 11 | "precompiledReferences": [], 12 | "autoReferenced": true, 13 | "defineConstraints": [], 14 | "versionDefines": [], 15 | "noEngineReferences": false 16 | } -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/Editor/SkinnedMeshToolsEditorConfig.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by: Peter @sHTiF Stefcek 3 | */ 4 | 5 | #if UNITY_EDITOR 6 | using System; 7 | using UnityEngine; 8 | 9 | [Serializable] 10 | public class SkinnedMeshToolsEditorConfig : ScriptableObject 11 | { 12 | public bool enabled = true; 13 | 14 | public int boneIndex = 1; 15 | 16 | public bool showBoneWeights = false; 17 | 18 | public bool showBones = true; 19 | 20 | public bool useAlphaForWeightColor = true; 21 | 22 | public Color boneWeightColor; 23 | 24 | public bool enableEditing = false; 25 | } 26 | #endif -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/Editor/SkinnedMeshToolsEditorMenu.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by: Peter @sHTiF Stefcek 3 | */ 4 | 5 | 6 | using UnityEditor; 7 | 8 | public class SkinnedMeshToolsEditorMenu 9 | { 10 | [MenuItem("Tools/SkinnedMeshTools/Enable")] 11 | static void EnableSkinnedMeshTool() 12 | { 13 | SkinnedMeshToolsEditorCore.Config.enabled = true; 14 | SceneView.RepaintAll(); 15 | } 16 | 17 | [MenuItem("Tools/SkinnedMeshTools/Enable", true)] 18 | static bool ValidateEnableSkinnedMeshTool() 19 | { 20 | return !SkinnedMeshToolsEditorCore.Config.enabled; 21 | } 22 | 23 | [MenuItem("Tools/SkinnedMeshTools/Disable")] 24 | static void DisableSkinnedMeshTool() 25 | { 26 | SkinnedMeshToolsEditorCore.Config.enabled = false; 27 | SceneView.RepaintAll(); 28 | } 29 | 30 | [MenuItem("Tools/SkinnedMeshTools/Disable", true)] 31 | static bool ValidateDisableSkinnedMeshTool() 32 | { 33 | return SkinnedMeshToolsEditorCore.Config.enabled; 34 | } 35 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Peter @sHTiF Stefcek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Mm]emoryCaptures/ 12 | 13 | # Asset meta data should only be ignored when the corresponding asset is also ignored 14 | !/[Aa]ssets/**/*.meta 15 | 16 | # Uncomment this line if you wish to ignore the asset store tools plugin 17 | # /[Aa]ssets/AssetStoreTools* 18 | 19 | # Autogenerated Jetbrains Rider plugin 20 | [Aa]ssets/Plugins/Editor/JetBrains* 21 | 22 | # Visual Studio cache directory 23 | .vs/ 24 | 25 | # Gradle cache directory 26 | .gradle/ 27 | 28 | # Autogenerated VS/MD/Consulo solution and project files 29 | ExportedObj/ 30 | .consulo/ 31 | *.csproj 32 | *.unityproj 33 | *.sln 34 | *.suo 35 | *.tmp 36 | *.user 37 | *.userprefs 38 | *.pidb 39 | *.booproj 40 | *.svd 41 | *.pdb 42 | *.mdb 43 | *.opendb 44 | *.VC.db 45 | 46 | # Unity3D generated meta files 47 | *.pidb.meta 48 | *.pdb.meta 49 | *.mdb.meta 50 | 51 | # Unity3D generated file on crash reports 52 | sysinfo.txt 53 | 54 | # Builds 55 | *.apk 56 | *.unitypackage 57 | 58 | # Crashlytics generated file 59 | crashlytics-build.properties 60 | 61 | /Assets/_EXTERNAL 62 | /Assets/_EXTERNAL.meta 63 | /.idea* 64 | /UserSettings/ 65 | /ProjectSettings/ 66 | /Packages/ 67 | /Assets/Resources* 68 | /Assets/Scenes* 69 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/Editor/Shaders/VertexColorShader.shader: -------------------------------------------------------------------------------- 1 | Shader "Hidden/SkinnedMeshTools/VertexColorShader" 2 | { 3 | Properties 4 | { 5 | _MainTex ("Texture", 2D) = "white" {} 6 | } 7 | SubShader 8 | { 9 | Tags { "RenderType"="Opaque" } 10 | LOD 100 11 | 12 | Pass 13 | { 14 | CGPROGRAM 15 | #pragma vertex vert 16 | #pragma fragment frag 17 | 18 | #include "UnityCG.cginc" 19 | 20 | struct appdata 21 | { 22 | float4 vertex : POSITION; 23 | float2 uv : TEXCOORD0; 24 | half4 color : COLOR0; 25 | 26 | }; 27 | 28 | struct v2f 29 | { 30 | float2 uv : TEXCOORD0; 31 | float4 vertex : SV_POSITION; 32 | float4 color : COLOR0; 33 | }; 34 | 35 | sampler2D _MainTex; 36 | float4 _MainTex_ST; 37 | 38 | v2f vert (appdata v) 39 | { 40 | v2f o; 41 | o.vertex = UnityObjectToClipPos(v.vertex); 42 | o.uv = TRANSFORM_TEX(v.uv, _MainTex); 43 | o.color = v.color; 44 | return o; 45 | } 46 | 47 | fixed4 frag (v2f i) : SV_Target 48 | { 49 | return i.color; 50 | } 51 | ENDCG 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/Editor/Resources/Circle_Icon.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d97791b28e1e05c4ea57761369fb9513 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | vTOnly: 0 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | serializedVersion: 2 35 | filterMode: -1 36 | aniso: -1 37 | mipBias: -100 38 | wrapU: -1 39 | wrapV: -1 40 | wrapW: -1 41 | nPOTScale: 1 42 | lightmap: 0 43 | compressionQuality: 50 44 | spriteMode: 0 45 | spriteExtrude: 1 46 | spriteMeshType: 1 47 | alignment: 0 48 | spritePivot: {x: 0.5, y: 0.5} 49 | spritePixelsToUnits: 100 50 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 51 | spriteGenerateFallbackPhysicsShape: 1 52 | alphaUsage: 1 53 | alphaIsTransparency: 0 54 | spriteTessellationDetail: -1 55 | textureType: 0 56 | textureShape: 1 57 | singleChannelComponent: 0 58 | flipbookRows: 1 59 | flipbookColumns: 1 60 | maxTextureSizeSet: 0 61 | compressionQualitySet: 0 62 | textureFormatSet: 0 63 | ignorePngGamma: 0 64 | applyGammaDecoding: 0 65 | platformSettings: 66 | - serializedVersion: 3 67 | buildTarget: DefaultTexturePlatform 68 | maxTextureSize: 2048 69 | resizeAlgorithm: 0 70 | textureFormat: -1 71 | textureCompression: 1 72 | compressionQuality: 50 73 | crunchedCompression: 0 74 | allowsAlphaSplitting: 0 75 | overridden: 0 76 | androidETC2FallbackOverride: 0 77 | forceMaximumCompressionQuality_BC6H_BC7: 0 78 | spriteSheet: 79 | serializedVersion: 2 80 | sprites: [] 81 | outline: [] 82 | physicsShape: [] 83 | bones: [] 84 | spriteID: 85 | internalID: 0 86 | vertices: [] 87 | indices: 88 | edges: [] 89 | weights: [] 90 | secondaryTextures: [] 91 | spritePackingTag: 92 | pSDRemoveMatte: 0 93 | pSDShowRemoveMatteOption: 0 94 | userData: 95 | assetBundleName: 96 | assetBundleVariant: 97 | -------------------------------------------------------------------------------- /Assets/Plugins/SkinnedMeshTools/Editor/SkinnedMeshToolsEditorCore.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnityEditor; 5 | using UnityEditor.Graphs; 6 | using UnityEngine; 7 | 8 | [InitializeOnLoad] 9 | public class SkinnedMeshToolsEditorCore 10 | { 11 | static private Texture circleTexture => Resources.Load("Circle_Icon"); 12 | 13 | static private Material _boneWeightMaterial; 14 | static private Material boneWeightMaterial 15 | { 16 | get 17 | { 18 | if (_boneWeightMaterial == null) 19 | _boneWeightMaterial = new Material(Shader.Find("Hidden/SkinnedMeshTools/VertexColorShader")); 20 | return _boneWeightMaterial; 21 | } 22 | } 23 | static private GameObject _previousSelected; 24 | 25 | static private SkinnedMeshRenderer _currentSkinnedMesh; 26 | 27 | static public SkinnedMeshToolsEditorConfig Config { get; private set; } 28 | 29 | static void CreateConfig() 30 | { 31 | Config = (SkinnedMeshToolsEditorConfig) AssetDatabase.LoadAssetAtPath("Assets/Resources/SkinnedMeshToolsEditorConfig.asset", 32 | typeof(SkinnedMeshToolsEditorConfig)); 33 | 34 | if (Config == null) 35 | { 36 | Config = ScriptableObject.CreateInstance(); 37 | Config.boneWeightColor = new Color(1, 0, 0, 0); 38 | if (Config != null) 39 | { 40 | if (!AssetDatabase.IsValidFolder("Assets/Resources")) 41 | { 42 | AssetDatabase.CreateFolder("Assets","Resources"); 43 | } 44 | AssetDatabase.CreateAsset(Config, "Assets/Resources/SkinnedMeshToolsEditorConfig.asset"); 45 | AssetDatabase.SaveAssets(); 46 | AssetDatabase.Refresh(); 47 | } 48 | } 49 | } 50 | 51 | static SkinnedMeshToolsEditorCore() 52 | { 53 | CreateConfig(); 54 | 55 | SceneView.duringSceneGui -= OnSceneGUI; 56 | SceneView.duringSceneGui += OnSceneGUI; 57 | } 58 | 59 | private static void OnSceneGUI(SceneView p_view) 60 | { 61 | Tools.hidden = false; 62 | GameObject selected = Selection.activeGameObject; 63 | if (selected == null || !selected.activeInHierarchy || !Config.enabled) 64 | return; 65 | 66 | _currentSkinnedMesh = selected.GetComponent(); 67 | if (_currentSkinnedMesh == null) 68 | { 69 | _currentSkinnedMesh = selected.GetComponentInChildren(); 70 | if (_currentSkinnedMesh == null) 71 | return; 72 | } 73 | 74 | if (Config.showBones && Config.showBoneWeights) 75 | DrawBoneWeights(Config.boneIndex); 76 | 77 | if (Config.showBones) 78 | DrawBones(); 79 | 80 | //DrawBindPose(smr); 81 | 82 | DrawGUI(); 83 | } 84 | 85 | private static void DrawGUI() 86 | { 87 | Handles.BeginGUI(); 88 | 89 | GUIStyle style = new GUIStyle(GUI.skin.box); 90 | style.normal.background = Texture2D.whiteTexture; // must be white to tint properly 91 | GUI.color = new Color(0,0,0,.7f); 92 | GUI.Box(new Rect(0,0,Screen.width,30),"", style); 93 | 94 | GUILayout.BeginArea(new Rect(5,5,600,20)); 95 | GUILayout.BeginHorizontal(); 96 | 97 | GUI.color = Color.white; 98 | Config.showBones = GUILayout.Toggle(Config.showBones, "Show Bones", GUILayout.Width(100)); 99 | 100 | if (Config.showBones) 101 | { 102 | Config.enableEditing = GUILayout.Toggle(Config.enableEditing, "Enable editing", GUILayout.Width(100)); 103 | Config.showBoneWeights = GUILayout.Toggle(Config.showBoneWeights, "Show Bone Weights"); 104 | } 105 | 106 | if (Config.showBones && Config.showBoneWeights) 107 | { 108 | string[] boneNames = GetBoneNames(_currentSkinnedMesh); 109 | Config.boneIndex = EditorGUILayout.Popup(Config.boneIndex, boneNames); 110 | 111 | Config.useAlphaForWeightColor = GUILayout.Toggle(Config.useAlphaForWeightColor, "Use Alpha"); 112 | } 113 | GUILayout.EndHorizontal(); 114 | GUILayout.EndArea(); 115 | 116 | GUI.color = new Color(.75f, .75f, .75f); 117 | GUI.Label(new Rect(Screen.width-180,5, 180, 20), "SkinnedMeshTools v0.1b"); 118 | GUI.color = Color.white; 119 | 120 | Handles.EndGUI(); 121 | } 122 | 123 | private static void DrawBindPose() 124 | { 125 | Handles.BeginGUI(); 126 | GUI.color = Color.green; 127 | 128 | List bindPoses = new List(); 129 | _currentSkinnedMesh.sharedMesh.GetBindposes(bindPoses); 130 | foreach (Matrix4x4 pose in bindPoses) 131 | { 132 | Vector3 position = pose.inverse.MultiplyPoint(Vector3.zero); 133 | DrawPoint(position, Color.white, 1); 134 | } 135 | 136 | GUI.color = Color.white; 137 | Handles.EndGUI(); 138 | } 139 | 140 | private static void DrawBones() 141 | { 142 | List bones = _currentSkinnedMesh.bones.ToList(); 143 | if (bones == null || bones.Count == 0) 144 | return; 145 | 146 | bones.FindAll(b => bones.Contains(b.parent)).ForEach(b => Handles.DrawLine(b.parent.position, b.position)); 147 | Handles.BeginGUI(); 148 | bones.ForEach(b => DrawBone(bones.IndexOf(b), b.position)); 149 | Handles.EndGUI(); 150 | 151 | if (Config.enableEditing) 152 | { 153 | Tools.hidden = true; 154 | EditorGUI.BeginChangeCheck(); 155 | Transform currentBone = _currentSkinnedMesh.bones[Config.boneIndex]; 156 | Quaternion rot = Handles.RotationHandle(currentBone.rotation, currentBone.position); 157 | if (EditorGUI.EndChangeCheck()) 158 | { 159 | Undo.RecordObject(_currentSkinnedMesh.gameObject, "Bone rotation"); 160 | currentBone.rotation = rot; 161 | } 162 | } 163 | } 164 | 165 | private static void DrawBone(int p_index, Vector3 p_position) 166 | { 167 | GUI.color = Color.white; 168 | Vector2 pos2D = HandleUtility.WorldToGUIPoint(p_position); 169 | int scale = 10; 170 | Rect mouseRect = new Rect(pos2D.x - scale / 2, pos2D.y - scale / 2, scale, scale); 171 | 172 | if (Config.showBoneWeights) 173 | { 174 | if (p_index == Config.boneIndex) 175 | { 176 | GUI.color = Color.green; 177 | scale = 16; 178 | } 179 | else if (mouseRect.Contains(Event.current.mousePosition)) 180 | { 181 | GUI.color = Color.yellow; 182 | scale = 16; 183 | } 184 | } 185 | 186 | if (GUI.Button(new Rect(pos2D.x - scale / 2, pos2D.y - scale / 2, scale, scale), circleTexture, GUIStyle.none)) 187 | { 188 | Config.boneIndex = p_index; 189 | } 190 | 191 | GUI.color = Color.white; 192 | } 193 | 194 | private static void DrawPoint(Vector3 p_position, Color p_color, float p_scale) 195 | { 196 | GUI.color = p_color; 197 | Vector2 pos2D = HandleUtility.WorldToGUIPoint(p_position); 198 | GUI.DrawTexture(new Rect(pos2D.x - 4*p_scale, pos2D.y - 4*p_scale, 8*p_scale, 8*p_scale), circleTexture); 199 | GUI.color = Color.white; 200 | } 201 | 202 | private static void DrawBoneWeights(int p_boneIndex) 203 | { 204 | GL.Clear(true, false, Color.black); 205 | Mesh mesh = GenerateBoneWeightMesh(_currentSkinnedMesh, p_boneIndex); 206 | if (boneWeightMaterial != null) 207 | { 208 | boneWeightMaterial.SetPass(0); 209 | Graphics.DrawMeshNow(mesh, _currentSkinnedMesh.transform.localToWorldMatrix); 210 | } 211 | } 212 | 213 | private static Mesh GenerateBoneWeightMesh(SkinnedMeshRenderer p_skinnedMesh, int p_boneIndex) 214 | { 215 | Mesh mesh = new Mesh(); 216 | p_skinnedMesh.BakeMesh(mesh); 217 | Color[] colors = new Color[mesh.vertexCount]; 218 | BoneWeight[] boneWeights = p_skinnedMesh.sharedMesh.boneWeights; 219 | for (int i =0; i< mesh.vertexCount; i++) 220 | { 221 | colors[i] = GetBoneWeightColor(boneWeights[i], p_boneIndex); 222 | } 223 | 224 | mesh.colors = colors; 225 | return mesh; 226 | } 227 | 228 | private static Color GetBoneWeightColor(BoneWeight p_boneWeight, int p_boneIndex) 229 | { 230 | if (Config.useAlphaForWeightColor) 231 | { 232 | if (p_boneWeight.boneIndex0 == p_boneIndex) 233 | return new Color(Config.boneWeightColor.r, Config.boneWeightColor.g, Config.boneWeightColor.b, 234 | p_boneWeight.weight0); 235 | if (p_boneWeight.boneIndex1 == p_boneIndex) 236 | return new Color(Config.boneWeightColor.r, Config.boneWeightColor.g, Config.boneWeightColor.b, 237 | p_boneWeight.weight1); 238 | if (p_boneWeight.boneIndex2 == p_boneIndex) 239 | return new Color(Config.boneWeightColor.r, Config.boneWeightColor.g, Config.boneWeightColor.b, 240 | p_boneWeight.weight2); 241 | if (p_boneWeight.boneIndex3 == p_boneIndex) 242 | return new Color(Config.boneWeightColor.r, Config.boneWeightColor.g, Config.boneWeightColor.b, 243 | p_boneWeight.weight3); 244 | 245 | return new Color(0, 0, 0, 0); 246 | } 247 | 248 | if (p_boneWeight.boneIndex0 == p_boneIndex) 249 | return new Color(Config.boneWeightColor.r * p_boneWeight.weight0, 250 | Config.boneWeightColor.g * p_boneWeight.weight0, Config.boneWeightColor.b * p_boneWeight.weight0, 1); 251 | if (p_boneWeight.boneIndex1 == p_boneIndex) 252 | return new Color(Config.boneWeightColor.r * p_boneWeight.weight1, 253 | Config.boneWeightColor.g * p_boneWeight.weight1, Config.boneWeightColor.b * p_boneWeight.weight1, 1); 254 | if (p_boneWeight.boneIndex2 == p_boneIndex) 255 | return new Color(Config.boneWeightColor.r * p_boneWeight.weight2, 256 | Config.boneWeightColor.g * p_boneWeight.weight2, Config.boneWeightColor.b * p_boneWeight.weight2, 1); 257 | if (p_boneWeight.boneIndex3 == p_boneIndex) 258 | return new Color(Config.boneWeightColor.r * p_boneWeight.weight3, 259 | Config.boneWeightColor.g * p_boneWeight.weight3, Config.boneWeightColor.b * p_boneWeight.weight3, 1); 260 | 261 | return new Color(0, 0, 0, 1); 262 | } 263 | 264 | private static string[] GetBoneNames(SkinnedMeshRenderer p_skinnedMesh) 265 | { 266 | return p_skinnedMesh.bones.ToList().Select(b => b.name).ToArray(); 267 | } 268 | } 269 | #endif --------------------------------------------------------------------------------