public static string GetTrackMenuName(System.Type trackType) { return(L10n.Tr(TypeUtility.GetDisplayName(trackType))); }
internal static void SetShowTrackMarkers(this TrackAsset track, bool showMarkers) { var currentValue = track.GetShowMarkers(); if (currentValue != showMarkers) { TimelineUndo.PushUndo(TimelineWindow.instance.state.editSequence.viewModel, L10n.Tr("Toggle Show Markers")); track.SetShowMarkers(showMarkers); if (!showMarkers) { foreach (var marker in track.GetMarkers()) { SelectionManager.Remove(marker); } } } }
internal static void AddTimeAreaMenuItems(GenericMenu menu, WindowState state) { foreach (var value in Enum.GetValues(typeof(TimelineAsset.DurationMode))) { var mode = (TimelineAsset.DurationMode)value; var item = EditorGUIUtility.TextContent(string.Format(TimelineWindow.Styles.DurationModeText, L10n.Tr(ObjectNames.NicifyVariableName(mode.ToString())))); if (state.recording || state.IsEditingASubTimeline() || state.editSequence.asset == null || state.editSequence.isReadOnly) { menu.AddDisabledItem(item); } else { menu.AddItem(item, state.editSequence.asset.durationMode == mode, () => SelectDurationCallback(state, mode)); } menu.AddItem(DirectorStyles.showMarkersOnTimeline, state.showMarkerHeader, () => new ToggleShowMarkersOnTimeline().Execute(state)); } }
internal static TrackAsset Duplicate(this TrackAsset track, IExposedPropertyTable sourceTable, IExposedPropertyTable destTable, TimelineAsset destinationTimeline = null) { if (track == null) { return(null); } // if the destination is us, clear to avoid bad parenting (case 919421) if (destinationTimeline == track.timelineAsset) { destinationTimeline = null; } var timelineParent = track.parent as TimelineAsset; var trackParent = track.parent as TrackAsset; if (timelineParent == null && trackParent == null) { Debug.LogWarning("Cannot duplicate track because it is not parented to known type"); return(null); } // Determine who the final parent is. If we are pasting into another track, it's always the timeline. // Otherwise it's the original parent PlayableAsset finalParent = destinationTimeline != null ? destinationTimeline : track.parent; // grab the list of tracks to generate a name from (923360) to get the list of names // no need to do this part recursively var finalTrackParent = finalParent as TrackAsset; var finalTimelineAsset = finalParent as TimelineAsset; var otherTracks = (finalTimelineAsset != null) ? finalTimelineAsset.trackObjects : finalTrackParent.subTracksObjects; // Important to create the new objects before pushing the original undo, or redo breaks the // sequence var newTrack = TimelineHelpers.Clone(finalParent, track, sourceTable, destTable, finalParent); newTrack.name = TimelineCreateUtilities.GenerateUniqueActorName(otherTracks, newTrack.name); RecursiveSubtrackClone(track, newTrack, sourceTable, destTable, finalParent); TimelineCreateUtilities.SaveAssetIntoObject(newTrack, finalParent); TimelineUndo.RegisterCreatedObjectUndo(newTrack, L10n.Tr("Duplicate")); UndoExtensions.RegisterPlayableAsset(finalParent, L10n.Tr("Duplicate")); if (destinationTimeline != null) // other timeline { destinationTimeline.AddTrackInternal(newTrack); } else if (timelineParent != null) // this timeline, no parent { ReparentTracks(new List <TrackAsset> { newTrack }, timelineParent, timelineParent.GetRootTracks().Last(), false); } else // this timeline, with parent { trackParent.AddChild(newTrack); } // Call the custom editor. this check prevents the call when copying to the clipboard if (destinationTimeline == null || destinationTimeline == TimelineEditor.inspectedAsset) { var customEditor = CustomTimelineEditorCache.GetTrackEditor(newTrack); customEditor.OnCreate_Safe(newTrack, track); } return(newTrack); }
public override void OnInspectorGUI() { if (target == null) { return; } serializedObject.Update(); m_SourceObjectLabel.text = m_SourceObject.displayName; if (m_PrefabObject.objectReferenceValue != null) { m_SourceObjectLabel.text = L10n.Tr("Parent Object"); } bool selfControlled = false; EditorGUI.BeginChangeCheck(); using (new GUIMixedValueScope(m_SourceObject.hasMultipleDifferentValues)) EditorGUILayout.PropertyField(m_SourceObject, m_SourceObjectLabel); var sourceGameObject = m_SourceObject.exposedReferenceValue as GameObject; selfControlled = m_PrefabObject.objectReferenceValue == null && TimelineWindow.instance != null && TimelineWindow.instance.state != null && contextDirector != null && sourceGameObject == contextDirector.gameObject; if (EditorGUI.EndChangeCheck()) { CheckForCyclicReference(); if (!selfControlled) { DisablePlayOnAwake(sourceGameObject); } } if (selfControlled) { EditorGUILayout.HelpBox(L10n.Tr("The assigned GameObject references the same PlayableDirector component being controlled."), MessageType.Warning); } else if (m_CycleReference) { EditorGUILayout.HelpBox(L10n.Tr("The assigned GameObject contains a PlayableDirector component that results in a circular reference."), MessageType.Warning); } EditorGUI.indentLevel++; EditorGUILayout.PropertyField(m_PrefabObject, Styles.prefabContent); EditorGUI.indentLevel--; using (new EditorGUI.DisabledScope(selfControlled)) { EditorGUILayout.PropertyField(m_UseActivation, selfControlled ? Styles.activationDisabledContent : Styles.activationContent); if (m_UseActivation.boolValue) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(m_PostPlayback, Styles.postPlayableContent); EditorGUI.indentLevel--; } } m_SourceObject.isExpanded = EditorGUILayout.Foldout(m_SourceObject.isExpanded, Styles.advancedContent, true); if (m_SourceObject.isExpanded) { EditorGUI.indentLevel++; using (new EditorGUI.DisabledScope(selfControlled && !m_SearchHierarchy.boolValue)) { EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(m_UpdateDirector, selfControlled ? Styles.updatePlayableDirectorDisabledContent : Styles.updatePlayableDirectorContent); if (EditorGUI.EndChangeCheck()) { CheckForCyclicReference(); } } EditorGUILayout.PropertyField(m_UpdateParticle, Styles.updateParticleSystemsContent); if (m_UpdateParticle.boolValue) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(m_RandomSeed, Styles.randomSeedContent); EditorGUI.indentLevel--; } EditorGUILayout.PropertyField(m_UpdateITimeControl, Styles.updateITimeControlContent); EditorGUILayout.PropertyField(m_SearchHierarchy, Styles.updateHierarchy); EditorGUI.indentLevel--; } serializedObject.ApplyModifiedProperties(); }
void DrawNoSequenceGUI(WindowState windowState) { bool showCreateButton = false; var currentlySelectedGo = UnityEditor.Selection.activeObject != null ? UnityEditor.Selection.activeObject as GameObject : null; var textContent = DirectorStyles.noTimelineAssetSelected; var existingDirector = currentlySelectedGo != null?currentlySelectedGo.GetComponent <PlayableDirector>() : null; var existingAsset = existingDirector != null ? existingDirector.playableAsset : null; if (currentlySelectedGo != null && !TimelineUtility.IsPrefabOrAsset(currentlySelectedGo) && existingAsset == null) { showCreateButton = true; textContent = new GUIContent(String.Format(DirectorStyles.createTimelineOnSelection.text, currentlySelectedGo.name, L10n.Tr("a Director component and a Timeline asset"))); } GUILayout.FlexibleSpace(); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); GUILayout.Label(textContent); if (showCreateButton) { GUILayout.BeginHorizontal(); var textSize = GUI.skin.label.CalcSize(textContent); GUILayout.Space((textSize.x / 2.0f) - (WindowConstants.createButtonWidth / 2.0f)); if (GUILayout.Button(L10n.Tr("Create"), GUILayout.Width(WindowConstants.createButtonWidth))) { var message = DirectorStyles.createNewTimelineText.text + " '" + currentlySelectedGo.name + "'"; var defaultName = currentlySelectedGo.name.EndsWith(DirectorStyles.newTimelineDefaultNameSuffix, StringComparison.OrdinalIgnoreCase) ? currentlySelectedGo.name : currentlySelectedGo.name + DirectorStyles.newTimelineDefaultNameSuffix; // Use the project window path by default only if it's under the asset folder. // Otherwise the saveFilePanel will reject the save (case 1289923) var defaultPath = ProjectWindowUtil.GetActiveFolderPath(); if (!defaultPath.StartsWith("Assets/", StringComparison.OrdinalIgnoreCase)) { defaultPath = "Assets"; } string newSequencePath = EditorUtility.SaveFilePanelInProject(DirectorStyles.createNewTimelineText.text, defaultName, "playable", message, defaultPath); if (!string.IsNullOrEmpty(newSequencePath)) { var newAsset = TimelineUtility.CreateAndSaveTimelineAsset(newSequencePath); Undo.IncrementCurrentGroup(); if (existingDirector == null) { existingDirector = Undo.AddComponent <PlayableDirector>(currentlySelectedGo); } existingDirector.playableAsset = newAsset; SetTimeline(existingDirector); windowState.previewMode = false; } // If we reach this point, the state of the panel has changed; skip the rest of this GUI phase // Fixes: case 955831 - [OSX] NullReferenceException when creating a timeline on a selected object GUIUtility.ExitGUI(); } GUILayout.EndHorizontal(); } GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.FlexibleSpace(); }
public void Grab(IEnumerable <ITimelineItem> items, TrackAsset referenceTrack, Vector2 mousePosition) { if (items == null) { return; } items = items.ToArray(); // Cache enumeration result if (!items.Any()) { return; } m_GrabbedModalUndoGroup = Undo.GetCurrentGroup(); var trackItems = items.GroupBy(c => c.parentTrack).ToArray(); var trackItemsCount = trackItems.Length; var tracks = items.Select(c => c.parentTrack).Where(x => x != null).Distinct(); movingItems = new MovingItems[trackItemsCount]; allowTrackSwitch = trackItemsCount == 1 && !trackItems.SelectMany(x => x).Any(x => x is MarkerItem); // For now, track switch is only supported when all items are on the same track and there are no items // one push per track handles all the clips on the track UndoExtensions.RegisterTracks(tracks, L10n.Tr("Move Items")); foreach (var sourceTrack in tracks) { // push all markers on the track because of ripple UndoExtensions.RegisterMarkers(sourceTrack.GetMarkers(), L10n.Tr("Move Items")); } for (var i = 0; i < trackItemsCount; ++i) { var track = trackItems[i].Key; var grabbedItems = new MovingItems(m_State, track, trackItems[i].ToArray(), referenceTrack, mousePosition, allowTrackSwitch); movingItems[i] = grabbedItems; } m_LeftMostMovingItems = null; m_RightMostMovingItems = null; foreach (var grabbedTrackItems in movingItems) { if (m_LeftMostMovingItems == null || m_LeftMostMovingItems.start > grabbedTrackItems.start) { m_LeftMostMovingItems = grabbedTrackItems; } if (m_RightMostMovingItems == null || m_RightMostMovingItems.end < grabbedTrackItems.end) { m_RightMostMovingItems = grabbedTrackItems; } } m_ItemGUIs = new HashSet <TimelineItemGUI>(); m_ItemsGroup = new ItemsGroup(items); foreach (var item in items) { m_ItemGUIs.Add(item.gui); } targetTrack = referenceTrack; EditMode.BeginMove(this); m_Grabbing = true; }
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, L10n.Tr("Record Key")); UndoExtensions.RegisterTrack(track, L10n.Tr("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); }