public List <AnimationWindowHierarchyNode> CreateTreeFromCurves() { List <AnimationWindowHierarchyNode> nodes = new List <AnimationWindowHierarchyNode>(); List <AnimationWindowCurve> singlePropertyCurves = new List <AnimationWindowCurve>(); AnimationWindowCurve[] curves = state.allCurves.ToArray(); AnimationWindowHierarchyNode parentNode = (AnimationWindowHierarchyNode)m_RootItem; for (int i = 0; i < curves.Length; i++) { AnimationWindowCurve curve = curves[i]; if (!state.ShouldShowCurve(curve)) { continue; } AnimationWindowCurve nextCurve = i < curves.Length - 1 ? curves[i + 1] : null; singlePropertyCurves.Add(curve); bool areSameGroup = nextCurve != null && AnimationWindowUtility.GetPropertyGroupName(nextCurve.propertyName) == AnimationWindowUtility.GetPropertyGroupName(curve.propertyName); bool areSamePathAndType = nextCurve != null && curve.path.Equals(nextCurve.path) && curve.type == nextCurve.type; // We expect curveBindings to come sorted by propertyname // So we compare curve vs nextCurve. If its different path or different group (think "scale.xyz" as group), then we know this is the last element of such group. if (i == curves.Length - 1 || !areSameGroup || !areSamePathAndType) { if (singlePropertyCurves.Count > 1) { nodes.Add(AddPropertyGroupToHierarchy(singlePropertyCurves.ToArray(), parentNode)); } else { nodes.Add(AddPropertyToHierarchy(singlePropertyCurves[0], parentNode)); } singlePropertyCurves.Clear(); } } return(nodes); }
public static bool DoesPropertyPathMatch(string a, string b) { return(AnimationWindowUtility.GetPropertyGroupName(a).Equals(AnimationWindowUtility.GetPropertyGroupName(b)) || IsRotationCurve(a) && IsRotationCurve(b)); }
static bool IsRotationCurve(string propertyName) { string groupName = AnimationWindowUtility.GetPropertyGroupName(propertyName); return(groupName == kLocalRotation || groupName == kLocalEulerHint); }
static void AddRotationKey(AnimationClip clip, EditorCurveBinding sourceBind, SerializedProperty prop, double time) { if (prop.propertyType != SerializedPropertyType.Quaternion) { return; } var updateCurves = new List <AnimationCurve>(); var updateBindings = new List <EditorCurveBinding>(); var info = AnimationClipCurveCache.Instance.GetCurveInfo(clip); for (var i = 0; i < info.bindings.Length; i++) { if (sourceBind.type != info.bindings[i].type) { continue; } if (info.bindings[i].propertyName.Contains("localEuler")) { updateBindings.Add(info.bindings[i]); updateCurves.Add(info.curves[i]); } } // use this instead of serialized properties because the editor will attempt to maintain // correct localeulers var eulers = ((Transform)prop.serializedObject.targetObject).localEulerAngles; if (updateBindings.Count == 0) { var propName = AnimationWindowUtility.GetPropertyGroupName(sourceBind.propertyName); updateBindings.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.type, propName + ".x")); updateBindings.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.type, propName + ".y")); updateBindings.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.type, propName + ".z")); var curveX = new AnimationCurve(); var curveY = new AnimationCurve(); var curveZ = new AnimationCurve(); AddKeyFrameToCurve(curveX, (float)time, clip.frameRate, eulers.x, false); AddKeyFrameToCurve(curveY, (float)time, clip.frameRate, eulers.y, false); AddKeyFrameToCurve(curveZ, (float)time, clip.frameRate, eulers.z, false); updateCurves.Add(curveX); updateCurves.Add(curveY); updateCurves.Add(curveZ); } for (var i = 0; i < updateBindings.Count; i++) { var c = updateBindings[i].propertyName.Last(); var value = eulers.x; if (c == 'y') { value = eulers.y; } else if (c == 'z') { value = eulers.z; } AddKeyFrameToCurve(updateCurves[i], (float)time, clip.frameRate, value, false); } UpdateEditorCurves(clip, updateBindings, updateCurves); }
// Add a floating point curve key static void AddFloatKey(AnimationClip clip, EditorCurveBinding sourceBind, SerializedProperty prop, double time) { var updateCurves = new List <AnimationCurve>(); var updateBindings = new List <EditorCurveBinding>(); var updated = false; var info = AnimationClipCurveCache.Instance.GetCurveInfo(clip); for (var i = 0; i < info.bindings.Length; i++) { var binding = info.bindings[i]; if (binding.type != sourceBind.type) { continue; } SerializedProperty valProp = null; var curve = info.curves[i]; // perfect match on property path, editting a float if (prop.propertyPath.Equals(binding.propertyName)) { valProp = prop; } // this is a child object else if (binding.propertyName.Contains(prop.propertyPath)) { valProp = prop.serializedObject.FindProperty(binding.propertyName); } if (valProp != null) { var value = GetKeyValue(valProp); if (!float.IsNaN(value)) // Nan indicates an error retrieving the property value { updated = true; AddKeyFrameToCurve(curve, (float)time, clip.frameRate, value, valProp.propertyType == SerializedPropertyType.Boolean); updateCurves.Add(curve); updateBindings.Add(binding); } } } // Curves don't exist, add them if (!updated) { var propName = AnimationWindowUtility.GetPropertyGroupName(sourceBind.propertyName); if (!prop.hasChildren) { var value = GetKeyValue(prop); if (!float.IsNaN(value)) { updateBindings.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.type, sourceBind.propertyName)); var curve = new AnimationCurve(); AddKeyFrameToCurve(curve, (float)time, clip.frameRate, value, prop.propertyType == SerializedPropertyType.Boolean); updateCurves.Add(curve); } } else { // special case because subproperties on color aren't 'visible' so you can't iterate over them if (prop.propertyType == SerializedPropertyType.Color) { updateBindings.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.type, propName + ".r")); updateBindings.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.type, propName + ".g")); updateBindings.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.type, propName + ".b")); updateBindings.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.type, propName + ".a")); var c = prop.colorValue; for (var i = 0; i < 4; i++) { var curve = new AnimationCurve(); AddKeyFrameToCurve(curve, (float)time, clip.frameRate, c[i], prop.propertyType == SerializedPropertyType.Boolean); updateCurves.Add(curve); } } else { prop = prop.Copy(); foreach (SerializedProperty cp in prop) { updateBindings.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.type, cp.propertyPath)); var curve = new AnimationCurve(); AddKeyFrameToCurve(curve, (float)time, clip.frameRate, GetKeyValue(cp), cp.propertyType == SerializedPropertyType.Boolean); updateCurves.Add(curve); } } } } UpdateEditorCurves(clip, updateBindings, updateCurves); }
public AnimationWindowHierarchyPropertyGroupNode(System.Type animatableObjectType, int setId, string propertyName, string path, TreeViewItem parent) : base(AnimationWindowUtility.GetPropertyNodeID(setId, path, animatableObjectType, propertyName), parent != null ? parent.depth + 1 : -1, parent, animatableObjectType, AnimationWindowUtility.GetPropertyGroupName(propertyName), path, AnimationWindowUtility.GetNicePropertyGroupDisplayName(animatableObjectType, propertyName)) { }
public static string GetGroupID(this EditorCurveBinding binding) { return(binding.get_type() + AnimationWindowUtility.GetPropertyGroupName(binding.propertyName)); }
public int CompareTo(AnimationWindowCurve obj) { if (!path.Equals(obj.path)) { return(ComparePaths(obj.path)); } bool sameTransformComponent = type == typeof(Transform) && obj.type == typeof(Transform); bool oneIsTransformComponent = (type == typeof(Transform) || obj.type == typeof(Transform)); // We want to sort position before rotation if (sameTransformComponent) { string propertyGroupA = AnimationWindowUtility.GetNicePropertyGroupDisplayName(typeof(Transform), AnimationWindowUtility.GetPropertyGroupName(propertyName)); string propertyGroupB = AnimationWindowUtility.GetNicePropertyGroupDisplayName(typeof(Transform), AnimationWindowUtility.GetPropertyGroupName(obj.propertyName)); if (propertyGroupA.Contains("Position") && propertyGroupB.Contains("Rotation")) { return(-1); } if (propertyGroupA.Contains("Rotation") && propertyGroupB.Contains("Position")) { return(1); } } // Transform component should always come first. else if (oneIsTransformComponent) { if (type == typeof(Transform)) { return(-1); } else { return(1); } } // Sort (.r, .g, .b, .a) and (.x, .y, .z, .w) if (obj.type == type) { int lhsIndex = AnimationWindowUtility.GetComponentIndex(obj.propertyName); int rhsIndex = AnimationWindowUtility.GetComponentIndex(propertyName); if (lhsIndex != -1 && rhsIndex != -1 && propertyName.Substring(0, propertyName.Length - 2) == obj.propertyName.Substring(0, obj.propertyName.Length - 2)) { return(rhsIndex - lhsIndex); } } return(string.Compare((path + type + propertyName), obj.path + obj.type + obj.propertyName, StringComparison.Ordinal)); }
public AddCurvesPopupPropertyNode(TreeViewItem parent, EditorCurveBinding[] curveBindings) : base(curveBindings[0].GetHashCode(), parent.depth + 1, parent, AnimationWindowUtility.NicifyPropertyGroupName(curveBindings[0].type, AnimationWindowUtility.GetPropertyGroupName(curveBindings[0].propertyName))) { this.curveBindings = curveBindings; }
private TreeViewItem AddAnimatableObjectToHierarchy(EditorCurveBinding[] curveBindings, TreeViewItem parentNode, string path) { TreeViewItem node = new AddCurvesPopupObjectNode(parentNode, path, GetClassName(curveBindings[0])); node.icon = GetIcon(curveBindings[0]); List <TreeViewItem> childNodes = new List <TreeViewItem>(); List <EditorCurveBinding> singlePropertyBindings = new List <EditorCurveBinding>(); for (int i = 0; i < curveBindings.Length; i++) { EditorCurveBinding curveBinding = curveBindings[i]; singlePropertyBindings.Add(curveBinding); // We expect curveBindings to come sorted by propertyname if (i == curveBindings.Length - 1 || AnimationWindowUtility.GetPropertyGroupName(curveBindings[i + 1].propertyName) != AnimationWindowUtility.GetPropertyGroupName(curveBinding.propertyName)) { TreeViewItem newNode = CreateNode(singlePropertyBindings.ToArray(), node); if (newNode != null) { childNodes.Add(newNode); } singlePropertyBindings.Clear(); } } childNodes.Sort(); TreeViewUtility.SetChildParentReferences(childNodes, node); return(node); }
private static void AddFloatKey(AnimationClip clip, EditorCurveBinding sourceBind, SerializedProperty prop, double time) { List <AnimationCurve> list = new List <AnimationCurve>(); List <EditorCurveBinding> list2 = new List <EditorCurveBinding>(); bool flag = false; AnimationClipCurveInfo curveInfo = AnimationClipCurveCache.Instance.GetCurveInfo(clip); for (int i = 0; i < curveInfo.bindings.Length; i++) { EditorCurveBinding item = curveInfo.bindings[i]; if (item.get_type() == sourceBind.get_type()) { SerializedProperty serializedProperty = null; AnimationCurve animationCurve = curveInfo.curves[i]; if (prop.get_propertyPath().Equals(item.propertyName)) { serializedProperty = prop; } else if (item.propertyName.Contains(prop.get_propertyPath())) { serializedProperty = prop.get_serializedObject().FindProperty(item.propertyName); } if (serializedProperty != null) { float keyValue = CurveEditUtility.GetKeyValue(serializedProperty); if (!float.IsNaN(keyValue)) { flag = true; CurveEditUtility.AddKeyFrameToCurve(animationCurve, (float)time, clip.get_frameRate(), keyValue, serializedProperty.get_propertyType() == 1); list.Add(animationCurve); list2.Add(item); } } } } if (!flag) { string propertyGroupName = AnimationWindowUtility.GetPropertyGroupName(sourceBind.propertyName); if (!prop.get_hasChildren()) { float keyValue2 = CurveEditUtility.GetKeyValue(prop); if (!float.IsNaN(keyValue2)) { list2.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.get_type(), sourceBind.propertyName)); AnimationCurve animationCurve2 = new AnimationCurve(); CurveEditUtility.AddKeyFrameToCurve(animationCurve2, (float)time, clip.get_frameRate(), keyValue2, prop.get_propertyType() == 1); list.Add(animationCurve2); } } else if (prop.get_propertyType() == 4) { list2.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.get_type(), propertyGroupName + ".r")); list2.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.get_type(), propertyGroupName + ".g")); list2.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.get_type(), propertyGroupName + ".b")); list2.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.get_type(), propertyGroupName + ".a")); Color colorValue = prop.get_colorValue(); for (int j = 0; j < 4; j++) { AnimationCurve animationCurve3 = new AnimationCurve(); CurveEditUtility.AddKeyFrameToCurve(animationCurve3, (float)time, clip.get_frameRate(), colorValue.get_Item(j), prop.get_propertyType() == 1); list.Add(animationCurve3); } } else { prop = prop.Copy(); IEnumerator enumerator = prop.GetEnumerator(); try { while (enumerator.MoveNext()) { SerializedProperty serializedProperty2 = (SerializedProperty)enumerator.Current; list2.Add(EditorCurveBinding.FloatCurve(sourceBind.path, sourceBind.get_type(), serializedProperty2.get_propertyPath())); AnimationCurve animationCurve4 = new AnimationCurve(); CurveEditUtility.AddKeyFrameToCurve(animationCurve4, (float)time, clip.get_frameRate(), CurveEditUtility.GetKeyValue(serializedProperty2), serializedProperty2.get_propertyType() == 1); list.Add(animationCurve4); } } finally { IDisposable disposable; if ((disposable = (enumerator as IDisposable)) != null) { disposable.Dispose(); } } } } CurveEditUtility.UpdateEditorCurves(clip, list2, list); }
private void FillInMissingTransformCurves(List <AnimationWindowCurve> transformCurves, ref List <AnimationWindowCurve> curvesCache) { EditorCurveBinding lastBinding = transformCurves[0].binding; var propertyGroup = new EditorCurveBinding?[3]; string propertyGroupName; foreach (var transformCurve in transformCurves) { var transformBinding = transformCurve.binding; //if it's a new property group if (transformBinding.path != lastBinding.path || AnimationWindowUtility.GetPropertyGroupName(transformBinding.propertyName) != AnimationWindowUtility.GetPropertyGroupName(lastBinding.propertyName)) { propertyGroupName = AnimationWindowUtility.GetPropertyGroupName(lastBinding.propertyName); FillPropertyGroup(ref propertyGroup, lastBinding, propertyGroupName, ref curvesCache); lastBinding = transformBinding; propertyGroup = new EditorCurveBinding?[3]; } AssignBindingToRightSlot(transformBinding, ref propertyGroup); } FillPropertyGroup(ref propertyGroup, lastBinding, AnimationWindowUtility.GetPropertyGroupName(lastBinding.propertyName), ref curvesCache); }
static bool DoesPropertyPathMatch(string a, string b) { return(AnimationWindowUtility.GetPropertyGroupName(a).Equals(AnimationWindowUtility.GetPropertyGroupName(a))); }
private AnimationWindowHierarchyPropertyGroupNode AddPropertyGroupToHierarchy(AnimationWindowCurve[] curves, AnimationWindowHierarchyNode parentNode) { List <AnimationWindowHierarchyNode> childNodes = new List <AnimationWindowHierarchyNode>(); System.Type animatableObjectType = curves[0].type; AnimationWindowHierarchyPropertyGroupNode node = new AnimationWindowHierarchyPropertyGroupNode(animatableObjectType, 0, AnimationWindowUtility.GetPropertyGroupName(curves[0].propertyName), curves[0].path, parentNode); node.icon = GetIcon(curves[0].binding); node.indent = curves[0].depth; node.curves = curves; foreach (AnimationWindowCurve curve in curves) { AnimationWindowHierarchyPropertyNode childNode = AddPropertyToHierarchy(curve, node); // For child nodes we do not want to display the type in front (It is already shown by the group node) childNode.displayName = AnimationWindowUtility.GetPropertyDisplayName(childNode.propertyName); childNodes.Add(childNode); } TreeViewUtility.SetChildParentReferences(new List <TreeViewItem>(childNodes.ToArray()), node); return(node); }