// Given a track, return the animation clip internal static AnimationClip FindRecordingAnimationClipAtTime(this TrackAsset trackAsset, double time) { if (trackAsset == null) return null; AnimationTrack animTrack = trackAsset as AnimationTrack; if (animTrack != null && !animTrack.inClipMode) { return animTrack.infiniteClip; } TimelineClip displayBackground = null; trackAsset.FindRecordingClipAtTime(time, out displayBackground); if (displayBackground != null) { if (displayBackground.recordable) { AnimationPlayableAsset asset = displayBackground.asset as AnimationPlayableAsset; if (asset != null) return asset.clip; } else if (animTrack == null) { AnimatedParameterExtensions.CreateCurvesIfRequired(displayBackground); return displayBackground.curves; } } return null; }
private void DoManipulators() { if (!(this.m_EditorClip == null) && this.m_EditorClip.clip != null) { AnimationPlayableAsset animationPlayableAsset = this.m_EditorClip.clip.asset as AnimationPlayableAsset; AnimationTrack animationTrack = this.m_EditorClip.clip.parentTrack as AnimationTrack; Transform transform = this.GetTransform(); if (transform != null && animationPlayableAsset != null && this.m_OffsetEditMode != TimelineAnimationUtilities.OffsetEditMode.None && animationTrack != null) { Vector3 vector = transform.get_position(); Quaternion quaternion = transform.get_rotation(); EditorGUI.BeginChangeCheck(); if (this.m_OffsetEditMode == TimelineAnimationUtilities.OffsetEditMode.Translation) { vector = Handles.PositionHandle(vector, (Tools.get_pivotRotation() != 1) ? quaternion : Quaternion.get_identity()); } else if (this.m_OffsetEditMode == TimelineAnimationUtilities.OffsetEditMode.Rotation) { quaternion = Handles.RotationHandle(quaternion, vector); } if (EditorGUI.EndChangeCheck()) { TimelineAnimationUtilities.RigidTransform rigidTransform = TimelineAnimationUtilities.UpdateClipOffsets(animationPlayableAsset, animationTrack, transform, vector, quaternion); animationPlayableAsset.position = rigidTransform.position; animationPlayableAsset.rotation = rigidTransform.rotation; this.Reevaluate(); base.Repaint(); } } } }
public static TimelineClip Clone(TimelineClip clip, PlayableDirector directorInstance) { EditorClip editorClip = EditorItemFactory.GetEditorClip(clip); TimelineClip clip2 = Object.Instantiate <EditorClip>(editorClip).clip; SelectionManager.Remove(clip2); clip2.parentTrack = null; clip2.ClearAnimatedParameterCurves(); if (clip.curves != null) { AnimatedParameterExtensions.CreateCurvesIfRequired(clip2, clip.parentTrack); EditorUtility.CopySerialized(clip.curves, clip2.curves); } ScriptableObject scriptableObject = clip2.asset as ScriptableObject; if (scriptableObject != null && clip2.asset is IPlayableAsset) { ScriptableObject scriptableObject2 = TimelineHelpers.CloneReferencedPlayableAsset(scriptableObject, directorInstance); TimelineHelpers.SaveCloneToOriginalAsset(scriptableObject, scriptableObject2); clip2.asset = scriptableObject2; AnimationPlayableAsset animationPlayableAsset = scriptableObject2 as AnimationPlayableAsset; if (clip2.recordable && animationPlayableAsset != null && animationPlayableAsset.clip != null) { clip2.displayName = animationPlayableAsset.clip.get_name(); } } return(clip2); }
internal static bool IsRecordingToClip(this TrackAsset track, TimelineClip clip) { bool result; if (track == null || clip == null) { result = false; } else { AnimationClip activeRecordingAnimationClip = track.GetActiveRecordingAnimationClip(); if (activeRecordingAnimationClip == null) { result = false; } else if (activeRecordingAnimationClip == clip.curves) { result = true; } else { AnimationPlayableAsset animationPlayableAsset = clip.asset as AnimationPlayableAsset; result = (animationPlayableAsset != null && activeRecordingAnimationClip == animationPlayableAsset.clip); } } return(result); }
public override void DrawClip(TrackDrawer.ClipDrawData drawData) { TimelineClip clip = drawData.clip; if (clip.animationClip == null) { base.DrawClip(drawData); } else { bool flag = false; if (clip.asset != null) { AnimationPlayableAsset animationPlayableAsset = clip.asset as AnimationPlayableAsset; if (animationPlayableAsset != null) { flag = (animationPlayableAsset.clip == null); } } if (flag) { if (AnimationTrackDrawer.s_MissingIcon == null) { Texture2D errorIcon = EditorGUIUtility.get_errorIcon(); AnimationTrackDrawer.s_MissingIcon = new GUIContent(errorIcon, "This clip has no animation assigned"); } base.DrawClipErrorIcon(drawData, AnimationTrackDrawer.s_MissingIcon); } base.DrawClip(drawData); } }
public static void ConvertToClipMode(this AnimationTrack track) { if (track.CanConvertToClipMode()) { TimelineUndo.PushUndo(track, "Convert To Clip"); if (!track.animClip.get_empty()) { TimelineUndo.PushUndo(track.animClip, "Convert To Clip"); float num = AnimationClipCurveCache.Instance.GetCurveInfo(track.animClip).keyTimes.FirstOrDefault <float>(); track.animClip.ShiftBySeconds(-num); TimelineClip timelineClip = track.CreateClipFromAsset(track.animClip); TimelineCreateUtilities.SaveAssetIntoObject(timelineClip.asset, track); timelineClip.start = (double)num; timelineClip.preExtrapolationMode = track.openClipPreExtrapolation; timelineClip.postExtrapolationMode = track.openClipPostExtrapolation; timelineClip.recordable = true; if (Math.Abs(timelineClip.duration) < 1.4012984643248171E-45) { timelineClip.duration = 1.0; } AnimationPlayableAsset animationPlayableAsset = timelineClip.asset as AnimationPlayableAsset; if (animationPlayableAsset) { animationPlayableAsset.position = track.openClipOffsetPosition; animationPlayableAsset.rotation = track.openClipOffsetRotation; track.openClipOffsetPosition = Vector3.get_zero(); track.openClipOffsetRotation = Quaternion.get_identity(); } track.CalculateExtrapolationTimes(); } track.animClip = null; EditorUtility.SetDirty(track); } }
void setClipOffset(GameObject animTimeline, Vector3 anim_location, Quaternion anim_rotation) { // SET ATTRIBUTES OF TARGET TIMELINE, a child of some gameobject is the convention PlayableDirector anim_director = animTimeline.GetComponent <PlayableDirector>(); List <PlayableBinding> playable_list = anim_director.playableAsset.outputs.ToList(); TrackAsset target_anim_track = playable_list[0].sourceObject as AnimationTrack; foreach (TimelineClip track_clip in target_anim_track.GetClips()) { AnimationPlayableAsset target_anim_clip = track_clip.asset as AnimationPlayableAsset; target_anim_clip.position = anim_location; target_anim_clip.rotation = anim_rotation; } // this is the animation track, always; here, we are setting an offset //TrackAsset target_anim_track = playable_list[0].sourceObject as AnimationTrack; //List<TimelineClip> track_clips = target_anim_track.GetClips().ToList(); //AnimationPlayableAsset target_anim_clip = track_clips[0].asset as AnimationPlayableAsset; //target_anim_clip.position = start_pos; // this is the lerp track, always; here, we set destination //TrackAsset target_lerp_track = playable_list[1].sourceObject as PlayableTrack; //List<TimelineClip> lerp_clips = target_lerp_track.GetClips().ToList(); }
string GetErrorText(AnimationPlayableAsset animationAsset, AnimationTrack track, string defaultError) { if (animationAsset.clip == null) { return(k_NoClipAssignedError); } if (animationAsset.clip.legacy) { return(k_LegacyClipError); } if (animationAsset.clip.hasMotionCurves || animationAsset.clip.hasRootCurves) { if (track != null && track.trackOffset == TrackOffset.Auto) { var animator = track.GetBinding(TimelineEditor.inspectedDirector); if (animator != null && !animator.applyRootMotion && !animationAsset.clip.hasGenericRootTransform) { if (animationAsset.clip.hasMotionCurves) { return(k_MotionCurveError); } return(k_RootCurveError); } } } return(defaultError); }
public virtual bool GetHasRootTransforms(AnimationPlayableAsset instance) { if (instance == null) { return(false); } return(uAnimationUtility.HasRootCurves(instance.clip)); }
// Is this a recordable clip on an animation track. internal static bool IsRecordableAnimationClip(TimelineClip clip) { if (!clip.recordable) return false; AnimationPlayableAsset asset = clip.asset as AnimationPlayableAsset; if (asset == null) return false; return true; }
public override bool GetHasRootTransforms(AnimationPlayableAsset instance) { if (instance == null) { return(false); } if (dg_get_hasRootTransforms == null || dg_get_hasRootTransforms.Target != (object)instance) { dg_get_hasRootTransforms = (Func <bool>)Delegate.CreateDelegate(typeof(Func <bool>), instance, instance.GetType().GetProperty("hasRootTransforms", BindingFlags.NonPublic | BindingFlags.Instance).GetGetMethod(true)); } return(dg_get_hasRootTransforms()); }
private static void ResetClipOffsets(ITimelineState state, TimelineClip[] clips) { for (int i = 0; i < clips.Length; i++) { TimelineClip timelineClip = clips[i]; if (timelineClip.asset is AnimationPlayableAsset) { AnimationPlayableAsset animationPlayableAsset = (AnimationPlayableAsset)timelineClip.asset; animationPlayableAsset.ResetOffsets(); } } state.rebuildGraph = true; }
public void SetClipOffset(Vector3 _position, Vector3 _normal) { var obj = UnityEditor.Selection.activeObject; if (obj != null) { var fi = obj.GetType().GetField("m_Clip", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); if (fi != null) { var clip = fi.GetValue(obj) as TimelineClip; if (clip != null) { AnimationPlayableAsset animationPlayableAsset = clip.asset as AnimationPlayableAsset; animationPlayableAsset.position = new Vector3(0, 0, 0); var view = SceneView.lastActiveSceneView; if (view != null) { Undo.RecordObject(animationPlayableAsset, "Object Placer: Adjusting Clip Offset"); if (lookUp) { animationPlayableAsset.rotation *= Quaternion.FromToRotation(Vector3.up, _normal); } if (useOffset) { animationPlayableAsset.position = _position + offset; } else { animationPlayableAsset.position = _position; } } } else { Debug.Log("Select a clip please."); } } else { Debug.Log("Select a clip please."); } } else { Debug.Log("Select a clip please."); } HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Keyboard)); opg.isDrawing = false; isMoving = false; }
// Given a track, return the animation clip internal static AnimationClip FindRecordingAnimationClipAtTime(this TrackAsset trackAsset, double time) { if (trackAsset == null) { return(null); } AnimationTrack animTrack = trackAsset as AnimationTrack; if (animTrack != null && !animTrack.inClipMode) { return(animTrack.infiniteClip); } TimelineClip displayBackground; trackAsset.FindRecordingClipAtTime(time, out displayBackground); if (displayBackground != null) { if (displayBackground.recordable) { AnimationPlayableAsset asset = displayBackground.asset as AnimationPlayableAsset; if (asset != null) { return(asset.clip); } } else if (animTrack == null) { if (displayBackground.curves == null) { displayBackground.CreateCurves(AnimationTrackRecorder.GetUniqueRecordedClipName(displayBackground.parentTrack, TimelineClip.kDefaultCurvesName)); } return(displayBackground.curves); } } else if (trackAsset.HasAnyAnimatableParameters()) { if (trackAsset.curves == null) { trackAsset.CreateCurves(AnimationTrackRecorder.GetUniqueRecordedClipName(trackAsset.timelineAsset, TrackAsset.kDefaultCurvesName)); } return(trackAsset.curves); } return(null); }
public static bool CanConvertFromClipMode(this AnimationTrack track) { bool result; if (track == null || !track.inClipMode || track.clips.Length != 1 || track.clips[0].start < 0.0 || !track.clips[0].recordable) { result = false; } else { AnimationPlayableAsset animationPlayableAsset = track.clips[0].asset as AnimationPlayableAsset; result = (!(animationPlayableAsset == null) && TimelineHelpers.HaveSameContainerAsset(track, animationPlayableAsset.clip)); } return(result); }
private static void GetAnimationClips(IEnumerable <TimelineClip> timelineClips, List <AnimationClip> clips) { foreach (var timelineClip in timelineClips) { if (timelineClip.curves != null) { clips.Add(timelineClip.curves); } AnimationPlayableAsset apa = timelineClip.asset as AnimationPlayableAsset; if (apa != null && apa.clip != null) { clips.Add(apa.clip); } } }
// Is this a recordable clip on an animation track. internal static bool IsRecordableAnimationClip(TimelineClip clip) { if (!clip.recordable) { return(false); } AnimationPlayableAsset asset = clip.asset as AnimationPlayableAsset; if (asset == null) { return(false); } return(true); }
internal static TimelineClip Clone(TimelineClip clip, PlayableDirector director, PlayableAsset newOwner) { var editorClip = EditorClipFactory.GetEditorClip(clip); // Workaround for Clips not being unity object, assign it to a editor clip wrapper, clone it, and pull the clip back out var newClip = Object.Instantiate(editorClip).clip; // perform fix ups for what Instantiate cannot properly detect SelectionManager.Remove(newClip); newClip.parentTrack = null; newClip.curves = null; // instantiate might copy the reference, we need to clear it // curves are explicitly owned by the clip if (clip.curves != null) { newClip.CreateCurves(AnimationTrackRecorder.GetUniqueRecordedClipName(newOwner, clip.curves.name)); EditorUtility.CopySerialized(clip.curves, newClip.curves); TimelineCreateUtilities.SaveAssetIntoObject(newClip.curves, newOwner); } ScriptableObject playableAsset = newClip.asset as ScriptableObject; if (playableAsset != null && newClip.asset is IPlayableAsset) { var clone = CloneReferencedPlayableAsset(playableAsset, director); SaveCloneToAsset(clone, newOwner); newClip.asset = clone; // special case to make the name match the recordable clips, but only if they match on the original clip var originalRecordedAsset = clip.asset as AnimationPlayableAsset; if (clip.recordable && originalRecordedAsset != null && originalRecordedAsset.clip != null) { AnimationPlayableAsset clonedAnimationAsset = clone as AnimationPlayableAsset; if (clonedAnimationAsset != null && clonedAnimationAsset.clip != null) { clonedAnimationAsset.clip = CloneAnimationClip(originalRecordedAsset.clip, newOwner); if (clip.displayName == originalRecordedAsset.clip.name && newClip.recordable) { clonedAnimationAsset.name = clonedAnimationAsset.clip.name; newClip.displayName = clonedAnimationAsset.name; } } } } return(newClip); }
private static void WriteMatchFields(AnimationPlayableAsset asset, TimelineAnimationUtilities.RigidTransform result, MatchTargetFields fields) { Vector3 position = asset.position; position.x = ((!fields.HasAny(MatchTargetFields.PositionX)) ? position.x : result.position.x); position.y = ((!fields.HasAny(MatchTargetFields.PositionY)) ? position.y : result.position.y); position.z = ((!fields.HasAny(MatchTargetFields.PositionZ)) ? position.z : result.position.z); asset.position = position; if (fields.HasAny(MatchTargetFieldConstants.Rotation)) { Vector3 eulerAngles = asset.rotation.get_eulerAngles(); Vector3 eulerAngles2 = result.rotation.get_eulerAngles(); eulerAngles.x = ((!fields.HasAny(MatchTargetFields.RotationX)) ? eulerAngles.x : eulerAngles2.x); eulerAngles.y = ((!fields.HasAny(MatchTargetFields.RotationY)) ? eulerAngles.y : eulerAngles2.y); eulerAngles.z = ((!fields.HasAny(MatchTargetFields.RotationZ)) ? eulerAngles.z : eulerAngles2.z); asset.rotation = Quaternion.Euler(eulerAngles); } }
public static void MatchPrevious(TimelineClip currentClip, Transform matchPoint, PlayableDirector director) { MatchTargetFields matchFields = TimelineAnimationUtilities.GetMatchFields(currentClip); if (matchFields != MatchTargetFieldConstants.None && !(matchPoint == null)) { double time = director.get_time(); TimelineClip previousClip = TimelineAnimationUtilities.GetPreviousClip(currentClip); if (previousClip != null && currentClip != previousClip) { AnimationTrack animationTrack = currentClip.parentTrack as AnimationTrack; double blendInDuration = currentClip.blendInDuration; currentClip.blendInDuration = 0.0; double blendOutDuration = previousClip.blendOutDuration; previousClip.blendOutDuration = 0.0; director.Stop(); animationTrack.RemoveClip(currentClip); director.Play(); double num = (currentClip.start <= previousClip.end) ? currentClip.start : previousClip.end; director.set_time(num - 1E-05); director.Evaluate(); Vector3 position = matchPoint.get_position(); Quaternion rotation = matchPoint.get_rotation(); director.Stop(); animationTrack.AddClip(currentClip); animationTrack.RemoveClip(previousClip); director.Play(); director.set_time(currentClip.start + 1E-05); director.Evaluate(); AnimationPlayableAsset asset = currentClip.asset as AnimationPlayableAsset; TimelineAnimationUtilities.RigidTransform result = TimelineAnimationUtilities.UpdateClipOffsets(asset, animationTrack, matchPoint, position, rotation); TimelineAnimationUtilities.WriteMatchFields(asset, result, matchFields); currentClip.blendInDuration = blendInDuration; previousClip.blendOutDuration = blendOutDuration; director.Stop(); animationTrack.AddClip(previousClip); director.Play(); director.set_time(time); director.Evaluate(); } } }
public static void ComputeClipWorldSpaceOffset(PlayableDirector director, TimelineClip clip, out Vector3 clipPositionOffset, out Quaternion clipRotationOffset) { GameObject sceneGameObject = TimelineUtility.GetSceneGameObject(director, clip.parentTrack); double time = director.get_time(); TrackAsset parentTrack = clip.parentTrack; TimelineClip[] clips = parentTrack.clips; director.Stop(); for (int i = 0; i < clips.Length; i++) { parentTrack.RemoveClip(clips[i]); } parentTrack.AddClip(clip); double start = clip.start; double blendInDuration = clip.blendInDuration; clip.blendInDuration = 0.0; clip.start = 1.0; director.Play(); director.set_time(0.0); director.Evaluate(); clipPositionOffset = sceneGameObject.get_transform().get_position(); clipRotationOffset = sceneGameObject.get_transform().get_rotation(); AnimationPlayableAsset animationPlayableAsset = clip.asset as AnimationPlayableAsset; if (!(animationPlayableAsset == null)) { clipPositionOffset += clipRotationOffset * animationPlayableAsset.position; clipRotationOffset *= animationPlayableAsset.rotation; director.Stop(); clip.start = start; clip.blendInDuration = blendInDuration; parentTrack.RemoveClip(clip); for (int j = 0; j < clips.Length; j++) { parentTrack.AddClip(clips[j]); } director.Play(); director.set_time(time); director.Evaluate(); } }
private static MatchTargetFields GetMatchFields(TimelineClip clip) { AnimationTrack animationTrack = clip.parentTrack as AnimationTrack; MatchTargetFields result; if (animationTrack == null) { result = MatchTargetFieldConstants.None; } else { AnimationPlayableAsset animationPlayableAsset = clip.asset as AnimationPlayableAsset; MatchTargetFields matchTargetFields = animationTrack.matchTargetFields; if (animationPlayableAsset != null && animationPlayableAsset.useTrackMatchFields) { matchTargetFields = animationPlayableAsset.matchTargetFields; } result = matchTargetFields; } return(result); }
internal static AnimationClip FindRecordingAnimationClipAtTime(this TrackAsset trackAsset, double time) { AnimationClip result; if (trackAsset == null) { result = null; } else { AnimationTrack animationTrack = trackAsset as AnimationTrack; if (animationTrack != null && !animationTrack.inClipMode) { result = animationTrack.animClip; } else { TimelineClip timelineClip = trackAsset.FindRecordingClipAtTime(time); if (timelineClip != null) { AnimationPlayableAsset animationPlayableAsset = timelineClip.asset as AnimationPlayableAsset; if (animationPlayableAsset != null) { result = animationPlayableAsset.clip; } else { AnimatedParameterExtensions.CreateCurvesIfRequired(timelineClip, null); result = timelineClip.curves; } } else { result = null; } } } return(result); }
public static TimelineAnimationUtilities.RigidTransform UpdateClipOffsets(AnimationPlayableAsset asset, AnimationTrack track, Transform transform, Vector3 globalPosition, Quaternion globalRotation) { Matrix4x4 worldToLocalMatrix = transform.get_worldToLocalMatrix(); Matrix4x4 matrix4x = Matrix4x4.TRS(asset.position, asset.rotation, Vector3.get_one()); Matrix4x4 matrix4x2 = Matrix4x4.TRS(track.position, track.rotation, Vector3.get_one()); if (transform.get_parent() != null) { matrix4x2 = transform.get_parent().get_localToWorldMatrix() * matrix4x2; } Vector3 position = transform.get_position(); Quaternion rotation = transform.get_rotation(); transform.set_position(globalPosition); transform.set_rotation(globalRotation); Matrix4x4 localToWorldMatrix = transform.get_localToWorldMatrix(); transform.set_position(position); transform.set_rotation(rotation); Matrix4x4 matrix4x3 = matrix4x2.get_inverse() * localToWorldMatrix * worldToLocalMatrix * matrix4x2 * matrix4x; return(TimelineAnimationUtilities.RigidTransform.Compose(matrix4x3.GetColumn(3), MathUtils.QuaternionFromMatrix(matrix4x3))); }
static void WriteMatchFields(AnimationPlayableAsset asset, RigidTransform result, MatchTargetFields fields) { Vector3 position = asset.position; position.x = fields.HasAny(MatchTargetFields.PositionX) ? result.position.x : position.x; position.y = fields.HasAny(MatchTargetFields.PositionY) ? result.position.y : position.y; position.z = fields.HasAny(MatchTargetFields.PositionZ) ? result.position.z : position.z; asset.position = position; // check first to avoid unnecessary conversion errors if (fields.HasAny(MatchTargetFieldConstants.Rotation)) { Vector3 eulers = asset.eulerAngles; Vector3 resultEulers = result.rotation.eulerAngles; eulers.x = fields.HasAny(MatchTargetFields.RotationX) ? resultEulers.x : eulers.x; eulers.y = fields.HasAny(MatchTargetFields.RotationY) ? resultEulers.y : eulers.y; eulers.z = fields.HasAny(MatchTargetFields.RotationZ) ? resultEulers.z : eulers.z; asset.eulerAngles = AnimationUtility.GetClosestEuler(Quaternion.Euler(eulers), asset.eulerAngles, RotationOrder.OrderZXY); } }
// Given a world space position and rotation, updates the clip offsets to match that public static RigidTransform UpdateClipOffsets(AnimationPlayableAsset asset, AnimationTrack track, Transform transform, Vector3 globalPosition, Quaternion globalRotation) { Matrix4x4 worldToLocal = transform.worldToLocalMatrix; Matrix4x4 clipMatrix = Matrix4x4.TRS(asset.position, asset.rotation, Vector3.one); Matrix4x4 trackMatrix = GetTrackMatrix(transform, track); // Use the transform to find the proper goal matrix with scale taken into account var oldPos = transform.position; var oldRot = transform.rotation; transform.position = globalPosition; transform.rotation = globalRotation; Matrix4x4 goal = transform.localToWorldMatrix; transform.position = oldPos; transform.rotation = oldRot; // compute the new clip matrix. Matrix4x4 newClip = trackMatrix.inverse * goal * worldToLocal * trackMatrix * clipMatrix; return(RigidTransform.Compose(newClip.GetColumn(3), MathUtils.QuaternionFromMatrix(newClip))); }
void DoManipulators() { if (m_EditorClip == null || m_EditorClip.clip == null) { return; } AnimationPlayableAsset animationPlayable = m_EditorClip.clip.asset as AnimationPlayableAsset; AnimationTrack track = m_EditorClip.clip.parentTrack as AnimationTrack; Transform transform = GetTransform(); if (transform != null && animationPlayable != null && m_OffsetEditMode != TimelineAnimationUtilities.OffsetEditMode.None && track != null) { UndoExtensions.RegisterPlayableAsset(animationPlayable, "Inspector"); Vector3 position = transform.position; Quaternion rotation = transform.rotation; EditorGUI.BeginChangeCheck(); if (m_OffsetEditMode == TimelineAnimationUtilities.OffsetEditMode.Translation) { position = Handles.PositionHandle(position, Tools.pivotRotation == PivotRotation.Global ? Quaternion.identity : rotation); } else if (m_OffsetEditMode == TimelineAnimationUtilities.OffsetEditMode.Rotation) { rotation = Handles.RotationHandle(rotation, position); } if (EditorGUI.EndChangeCheck()) { var res = TimelineAnimationUtilities.UpdateClipOffsets(animationPlayable, track, transform, position, rotation); animationPlayable.position = res.position; animationPlayable.eulerAngles = AnimationUtility.GetClosestEuler(res.rotation, animationPlayable.eulerAngles, RotationOrder.OrderZXY); Reevaluate(); Repaint(); } } }
public static void ConvertFromClipMode(this AnimationTrack track, TimelineAsset timeline) { if (track.CanConvertFromClipMode()) { TimelineUndo.PushUndo(track, "Convert From Clip"); TimelineClip timelineClip = track.clips[0]; float time = (float)timelineClip.start; track.openClipTimeOffset = 0.0; track.openClipPreExtrapolation = timelineClip.preExtrapolationMode; track.openClipPostExtrapolation = timelineClip.postExtrapolationMode; AnimationPlayableAsset animationPlayableAsset = timelineClip.asset as AnimationPlayableAsset; if (animationPlayableAsset) { track.openClipOffsetPosition = animationPlayableAsset.position; track.openClipOffsetRotation = animationPlayableAsset.rotation; } AnimationClip animationClip = timelineClip.animationClip; float num = (float)timelineClip.timeScale; if (!Mathf.Approximately(num, 1f)) { if (!Mathf.Approximately(num, 0f)) { num = 1f / num; } animationClip.ScaleTime(num); } TimelineUndo.PushUndo(animationClip, "Convert From Clip"); animationClip.ShiftBySeconds(time); Object asset = timelineClip.asset; timelineClip.asset = null; ClipModifier.Delete(timeline, timelineClip); TimelineUndo.PushDestroyUndo(null, track, asset, "Convert From Clip"); track.animClip = animationClip; EditorUtility.SetDirty(track); } }
// 导出AnimationTrack private int ExportAnimationTrack(AnimationTrack animationTrack, JSONObject trackListArr, JSONObject clipListArr) { JSONObject trackJSON = GenerateBaseTrack(animationTrack, PlaybaleTrackTypeMap["AnimationTrack"]); trackJSON.AddField("applyAvatarMask", animationTrack.applyAvatarMask); JSONObject infiniteClipOffsetPositionArr = new JSONObject(JSONObject.Type.ARRAY); JSONObject infiniteClipOffsetRotationArr = new JSONObject(JSONObject.Type.ARRAY); trackJSON.AddField("infiniteClipOffsetPosition", infiniteClipOffsetPositionArr); trackJSON.AddField("infiniteClipOffsetRotation", infiniteClipOffsetRotationArr); #if UNITY_2018_3_OR_NEWER trackJSON.AddField("trackOffset", TrackOffsetMap[animationTrack.trackOffset]); #else if (animationTrack.applyOffsets) { trackJSON.AddField("trackOffset", TrackOffsetMap["ApplyTransformOffsets"]); } else { trackJSON.AddField("trackOffset", TrackOffsetMap["Auto"]); } #endif #if UNITY_2019_1_OR_NEWER infiniteClipOffsetPositionArr.Add(-animationTrack.infiniteClipOffsetPosition.x); infiniteClipOffsetPositionArr.Add(animationTrack.infiniteClipOffsetPosition.y); infiniteClipOffsetPositionArr.Add(animationTrack.infiniteClipOffsetPosition.z); infiniteClipOffsetRotationArr.Add(-animationTrack.infiniteClipOffsetRotation.x); infiniteClipOffsetRotationArr.Add(animationTrack.infiniteClipOffsetRotation.y); infiniteClipOffsetRotationArr.Add(animationTrack.infiniteClipOffsetRotation.z); infiniteClipOffsetRotationArr.Add(-animationTrack.infiniteClipOffsetRotation.w); #else infiniteClipOffsetPositionArr.Add(-animationTrack.openClipOffsetPosition.x); infiniteClipOffsetPositionArr.Add(animationTrack.openClipOffsetPosition.y); infiniteClipOffsetPositionArr.Add(animationTrack.openClipOffsetPosition.z); infiniteClipOffsetRotationArr.Add(-animationTrack.openClipOffsetRotation.x); infiniteClipOffsetRotationArr.Add(animationTrack.openClipOffsetRotation.y); infiniteClipOffsetRotationArr.Add(animationTrack.openClipOffsetRotation.z); infiniteClipOffsetRotationArr.Add(-animationTrack.openClipOffsetRotation.w); #endif if (animationTrack.avatarMask != null) { WXAvatarMask mask = new WXAvatarMask(animationTrack.avatarMask); string uid = AddDependencies(mask); trackJSON.AddField("avatarMask", uid); } else { trackJSON.AddField("avatarMask", new JSONObject(JSONObject.Type.NULL)); } JSONObject positionArr = new JSONObject(JSONObject.Type.ARRAY); positionArr.Add(-animationTrack.position.x); positionArr.Add(animationTrack.position.y); positionArr.Add(animationTrack.position.z); trackJSON.AddField("position", positionArr); JSONObject rotationArr = new JSONObject(JSONObject.Type.ARRAY); rotationArr.Add(-animationTrack.rotation.x); rotationArr.Add(animationTrack.rotation.y); rotationArr.Add(animationTrack.rotation.z); rotationArr.Add(-animationTrack.rotation.w); trackJSON.AddField("rotation", rotationArr); JSONObject matchTargetFieldsJSON = new JSONObject(JSONObject.Type.OBJECT); trackJSON.AddField("matchTargetFields", matchTargetFieldsJSON); matchTargetFieldsJSON.AddField("PositionX", (animationTrack.matchTargetFields & MatchTargetFields.PositionX) == MatchTargetFields.PositionX); matchTargetFieldsJSON.AddField("PositionY", (animationTrack.matchTargetFields & MatchTargetFields.PositionY) == MatchTargetFields.PositionY); matchTargetFieldsJSON.AddField("PositionZ", (animationTrack.matchTargetFields & MatchTargetFields.PositionZ) == MatchTargetFields.PositionZ); matchTargetFieldsJSON.AddField("RotationX", (animationTrack.matchTargetFields & MatchTargetFields.RotationX) == MatchTargetFields.RotationX); matchTargetFieldsJSON.AddField("RotationY", (animationTrack.matchTargetFields & MatchTargetFields.RotationY) == MatchTargetFields.RotationY); matchTargetFieldsJSON.AddField("RotationZ", (animationTrack.matchTargetFields & MatchTargetFields.RotationZ) == MatchTargetFields.RotationZ); UnityEditor.SerializedObject serializedObject = new UnityEditor.SerializedObject(animationTrack); UnityEditor.SerializedProperty serializedClip = serializedObject.FindProperty("m_Clips"); JSONObject clipsIndexArr = trackJSON.GetField("clips"); if (animationTrack.inClipMode) // 普通clip // 貌似有时候序列化的m_Clips顺序跟 timelineClipList 的顺序对不上,但是很难复现。没有找到顺序可以必定对上的方法,先这样吧 { IEnumerable <TimelineClip> timelineClipList = animationTrack.GetClips(); int num = 0; foreach (TimelineClip timelineClip in timelineClipList) { JSONObject clipJSON = GenerateBaseTimelineClip(timelineClip, PlaybaleClipTypeMap["Animation"]); JSONObject clipData = new JSONObject(JSONObject.Type.OBJECT); float m_PostExtrapolationTime = (float)serializedClip.FindPropertyRelative("Array.data[" + num + "].m_PostExtrapolationTime").doubleValue; float m_PreExtrapolationTime = (float)serializedClip.FindPropertyRelative("Array.data[" + num + "].m_PreExtrapolationTime").doubleValue; clipJSON.SetField("postExtrapolationTime", m_PostExtrapolationTime); clipJSON.SetField("preExtrapolationTime", m_PreExtrapolationTime); clipJSON.AddField("data", clipData); bool m_Recordable = serializedClip.FindPropertyRelative("Array.data[" + num + "].m_Recordable").boolValue; clipData.AddField("recordable", m_Recordable); string clipPath = ExportAnimationClip(timelineClip.animationClip); if (string.IsNullOrEmpty(clipPath)) { clipData.AddField("clip", JSONObject.nullJO); } else { clipData.AddField("clip", clipPath); } AnimationPlayableAsset asset = (AnimationPlayableAsset)timelineClip.asset; // clipData.AddField("clipCaps", ClipCapsMap.ContainsKey(timelineClip.clipCaps) ? ClipCapsMap[timelineClip.clipCaps] : ClipCapsMap[ClipCaps.None]); // clipData.AddField("duration", (float)asset.duration); #if UNITY_2018_3_OR_NEWER // 2018_3才开始支持 clipData.AddField("applyFootIK", asset.applyFootIK); #else clipData.AddField("applyFootIK", false); #endif #if UNITY_2019_1_OR_NEWER // 2019_1才开始支持 clipData.AddField("loop", LoopModeMap[asset.loop]); #else clipData.AddField("loop", LoopModeMap["UseSourceAsset"]); #endif clipData.AddField("useTrackMatchFields", asset.useTrackMatchFields); JSONObject clipMatchTargetFieldsJSON = new JSONObject(JSONObject.Type.OBJECT); clipData.AddField("matchTargetFields", clipMatchTargetFieldsJSON); clipMatchTargetFieldsJSON.AddField("PositionX", (asset.matchTargetFields & MatchTargetFields.PositionX) == MatchTargetFields.PositionX); clipMatchTargetFieldsJSON.AddField("PositionY", (asset.matchTargetFields & MatchTargetFields.PositionY) == MatchTargetFields.PositionY); clipMatchTargetFieldsJSON.AddField("PositionZ", (asset.matchTargetFields & MatchTargetFields.PositionZ) == MatchTargetFields.PositionZ); clipMatchTargetFieldsJSON.AddField("RotationX", (asset.matchTargetFields & MatchTargetFields.RotationX) == MatchTargetFields.RotationX); clipMatchTargetFieldsJSON.AddField("RotationY", (asset.matchTargetFields & MatchTargetFields.RotationY) == MatchTargetFields.RotationY); clipMatchTargetFieldsJSON.AddField("RotationZ", (asset.matchTargetFields & MatchTargetFields.RotationZ) == MatchTargetFields.RotationZ); JSONObject clipPositionArr = new JSONObject(JSONObject.Type.ARRAY); clipPositionArr.Add(-asset.position.x); clipPositionArr.Add(asset.position.y); clipPositionArr.Add(asset.position.z); clipData.AddField("position", clipPositionArr); JSONObject clipRotationArr = new JSONObject(JSONObject.Type.ARRAY); clipRotationArr.Add(-asset.rotation.x); clipRotationArr.Add(asset.rotation.y); clipRotationArr.Add(asset.rotation.z); clipRotationArr.Add(-asset.rotation.w); clipData.AddField("rotation", clipRotationArr); clipsIndexArr.Add(ExportTimelineClip(clipJSON, clipListArr)); num++; } } else // infiniteClip { #if UNITY_2019_1_OR_NEWER // 2019_1才开始支持 AnimationClip infiniteClip = animationTrack.infiniteClip; #else // 序列化取出私有变量 UnityEditor.SerializedObject trackSerializedObject = new UnityEditor.SerializedObject(animationTrack); UnityEditor.SerializedProperty animClipSerialize = trackSerializedObject.FindProperty("m_AnimClip"); AnimationClip infiniteClip = animClipSerialize.objectReferenceValue as AnimationClip; #endif string infinityClipPath = ExportAnimationClip(infiniteClip); if (string.IsNullOrEmpty(infinityClipPath)) { trackJSON.SetField("infinityClip", JSONObject.nullJO); } else { trackJSON.SetField("infinityClip", infinityClipPath); } } // 导出子track JSONObject childrenJSON = trackJSON.GetField("children"); IEnumerable <TrackAsset> childTrackAssetList = animationTrack.GetChildTracks(); List <int> indexList = ExportTrackList(childTrackAssetList, trackListArr, clipListArr); foreach (int index in indexList) { childrenJSON.Add(index); } return(ExportTrack(trackJSON, trackListArr)); }