using UnityEngine; using UnityEngine.Assertions; using UnityEditor; using System; using System.Collections; using System.Collections.Generic; namespace VoxelImporter { public class VoxelSkinnedAnimationObjectBoneCore { public VoxelSkinnedAnimationObjectBone voxelBone { get; protected set; } public VoxelSkinnedAnimationObjectCore objectCore { get; protected set; } private VoxelSkinnedAnimationObjectBoneCore _mirrorBoneCore; public VoxelSkinnedAnimationObjectBoneCore mirrorBoneCore { get { if(_mirrorBoneCore == null) _mirrorBoneCore = new VoxelSkinnedAnimationObjectBoneCore(voxelBone.mirrorBone, objectCore); return _mirrorBoneCore; } } public VoxelSkinnedAnimationObjectBoneCore(VoxelSkinnedAnimationObjectBone target, VoxelSkinnedAnimationObjectCore objCore) { voxelBone = target; objectCore = objCore; } public void Initialize() { voxelBone.EditorInitialize(); } public void UpdateBoneWeight(int boneIndex = -1) { Undo.RecordObject(voxelBone, "Update Bone Weight"); if (boneIndex >= 0) voxelBone.boneIndex = boneIndex; if (voxelBone.weightData == null) { voxelBone.weightData = new WeightData(); } #region Erase { List removeList = new List(); voxelBone.weightData.AllAction((pos, weights) => { if (voxelBone.voxelObject.voxelData.VoxelTableContains(pos) < 0 || !weights.HasValue()) { removeList.Add(pos); } }); for (int i = 0; i < removeList.Count; i++) { voxelBone.weightData.RemoveWeight(removeList[i]); } } #endregion } public bool IsHaveEraseDisablePositionAnimation() { var animator = voxelBone.voxelObject.GetComponent(); if (animator != null && animator.runtimeAnimatorController != null) { foreach (var clip in animator.runtimeAnimatorController.animationClips) { var bindings = AnimationUtility.GetCurveBindings(clip); for (int i = 0; i < bindings.Length; i++) { if (bindings[i].path != fullPathBoneName) continue; if (bindings[i].propertyName.StartsWith("m_LocalPosition.")) { return true; } } } } return false; } public bool IsHaveEraseDisableRotationAnimation() { var animator = voxelBone.voxelObject.GetComponent(); if (animator != null && animator.runtimeAnimatorController != null) { foreach (var clip in animator.runtimeAnimatorController.animationClips) { var bindings = AnimationUtility.GetCurveBindings(clip); for (int i = 0; i < bindings.Length; i++) { if (bindings[i].path != fullPathBoneName) continue; if (bindings[i].propertyName.StartsWith("localEulerAnglesRaw.")) { return true; } } } } return false; } public bool IsHaveEraseDisableScaleAnimation() { var animator = voxelBone.voxelObject.GetComponent(); if (animator != null && animator.runtimeAnimatorController != null) { foreach (var clip in animator.runtimeAnimatorController.animationClips) { var bindings = AnimationUtility.GetCurveBindings(clip); for (int i = 0; i < bindings.Length; i++) { if (bindings[i].path != fullPathBoneName) continue; if (bindings[i].propertyName.StartsWith("m_LocalScale.")) { return true; } } } } return false; } public void EraseDisableAnimation() { if (voxelBone.edit_disablePositionAnimation || voxelBone.edit_disableRotationAnimation || voxelBone.edit_disableScaleAnimation) { var animator = voxelBone.voxelObject.GetComponent(); if (animator != null && animator.runtimeAnimatorController != null) { foreach (var clip in animator.runtimeAnimatorController.animationClips) { var bindings = AnimationUtility.GetCurveBindings(clip); if (bindings.IsReadOnly) continue; for (int i = 0; i < bindings.Length; i++) { if (bindings[i].path != fullPathBoneName) continue; if ((voxelBone.edit_disablePositionAnimation && bindings[i].propertyName.StartsWith("m_LocalPosition.")) || (voxelBone.edit_disableRotationAnimation && bindings[i].propertyName.StartsWith("localEulerAnglesRaw.")) || (voxelBone.edit_disableScaleAnimation && bindings[i].propertyName.StartsWith("m_LocalScale."))) { AnimationUtility.SetEditorCurve(clip, bindings[i], null); } } } } } } public void MirroringAnimation() { if (voxelBone.edit_mirrorSetBoneAnimation && voxelBone.mirrorBone != null) { var animator = voxelBone.voxelObject.GetComponent(); if (animator != null && animator.runtimeAnimatorController != null) { foreach (var clip in animator.runtimeAnimatorController.animationClips) { var bindings = AnimationUtility.GetCurveBindings(clip); if (bindings.IsReadOnly) continue; for (int i = 0; i < bindings.Length; i++) { if (bindings[i].path != fullPathBoneName) continue; var curve = AnimationUtility.GetEditorCurve(clip, bindings[i]); if ((!voxelBone.edit_disablePositionAnimation && ((voxelBone.voxelObject.edit_mirrorPosition[0] != VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None && bindings[i].propertyName.StartsWith("m_LocalPosition.x")) || (voxelBone.voxelObject.edit_mirrorPosition[1] != VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None && bindings[i].propertyName.StartsWith("m_LocalPosition.y")) || (voxelBone.voxelObject.edit_mirrorPosition[2] != VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None && bindings[i].propertyName.StartsWith("m_LocalPosition.z")))) || (!voxelBone.edit_disableRotationAnimation && ((voxelBone.voxelObject.edit_mirrorRotation[0] != VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None && bindings[i].propertyName.StartsWith("localEulerAnglesRaw.x")) || (voxelBone.voxelObject.edit_mirrorRotation[1] != VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None && bindings[i].propertyName.StartsWith("localEulerAnglesRaw.y")) || (voxelBone.voxelObject.edit_mirrorRotation[2] != VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None && bindings[i].propertyName.StartsWith("localEulerAnglesRaw.z")))) || (!voxelBone.edit_disableScaleAnimation && ((voxelBone.voxelObject.edit_mirrorScale[0] != VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None && bindings[i].propertyName.StartsWith("m_LocalScale.x")) || (voxelBone.voxelObject.edit_mirrorScale[1] != VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None && bindings[i].propertyName.StartsWith("m_LocalScale.y")) || (voxelBone.voxelObject.edit_mirrorScale[2] != VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None && bindings[i].propertyName.StartsWith("m_LocalScale.z"))))) { EditorCurveBinding? mirrorBinding = null; AnimationCurve mirrorCurve = null; for (int j = 0; j < bindings.Length; j++) { if (bindings[j].path == mirrorBoneCore.fullPathBoneName && bindings[j].propertyName == bindings[i].propertyName) { mirrorBinding = bindings[j]; mirrorCurve = AnimationUtility.GetEditorCurve(clip, bindings[j]); break; } } Func Mirroring = (keys) => { if ((voxelBone.voxelObject.edit_mirrorPosition[0] == VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative && bindings[i].propertyName.StartsWith("m_LocalPosition.x")) || (voxelBone.voxelObject.edit_mirrorPosition[1] == VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative && bindings[i].propertyName.StartsWith("m_LocalPosition.y")) || (voxelBone.voxelObject.edit_mirrorPosition[2] == VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative && bindings[i].propertyName.StartsWith("m_LocalPosition.z")) || (voxelBone.voxelObject.edit_mirrorRotation[0] == VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative && bindings[i].propertyName.StartsWith("localEulerAnglesRaw.x")) || (voxelBone.voxelObject.edit_mirrorRotation[1] == VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative && bindings[i].propertyName.StartsWith("localEulerAnglesRaw.y")) || (voxelBone.voxelObject.edit_mirrorRotation[2] == VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative && bindings[i].propertyName.StartsWith("localEulerAnglesRaw.z")) || (voxelBone.voxelObject.edit_mirrorScale[0] == VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative && bindings[i].propertyName.StartsWith("m_LocalScale.x")) || (voxelBone.voxelObject.edit_mirrorScale[1] == VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative && bindings[i].propertyName.StartsWith("m_LocalScale.y")) || (voxelBone.voxelObject.edit_mirrorScale[2] == VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative && bindings[i].propertyName.StartsWith("m_LocalScale.z"))) { for (int k = 0; k < keys.Length; k++) { keys[k].inTangent = -keys[k].inTangent; keys[k].outTangent = -keys[k].outTangent; keys[k].value = -keys[k].value; } } return keys; }; bool updateCurve = false; if (!mirrorBinding.HasValue) { EditorCurveBinding newBinding = new EditorCurveBinding(); newBinding.path = mirrorBoneCore.fullPathBoneName; newBinding.type = bindings[i].type; newBinding.propertyName = bindings[i].propertyName; mirrorBinding = newBinding; mirrorCurve = new AnimationCurve(Mirroring(curve.keys)); updateCurve = true; } else { mirrorCurve = AnimationUtility.GetEditorCurve(clip, mirrorBinding.Value); if (curve.length != mirrorCurve.length) { mirrorCurve = new AnimationCurve(Mirroring(curve.keys)); updateCurve = true; } else { var mirrorKeys = Mirroring(curve.keys); for (int k = 0; k < mirrorCurve.length; k++) { if (mirrorCurve[k].inTangent != mirrorKeys[k].inTangent || mirrorCurve[k].outTangent != mirrorKeys[k].outTangent || mirrorCurve[k].time != mirrorKeys[k].time || mirrorCurve[k].value != mirrorKeys[k].value) { mirrorCurve = new AnimationCurve(mirrorKeys); updateCurve = true; break; } } } } if (updateCurve) { AnimationUtility.SetEditorCurve(clip, mirrorBinding.Value, mirrorCurve); } } } } } } } public void FixMissingAnimation() { var animator = voxelBone.voxelObject.GetComponent(); if (animator != null && animator.runtimeAnimatorController != null) { string[] bonePaths = new string[objectCore.animationObject.bones.Length]; for (int i = 0; i < objectCore.animationObject.bones.Length; i++) { if (objectCore.animationObject.bones[i] == null) continue; bonePaths[i] = AnimationUtility.CalculateTransformPath(objectCore.animationObject.bones[i].transform, voxelBone.voxelObject.transform); } foreach (var clip in animator.runtimeAnimatorController.animationClips) { var bindings = AnimationUtility.GetCurveBindings(clip); if (bindings.IsReadOnly) continue; for (int i = 0; i < bindings.Length; i++) { bool missing = true; for (int j = 0; j < bonePaths.Length; j++) { if(bindings[i].path == bonePaths[j]) { missing = false; break; } } if (!missing) continue; var curve = AnimationUtility.GetEditorCurve(clip, bindings[i]); { var index = bindings[i].path.IndexOf(fullPathBoneName); if (index >= 0 && bindings[i].path.Length == index + fullPathBoneName.Length) { AnimationUtility.SetEditorCurve(clip, bindings[i], null); bindings[i].path = fullPathBoneName; AnimationUtility.SetEditorCurve(clip, bindings[i], curve); continue; } } { var index = fullPathBoneName.IndexOf(bindings[i].path); if (index >= 0 && fullPathBoneName.Length == index + bindings[i].path.Length) { AnimationUtility.SetEditorCurve(clip, bindings[i], null); bindings[i].path = fullPathBoneName; AnimationUtility.SetEditorCurve(clip, bindings[i], curve); continue; } } { var index = bindings[i].path.LastIndexOf(voxelBone.name); if (index >= 0 && bindings[i].path.Length == index + voxelBone.name.Length) { AnimationUtility.SetEditorCurve(clip, bindings[i], null); bindings[i].path = fullPathBoneName; AnimationUtility.SetEditorCurve(clip, bindings[i], curve); continue; } } } } } } public void MirrorBoneAnimation() { if (voxelBone.mirrorBone == null) return; if (!voxelBone.edit_mirrorSetBoneAnimation) return; #region Position { var tmp = voxelBone.transform.localPosition; switch (voxelBone.mirrorBone.voxelObject.edit_mirrorPosition[0]) { case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None: tmp.x = voxelBone.mirrorBone.transform.localPosition.x; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Positive: tmp.x = voxelBone.transform.localPosition.x; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative: tmp.x = -voxelBone.transform.localPosition.x; break; } switch (voxelBone.mirrorBone.voxelObject.edit_mirrorPosition[1]) { case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None: tmp.y = voxelBone.mirrorBone.transform.localPosition.y; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Positive: tmp.y = voxelBone.transform.localPosition.y; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative: tmp.y = -voxelBone.transform.localPosition.y; break; } switch (voxelBone.mirrorBone.voxelObject.edit_mirrorPosition[2]) { case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None: tmp.z = voxelBone.mirrorBone.transform.localPosition.z; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Positive: tmp.z = voxelBone.transform.localPosition.z; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative: tmp.z = -voxelBone.transform.localPosition.z; break; } if (voxelBone.mirrorBone.transform.localPosition != tmp) voxelBone.mirrorBone.transform.localPosition = tmp; } #endregion #region Rotation { var tmp = voxelBone.transform.localEulerAngles; switch (voxelBone.mirrorBone.voxelObject.edit_mirrorRotation[0]) { case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None: tmp.x = voxelBone.mirrorBone.transform.localEulerAngles.x; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Positive: tmp.x = voxelBone.transform.localEulerAngles.x; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative: tmp.x = -voxelBone.transform.localEulerAngles.x; break; } switch (voxelBone.mirrorBone.voxelObject.edit_mirrorRotation[1]) { case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None: tmp.y = voxelBone.mirrorBone.transform.localEulerAngles.y; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Positive: tmp.y = voxelBone.transform.localEulerAngles.y; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative: tmp.y = -voxelBone.transform.localEulerAngles.y; break; } switch (voxelBone.mirrorBone.voxelObject.edit_mirrorRotation[2]) { case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None: tmp.z = voxelBone.mirrorBone.transform.localEulerAngles.z; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Positive: tmp.z = voxelBone.transform.localEulerAngles.z; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative: tmp.z = -voxelBone.transform.localEulerAngles.z; break; } if (voxelBone.mirrorBone.transform.localEulerAngles != tmp) voxelBone.mirrorBone.transform.localEulerAngles = tmp; } #endregion #region Scale { var tmp = voxelBone.transform.localScale; switch (voxelBone.mirrorBone.voxelObject.edit_mirrorScale[0]) { case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None: tmp.x = voxelBone.mirrorBone.transform.localScale.x; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Positive: tmp.x = voxelBone.transform.localScale.x; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative: tmp.x = -voxelBone.transform.localScale.x; break; } switch (voxelBone.mirrorBone.voxelObject.edit_mirrorScale[1]) { case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None: tmp.y = voxelBone.mirrorBone.transform.localScale.y; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Positive: tmp.y = voxelBone.transform.localScale.y; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative: tmp.y = -voxelBone.transform.localScale.y; break; } switch (voxelBone.mirrorBone.voxelObject.edit_mirrorScale[2]) { case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.None: tmp.z = voxelBone.mirrorBone.transform.localScale.z; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Positive: tmp.z = voxelBone.transform.localScale.z; break; case VoxelSkinnedAnimationObject.Edit_MirrorSetMode.Negative: tmp.z = -voxelBone.transform.localScale.z; break; } if (voxelBone.mirrorBone.transform.localScale != tmp) voxelBone.mirrorBone.transform.localScale = tmp; } #endregion } public void MirrorBonePosition() { if (voxelBone.mirrorBone == null) return; if (!voxelBone.edit_mirrorSetBonePosition) return; var tmp = voxelBone.transform.localPosition; tmp.x = -voxelBone.transform.localPosition.x; voxelBone.mirrorBone.transform.localPosition = tmp; } public void MirrorBoneWeight() { if (voxelBone.mirrorBone == null) return; if (!voxelBone.edit_mirrorSetBoneWeight) return; voxelBone.mirrorBone.transform.localPosition = new Vector3(-voxelBone.transform.localPosition.x, voxelBone.transform.localPosition.y, voxelBone.transform.localPosition.z); #region Weight { voxelBone.mirrorBone.weightData.ClearWeight(); voxelBone.weightData.AllAction((pos, weights) => { var newPos = GetMirrorVoxelPosition(pos); var newWeights = new WeightData.VoxelWeight(); newWeights.weightXYZ = weights.weight_XYZ; newWeights.weight_XYZ = weights.weightXYZ; newWeights.weightX_YZ = weights.weight_X_YZ; newWeights.weightXY_Z = weights.weight_XY_Z; newWeights.weight_X_YZ = weights.weightX_YZ; newWeights.weight_XY_Z = weights.weightXY_Z; newWeights.weightX_Y_Z = weights.weight_X_Y_Z; newWeights.weight_X_Y_Z = weights.weightX_Y_Z; voxelBone.mirrorBone.weightData.SetWeight(newPos, newWeights); }); } #endregion } public IntVector3 GetMirrorVoxelPosition(IntVector3 pos) { Assert.IsNotNull(voxelBone.mirrorBone); var srcVoxelPosition = objectCore.GetVoxelPosition(voxelBone.voxelObject.bindposes[voxelBone.boneIndex].inverse.GetColumn(3)); var voxelPosition = objectCore.GetVoxelPosition(voxelBone.mirrorBone.voxelObject.bindposes[voxelBone.mirrorBone.boneIndex].inverse.GetColumn(3)); IntVector3 newPos; { var offset = new Vector3(pos.x, pos.y, pos.z) - srcVoxelPosition; var mirror = voxelPosition + new Vector3(-offset.x - 1, offset.y, offset.z); newPos = new IntVector3(Mathf.RoundToInt(mirror.x), Mathf.RoundToInt(mirror.y), Mathf.RoundToInt(mirror.z)); } return newPos; } private string _fullPathBoneName; public string fullPathBoneName { get { if (string.IsNullOrEmpty(_fullPathBoneName)) _fullPathBoneName = AnimationUtility.CalculateTransformPath(voxelBone.transform, voxelBone.voxelObject.transform); return _fullPathBoneName; } } } }