/// <summary> /// for specified shape, /// 1. apply mesh changes based on weight /// 2. ensure animWeight == cmpWeight /// </summary> private void _ApplyWeightChange(int shapeIdx, float newWeight) { float curWeight = m_CmpWeights[shapeIdx]; _SetAnimWeight(shapeIdx, newWeight); if (Mathf.Approximately(curWeight, newWeight)) { return; } Mesh m = m_Mesh.mesh; ShapeKeyMorphSO tarMorph = m_Deforms[shapeIdx]; tarMorph.LerpDiff(_GetBasisShapeKey(), curWeight, newWeight, m_OutData); if (m_UseMeshCache) { m_OutData.ApplyToMeshAsSubtract(m, m_MeshCache); } else { m_OutData.ApplyToMeshAsSubtract(m); } m_CmpWeights[shapeIdx] = newWeight; _MarkNeedFix(); }
/// <summary> /// used to init real data /// </summary> public static ShapeKeyDataDiff New(ShapeKeyMorphSO basis, float weight, bool isFullData) { var d = new ShapeKeyDataDiff(); d.weight = weight; d.basisSO = basis; d.isFullData = isFullData; d.vertices = new List <Vector3>(); d.normals = new List <Vector3>(); d.tangents = new List <Vector4>(); d.indV = new List <int>(); d.indN = new List <int>(); d.indT = new List <int>(); if (!isFullData) { d.UpdateDiffDataWithCurrentMesh(); } else { d.SetFullData(); } return(d); }
/// <summary> /// called only by MeshManipulator /// </summary> public void InitWhenCreatedByEditor() { Dbg.Assert(m_Deforms.Count == 0, "MorphProc.InitWhenCreatedByEditor: m_Deforms not empty!?"); ShapeKeyMorphSO newShape = ShapeKeyMorphSO.NewAsBasis(m_Mesh.mesh); SetMorphAt(BASIS_MORPH_IDX, newShape); m_CmpWeights[BASIS_MORPH_IDX] = FULL_WEIGHT; _SetAnimWeight(BASIS_MORPH_IDX, FULL_WEIGHT); m_OutData = ShapeKeyDataDiff.TempVarNew(m_Deforms[BASIS_MORPH_IDX]); }
public override void OnInspectorGUI() { serializedObject.Update(); ShapeKeyMorphSO morph = (ShapeKeyMorphSO)serializedObject.targetObject; Mesh m = (Mesh)m_propMesh.objectReferenceValue; EditorGUILayout.BeginHorizontal(); { GUILayout.Label("Morph Name:"); GUILayout.Space(20f); string morphName = m_propName.stringValue; if (EUtil.StringField("MorphName", ref morphName)) { m_propName.stringValue = morphName; _ChangeAssetNameIfNeeded(); } } EditorGUILayout.EndHorizontal(); EditorGUILayout.ObjectField(new GUIContent("Working Mesh", "The mesh on which this morph is applied"), m, typeof(Mesh), true); EditorGUILayout.HelpBox( string.Format("vertex: {0}, {1}, {2}", m.vertexCount, morph.HasNormals ? "normals" : "NO normals", morph.HasTangents ? "tangents" : "NO tangents"), MessageType.Info); // show each shapeKeyData for (int i = 0; i < morph.ShapeKeyCnt; ++i) { _DrawShapeKeyData(morph, i); } // add new shapeKeyData button GUILayout.BeginHorizontal(); { GUILayout.Space(30f); if (GUILayout.Button("Add New Shape Key")) { Undo.RecordObject(morph, "ShapeKeyMorphSO inspector"); morph.AddNewShapeKeyByMeshCurrentData(); } GUILayout.Space(30f); } GUILayout.EndHorizontal(); serializedObject.ApplyModifiedProperties(); }
/// <summary> /// add a new deform using current mesh status /// </summary> public void AddCurrentMeshAsNewShapeKeyMorph() { if (m_Deforms.Count >= MAX_SHAPEKEY_CNT) { return; } int newIdx = m_Deforms.Count; ShapeKeyMorphSO newShape = ShapeKeyMorphSO.NewAsNonBasis(m_Deforms[BASIS_MORPH_IDX]); SetMorphAt(newIdx, newShape); m_CmpWeights[newIdx] = FULL_WEIGHT; _SetAnimWeight(newIdx, FULL_WEIGHT); }
public static ShapeKeyData New(float weight, ShapeKeyMorphSO basisSO) { ShapeKeyData d = new ShapeKeyData(); //int vcnt = m.vertexCount; d.basisSO = basisSO; Mesh m = basisSO.GetMesh(); d.vertices = m.vertices; d.normals = m.normals; d.tangents = m.tangents; d.weight = weight; return(d); }
// public method /// <summary> /// used to init temp var /// </summary> public static ShapeKeyDataDiff TempVarNew(ShapeKeyMorphSO basis) { var d = new ShapeKeyDataDiff(); d.weight = 0; d.basisSO = basis; d.isFullData = false; d.vertices = new List <Vector3>(); d.normals = new List <Vector3>(); d.tangents = new List <Vector4>(); d.indV = new List <int>(); d.indN = new List <int>(); d.indT = new List <int>(); return(d); }
public void SetMorphAt(int idx, ShapeKeyMorphSO shape) { Dbg.Assert(m_Deforms != null, "SetMorphAt: m_Deforms == null"); if (idx < m_Deforms.Count) { m_Deforms[idx] = shape; } else if (idx == m_Deforms.Count) { m_Deforms.Add(shape); } else if (idx >= MAX_SHAPEKEY_CNT) { Dbg.LogErr("MorphProc.SetMorphAt: current only support up to 10 shape keys"); } else { Dbg.LogErr("MorphProc.SetMorphAt: idx beyond range: {0}, {1}", idx, m_Deforms.Count); } }
public static ShapeKeyMorphSO NewAsBasis(Mesh m) { ShapeKeyMorphSO deform = ScriptableObject.CreateInstance <ShapeKeyMorphSO>(); deform.name = "Deform" + deform.GetInstanceID(); deform.m_Mesh = m; deform.m_Keys = new List <ShapeKeyDataDiff>(); deform.m_BasisSO = deform; var data = ShapeKeyDataDiff.New(deform, MorphProc.FULL_WEIGHT, true); deform.m_Keys.Add(data); deform._PrepareTmpVar(); deform.m_hasNormals = data.normals.Count > 0; deform.m_hasTangents = data.tangents.Count > 0; return(deform); }
// public method #endregion "public method" #region "private method" // private method private void _DrawShapeKeyData(ShapeKeyMorphSO morph, int keyIdx) { ShapeKeyDataDiff keyData = morph.GetShapeKeyDataDiff(keyIdx); EditorGUILayout.BeginHorizontal(); { EditorGUILayout.LabelField("Weight:", GUILayout.Width(50f)); float newWeight = keyData.weight; if (EUtil.FloatField("weight" + keyIdx, ref newWeight)) //only true when use enter to confirm { morph.SetShapeKeyWeight(keyIdx, newWeight); //this will ensure all keys are sorted } if (EUtil.Button(EditorRes.texSample, "Sample current mesh status as shape key", EditorRes.styleBtnMorphProc, GUILayout.Width(20f))) { morph.SetMeshCurrentDataToShapeKey(keyIdx); } if (EUtil.Button(EditorRes.texApplyToMesh, "Apply this shape key to mesh", EditorRes.styleBtnMorphProc, GUILayout.Width(20f))) { Undo.RecordObject(m_MorphProc, "MorphProc Inspector"); m_MorphProc.ResetToBasisShape(); m_MorphProc.ApplyOnlyMorphAt(m_MorphIdx, keyData.weight); } if (EUtil.Button(EditorRes.texDelete, "Delete this shape key from this morph", EditorRes.styleBtnMorphProc, GUILayout.Width(20f))) { if (morph.ShapeKeyCnt == 1) { EditorUtility.DisplayDialog("Only one shape key", "Cannot delete shape key when there's no others", "Got it"); } else { morph.DelShapeKeyDataDiff(keyIdx); } } } EditorGUILayout.EndHorizontal(); }
public void Copy(ShapeKeyData rhs) { Dbg.Assert(this.vertices.Length == rhs.vertices.Length, "ShapeKeyData.Copy: vertices cnt: {0}!={1}", vertices.Length, rhs.vertices.Length); Dbg.Assert(this.normals.Length == rhs.normals.Length, "ShapeKeyData.Copy: normals cnt: {0}!={1}", normals.Length, rhs.normals.Length); Dbg.Assert(this.tangents.Length == rhs.tangents.Length, "ShapeKeyData.Copy: tangents cnt: {0}!={1}", tangents.Length, rhs.tangents.Length); for (int i = 0; i < vertices.Length; ++i) { this.vertices[i] = rhs.vertices[i]; } for (int i = 0; i < normals.Length; ++i) { this.normals[i] = rhs.normals[i]; } for (int i = 0; i < tangents.Length; ++i) { this.tangents[i] = rhs.tangents[i]; } this.weight = rhs.weight; this.basisSO = rhs.basisSO; }
// public method #endregion "public method" #region "private method" private void _DrawDeformEntry(MorphProc proc, int deformIdx, bool isBasis = true) { ShapeKeyMorphSO deform = (ShapeKeyMorphSO)m_propDeforms.GetArrayElementAtIndex(deformIdx).objectReferenceValue; EditorGUILayout.BeginHorizontal(); { float newWeight = 0f; // weight if (isBasis) { EUtil.PushGUIEnable(false); } EditorGUI.BeginChangeCheck(); newWeight = EditorGUILayout.FloatField(deform.name, m_propAnimWeights[deformIdx].floatValue); if (EditorGUI.EndChangeCheck()) { m_propAnimWeights[deformIdx].floatValue = Mathf.Clamp(newWeight, 0, 100f); } if (isBasis) { EUtil.PopGUIEnable(); } // after weight if (isBasis) { //the basis GUILayout.Space(20f); if (EUtil.Button("R", "Reset as Basis", Color.green, GUILayout.Width(42f))) { Undo.RecordObject(proc, "MorphProc Inspector"); proc.ResetToBasisShape(); } } else { if (GUILayout.Button(new GUIContent(m_texDetail, "Edit details of this deform"), m_styleBtn, GUILayout.Width(20f))) { var e = (BaseMorphSOEditor)Editor.CreateEditor(deform); e.m_MorphProcEditor = this; e.m_MorphProc = proc; e.m_MorphIdx = deformIdx; EditorEditorWindow.OpenWindowWithEditor(e); } if (GUILayout.Button(new GUIContent(m_texApply, "Apply only this deform 100%"), m_styleBtn, GUILayout.Width(20f))) { Undo.RecordObject(proc, "MorphProc Inspector"); proc.ApplyOnlyMorphAt(deformIdx); } if (GUILayout.Button(new GUIContent(m_texDelete, "Delete this deform"), m_styleBtn, GUILayout.Width(20f))) { if (EditorUtility.DisplayDialog("To be or not to be", "Are you sure to delete this Morph?", "Go Ahead", "No No No")) { Undo.RecordObject(proc, "MorphProc Inspector"); proc.RemoveShapeKeyMorphAt(deformIdx); } } } } EditorGUILayout.EndHorizontal(); }