protected void finishRecording(ProgressBar progress) { string targetFolderPath = targetFolder.Path; if (targetFolderPath == null) { if (gameObject.scene.IsValid() && !string.IsNullOrEmpty(gameObject.scene.path)) { string sceneFolder = Path.GetDirectoryName(gameObject.scene.path); targetFolderPath = Path.Combine(sceneFolder, "Recordings"); } else { targetFolderPath = Path.Combine("Assets", "Recordings"); } } int folderSuffix = 1; string finalSubFolder; do { finalSubFolder = Path.Combine(targetFolderPath, recordingName + " " + folderSuffix.ToString().PadLeft(2, '0')); folderSuffix++; } while (Directory.Exists(finalSubFolder)); string dataDirectory = Path.Combine(finalSubFolder, "_Data"); Directory.CreateDirectory(dataDirectory); Directory.CreateDirectory(finalSubFolder); AssetDatabase.Refresh(); progress.Begin(6, "Saving Recording", "", () => { if (!_isRecording) { return; } _isRecording = false; //Turn on auto-pushing for all auto-proxy components foreach (var autoProxy in GetComponentsInChildren <AutoValueProxy>()) { autoProxy.autoPushingEnabled = true; } progress.Begin(3, "", "Reverting Scene State", () => { //For all of our transform data, revert to the first piece recorded progress.Begin(_transformData.Count, "", "", () => { foreach (var pair in _transformData) { progress.Step(); var transform = pair.Key; var data = pair.Value; if (transform == null || data.Count == 0) { continue; } data[0].ApplyTo(transform); } }); //For all recorded curves, revert to start of curve progress.Begin(_curves.Count, "", "", () => { AnimationClip tempClip = new AnimationClip(); foreach (var data in _curves) { progress.Step(); AnimationUtility.SetEditorCurve(tempClip, data.binding, data.curve); } tempClip.SampleAnimation(gameObject, 0); }); //For all non-transform components, revert to original serialized values progress.Begin(_initialComponentData.Count, "", "", () => { foreach (var pair in _initialComponentData) { progress.Step(); var component = pair.Key; var sobj = pair.Value; if (component == null || component is Transform) { continue; } //We don't want to revert method recordings! if (component is MethodRecording || component is RecordedAudio) { continue; } var flags = sobj.FindProperty("m_ObjectHideFlags"); if (flags == null) { Debug.LogError("Could not find hide flags for " + component); continue; } //We have to dirty the serialized object somehow //apparently there is no api to do this //all objects have hide flags so we just touch them and revert them int originalFlags = flags.intValue; flags.intValue = ~originalFlags; flags.intValue = originalFlags; try { //Applies previous state of entire component sobj.ApplyModifiedProperties(); } catch (Exception e) { Debug.LogError("Exception when trying to apply properties to " + component); Debug.LogException(e); } } }); }); progress.Begin(1, "", "Patching Materials: ", () => { GetComponentsInChildren(true, _recorders); foreach (var recorder in _recorders) { DestroyImmediate(recorder); } //Patch up renderer references to materials var allMaterials = Resources.FindObjectsOfTypeAll <Material>(). Query(). Where(AssetDatabase.IsMainAsset). ToList(); var renderers = GetComponentsInChildren <Renderer>(includeInactive: true); progress.Begin(renderers.Length, "", "", () => { foreach (var renderer in renderers) { progress.Step(renderer.name); var materials = renderer.sharedMaterials; for (int i = 0; i < materials.Length; i++) { var material = materials[i]; if (material == null) { continue; } if (!AssetDatabase.IsMainAsset(material)) { var matchingMaterial = allMaterials.Query().FirstOrDefault(m => material.name.Contains(m.name) && material.shader == m.shader); if (matchingMaterial != null) { materials[i] = matchingMaterial; } } } renderer.sharedMaterials = materials; } }); }); progress.Begin(_behaviourActivity.Count, "", "Converting Activity Data: ", () => { foreach (var pair in _behaviourActivity) { var targetBehaviour = pair.Key; var activityData = pair.Value; if (targetBehaviour == null) { continue; } progress.Step(targetBehaviour.name); string path = AnimationUtility.CalculateTransformPath(targetBehaviour.transform, transform); Type type = targetBehaviour.GetType(); string propertyName = "m_Enabled"; AnimationCurve curve = new AnimationCurve(); foreach (var dataPoint in activityData) { int index = curve.AddKey(dataPoint.time, dataPoint.enabled ? 1 : 0); AnimationUtility.SetKeyLeftTangentMode(curve, index, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(curve, index, AnimationUtility.TangentMode.Constant); } if (curve.IsConstant()) { continue; } var binding = EditorCurveBinding.FloatCurve(path, type, propertyName); if (_curves.Query().Any(c => c.binding == binding)) { Debug.LogError("Binding already existed?"); Debug.LogError(binding.path + " : " + binding.propertyName); continue; } _curves.Add(new CurveData() { binding = binding, curve = curve }); } }); progress.Begin(_transformData.Count, "", "Converting Transform Data: ", () => { foreach (var pair in _transformData) { var targetTransform = pair.Key; var targetData = pair.Value; progress.Step(targetTransform.name); string path = AnimationUtility.CalculateTransformPath(targetTransform, transform); bool isActivityConstant = true; bool isPositionConstant = true; bool isRotationConstant = true; bool isScaleConstant = true; { bool startEnabled = targetData[0].enabled; Vector3 startPosition = targetData[0].localPosition; Quaternion startRotation = targetData[0].localRotation; Vector3 startScale = targetData[0].localScale; for (int i = 1; i < targetData.Count; i++) { isActivityConstant &= targetData[i].enabled == startEnabled; isPositionConstant &= targetData[i].localPosition == startPosition; isRotationConstant &= targetData[i].localRotation == startRotation; isScaleConstant &= targetData[i].localScale == startScale; } } for (int i = 0; i < TransformData.CURVE_COUNT; i++) { string propertyName = TransformData.GetName(i); Type type = typeof(Transform); AnimationCurve curve = new AnimationCurve(); var dataType = TransformData.GetDataType(i); switch (dataType) { case TransformDataType.Position: if (isPositionConstant) { continue; } break; case TransformDataType.Rotation: if (isRotationConstant) { continue; } break; case TransformDataType.Scale: if (isScaleConstant) { continue; } break; case TransformDataType.Activity: if (isActivityConstant) { continue; } type = typeof(GameObject); break; } for (int j = 0; j < targetData.Count; j++) { int index = curve.AddKey(targetData[j].time, targetData[j].GetFloat(i)); if (dataType == TransformDataType.Activity) { AnimationUtility.SetKeyLeftTangentMode(curve, index, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(curve, index, AnimationUtility.TangentMode.Constant); } } var binding = EditorCurveBinding.FloatCurve(path, type, propertyName); if (_curves.Query().Any(c => c.binding == binding)) { Debug.LogError("Duplicate object was created??"); Debug.LogError("Named " + targetTransform.name + " : " + binding.path + " : " + binding.propertyName); } else { _curves.Add(new CurveData() { binding = binding, curve = curve }); } } } }); progress.Begin(_curves.Count, "", "Compressing Data: ", () => { _curves.Sort((a, b) => a.binding.propertyName.CompareTo(b.binding.propertyName)); foreach (var data in _curves) { using (new ProfilerSample("A")) { EditorCurveBinding binding = data.binding; AnimationCurve curve = data.curve; progress.Step(binding.propertyName); GameObject animationGameObject; { var animatedObj = AnimationUtility.GetAnimatedObject(gameObject, binding); if (animatedObj is GameObject) { animationGameObject = animatedObj as GameObject; } else { animationGameObject = (animatedObj as Component).gameObject; } } bool isMatBinding = binding.propertyName.StartsWith("material.") && binding.type.IsSubclassOf(typeof(Renderer)); //But if the curve is constant, just get rid of it! //Except for material curves, which we always need to keep if (curve.IsConstant() && !isMatBinding) { //Check to make sure there are no other matching curves that are //non constant. If X and Y are constant but Z is not, we need to //keep them all :( if (_curves.Query().Where(p => p.binding.path == binding.path && p.binding.type == binding.type && p.binding.propertyName.TrimEnd(2) == binding.propertyName.TrimEnd(2)). All(k => k.curve.IsConstant())) { continue; } } //First do a lossless compression using (new ProfilerSample("B")) { curve = AnimationCurveUtil.Compress(curve, Mathf.Epsilon, checkSteps: 3); } Transform targetTransform = null; var targetObj = AnimationUtility.GetAnimatedObject(gameObject, binding); if (targetObj is GameObject) { targetTransform = (targetObj as GameObject).transform; } else if (targetObj is Component) { targetTransform = (targetObj as Component).transform; } else { Debug.LogError("Target obj was of type " + targetObj.GetType().Name); } } } }); }); progress.Begin(4, "Finalizing Assets", "", () => { var postProcessComponent = gameObject.AddComponent <HierarchyPostProcess>(); GameObject myGameObject = gameObject; DestroyImmediate(this); //Create all the files for the method recording progress.Step("Creating Method Recording Files..."); var methodRecordings = myGameObject.GetComponentsInChildren <MethodRecording>(); for (int i = 0; i < methodRecordings.Length; i++) { var methodRecording = methodRecordings[i]; string fullPath = Path.Combine(finalSubFolder, "MethodRecording_" + i + ".asset"); methodRecording.ExitRecordingMode(fullPath); } postProcessComponent.dataFolder = new AssetFolder(dataDirectory); //Create the asset that holds all of the curve data progress.Begin(_curves.Count, "", "", () => { string curveFile = Path.Combine(dataDirectory, "Curves.data"); using (var writer = File.CreateText(curveFile)) { foreach (var data in _curves) { progress.Step(data.binding.propertyName); var bindingData = new EditorCurveBindingData() { path = data.binding.path, propertyName = data.binding.propertyName, typeName = data.binding.type.Name, curve = data.curve }; writer.WriteLine(JsonUtility.ToJson(bindingData)); } } }); //Create the asset that holds all of the leap data if (_leapData.Count > 0) { progress.Begin(_leapData.Count, "", "", () => { string leapFile = Path.Combine(dataDirectory, "Frames.data"); using (var writer = File.CreateText(leapFile)) { for (int i = 0; i < _leapData.Count; i++) { progress.Step("Frame " + i); writer.WriteLine(JsonUtility.ToJson(_leapData[i])); } } }); } progress.Step("Creating Final Prefab..."); //Init the post process component postProcessComponent.recordingName = recordingName; postProcessComponent.assetFolder = new AssetFolder(finalSubFolder); string prefabPath = Path.Combine(finalSubFolder, recordingName + " Raw.prefab"); PrefabUtility.CreatePrefab(prefabPath.Replace('\\', '/'), myGameObject); AssetDatabase.Refresh(); EditorApplication.isPlaying = false; }); }
public void AddPropertyModification(EditorCurveBinding binding, PropertyModification propertyModification, bool keepPrefabOverride) { AnimationMode.AddPropertyModification(binding, propertyModification, keepPrefabOverride); }
public void OnGUI() { // Make sure we have more than one clip selected if (animationClips.Count > 0) { scrollPos = GUILayout.BeginScrollView(scrollPos, GUIStyle.none); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Animation Clip:", GUILayout.Width(columnWidth)); if (animationClips.Count == 1) { animationClips[0] = ((AnimationClip)EditorGUILayout.ObjectField( animationClips[0], typeof(AnimationClip), true, GUILayout.Width(columnWidth)) ); } else { GUILayout.Label("Multiple Anim Clips: " + animationClips.Count, GUILayout.Width(columnWidth)); } EditorGUILayout.EndHorizontal(); GUILayout.Space(20); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Control Points:"); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Change Control Points")) { changeAllPoints = true; } EditorGUILayout.EndHorizontal(); for (int i = 0; i < animationClips.Count; i++) { // Iterate through all the bindings in the animation clip var bindings = AnimationUtility.GetCurveBindings(animationClips[i]); for (int n = 0; n < bindings.Length; n++) { // If the property is the x,y,z position of the control point then edit the new position if (bindings[n].propertyName.Contains("m_LocalPosition") && bindings[n].path.Contains("Control Point")) { // Get the animation curve AnimationCurve curve = AnimationUtility.GetEditorCurve(animationClips[i], bindings[n]); // Get the curve's keyframes Keyframe[] keyframes = curve.keys; // Show the binding and the keys length it has in the editor window EditorGUILayout.LabelField(bindings[n].path + "/" + bindings[n].propertyName + ", Keys: " + keyframes.Length); // Debug.Log(binding.type); if (changeAllPoints) { // First you need to create a Editor Curve Binding EditorCurveBinding curveBinding = new EditorCurveBinding(); // I want to change the ControlPoints of the control point, so I put the typeof(ControlPoints) as the binding type. curveBinding.type = typeof(ControlPoints); // Regular path to the control point gameobject will be changed to the parent curveBinding.path = RenameControlPointPath(bindings[n].path); // This is the property name to change to the matching control point curveBinding.propertyName = GetControlPointName(bindings[n].path) + bindings[n].propertyName.Substring(bindings[n].propertyName.Length - 2); // Create a new curve from these keyframes curve = new AnimationCurve(keyframes); // Set the new curve to the animation clip AnimationUtility.SetEditorCurve(animationClips[i], curveBinding, curve); // Remove the old binding AnimationUtility.SetEditorCurve(animationClips[i], bindings[n], null); // Track progress float fChunk = 1f / animationClips.Count; float fProgress = (i * fChunk) + fChunk * ((float)n / (float)bindings.Length); EditorUtility.DisplayProgressBar( "Replacing Control Points with new Control Point System", "How far along the animation editing has progressed.", fProgress); } // Loop through the keyframes and change the curve to the new control points curve for (int j = 0; j < keyframes.Length; j++) { // Show the new curve in the editor window EditorGUILayout.CurveField(curve, GUILayout.Width(columnWidth * 0.75f)); } } } } EditorUtility.ClearProgressBar(); // Reset the button changeAllPoints = false; GUILayout.Space(40); GUILayout.EndScrollView(); } else { GUILayout.Label("Please select an Animation Clip"); } }
static private void CollectRotationModifications(IAnimationRecordingState state, ref UndoPropertyModification[] modifications, ref Dictionary <object, RotationModification> rotationModifications) { List <UndoPropertyModification> outModifs = new List <UndoPropertyModification>(); foreach (var modification in modifications) { PropertyModification prop = modification.previousValue; if (!(prop.target is Transform)) { outModifs.Add(modification); continue; } EditorCurveBinding binding = new EditorCurveBinding(); AnimationUtility.PropertyModificationToEditorCurveBinding(prop, state.activeRootGameObject, out binding); if (binding.propertyName.StartsWith(kLocalRotation)) { RotationModification rotationModification; if (!rotationModifications.TryGetValue(prop.target, out rotationModification)) { rotationModification = new RotationModification(); rotationModifications[prop.target] = rotationModification; } if (binding.propertyName.EndsWith("x")) { rotationModification.x = modification; } else if (binding.propertyName.EndsWith("y")) { rotationModification.y = modification; } else if (binding.propertyName.EndsWith("z")) { rotationModification.z = modification; } else if (binding.propertyName.EndsWith("w")) { rotationModification.w = modification; } rotationModification.lastQuatModification = modification; } else if (prop.propertyPath.StartsWith(kLocalEulerAnglesHint)) { RotationModification rotationModification; if (!rotationModifications.TryGetValue(prop.target, out rotationModification)) { rotationModification = new RotationModification(); rotationModifications[prop.target] = rotationModification; } rotationModification.useEuler = true; if (prop.propertyPath.EndsWith("x")) { rotationModification.eulerX = modification; } else if (prop.propertyPath.EndsWith("y")) { rotationModification.eulerY = modification; } else if (prop.propertyPath.EndsWith("z")) { rotationModification.eulerZ = modification; } } else { outModifs.Add(modification); } } if (rotationModifications.Count > 0) { modifications = outModifs.ToArray(); } }
public AnimationWindowHierarchyPropertyNode(Type animatableObjectType, string propertyName, string path, TreeViewItem parent, EditorCurveBinding binding, bool isPptrNode) : base(AnimationWindowUtility.GetPropertyNodeID(path, animatableObjectType, propertyName), (parent == null) ? -1 : (parent.depth + 1), parent, animatableObjectType, propertyName, path, AnimationWindowUtility.GetNicePropertyDisplayName(animatableObjectType, propertyName)) { this.binding = new EditorCurveBinding?(binding); this.isPptrNode = isPptrNode; }
static private void AddRotationPropertyModification(IAnimationRecordingState state, EditorCurveBinding baseBinding, UndoPropertyModification modification) { if (modification.previousValue == null) { return; } // case 817356. Reuse baseBinding as basis for rotation binding. // This is needed to register valid bindings for m_LocalEulerAnglesHint // that cannot be converted to EditorCurveBinding otherwise. EditorCurveBinding binding = baseBinding; binding.propertyName = modification.previousValue.propertyPath; state.AddPropertyModification(binding, modification.previousValue, modification.keepPrefabOverride); }
static private void ProcessVector3Modification(IAnimationRecordingState state, EditorCurveBinding baseBinding, UndoPropertyModification modification, Transform target, string axis, float scale = 1.0f) { var binding = baseBinding; binding.propertyName = binding.propertyName.Remove(binding.propertyName.Length - 1, 1) + axis; object currentValue = CurveBindingUtility.GetCurrentValue(state.activeRootGameObject, binding); var previousModification = modification.previousValue; if (previousModification == null) { // create dummy previousModification = new PropertyModification(); previousModification.target = target; previousModification.propertyPath = binding.propertyName; previousModification.value = ((float)currentValue).ToString(CultureInfo.InvariantCulture.NumberFormat); } object previousValue = currentValue; ValueFromPropertyModification(previousModification, binding, out previousValue); state.AddPropertyModification(binding, previousModification, modification.keepPrefabOverride); if (scale != 1.0f) { previousValue = (object)((float)previousValue / scale); currentValue = (object)((float)currentValue / scale); } AddKey(state, binding, typeof(float), previousValue, currentValue); }
public override void OnInspectorGUI() { DrawDefaultInspector(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Add Eight")) { mySelf.dirs.Clear(); for (int i = 0; i < 8; i++) { mySelf.dirs.Add((SpriteSheetToAnim.Dirs)i); } EditorUtility.SetDirty(mySelf); } if (GUILayout.Button("Add Four")) { mySelf.dirs.Clear(); for (int i = 0; i < 4; i++) { mySelf.dirs.Add((SpriteSheetToAnim.Dirs)i); } EditorUtility.SetDirty(mySelf); } if (GUILayout.Button("Add Two")) { mySelf.dirs.Clear(); mySelf.dirs.Add(SpriteSheetToAnim.Dirs.Right); mySelf.dirs.Add(SpriteSheetToAnim.Dirs.Left); EditorUtility.SetDirty(mySelf); } if (GUILayout.Button("Add One")) { mySelf.dirs.Clear(); mySelf.dirs.Add(SpriteSheetToAnim.Dirs.Right); EditorUtility.SetDirty(mySelf); } if (GUILayout.Button("Set None")) { mySelf.dirs.Clear(); mySelf.dirs.Add(SpriteSheetToAnim.Dirs.None); EditorUtility.SetDirty(mySelf); } EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Create Animations")) { foreach (var tex in mySelf.texes) { List <Sprite> sprites = GetAllSprites(tex); for (int i = 0; i < mySelf.dirs.Count; i++) { AnimationClip animClip = GetAnimClip(); EditorCurveBinding spriteBinding = GetSpriteBinding(); List <Sprite> slicedSprites = GetDirSprites(sprites, i); ObjectReferenceKeyframe[] spriteKeyFrames = GetKeyFrames(slicedSprites); AnimationUtility.SetObjectReferenceCurve(animClip, spriteBinding, spriteKeyFrames); string animClipPath = GetAnimClipFileName(tex, i); AssetDatabase.CreateAsset(animClip, animClipPath + ".anim"); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } } } }
public static void SetCurve(AnimationClip clip, EditorCurveBinding binding, AnimationCurve curve) { // see above //AnimationUtility.SetEditorCurve(clip, binding, curve); clip.SetCurve(binding.path, binding.type, binding.propertyName, curve); }
private static PropertyModification FindPropertyModification(GameObject root, UndoPropertyModification[] modifications, EditorCurveBinding binding) { for (int i = 0; i < modifications.Length; i++) { EditorCurveBinding lhs; AnimationUtility.PropertyModificationToEditorCurveBinding(modifications[i].previousValue, root, out lhs); if (lhs == binding) { return(modifications[i].previousValue); } } return(null); }
private static void CollectRotationModifications(IAnimationRecordingState state, ref UndoPropertyModification[] modifications, ref Dictionary <object, AnimationRecording.RotationModification> rotationModifications) { List <UndoPropertyModification> list = new List <UndoPropertyModification>(); UndoPropertyModification[] array = modifications; for (int i = 0; i < array.Length; i++) { UndoPropertyModification undoPropertyModification = array[i]; EditorCurveBinding editorCurveBinding = default(EditorCurveBinding); PropertyModification previousValue = undoPropertyModification.previousValue; AnimationUtility.PropertyModificationToEditorCurveBinding(previousValue, state.activeRootGameObject, out editorCurveBinding); if (editorCurveBinding.propertyName.StartsWith("m_LocalRotation")) { AnimationRecording.RotationModification rotationModification; if (!rotationModifications.TryGetValue(previousValue.target, out rotationModification)) { rotationModification = new AnimationRecording.RotationModification(); rotationModifications[previousValue.target] = rotationModification; } if (editorCurveBinding.propertyName.EndsWith("x")) { rotationModification.x = undoPropertyModification; } else if (editorCurveBinding.propertyName.EndsWith("y")) { rotationModification.y = undoPropertyModification; } else if (editorCurveBinding.propertyName.EndsWith("z")) { rotationModification.z = undoPropertyModification; } else if (editorCurveBinding.propertyName.EndsWith("w")) { rotationModification.w = undoPropertyModification; } rotationModification.lastQuatModification = undoPropertyModification; } else if (previousValue.propertyPath.StartsWith("m_LocalEulerAnglesHint")) { AnimationRecording.RotationModification rotationModification2; if (!rotationModifications.TryGetValue(previousValue.target, out rotationModification2)) { rotationModification2 = new AnimationRecording.RotationModification(); rotationModifications[previousValue.target] = rotationModification2; } rotationModification2.useEuler = true; if (previousValue.propertyPath.EndsWith("x")) { rotationModification2.eulerX = undoPropertyModification; } else if (previousValue.propertyPath.EndsWith("y")) { rotationModification2.eulerY = undoPropertyModification; } else if (previousValue.propertyPath.EndsWith("z")) { rotationModification2.eulerZ = undoPropertyModification; } list.Add(undoPropertyModification); } else { list.Add(undoPropertyModification); } } if (rotationModifications.Count > 0) { modifications = list.ToArray(); } }
private static bool ValueFromPropertyModification(PropertyModification modification, EditorCurveBinding binding, out object outObject) { if (modification == null) { outObject = null; return(false); } if (binding.isPPtrCurve) { outObject = modification.objectReference; return(true); } float num; if (float.TryParse(modification.value, out num)) { outObject = num; return(true); } outObject = null; return(false); }
private static void ProcessRotationModifications(IAnimationRecordingState state, ref UndoPropertyModification[] modifications) { Dictionary <object, AnimationRecording.RotationModification> dictionary = new Dictionary <object, AnimationRecording.RotationModification>(); AnimationRecording.CollectRotationModifications(state, ref modifications, ref dictionary); foreach (KeyValuePair <object, AnimationRecording.RotationModification> current in dictionary) { AnimationRecording.RotationModification value = current.Value; Transform transform = current.Key as Transform; if (!(transform == null)) { EditorCurveBinding binding = default(EditorCurveBinding); Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(value.lastQuatModification.currentValue, state.activeRootGameObject, out binding); AnimationRecording.AddRotationPropertyModification(state, value.x); AnimationRecording.AddRotationPropertyModification(state, value.y); AnimationRecording.AddRotationPropertyModification(state, value.z); AnimationRecording.AddRotationPropertyModification(state, value.w); if (value.useEuler) { Vector3 localEulerAngles = transform.GetLocalEulerAngles(RotationOrder.OrderZXY); Vector3 localEulerAngles2 = transform.GetLocalEulerAngles(RotationOrder.OrderZXY); object obj; if (AnimationRecording.ValueFromPropertyModification(value.eulerX.previousValue, binding, out obj)) { localEulerAngles.x = (float)obj; } object obj2; if (AnimationRecording.ValueFromPropertyModification(value.eulerY.previousValue, binding, out obj2)) { localEulerAngles.y = (float)obj2; } object obj3; if (AnimationRecording.ValueFromPropertyModification(value.eulerZ.previousValue, binding, out obj3)) { localEulerAngles.z = (float)obj3; } if (AnimationRecording.ValueFromPropertyModification(value.eulerX.currentValue, binding, out obj)) { localEulerAngles2.x = (float)obj; } if (AnimationRecording.ValueFromPropertyModification(value.eulerY.currentValue, binding, out obj2)) { localEulerAngles2.y = (float)obj2; } if (AnimationRecording.ValueFromPropertyModification(value.eulerZ.currentValue, binding, out obj3)) { localEulerAngles2.z = (float)obj3; } AnimationRecording.AddRotationKey(state, binding, type, localEulerAngles, localEulerAngles2); } else { Quaternion localRotation = transform.localRotation; Quaternion localRotation2 = transform.localRotation; object obj4; if (AnimationRecording.ValueFromPropertyModification(value.x.previousValue, binding, out obj4)) { localRotation.x = (float)obj4; } object obj5; if (AnimationRecording.ValueFromPropertyModification(value.y.previousValue, binding, out obj5)) { localRotation.y = (float)obj5; } object obj6; if (AnimationRecording.ValueFromPropertyModification(value.z.previousValue, binding, out obj6)) { localRotation.z = (float)obj6; } object obj7; if (AnimationRecording.ValueFromPropertyModification(value.w.previousValue, binding, out obj7)) { localRotation.w = (float)obj7; } if (AnimationRecording.ValueFromPropertyModification(value.x.currentValue, binding, out obj4)) { localRotation2.x = (float)obj4; } if (AnimationRecording.ValueFromPropertyModification(value.y.currentValue, binding, out obj5)) { localRotation2.y = (float)obj5; } if (AnimationRecording.ValueFromPropertyModification(value.z.currentValue, binding, out obj6)) { localRotation2.z = (float)obj6; } if (AnimationRecording.ValueFromPropertyModification(value.w.currentValue, binding, out obj7)) { localRotation2.w = (float)obj7; } AnimationRecording.AddRotationKey(state, binding, type, localRotation.eulerAngles, localRotation2.eulerAngles); } } } }
public override void Process(ImportContext ctx, Layer layer) { var childName = layer.GetParamString(0); EditorCurveBinding bindingX = new EditorCurveBinding { path = childName, type = typeof(Transform), propertyName = "m_LocalPosition.x" }, bindingY = new EditorCurveBinding { path = childName, type = typeof(Transform), propertyName = "m_LocalPosition.y" }; var frames = new Dictionary <int, Vector2> (); var file = ctx.file; for (int i = 0; i < file.frames.Count; ++i) { Vector2 center = Vector2.zero; int pixelCount = 0; Cel cel; file.frames[i].cels.TryGetValue(layer.index, out cel); if (cel == null) { continue; } for (int y = 0; y < cel.height; ++y) { for (int x = 0; x < cel.width; ++x) { int texX = cel.x + x; int texY = -(cel.y + y) + file.height - 1; var col = cel.GetPixelRaw(x, y); if (col.a > 0.1f) { center += new Vector2(texX, texY); pixelCount++; } } } if (pixelCount > 0) { center /= pixelCount; var pivot = Vector2.Scale(ctx.settings.PivotRelativePos, new Vector2(file.width, file.height)); var posWorld = (center - pivot) / ctx.settings.ppu; frames.Add(i, posWorld); } } foreach (var frameTag in file.frameTags) { var clip = ctx.generatedClips[frameTag]; AnimationCurve curveX = new AnimationCurve(), curveY = new AnimationCurve(); float t = 0; for (int f = frameTag.from; f <= frameTag.to + 1; ++f) { if (f == frameTag.to + 1) { if (frames.ContainsKey(frameTag.from)) { t = t - 1.0f / clip.frameRate; var pos = frames[frameTag.from]; curveX.AddKey(t, pos.x); curveY.AddKey(t, pos.y); } break; } if (frames.ContainsKey(f)) { var pos = frames[f]; curveX.AddKey(t, pos.x); curveY.AddKey(t, pos.y); } t += file.frames[f].duration * 1e-3f; } if (curveX.length > 0) { MakeConstant(curveX); MakeConstant(curveY); AnimationUtility.SetEditorCurve(clip, bindingX, curveX); AnimationUtility.SetEditorCurve(clip, bindingY, curveY); EditorUtility.SetDirty(clip); } } }
void ReplaceRoot(string oldRoot, string newRoot) { float fProgress = 0.0f; sReplacementOldRoot = oldRoot; sReplacementNewRoot = newRoot; AssetDatabase.StartAssetEditing(); for (int iCurrentClip = 0; iCurrentClip < animationClips.Count; iCurrentClip++) { AnimationClip animationClip = animationClips[iCurrentClip]; Undo.RecordObject(animationClip, "Animation Hierarchy Root Change"); for (int iCurrentPath = 0; iCurrentPath < pathsKeys.Count; iCurrentPath++) { string path = pathsKeys[iCurrentPath] as string; ArrayList curves = (ArrayList)paths[path]; for (int i = 0; i < curves.Count; i++) { EditorCurveBinding binding = (EditorCurveBinding)curves[i]; if (path.Contains(sReplacementOldRoot)) { if (!path.Contains(sReplacementNewRoot)) { string sNewPath = Regex.Replace(path, "^" + sReplacementOldRoot, sReplacementNewRoot); AnimationCurve curve = AnimationUtility.GetEditorCurve(animationClip, binding); if (curve != null) { AnimationUtility.SetEditorCurve(animationClip, binding, null); binding.path = sNewPath; AnimationUtility.SetEditorCurve(animationClip, binding, curve); } else { ObjectReferenceKeyframe[] objectReferenceCurve = AnimationUtility.GetObjectReferenceCurve(animationClip, binding); AnimationUtility.SetObjectReferenceCurve(animationClip, binding, null); binding.path = sNewPath; AnimationUtility.SetObjectReferenceCurve(animationClip, binding, objectReferenceCurve); } } } } // Update the progress meter float fChunk = 1f / animationClips.Count; fProgress = (iCurrentClip * fChunk) + fChunk * ((float)iCurrentPath / (float)pathsKeys.Count); EditorUtility.DisplayProgressBar( "Animation Hierarchy Progress", "How far along the animation editing has progressed.", fProgress); } } AssetDatabase.StopAssetEditing(); EditorUtility.ClearProgressBar(); FillModel(); this.Repaint(); }
static bool ProcessPlayableAssetRecording(UndoPropertyModification mod, WindowState state, ICurvesOwner curvesOwner, bool allowAdd) { if (mod.currentValue == null) { return(false); } if (!curvesOwner.IsParameterAnimatable(mod.currentValue.propertyPath)) { return(false); } // only animate items with existing curves if (!allowAdd && !curvesOwner.IsParameterAnimated(mod.currentValue.propertyPath)) { return(false); } var localTime = state.editSequence.time; var timelineClip = curvesOwner as TimelineClip; if (timelineClip != null) { // don't use time global to local since it will possibly loop. localTime = timelineClip.ToLocalTimeUnbound(state.editSequence.time); } if (localTime < 0) { return(false); } // grab the value from the current modification float fValue; if (!ExpressionEvaluator.Evaluate(mod.currentValue.value, out fValue)) { // case 916913 -- 'Add Key' menu item will passes 'True' or 'False' (instead of 1, 0) // so we need a special case to parse the boolean string bool bValue; if (!bool.TryParse(mod.currentValue.value, out bValue)) { Debug.Assert(false, "Invalid type in PlayableAsset recording"); return(false); } fValue = bValue ? 1 : 0; } var added = curvesOwner.AddAnimatedParameterValueAt(mod.currentValue.propertyPath, fValue, (float)localTime); if (added && AnimationMode.InAnimationMode()) { EditorCurveBinding binding = curvesOwner.GetCurveBinding(mod.previousValue.propertyPath); AnimationMode.AddPropertyModification(binding, mod.previousValue, true); curvesOwner.targetTrack.SetShowInlineCurves(true); if (state.GetWindow() != null && state.GetWindow().treeView != null) { state.GetWindow().treeView.CalculateRowRects(); } } return(added); }
void UpdatePath(string oldPath, string newPath) { if (paths[newPath] != null) { throw new UnityException("Path " + newPath + " already exists in that animation!"); } AssetDatabase.StartAssetEditing(); for (int iCurrentClip = 0; iCurrentClip < animationClips.Count; iCurrentClip++) { AnimationClip animationClip = animationClips[iCurrentClip]; Undo.RecordObject(animationClip, "Animation Hierarchy Change"); //recreating all curves one by one //to maintain proper order in the editor - //slower than just removing old curve //and adding a corrected one, but it's more //user-friendly for (int iCurrentPath = 0; iCurrentPath < pathsKeys.Count; iCurrentPath++) { string path = pathsKeys[iCurrentPath] as string; ArrayList curves = (ArrayList)paths[path]; for (int i = 0; i < curves.Count; i++) { EditorCurveBinding binding = (EditorCurveBinding)curves[i]; AnimationCurve curve = AnimationUtility.GetEditorCurve(animationClip, binding); ObjectReferenceKeyframe[] objectReferenceCurve = AnimationUtility.GetObjectReferenceCurve(animationClip, binding); if (curve != null) { AnimationUtility.SetEditorCurve(animationClip, binding, null); } else { AnimationUtility.SetObjectReferenceCurve(animationClip, binding, null); } if (path == oldPath) { binding.path = newPath; } if (curve != null) { AnimationUtility.SetEditorCurve(animationClip, binding, curve); } else { AnimationUtility.SetObjectReferenceCurve(animationClip, binding, objectReferenceCurve); } float fChunk = 1f / animationClips.Count; float fProgress = (iCurrentClip * fChunk) + fChunk * ((float)iCurrentPath / (float)pathsKeys.Count); EditorUtility.DisplayProgressBar( "Animation Hierarchy Progress", "How far along the animation editing has progressed.", fProgress); } } } AssetDatabase.StopAssetEditing(); EditorUtility.ClearProgressBar(); FillModel(); this.Repaint(); }
public override void OnInspectorGUI() { //base.OnInspectorGUI(); CharacterAnimation character_animation = (CharacterAnimation)target; #if SH_ASSETBUNDLE if (m_Prefab != null) { if (m_Prefab.PrefabState == false) { Debug.LogFormat("[{0}] CreateImport", m_Prefab.name); string skin = null; if (character_animation.CurrentSkin != null && character_animation.CurrentSkin.Asset != null) { skin = character_animation.CurrentSkin.Asset.name; } character_animation.CreateImport(); if (string.IsNullOrEmpty(skin) == false) { character_animation.SetSkin(skin); } } } #endif EditorGUILayout.BeginHorizontal(); // whole #if SH_ASSETBUNDLE if (!EditorUtility.IsPersistent(character_animation)) { if (GUILayout.Button("Create Import")) { character_animation.CreateImport(); CheckAnimations(); } } #endif if (GUILayout.Button(string.Format("Idle Mode({0})", character_animation.GetIdleRotation()))) { character_animation.SetIdleMode(); } if (GUILayout.Button("Battle Mode")) { character_animation.SetBattleMode(); } EditorGUILayout.EndHorizontal(); // whole if (character_animation.Animation == null) { return; } if (s_Animations == null || character_animation.Animation.GetClipCount() != s_Animations.Length) { CheckAnimations(); } EditorGUILayout.BeginVertical(); // whole EditorGUILayout.Separator(); character_animation.CheckDefaultState(); // if (EditorApplication.isPlaying) { if (s_Util.SeparatorToolbarFold("Debug", null)) { if (character_animation != null && character_animation.CurrentState != null) { EditorGUILayout.LabelField(string.Format("{0} : {1}/{2}", character_animation.CurrentState.name, character_animation.PlaybackTime, character_animation.CurrentState.length)); } else { EditorGUILayout.LabelField("none"); } if (character_animation.RootBone != null) { if (character_animation.CurrentMoveState != null) { EditorGUILayout.LabelField(string.Format("RootBonePos : {0} / {1} ({2:p}), Move : {3}", character_animation.RootBonePos, character_animation.CurrentMoveState.length, character_animation.RootBonePos.x / character_animation.CurrentMoveState.length, character_animation.MoveValue)); } } if (character_animation.FxBone != null && character_animation.CurrentFxState != null) { EditorGUILayout.LabelField(string.Format("FxBonePos : {0} / {1} ({2:p}), MoveFx : {3}", character_animation.FxBonePos, character_animation.CurrentFxState.fixed_length, character_animation.FxBonePos.x / character_animation.CurrentFxState.length, character_animation.MoveValueFx)); EditorGUILayout.LabelField(string.Format("FxBones : {0}", character_animation.FxBone.localPosition)); } EditorGUILayout.Toggle("IsUIMode", character_animation.IsUIMode); EditorUtility.SetDirty((MonoBehaviour)character_animation); } } // if (EditorApplication.isPlaying == false) { //if (EditorApplication.isPlaying == false) OnInspectorSkin(character_animation); OnInspectorPlay(character_animation); if (character_animation.MoveStates == null) { character_animation.MoveStates = new CharacterAnimation.MoveState[0]; } if (character_animation.FxStates == null) { character_animation.FxStates = new CharacterAnimation.FxState[0]; } } if (GUILayout.Button("Play Head")) { character_animation.PlayHead(); } bool fold_move = s_Util.SeparatorToolbarFold("MoveStates", string.Format("Move States ({0})", character_animation.MoveStates.Length), false, false); if (GUILayout.Button("Refresh", EditorStyles.toolbarButton)) { character_animation.RefreshMove(true); } s_Util.EndToolbar(); if (fold_move == true) { foreach (CharacterAnimation.MoveState state in character_animation.MoveStates) { EditorGUILayout.BeginHorizontal(); bool fold = false; if (fold_movestate.TryGetValue(state.name, out fold) == false) { fold_movestate.Add(state.name, fold); } bool fold_new = GUILayout.Toggle(fold, state.name, "Foldout"); if (fold_new != fold) { fold_movestate.Remove(state.name); fold_movestate.Add(state.name, fold_new); } bool new_enabled = GUILayout.Toggle(state.enabled, ""); if (new_enabled != state.enabled) { state.enabled = new_enabled; character_animation.SetMoveState(true); } EditorGUIUtility.labelWidth = 60f; EditorGUILayout.LabelField("Length", state.length.ToString()); state.fixed_length = EditorGUILayout.FloatField("Fixed", state.fixed_length); if (GUILayout.Button("Get")) { state.fixed_length = state.length; } EditorGUIUtility.labelWidth = 0f; EditorGUILayout.EndHorizontal(); if (fold_new == true) { EditorCurveBinding bind = new EditorCurveBinding(); bind.path = "Root"; bind.type = typeof(Transform); bind.propertyName = "m_LocalPosition.x"; AnimationClip clip = character_animation.Animation[state.name].clip; AnimationCurve data = AnimationUtility.GetEditorCurve(clip, bind); foreach (var key in data.keys) { EditorGUILayout.BeginHorizontal(); GUILayout.Space(20f); EditorGUILayout.LabelField(string.Format("{0} ({1})", key.time * clip.frameRate, key.time.ToString()), key.value.ToString()); EditorGUILayout.EndHorizontal(); } } } } int enable_fx_count = character_animation.FxStates.Count(s => s.enabled); bool fold_fx = s_Util.SeparatorToolbarFold("FxStates", string.Format("Fx States ({0}/{1})", enable_fx_count, character_animation.FxStates.Length), false, false); if (GUILayout.Button("Refresh", EditorStyles.toolbarButton)) { character_animation.RefreshFx(true); } s_Util.EndToolbar(); if (fold_fx == true) { foreach (CharacterAnimation.FxState state in character_animation.FxStates) { EditorGUILayout.BeginHorizontal(); bool fold = false; if (fold_fxstate.TryGetValue(state.name, out fold) == false) { fold_fxstate.Add(state.name, fold); } if (state.SubBoneNames == null) { state.SubBoneNames = new string[0]; } state.CheckBone(character_animation.transform); bool fold_new = GUILayout.Toggle(fold, string.Format("{0} ({1}/{2})", state.name, state.SubBones.Count(b => b != null), state.SubBones.Count), "Foldout"); if (fold_new != fold) { fold_fxstate.Remove(state.name); fold_fxstate.Add(state.name, fold_new); } bool new_enabled = GUILayout.Toggle(state.enabled, ""); if (new_enabled != state.enabled) { state.enabled = new_enabled; character_animation.SetFxState(true); } EditorGUIUtility.labelWidth = 60f; EditorGUILayout.LabelField("Length", state.length.ToString()); state.fixed_length = EditorGUILayout.FloatField("Fixed", state.fixed_length); if (GUILayout.Button("Get")) { state.fixed_length = state.length; } EditorGUIUtility.labelWidth = 0f; EditorGUILayout.EndHorizontal(); if (fold_new == true) { int remove_index = -1; for (int bone_index = 0; bone_index < state.SubBoneNames.Length; ++bone_index) { EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("-", GUILayout.Width(22f))) { remove_index = bone_index; } Transform new_bone = EditorGUILayout.ObjectField("SubBone", state.SubBones[bone_index], typeof(Transform), true) as Transform; if (new_bone != state.SubBones[bone_index]) { state.SubBones[bone_index] = new_bone; state.SubBoneNames[bone_index] = CoreUtility.GetHierachy(new_bone, character_animation.transform); EditorUtility.SetDirty((MonoBehaviour)character_animation); } EditorGUILayout.EndHorizontal(); } if (remove_index != -1) { List <string> temp_list = new List <string>(state.SubBoneNames); temp_list.RemoveAt(remove_index); state.SubBoneNames = temp_list.ToArray(); } EditorGUI.indentLevel = 2; { Transform new_bone = EditorGUILayout.ObjectField("SubBone", null, typeof(Transform), true) as Transform; if (new_bone != null) { Array.Resize <string>(ref state.SubBoneNames, state.SubBoneNames.Length + 1); state.SubBoneNames[state.SubBoneNames.Length - 1] = CoreUtility.GetHierachy(new_bone, character_animation.transform); EditorUtility.SetDirty((MonoBehaviour)character_animation); } } EditorGUI.indentLevel = 0; EditorCurveBinding bind = new EditorCurveBinding(); bind.path = "fx_bone"; bind.type = typeof(Transform); bind.propertyName = "m_LocalPosition.x"; AnimationClip clip = character_animation.Animation[state.name].clip; AnimationCurve data = AnimationUtility.GetEditorCurve(clip, bind); foreach (var key in data.keys) { EditorGUILayout.BeginHorizontal(); GUILayout.Space(20f); EditorGUILayout.LabelField(string.Format("{0} ({1})", key.time * clip.frameRate, key.time.ToString()), key.value.ToString()); EditorGUILayout.EndHorizontal(); } } } } loop_state_list.OnInspectorGUI(); EditorGUILayout.EndVertical(); // whole if (GUI.changed) { EditorUtility.SetDirty((MonoBehaviour)character_animation); } }
static private void ProcessRotationModifications(IAnimationRecordingState state, ref Dictionary <object, RotationModification> rotationModifications) { AnimationClip clip = state.activeAnimationClip; GameObject root = state.activeRootGameObject; foreach (KeyValuePair <object, RotationModification> item in rotationModifications) { RotationModification m = item.Value; Transform target = item.Key as Transform; if (target == null) { continue; } EditorCurveBinding binding = new EditorCurveBinding(); Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.lastQuatModification.currentValue, state.activeRootGameObject, out binding); if (type == null) { continue; } AddRotationPropertyModification(state, binding, m.x); AddRotationPropertyModification(state, binding, m.y); AddRotationPropertyModification(state, binding, m.z); AddRotationPropertyModification(state, binding, m.w); Quaternion previousValue = target.localRotation; Quaternion currentValue = target.localRotation; object x, y, z, w; if (ValueFromPropertyModification(m.x.previousValue, binding, out x)) { previousValue.x = (float)x; } if (ValueFromPropertyModification(m.y.previousValue, binding, out y)) { previousValue.y = (float)y; } if (ValueFromPropertyModification(m.z.previousValue, binding, out z)) { previousValue.z = (float)z; } if (ValueFromPropertyModification(m.w.previousValue, binding, out w)) { previousValue.w = (float)w; } if (ValueFromPropertyModification(m.x.currentValue, binding, out x)) { currentValue.x = (float)x; } if (ValueFromPropertyModification(m.y.currentValue, binding, out y)) { currentValue.y = (float)y; } if (ValueFromPropertyModification(m.z.currentValue, binding, out z)) { currentValue.z = (float)z; } if (ValueFromPropertyModification(m.w.currentValue, binding, out w)) { currentValue.w = (float)w; } // Favour euler hints if one or more exist on any axis. if (m.useEuler) { AddRotationPropertyModification(state, binding, m.eulerX); AddRotationPropertyModification(state, binding, m.eulerY); AddRotationPropertyModification(state, binding, m.eulerZ); Vector3 previousEulerAngles = target.GetLocalEulerAngles(RotationOrder.OrderZXY); Vector3 currentEulerAngles = previousEulerAngles; object eulerX, eulerY, eulerZ; if (ValueFromPropertyModification(m.eulerX.previousValue, binding, out eulerX)) { previousEulerAngles.x = (float)eulerX; } if (ValueFromPropertyModification(m.eulerY.previousValue, binding, out eulerY)) { previousEulerAngles.y = (float)eulerY; } if (ValueFromPropertyModification(m.eulerZ.previousValue, binding, out eulerZ)) { previousEulerAngles.z = (float)eulerZ; } if (ValueFromPropertyModification(m.eulerX.currentValue, binding, out eulerX)) { currentEulerAngles.x = (float)eulerX; } if (ValueFromPropertyModification(m.eulerY.currentValue, binding, out eulerY)) { currentEulerAngles.y = (float)eulerY; } if (ValueFromPropertyModification(m.eulerZ.currentValue, binding, out eulerZ)) { currentEulerAngles.z = (float)eulerZ; } // Fallback to quaternion euler values if euler hint and quaternion are out of sync. previousEulerAngles = AnimationUtility.GetClosestEuler(previousValue, previousEulerAngles, RotationOrder.OrderZXY); currentEulerAngles = AnimationUtility.GetClosestEuler(currentValue, currentEulerAngles, RotationOrder.OrderZXY); AddRotationKey(state, binding, type, previousEulerAngles, currentEulerAngles); } else { Vector3 eulerAngles = target.GetLocalEulerAngles(RotationOrder.OrderZXY); Vector3 previousEulerAngles = AnimationUtility.GetClosestEuler(previousValue, eulerAngles, RotationOrder.OrderZXY); Vector3 currentEulerAngles = AnimationUtility.GetClosestEuler(currentValue, eulerAngles, RotationOrder.OrderZXY); AddRotationKey(state, binding, type, previousEulerAngles, currentEulerAngles); } } }
private GenericMenu GenerateMenu(List <AnimationWindowHierarchyNode> interactedNodes) { List <AnimationWindowCurve> curvesAffectedByNodes = this.GetCurvesAffectedByNodes(interactedNodes, false); List <AnimationWindowCurve> curvesAffectedByNodes2 = this.GetCurvesAffectedByNodes(interactedNodes, true); bool flag = curvesAffectedByNodes.Count == 1 && AnimationWindowUtility.ForceGrouping(curvesAffectedByNodes[0].binding); GenericMenu genericMenu = new GenericMenu(); genericMenu.AddItem(new GUIContent((curvesAffectedByNodes.Count <= 1 && !flag) ? "Remove Property" : "Remove Properties"), false, new GenericMenu.MenuFunction(this.RemoveCurvesFromSelectedNodes)); bool flag2 = true; EditorCurveBinding[] array = new EditorCurveBinding[curvesAffectedByNodes2.Count]; for (int i = 0; i < curvesAffectedByNodes2.Count; i++) { array[i] = curvesAffectedByNodes2[i].binding; } RotationCurveInterpolation.Mode rotationInterpolationMode = this.GetRotationInterpolationMode(array); if (rotationInterpolationMode == RotationCurveInterpolation.Mode.Undefined) { flag2 = false; } else { foreach (AnimationWindowHierarchyNode current in interactedNodes) { if (!(current is AnimationWindowHierarchyPropertyGroupNode)) { flag2 = false; } } } if (flag2) { string str = (!this.state.activeAnimationClip.legacy) ? string.Empty : " (Not fully supported in Legacy)"; genericMenu.AddItem(new GUIContent("Interpolation/Euler Angles" + str), rotationInterpolationMode == RotationCurveInterpolation.Mode.RawEuler, new GenericMenu.MenuFunction2(this.ChangeRotationInterpolation), RotationCurveInterpolation.Mode.RawEuler); genericMenu.AddItem(new GUIContent("Interpolation/Euler Angles (Quaternion Approximation)"), rotationInterpolationMode == RotationCurveInterpolation.Mode.Baked, new GenericMenu.MenuFunction2(this.ChangeRotationInterpolation), RotationCurveInterpolation.Mode.Baked); genericMenu.AddItem(new GUIContent("Interpolation/Quaternion"), rotationInterpolationMode == RotationCurveInterpolation.Mode.NonBaked, new GenericMenu.MenuFunction2(this.ChangeRotationInterpolation), RotationCurveInterpolation.Mode.NonBaked); } if (AnimationMode.InAnimationMode()) { genericMenu.AddSeparator(string.Empty); bool flag3 = true; bool flag4 = true; bool flag5 = true; foreach (AnimationWindowCurve current2 in curvesAffectedByNodes) { if (!current2.HasKeyframe(this.state.time)) { flag3 = false; } else { flag4 = false; if (!current2.isPPtrCurve) { flag5 = false; } } } string text = "Add Key"; if (flag3) { genericMenu.AddDisabledItem(new GUIContent(text)); } else { genericMenu.AddItem(new GUIContent(text), false, new GenericMenu.MenuFunction2(this.AddKeysAtCurrentTime), curvesAffectedByNodes); } text = "Delete Key"; if (flag4) { genericMenu.AddDisabledItem(new GUIContent(text)); } else { genericMenu.AddItem(new GUIContent(text), false, new GenericMenu.MenuFunction2(this.DeleteKeysAtCurrentTime), curvesAffectedByNodes); } if (!flag5) { genericMenu.AddSeparator(string.Empty); List <KeyIdentifier> list = new List <KeyIdentifier>(); foreach (AnimationWindowCurve current3 in curvesAffectedByNodes) { if (!current3.isPPtrCurve) { int keyframeIndex = current3.GetKeyframeIndex(this.state.time); if (keyframeIndex != -1) { CurveRenderer curveRenderer = CurveRendererCache.GetCurveRenderer(this.state.activeAnimationClip, current3.binding); int curveID = CurveUtility.GetCurveID(this.state.activeAnimationClip, current3.binding); list.Add(new KeyIdentifier(curveRenderer, curveID, keyframeIndex)); } } } } } return(genericMenu); }
static private void ProcessAnimatorModifications(IAnimationRecordingState state, ref Dictionary <object, Vector3Modification> positionModifications, ref Dictionary <object, RotationModification> rotationModifications, ref Dictionary <object, Vector3Modification> scaleModifications) { Dictionary <object, RootMotionModification> rootMotionModifications = new Dictionary <object, RootMotionModification>(); AnimationClip clip = state.activeAnimationClip; GameObject root = state.activeRootGameObject; Animator animator = root.GetComponent <Animator>(); bool isHuman = animator != null ? animator.isHuman : false; bool hasRootMotion = animator != null ? animator.hasRootMotion : false; bool applyRootMotion = animator != null ? animator.applyRootMotion : false; bool hasRootCurves = clip.hasRootCurves; // process animator positions List <object> discardListPos = new List <object>(); foreach (KeyValuePair <object, Vector3Modification> item in positionModifications) { Vector3Modification m = item.Value; Transform target = item.Key as Transform; if (target == null) { continue; } EditorCurveBinding binding = new EditorCurveBinding(); Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.last.currentValue, state.activeRootGameObject, out binding); if (type == null) { continue; } bool isRootTransform = root.transform == target; bool isRootMotion = isRootTransform && applyRootMotion && hasRootCurves && (isHuman || hasRootMotion); bool isHumanBone = isHuman && !isRootTransform && animator.IsBoneTransform(target); if (isHumanBone) { Debug.LogWarning("Keyframing translation on humanoid rig is not supported!", target as Transform); discardListPos.Add(item.Key); } else if (isRootMotion) { RootMotionModification rootMotionModification; if (!rootMotionModifications.TryGetValue(target, out rootMotionModification)) { rootMotionModification = new RootMotionModification(); rootMotionModifications[target] = rootMotionModification; } rootMotionModification.lastP = m.last; rootMotionModification.px = m.x; rootMotionModification.py = m.y; rootMotionModification.pz = m.z; discardListPos.Add(item.Key); } else if (applyRootMotion && isRootTransform) { Vector3 scale = root.transform.localScale * (isHuman ? animator.humanScale : 1); ProcessVector3Modification(state, binding, m.x, target, "x", scale.x); ProcessVector3Modification(state, binding, m.y, target, "y", scale.y); ProcessVector3Modification(state, binding, m.z, target, "z", scale.z); discardListPos.Add(item.Key); } } foreach (object key in discardListPos) { positionModifications.Remove(key); } // process animator rotation List <object> discardListRot = new List <object>(); foreach (KeyValuePair <object, RotationModification> item in rotationModifications) { RotationModification m = item.Value; Transform target = item.Key as Transform; if (target == null) { continue; } EditorCurveBinding binding = new EditorCurveBinding(); Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.lastQuatModification.currentValue, state.activeRootGameObject, out binding); if (type == null) { continue; } bool isRootTransform = root.transform == target; bool isRootMotion = isRootTransform && applyRootMotion && hasRootCurves && (isHuman || hasRootMotion); bool isHumanBone = isHuman && !isRootTransform && animator.IsBoneTransform(target); if (isHumanBone) { Debug.LogWarning("Keyframing rotation on humanoid rig is not supported!", target as Transform); discardListRot.Add(item.Key); } else if (isRootMotion) { RootMotionModification rootMotionModification; if (!rootMotionModifications.TryGetValue(target, out rootMotionModification)) { rootMotionModification = new RootMotionModification(); rootMotionModifications[target] = rootMotionModification; } rootMotionModification.lastR = m.lastQuatModification; rootMotionModification.rx = m.x; rootMotionModification.ry = m.y; rootMotionModification.rz = m.z; rootMotionModification.rw = m.w; discardListRot.Add(item.Key); } } foreach (object key in discardListRot) { rotationModifications.Remove(key); } // process animator scales List <object> discardListScale = new List <object>(); foreach (KeyValuePair <object, Vector3Modification> item in scaleModifications) { Vector3Modification m = item.Value; Transform target = item.Key as Transform; if (target == null) { continue; } EditorCurveBinding binding = new EditorCurveBinding(); Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.last.currentValue, state.activeRootGameObject, out binding); if (type == null) { continue; } bool isRootTransform = root.transform == target; bool isHumanBone = isHuman && !isRootTransform && animator.IsBoneTransform(target); if (isHumanBone) { Debug.LogWarning("Keyframing scale on humanoid rig is not supported!", target as Transform); discardListScale.Add(item.Key); } } foreach (object key in discardListScale) { scaleModifications.Remove(key); } ProcessRootMotionModifications(state, ref rootMotionModifications); }
// 移動のみの抽出 void CreateKeysForLocation(MMD.VMD.VMDFormat format, AnimationClip clip, string current_bone, string bone_path, int interpolationQuality, GameObject current_obj = null) { try { Vector3 default_position = Vector3.zero; if (current_obj != null) { default_position = current_obj.transform.localPosition; } List <MMD.VMD.VMDFormat.Motion> mlist = format.motion_list.motion[current_bone]; int keyframeCountX = GetKeyframeCount(mlist, 0, interpolationQuality); int keyframeCountY = GetKeyframeCount(mlist, 1, interpolationQuality); int keyframeCountZ = GetKeyframeCount(mlist, 2, interpolationQuality); FloatKeyframe[] lx_keys = new FloatKeyframe[keyframeCountX]; FloatKeyframe[] ly_keys = new FloatKeyframe[keyframeCountY]; FloatKeyframe[] lz_keys = new FloatKeyframe[keyframeCountZ]; FloatKeyframe lx_prev_key = null; FloatKeyframe ly_prev_key = null; FloatKeyframe lz_prev_key = null; int ix = 0; int iy = 0; int iz = 0; for (int i = 0; i < mlist.Count; i++) { const float tick_time = 1.0f / 30.0f; float tick = mlist[i].flame_no * tick_time; FloatKeyframe lx_cur_key = new FloatKeyframe(tick, mlist[i].location.x * scale_ + default_position.x); FloatKeyframe ly_cur_key = new FloatKeyframe(tick, mlist[i].location.y * scale_ + default_position.y); FloatKeyframe lz_cur_key = new FloatKeyframe(tick, mlist[i].location.z * scale_ + default_position.z); // 各軸別々に補間が付いてる FloatKeyframe.AddBezierKeyframes(mlist[i].interpolation, 0, lx_prev_key, lx_cur_key, interpolationQuality, ref lx_keys, ref ix); FloatKeyframe.AddBezierKeyframes(mlist[i].interpolation, 1, ly_prev_key, ly_cur_key, interpolationQuality, ref ly_keys, ref iy); FloatKeyframe.AddBezierKeyframes(mlist[i].interpolation, 2, lz_prev_key, lz_cur_key, interpolationQuality, ref lz_keys, ref iz); lx_prev_key = lx_cur_key; ly_prev_key = ly_cur_key; lz_prev_key = lz_cur_key; } // 回転ボーンの場合はデータが入ってないはず if (mlist.Count != 0) { AnimationCurve curve_x = new AnimationCurve(ToKeyframesForLocation(lx_keys)); AnimationCurve curve_y = new AnimationCurve(ToKeyframesForLocation(ly_keys)); AnimationCurve curve_z = new AnimationCurve(ToKeyframesForLocation(lz_keys)); #if !UNITY_4_2 //4.3以降 AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bone_path, typeof(Transform), "m_LocalPosition.x"), curve_x); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bone_path, typeof(Transform), "m_LocalPosition.y"), curve_y); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bone_path, typeof(Transform), "m_LocalPosition.z"), curve_z); #else AnimationUtility.SetEditorCurve(clip, bone_path, typeof(Transform), "m_LocalPosition.x", curve_x); AnimationUtility.SetEditorCurve(clip, bone_path, typeof(Transform), "m_LocalPosition.y", curve_y); AnimationUtility.SetEditorCurve(clip, bone_path, typeof(Transform), "m_LocalPosition.z", curve_z); #endif } } catch (KeyNotFoundException) { //Debug.LogError("互換性のないボーンが読み込まれました:" + current_bone); } }
public override void Process(ImportContext ctx, Layer layer) { var animPath = layer.group.path; var frames = new Dictionary <int, Vector2>(); var file = ctx.file; //Change this layer sprites pivot var processor = ASEImporter.getProcessor("pivot"); processor?.Process(ctx, layer); //Read data from cel for (var i = 0; i < file.frames.Count; ++i) { var center = Vector2.zero; var pixelCount = 0; file.frames[i].cels.TryGetValue(layer.layerIndex, out var cel); if (cel == null) { continue; } for (var y = 0; y < cel.height; ++y) { for (var x = 0; x < cel.width; ++x) { var texX = cel.x + x; var texY = -(cel.y + y) + file.height - 1; var col = cel.GetPixelRaw(x, y); if (col.a > 0.1f) { center += new Vector2(texX, texY); pixelCount++; } } } if (pixelCount > 0) { center /= pixelCount; var pivot = Vector2.Scale(ctx.settings.pivotRelativePos, new Vector2(file.width, file.height)); var posWorld = (center - pivot) / ctx.settings.ppu; frames.Add(i, posWorld); } } //Change animation clips foreach (var frameTag in file.frameTags) { var clip = ctx.generatedClips[frameTag]; AnimationCurve curveX = new AnimationCurve(), curveY = new AnimationCurve(); float t = 0; var firstFramePos = frames[frameTag.from]; for (var f = frameTag.from; f <= frameTag.to; ++f) { if (frames.ContainsKey(f)) { var pos = frames[f]; var currentGroup = layer.group.parent; while (currentGroup != null) { var path = currentGroup.path; var bindings = AnimationUtility.GetCurveBindings(clip); var xb = bindings.Where(it => it.path == path && it.propertyName == "m_LocalPosition.x") .ToList(); var yb = bindings.Where(it => it.path == path && it.propertyName == "m_LocalPosition.y") .ToList(); if (!(xb.IsNullOrEmpty() || yb.IsNullOrEmpty())) { var x = AnimationUtility.GetEditorCurve(clip, xb[0]).keys .First(it => Mathf.Approximately(it.time, t)).value; var y = AnimationUtility.GetEditorCurve(clip, yb[0]).keys .First(it => Mathf.Approximately(it.time, t)).value; pos -= new Vector2(x, y); } currentGroup = currentGroup.parent; } if (f == frameTag.from) { firstFramePos = pos; } curveX.AddKey(t, pos.x); curveY.AddKey(t, pos.y); } t += file.frames[f].duration * 1e-3f; } //Completing the end frame for the loop //t -= 1.0f / clip.frameRate; curveX.AddKey(t, firstFramePos.x); curveY.AddKey(t, firstFramePos.y); if (curveX.length <= 0) { continue; } MakeConstant(curveX); MakeConstant(curveY); EditorCurveBinding bindingX = new EditorCurveBinding { path = animPath, type = typeof(Transform), propertyName = "m_LocalPosition.x" }, bindingY = new EditorCurveBinding { path = animPath, type = typeof(Transform), propertyName = "m_LocalPosition.y" }; AnimationUtility.SetEditorCurve(clip, bindingX, curveX); AnimationUtility.SetEditorCurve(clip, bindingY, curveY); EditorUtility.SetDirty(clip); } if (ctx.settings.generatePrefab) { var layerTransform = ctx.name2GameObject[layer.group.name].transform; var position = frames[0]; var transform = layerTransform.parent; while (transform.gameObject != ctx.rootGameObject) { position -= (Vector2)transform.localPosition; transform = transform.parent; } layerTransform.transform.localPosition = position; } }
private void _CreateMirrorClip(string newPath) { ConvertMap convMap = new ConvertMap(); foreach (var entry in m_MatchMap) { string fromPath = entry.Key; string toPath = entry.Value.path; bool bFound = entry.Value.found; convMap[fromPath] = toPath; if (bFound) { convMap[toPath] = fromPath; } } AnimationClip newClip = new AnimationClip(); float totalTime = m_Clip.length; float deltaTime = 1 / m_Clip.frameRate; var allBindings = AnimationUtility.GetCurveBindings(m_Clip); //collect bindings based on same path Dictionary <string, CurveBindingGroup> bindingMap = new Dictionary <string, CurveBindingGroup>(); foreach (var oneBinding in allBindings) { string bindingPath = oneBinding.path; string bindingProp = oneBinding.propertyName; CurveBindingGroup grp = null; if (!bindingMap.TryGetValue(bindingPath, out grp)) { grp = new CurveBindingGroup(); grp.path = bindingPath; bindingMap.Add(bindingPath, grp); } if (bindingProp.StartsWith("m_LocalPosition")) { grp.HasPosCurves = true; } else if (bindingProp.StartsWith("m_LocalRotation")) { grp.HasRotCurves = true; } else { grp.OtherCurves.Add(oneBinding); } } // fix foreach (var oneEntry in bindingMap) { string oldBindingPath = oneEntry.Key; CurveBindingGroup grp = oneEntry.Value; // get newBindingPath string newBindingPath = oldBindingPath; if (convMap.ContainsKey(oldBindingPath)) { newBindingPath = convMap[oldBindingPath]; } Axis selfAxisValue = _GetAxisValue(oldBindingPath, convMap); Axis parentAxisValue = _GetAxisValueForParent(oldBindingPath, convMap); // fix rotation curve and bindingProp if (grp.HasRotCurves) { AnimationCurve xCurve = AnimationUtility.GetEditorCurve(m_Clip, EditorCurveBinding.FloatCurve(oldBindingPath, typeof(Transform), "m_LocalRotation.x")); AnimationCurve yCurve = AnimationUtility.GetEditorCurve(m_Clip, EditorCurveBinding.FloatCurve(oldBindingPath, typeof(Transform), "m_LocalRotation.y")); AnimationCurve zCurve = AnimationUtility.GetEditorCurve(m_Clip, EditorCurveBinding.FloatCurve(oldBindingPath, typeof(Transform), "m_LocalRotation.z")); AnimationCurve wCurve = AnimationUtility.GetEditorCurve(m_Clip, EditorCurveBinding.FloatCurve(oldBindingPath, typeof(Transform), "m_LocalRotation.w")); AnimationCurve newXCurve = null; AnimationCurve newYCurve = null; AnimationCurve newZCurve = null; AnimationCurve newWCurve = null; if (parentAxisValue != selfAxisValue) { newXCurve = new AnimationCurve(); newYCurve = new AnimationCurve(); newZCurve = new AnimationCurve(); newWCurve = new AnimationCurve(); Vector3 planeNormal = Vector3.zero; switch (parentAxisValue) { case Axis.XY: planeNormal = Vector3.forward; break; case Axis.XZ: planeNormal = Vector3.up; break; case Axis.YZ: planeNormal = Vector3.right; break; default: Dbg.LogErr("AnimMirrorEditorWindow._CreateMirrorClip: unexpected parentAxisValue: {0}", parentAxisValue); break; } for (float t = 0; t <= totalTime;) { Quaternion oldQ = _BakeQ(xCurve, yCurve, zCurve, wCurve, t); Quaternion newQ = _ReflectQ(oldQ, selfAxisValue, planeNormal); newXCurve.AddKey(t, newQ.x); newYCurve.AddKey(t, newQ.y); newZCurve.AddKey(t, newQ.z); newWCurve.AddKey(t, newQ.w); if (Mathf.Approximately(t, totalTime)) { break; } t = Mathf.Min(totalTime, t + deltaTime); } } else { newXCurve = xCurve; newYCurve = yCurve; newZCurve = zCurve; newWCurve = wCurve; switch (parentAxisValue) { case Axis.XY: { newXCurve = _NegateCurve(xCurve); newYCurve = _NegateCurve(yCurve); } break; case Axis.XZ: { newXCurve = _NegateCurve(xCurve); newZCurve = _NegateCurve(zCurve); } break; case Axis.YZ: { newYCurve = _NegateCurve(yCurve); newZCurve = _NegateCurve(zCurve); } break; default: Dbg.LogErr("AnimMirrorEditorWindow._CreateMirrorClip: unexpected parentAxisValue: {0}", parentAxisValue); break; } } AnimationUtility.SetEditorCurve(newClip, EditorCurveBinding.FloatCurve(newBindingPath, typeof(Transform), "m_LocalRotation.x"), newXCurve); AnimationUtility.SetEditorCurve(newClip, EditorCurveBinding.FloatCurve(newBindingPath, typeof(Transform), "m_LocalRotation.y"), newYCurve); AnimationUtility.SetEditorCurve(newClip, EditorCurveBinding.FloatCurve(newBindingPath, typeof(Transform), "m_LocalRotation.z"), newZCurve); AnimationUtility.SetEditorCurve(newClip, EditorCurveBinding.FloatCurve(newBindingPath, typeof(Transform), "m_LocalRotation.w"), newWCurve); } // fix position curve if (grp.HasPosCurves) { AnimationCurve xCurve = AnimationUtility.GetEditorCurve(m_Clip, EditorCurveBinding.FloatCurve(oldBindingPath, typeof(Transform), "m_LocalPosition.x")); AnimationCurve yCurve = AnimationUtility.GetEditorCurve(m_Clip, EditorCurveBinding.FloatCurve(oldBindingPath, typeof(Transform), "m_LocalPosition.y")); AnimationCurve zCurve = AnimationUtility.GetEditorCurve(m_Clip, EditorCurveBinding.FloatCurve(oldBindingPath, typeof(Transform), "m_LocalPosition.z")); AnimationCurve newXCurve = xCurve; AnimationCurve newYCurve = yCurve; AnimationCurve newZCurve = zCurve; Axis posAxisValue = _GetAxisValueForParent(oldBindingPath, convMap); switch (posAxisValue) { case Axis.XZ: { newYCurve = _NegateCurve(newYCurve); } break; case Axis.XY: { newZCurve = _NegateCurve(newZCurve); } break; case Axis.YZ: { newXCurve = _NegateCurve(newXCurve); } break; default: Dbg.LogErr("AnimMirrorEditorWindow._CreateMirrorClip: unexpected mirror axis value (2nd): {0}", posAxisValue); break; } AnimationUtility.SetEditorCurve(newClip, EditorCurveBinding.FloatCurve(newBindingPath, typeof(Transform), "m_LocalPosition.x"), newXCurve); AnimationUtility.SetEditorCurve(newClip, EditorCurveBinding.FloatCurve(newBindingPath, typeof(Transform), "m_LocalPosition.y"), newYCurve); AnimationUtility.SetEditorCurve(newClip, EditorCurveBinding.FloatCurve(newBindingPath, typeof(Transform), "m_LocalPosition.z"), newZCurve); } // other curves foreach (var oneBinding in grp.OtherCurves) { Type tp = oneBinding.type; string propName = oneBinding.propertyName; if (oneBinding.isPPtrCurve) { EditorCurveBinding newBinding = EditorCurveBinding.PPtrCurve(newBindingPath, tp, propName); ObjectReferenceKeyframe[] array = AnimationUtility.GetObjectReferenceCurve(m_Clip, oneBinding); AnimationUtility.SetObjectReferenceCurve(newClip, newBinding, array); //add new } else { EditorCurveBinding newBinding = EditorCurveBinding.FloatCurve(newBindingPath, tp, propName); AnimationCurve curve = AnimationUtility.GetEditorCurve(m_Clip, oneBinding); AnimationUtility.SetEditorCurve(newClip, newBinding, curve); //add new } } } //end of foreach // finishing part #if !U5 var oldAnimType = (ModelImporterAnimationType)RCall.CallMtd("UnityEditor.AnimationUtility", "GetAnimationType", null, m_Clip); AnimationUtility.SetAnimationType(newClip, oldAnimType); #endif AnimationClipSettings oldSettings = AnimationUtility.GetAnimationClipSettings(m_Clip); RCall.CallMtd("UnityEditor.AnimationUtility", "SetAnimationClipSettings", null, newClip, oldSettings); newClip.EnsureQuaternionContinuity(); // save to disk AnimationClip existingClip = AssetDatabase.LoadAssetAtPath(newPath, typeof(AnimationClip)) as AnimationClip; if (existingClip != null) { EditorUtility.CopySerialized(newClip, existingClip); } else { AssetDatabase.CreateAsset(newClip, newPath); } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Dbg.Log("Created mirror-ed animation clip at: {0}", newPath); }
private GenericMenu GenerateMenu(List <AnimationWindowHierarchyNode> interactedNodes, bool enabled) { List <AnimationWindowCurve> curves = GetCurvesAffectedByNodes(interactedNodes, false); // Linked curves are like regular affected curves but always include transform siblings List <AnimationWindowCurve> linkedCurves = GetCurvesAffectedByNodes(interactedNodes, true); bool forceGroupRemove = curves.Count == 1 ? AnimationWindowUtility.ForceGrouping(curves[0].binding) : false; GenericMenu menu = new GenericMenu(); // Remove curves GUIContent removePropertyContent = new GUIContent(curves.Count > 1 || forceGroupRemove ? "Remove Properties" : "Remove Property"); if (!enabled) { menu.AddDisabledItem(removePropertyContent); } else { menu.AddItem(removePropertyContent, false, RemoveCurvesFromSelectedNodes); } // Change rotation interpolation bool showInterpolation = true; EditorCurveBinding[] curveBindings = new EditorCurveBinding[linkedCurves.Count]; for (int i = 0; i < linkedCurves.Count; i++) { curveBindings[i] = linkedCurves[i].binding; } RotationCurveInterpolation.Mode rotationInterpolation = GetRotationInterpolationMode(curveBindings); if (rotationInterpolation == RotationCurveInterpolation.Mode.Undefined) { showInterpolation = false; } else { foreach (var node in interactedNodes) { if (!(node is AnimationWindowHierarchyPropertyGroupNode)) { showInterpolation = false; } } } if (showInterpolation) { string legacyWarning = state.activeAnimationClip.legacy ? " (Not fully supported in Legacy)" : ""; GenericMenu.MenuFunction2 nullMenuFunction2 = null; menu.AddItem(EditorGUIUtility.TrTextContent("Interpolation/Euler Angles" + legacyWarning), rotationInterpolation == RotationCurveInterpolation.Mode.RawEuler, enabled ? ChangeRotationInterpolation : nullMenuFunction2, RotationCurveInterpolation.Mode.RawEuler); menu.AddItem(EditorGUIUtility.TrTextContent("Interpolation/Euler Angles (Quaternion)"), rotationInterpolation == RotationCurveInterpolation.Mode.Baked, enabled ? ChangeRotationInterpolation : nullMenuFunction2, RotationCurveInterpolation.Mode.Baked); menu.AddItem(EditorGUIUtility.TrTextContent("Interpolation/Quaternion"), rotationInterpolation == RotationCurveInterpolation.Mode.NonBaked, enabled ? ChangeRotationInterpolation : nullMenuFunction2, RotationCurveInterpolation.Mode.NonBaked); } // Menu items that are only applicaple when in animation mode: if (state.previewing) { menu.AddSeparator(""); bool allHaveKeys = true; bool noneHaveKeys = true; foreach (AnimationWindowCurve curve in curves) { bool curveHasKey = curve.HasKeyframe(state.time); if (!curveHasKey) { allHaveKeys = false; } else { noneHaveKeys = false; } } string str; str = "Add Key"; if (allHaveKeys || !enabled) { menu.AddDisabledItem(new GUIContent(str)); } else { menu.AddItem(new GUIContent(str), false, AddKeysAtCurrentTime, curves); } str = "Delete Key"; if (noneHaveKeys || !enabled) { menu.AddDisabledItem(new GUIContent(str)); } else { menu.AddItem(new GUIContent(str), false, DeleteKeysAtCurrentTime, curves); } } return(menu); }
//生成动画 static void GenerateAnimation(string name, GifFile gif, string path, ref AnimationInfo info) { AnimationClip clip = new AnimationClip(); clip.name = name; clip.frameRate = 25; //创建动画文件 string asset = string.Format("{0}/{1}.anim", path, name); AssetDatabase.CreateAsset(clip, asset); SpriteImportData[] spriteImportData = new SpriteImportData[0]; Texture2D atlas = AtlasGenerator.GenerateAtlas(gif, out spriteImportData); atlas.filterMode = FilterMode.Point; atlas.name = name; //AssetDatabase.AddObjectToAsset(atlas, clip); byte[] pngBytes = atlas.EncodeToPNG(); string atlasPath = string.Format("{0}/{1}.png", path, name); File.WriteAllBytes(atlasPath, pngBytes); AssetDatabase.Refresh(); //生成的贴图 Texture2D atlasObject = (Texture2D)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(Texture2D)); atlasObject.filterMode = FilterMode.Point; //生成贴图 List <Sprite> sprites = GenerateSprites(atlasObject, spriteImportData, clip); //帧数 int length = sprites.Count; EditorCurveBinding spriteBinding = new EditorCurveBinding(); spriteBinding.type = typeof(SpriteRenderer); spriteBinding.path = ""; spriteBinding.propertyName = "m_Sprite"; //设置帧信息 ObjectReferenceKeyframe[] spriteKeyFrames = new ObjectReferenceKeyframe[length + 1]; float time = 0; for (int i = 0; i < length; i++) { ObjectReferenceKeyframe frame = new ObjectReferenceKeyframe(); frame.time = time; frame.value = sprites[i]; time += gif.textureList[i].m_delaySec; spriteKeyFrames[i] = frame; } //单独设置最后一帧 float frameTime = 1f / clip.frameRate; ObjectReferenceKeyframe lastFrame = new ObjectReferenceKeyframe(); lastFrame.time = time - frameTime; lastFrame.value = sprites[length - 1]; spriteKeyFrames[spriteKeyFrames.Length - 1] = lastFrame; AnimationUtility.SetObjectReferenceCurve(clip, spriteBinding, spriteKeyFrames); //循环设置 AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(clip); //循环设置 //if (animationSetting.loop) { // settings.loopTime = true; // clip.wrapMode = WrapMode.Loop; //} else { // settings.loopTime = false; // clip.wrapMode = WrapMode.Once; //} AnimationUtility.SetAnimationClipSettings(clip, settings); info.animationClip = clip; info.texture = atlasObject; }
private List <AnimationClip> GenerateAnimations(AseFile aseFile, List <Sprite> sprites) { List <AnimationClip> res = new List <AnimationClip>(); var animations = aseFile.GetAnimations(); if (animations.Length <= 0) { return(res); } var metadatas = aseFile.GetMetaData(Settings.spritePivot, Settings.pixelsPerUnit); int index = 0; foreach (var animation in animations) { var path = directoryName + "/" + fileName + "_" + animation.TagName + ".anim"; AnimationClip clip = AssetDatabase.LoadAssetAtPath <AnimationClip>(path); if (clip == null) { clip = new AnimationClip(); AssetDatabase.CreateAsset(clip, path); clip.wrapMode = GetDefaultWrapMode(animation.TagName); } else { AnimationClipSettings animSettings = AnimationUtility.GetAnimationClipSettings(clip); clip.wrapMode = animSettings.loopTime ? WrapMode.Loop : WrapMode.Once; } clip.name = fileName + "_" + animation.TagName; clip.frameRate = 25; EditorCurveBinding editorBinding = new EditorCurveBinding(); editorBinding.path = ""; editorBinding.propertyName = "m_Sprite"; switch (Settings.bindType) { case AseAnimationBindType.SpriteRenderer: editorBinding.type = typeof(SpriteRenderer); break; case AseAnimationBindType.UIImage: editorBinding.type = typeof(Image); break; } // plus last frame to keep the duration int length = animation.FrameTo - animation.FrameFrom + 1; ObjectReferenceKeyframe[] spriteKeyFrames = new ObjectReferenceKeyframe[length + 1]; Dictionary <string, AnimationCurve> transformCurveX = new Dictionary <string, AnimationCurve>(), transformCurveY = new Dictionary <string, AnimationCurve>(); float time = 0; int from = (animation.Animation != LoopAnimation.Reverse) ? animation.FrameFrom : animation.FrameTo; int step = (animation.Animation != LoopAnimation.Reverse) ? 1 : -1; int keyIndex = from; for (int i = 0; i < length; i++) { if (i >= length) { keyIndex = from; } ObjectReferenceKeyframe frame = new ObjectReferenceKeyframe(); frame.time = time; frame.value = sprites[keyIndex]; time += aseFile.Frames[keyIndex].FrameDuration / 1000f; spriteKeyFrames[i] = frame; foreach (var metadata in metadatas) { if (metadata.Type == MetaDataType.TRANSFORM && metadata.Transforms.ContainsKey(keyIndex)) { var childTransform = metadata.Args[0]; if (!transformCurveX.ContainsKey(childTransform)) { transformCurveX[childTransform] = new AnimationCurve(); transformCurveY[childTransform] = new AnimationCurve(); } var pos = metadata.Transforms[keyIndex]; transformCurveX[childTransform].AddKey(i, pos.x); transformCurveY[childTransform].AddKey(i, pos.y); } } keyIndex += step; } float frameTime = 1f / clip.frameRate; ObjectReferenceKeyframe lastFrame = new ObjectReferenceKeyframe(); lastFrame.time = time - frameTime; lastFrame.value = sprites[keyIndex - step]; spriteKeyFrames[spriteKeyFrames.Length - 1] = lastFrame; foreach (var metadata in metadatas) { if (metadata.Type == MetaDataType.TRANSFORM && metadata.Transforms.ContainsKey(keyIndex - step)) { var childTransform = metadata.Args[0]; var pos = metadata.Transforms[keyIndex - step]; transformCurveX[childTransform].AddKey(spriteKeyFrames.Length - 1, pos.x); transformCurveY[childTransform].AddKey(spriteKeyFrames.Length - 1, pos.y); } } AnimationUtility.SetObjectReferenceCurve(clip, editorBinding, spriteKeyFrames); foreach (var childTransform in transformCurveX.Keys) { EditorCurveBinding bindingX = new EditorCurveBinding { path = childTransform, type = typeof(Transform), propertyName = "m_LocalPosition.x" }, bindingY = new EditorCurveBinding { path = childTransform, type = typeof(Transform), propertyName = "m_LocalPosition.y" }; MakeConstant(transformCurveX[childTransform]); AnimationUtility.SetEditorCurve(clip, bindingX, transformCurveX[childTransform]); MakeConstant(transformCurveY[childTransform]); AnimationUtility.SetEditorCurve(clip, bindingY, transformCurveY[childTransform]); } AnimationClipSettings clipSettings = AnimationUtility.GetAnimationClipSettings(clip); clipSettings.loopTime = (clip.wrapMode == WrapMode.Loop); AnimationUtility.SetAnimationClipSettings(clip, clipSettings); EditorUtility.SetDirty(clip); index++; res.Add(clip); } return(res); }
private void GenerateAnimations(UnityEditor.AssetImporters.AssetImportContext ctx, AseFile aseFile, Sprite[] sprites) { if (animationSettings == null) { animationSettings = new AseFileAnimationSettings[0]; } var animSettings = new List <AseFileAnimationSettings>(animationSettings); var animations = aseFile.GetAnimations(); if (animations.Length <= 0) { return; } if (animationSettings != null) { RemoveUnusedAnimationSettings(animSettings, animations); } int index = 0; foreach (var animation in animations) { AnimationClip animationClip = new AnimationClip(); animationClip.name = name + "_" + animation.TagName; animationClip.frameRate = 25; AseFileAnimationSettings importSettings = GetAnimationSettingFor(animSettings, animation); importSettings.about = GetAnimationAbout(animation); EditorCurveBinding editorBinding = new EditorCurveBinding(); editorBinding.path = ""; editorBinding.propertyName = "m_Sprite"; switch (bindType) { case AseEditorBindType.SpriteRenderer: editorBinding.type = typeof(SpriteRenderer); break; case AseEditorBindType.UIImage: editorBinding.type = typeof(Image); break; } int length = animation.FrameTo - animation.FrameFrom + 1; ObjectReferenceKeyframe[] spriteKeyFrames = new ObjectReferenceKeyframe[length + 1]; // plus last frame to keep the duration float time = 0; int from = (animation.Animation != LoopAnimation.Reverse) ? animation.FrameFrom : animation.FrameTo; int step = (animation.Animation != LoopAnimation.Reverse) ? 1 : -1; int keyIndex = from; for (int i = 0; i < length; i++) { if (i >= length) { keyIndex = from; } ObjectReferenceKeyframe frame = new ObjectReferenceKeyframe(); frame.time = time; frame.value = sprites[keyIndex]; time += aseFile.Frames[keyIndex].FrameDuration / 1000f; keyIndex += step; spriteKeyFrames[i] = frame; } float frameTime = 1f / animationClip.frameRate; ObjectReferenceKeyframe lastFrame = new ObjectReferenceKeyframe(); lastFrame.time = time - frameTime; lastFrame.value = sprites[keyIndex - step]; spriteKeyFrames[spriteKeyFrames.Length - 1] = lastFrame; AnimationUtility.SetObjectReferenceCurve(animationClip, editorBinding, spriteKeyFrames); AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(animationClip); switch (animation.Animation) { case LoopAnimation.Forward: animationClip.wrapMode = WrapMode.Loop; settings.loopTime = true; break; case LoopAnimation.Reverse: animationClip.wrapMode = WrapMode.Loop; settings.loopTime = true; break; case LoopAnimation.PingPong: animationClip.wrapMode = WrapMode.PingPong; settings.loopTime = true; break; } if (!importSettings.loopTime) { animationClip.wrapMode = WrapMode.Once; settings.loopTime = false; } AnimationUtility.SetAnimationClipSettings(animationClip, settings); ctx.AddObjectToAsset(animation.TagName, animationClip); index++; } animationSettings = animSettings.ToArray(); }
private TreeViewItem AddGameObjectToHierarchy(GameObject gameObject, TreeViewItem parent) { string path = AnimationUtility.CalculateTransformPath(gameObject.transform, this.state.activeRootGameObject.transform); TreeViewItem parentNode = new AddCurvesPopupGameObjectNode(gameObject, parent, gameObject.name); List <TreeViewItem> visibleItems = new List <TreeViewItem>(); if (parent == null) { base.m_RootItem = parentNode; } EditorCurveBinding[] animatableBindings = AnimationUtility.GetAnimatableBindings(gameObject, this.state.activeRootGameObject); List <EditorCurveBinding> list2 = new List <EditorCurveBinding>(); for (int i = 0; i < animatableBindings.Length; i++) { EditorCurveBinding item = animatableBindings[i]; list2.Add(item); if (item.propertyName == "m_IsActive") { if (item.path != string.Empty) { TreeViewItem item2 = this.CreateNode(list2.ToArray(), parentNode); if (item2 != null) { visibleItems.Add(item2); } list2.Clear(); } else { list2.Clear(); } } else { bool flag = i == (animatableBindings.Length - 1); bool flag2 = false; if (!flag) { flag2 = animatableBindings[i + 1].type != item.type; } if (AnimationWindowUtility.IsCurveCreated(this.state.activeAnimationClip, item)) { list2.Remove(item); } if ((flag || flag2) && (list2.Count > 0)) { visibleItems.Add(this.AddAnimatableObjectToHierarchy(this.state.activeRootGameObject, list2.ToArray(), parentNode, path)); list2.Clear(); } } } if (showEntireHierarchy) { for (int j = 0; j < gameObject.transform.childCount; j++) { Transform child = gameObject.transform.GetChild(j); TreeViewItem item3 = this.AddGameObjectToHierarchy(child.gameObject, parentNode); if (item3 != null) { visibleItems.Add(item3); } } } TreeViewUtility.SetChildParentReferences(visibleItems, parentNode); return(parentNode); }
static private void ProcessVector3Modification(IAnimationRecordingState state, EditorCurveBinding baseBinding, UndoPropertyModification modification, Transform target, string axis) { var binding = baseBinding; var property = modification.previousValue; binding.propertyName = binding.propertyName.Remove(binding.propertyName.Length - 1, 1) + axis; if (property == null) { // create dummy property = new PropertyModification(); property.target = target; property.propertyPath = binding.propertyName; object currentValue = CurveBindingUtility.GetCurrentValue(state.activeRootGameObject, binding); property.value = ((float)currentValue).ToString(); } state.AddPropertyModification(binding, property, modification.keepPrefabOverride); AddKey(state, binding, typeof(float), property); }