public void FinializeTrack(TrackAsset track, WindowState state) { // make sure we dirty the clip if we are in non clip mode var animTrack = track as AnimationTrack; if (!animTrack.inClipMode) { EditorUtility.SetDirty(animTrack.GetOrCreateClip()); } // in clip mode we need to do some extra work if (recordClip != null) { // stretch the clip out to meet the new recording time if (m_ClipTime > recordClip.duration) { UndoExtensions.RegisterTrack(track, "Add Key"); recordClip.duration = m_ClipTime; } track.CalculateExtrapolationTimes(); } recordClip = null; m_ClipTime = 0; if (m_needRebuildRects) { state.CalculateRowRects(); m_needRebuildRects = false; } }
public static bool Tile(IEnumerable <TimelineClip> clips) { if (clips.Count() < 2) { return(false); } var clipsByTracks = clips.GroupBy(x => x.GetParentTrack()) .Select(track => new { track.Key, Items = track.OrderBy(c => c.start) }); foreach (var track in clipsByTracks) { UndoExtensions.RegisterTrack(track.Key, L10n.Tr("Tile")); } foreach (var track in clipsByTracks) { double newStart = track.Items.First().start; foreach (var c in track.Items) { c.start = newStart; newStart += c.duration; } } return(true); }
public void Drop() { if (IsValidDrop()) { foreach (var grabbedItems in movingItems) { var track = grabbedItems.targetTrack; UndoExtensions.RegisterTrack(track, L10n.Tr("Move Items")); if (EditModeUtils.IsInfiniteTrack(track) && grabbedItems.clips.Any()) { ((AnimationTrack)track).ConvertToClipMode(); } } EditMode.FinishMove(); Done(); } else { Cancel(); } EditMode.ClearEditMode(); }
internal static void ConvertFromClipMode(this AnimationTrack track, TimelineAsset timeline) { if (!track.CanConvertFromClipMode()) { return; } UndoExtensions.RegisterTrack(track, L10n.Tr("Convert From Clip")); var clip = track.clips[0]; var delta = (float)clip.start; track.infiniteClipTimeOffset = 0.0f; track.infiniteClipPreExtrapolation = clip.preExtrapolationMode; track.infiniteClipPostExtrapolation = clip.postExtrapolationMode; var animAsset = clip.asset as AnimationPlayableAsset; if (animAsset) { track.infiniteClipOffsetPosition = animAsset.position; track.infiniteClipOffsetEulerAngles = animAsset.eulerAngles; track.infiniteClipRemoveOffset = animAsset.removeStartOffset; track.infiniteClipApplyFootIK = animAsset.applyFootIK; track.infiniteClipLoop = animAsset.loop; } // clone it, it may not be in the same asset var animClip = clip.animationClip; float scale = (float)clip.timeScale; if (!Mathf.Approximately(scale, 1.0f)) { if (!Mathf.Approximately(scale, 0.0f)) { scale = 1.0f / scale; } animClip.ScaleTime(scale); } TimelineUndo.PushUndo(animClip, L10n.Tr("Convert From Clip")); animClip.ShiftBySeconds(delta); // manually delete the clip var asset = clip.asset; clip.asset = null; // Remove the clip, remove old assets ClipModifier.Delete(timeline, clip); TimelineUndo.PushDestroyUndo(null, track, asset); track.infiniteClip = animClip; EditorUtility.SetDirty(track); }
static void AddMarkerToParent(ScriptableObject marker, TrackAsset parent) { TimelineCreateUtilities.SaveAssetIntoObject(marker, parent); TimelineUndo.RegisterCreatedObjectUndo(marker, L10n.Tr("Duplicate Marker")); UndoExtensions.RegisterTrack(parent, L10n.Tr("Duplicate Marker")); if (parent != null) { parent.AddMarker(marker); ((IMarker)marker).Initialize(parent); } }
internal static void ConvertToClipMode(this AnimationTrack track) { if (!track.CanConvertToClipMode()) { return; } UndoExtensions.RegisterTrack(track, L10n.Tr("Convert To Clip")); if (!track.infiniteClip.empty) { var animClip = track.infiniteClip; TimelineUndo.PushUndo(animClip, L10n.Tr("Convert To Clip")); UndoExtensions.RegisterTrack(track, L10n.Tr("Convert To Clip")); var start = AnimationClipCurveCache.Instance.GetCurveInfo(animClip).keyTimes.FirstOrDefault(); animClip.ShiftBySeconds(-start); track.infiniteClip = null; var clip = track.CreateClip(animClip); clip.start = start; clip.preExtrapolationMode = track.infiniteClipPreExtrapolation; clip.postExtrapolationMode = track.infiniteClipPostExtrapolation; clip.recordable = true; if (Mathf.Abs(animClip.length) < TimelineClip.kMinDuration) { clip.duration = 1; } var animationAsset = clip.asset as AnimationPlayableAsset; if (animationAsset) { animationAsset.position = track.infiniteClipOffsetPosition; animationAsset.eulerAngles = track.infiniteClipOffsetEulerAngles; // going to / from infinite mode should reset this. infinite mode animationAsset.removeStartOffset = track.infiniteClipRemoveOffset; animationAsset.applyFootIK = track.infiniteClipApplyFootIK; animationAsset.loop = track.infiniteClipLoop; track.infiniteClipOffsetPosition = Vector3.zero; track.infiniteClipOffsetEulerAngles = Vector3.zero; } track.CalculateExtrapolationTimes(); } track.infiniteClip = null; EditorUtility.SetDirty(track); }
public static void BeginTrim(ITimelineItem item, TrimEdge trimDirection) { var itemToTrim = item as ITrimmable; if (itemToTrim == null) { return; } s_CurrentTrimItem = itemToTrim; s_CurrentTrimDirection = trimDirection; trimMode.OnBeforeTrim(itemToTrim, trimDirection); UndoExtensions.RegisterTrack(itemToTrim.parentTrack, L10n.Tr("Trim Clip")); }
private void ConvertToRecordableClip(AnimationTrack track) { if (track == null || !track.hasClips) { return; } UndoExtensions.RegisterTrack(track, L10n.Tr("ConvertToRecordableClip")); var clip = track.GetClips().First(); var delta = (float)clip.start; var duration = clip.duration; var animationAsset = clip.asset as AnimationPlayableAsset; if (animationAsset == null) { return; } var animationClipSource = animationAsset.clip; var animationName = animationClipSource.name; foreach (var c in track.GetClips()) { track.DeleteClip(c); } var recordableClip = track.CreateRecordableClip(animationName); recordableClip.start = delta; recordableClip.duration = duration; var newAnimationClip = (recordableClip.asset as AnimationPlayableAsset).clip; newAnimationClip.name = animationName; var setting = AnimationUtility.GetAnimationClipSettings(animationClipSource); AnimationUtility.SetAnimationClipSettings(newAnimationClip, setting); newAnimationClip.frameRate = animationClipSource.frameRate; EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(animationClipSource); for (int i = 0; i < curveBindings.Length; i++) { AnimationUtility.SetEditorCurve(newAnimationClip, curveBindings[i], AnimationUtility.GetEditorCurve(animationClipSource, curveBindings[i])); } EditorUtility.SetDirty(track); }
// Special method to remove a track that is in a broken state. i.e. the script won't load internal static bool RemoveBrokenTrack(PlayableAsset parent, ScriptableObject track) { var parentTrack = parent as TrackAsset; var parentTimeline = parent as TimelineAsset; if (parentTrack == null && parentTimeline == null) { throw new ArgumentException("parent is not a valid parent type", "parent"); } // this object must be a Unity null, but not actually null; object trackAsObject = track; if (trackAsObject == null || track as TrackAsset != null) // yes, this is correct { throw new ArgumentException("track is not in a broken state"); } // this belongs to a parent track if (parentTrack != null) { int index = parentTrack.subTracksObjects.FindIndex(t => t.GetInstanceID() == track.GetInstanceID()); if (index >= 0) { UndoExtensions.RegisterTrack(parentTrack, L10n.Tr("Remove Track")); parentTrack.subTracksObjects.RemoveAt(index); parentTrack.Invalidate(); Undo.DestroyObjectImmediate(track); return(true); } } else if (parentTimeline != null) { int index = parentTimeline.trackObjects.FindIndex(t => t.GetInstanceID() == track.GetInstanceID()); if (index >= 0) { UndoExtensions.RegisterPlayableAsset(parentTimeline, L10n.Tr("Remove Track")); parentTimeline.trackObjects.RemoveAt(index); parentTimeline.Invalidate(); Undo.DestroyObjectImmediate(track); return(true); } } return(false); }
void DoOffsetManipulator() { if (targets.Length > 1) //do not edit the track offset on a multiple selection { return; } if (timelineWindow == null || timelineWindow.state == null || timelineWindow.state.editSequence.director == null) { return; } AnimationTrack animationTrack = target as AnimationTrack; if (animationTrack != null && (animationTrack.trackOffset == TrackOffset.ApplyTransformOffsets) && m_OffsetEditMode != TimelineAnimationUtilities.OffsetEditMode.None) { var boundObject = TimelineUtility.GetSceneGameObject(timelineWindow.state.editSequence.director, animationTrack); var boundObjectTransform = boundObject != null ? boundObject.transform : null; var offsets = TimelineAnimationUtilities.GetTrackOffsets(animationTrack, boundObjectTransform); EditorGUI.BeginChangeCheck(); switch (m_OffsetEditMode) { case TimelineAnimationUtilities.OffsetEditMode.Translation: offsets.position = Handles.PositionHandle(offsets.position, (Tools.pivotRotation == PivotRotation.Global) ? Quaternion.identity : offsets.rotation); break; case TimelineAnimationUtilities.OffsetEditMode.Rotation: offsets.rotation = Handles.RotationHandle(offsets.rotation, offsets.position); break; } if (EditorGUI.EndChangeCheck()) { UndoExtensions.RegisterTrack(animationTrack, L10n.Tr("Inspector")); TimelineAnimationUtilities.UpdateTrackOffset(animationTrack, boundObjectTransform, offsets); Evaluate(); Repaint(); } } }
public void HandleTrackSwitch(IEnumerable <ItemsPerTrack> itemsGroups) { foreach (var itemsGroup in itemsGroups) { var targetTrack = itemsGroup.targetTrack; if (targetTrack != null && itemsGroup.items.Any()) { var compatible = itemsGroup.items.First().IsCompatibleWithTrack(targetTrack) && !EditModeUtils.IsInfiniteTrack(targetTrack); var track = compatible ? targetTrack : null; UndoExtensions.RegisterTrack(track, L10n.Tr("Move Items")); EditModeUtils.SetParentTrack(itemsGroup.items, track); } else { EditModeUtils.SetParentTrack(itemsGroup.items, null); } } }
public AnimationClip PrepareTrack(TrackAsset track, WindowState state, GameObject gameObject, out double startTime) { AnimationClip animationClip = null; // if we are not in clip mode, we simply use the track clip var animationTrack = (AnimationTrack)track; // ignore recording if we are in Legacy auto mode startTime = -1; var parentTrack = TimelineUtility.GetSceneReferenceTrack(track) as AnimationTrack; if (parentTrack != null && parentTrack.trackOffset == TrackOffset.Auto) { return(null); } if (!animationTrack.inClipMode) { var trackClip = animationTrack.GetOrCreateClip(); startTime = trackClip.frameRate * state.editSequence.time; // Make the first key be at time 0 of the clip if (trackClip.empty) { animationTrack.infiniteClipTimeOffset = 0; // state.time; animationTrack.infiniteClipPreExtrapolation = TimelineClip.ClipExtrapolation.Hold; animationTrack.infiniteClipPostExtrapolation = TimelineClip.ClipExtrapolation.Hold; } animationClip = trackClip; } else { TimelineClip activeClip = null; // if it fails, but returns no clip, we can add one. if (!track.FindRecordingClipAtTime(state.editSequence.time, out activeClip) && activeClip != null) { return(null); } if (activeClip == null) { activeClip = AddRecordableClip(track, state, state.editSequence.time); } var clip = activeClip.animationClip; // flags this as the clip being recorded for the track var clipTime = state.editSequence.time - activeClip.start; // if we are in the past if (clipTime < 0) { Undo.RegisterCompleteObjectUndo(clip, "Record Key"); UndoExtensions.RegisterTrack(track, "Prepend Key"); ShiftAnimationClip(clip, (float)-clipTime); activeClip.start = state.editSequence.time; activeClip.duration += -clipTime; clipTime = 0; } m_ClipTime = clipTime; recordClip = activeClip; startTime = recordClip.ToLocalTimeUnbound(state.editSequence.time) * clip.frameRate; m_needRebuildRects = clip.empty; animationClip = clip; } m_TargetClip = animationClip; m_CurveCount = GetCurveCount(animationClip); m_TrackHasPreviewComponents = animationTrack.hasPreviewComponents; return(animationClip); }