diff options
Diffstat (limited to 'Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals')
25 files changed, 1355 insertions, 0 deletions
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalAssetInspector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalAssetInspector.cs new file mode 100644 index 0000000..1c8c6f9 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalAssetInspector.cs @@ -0,0 +1,28 @@ +using JetBrains.Annotations; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline.Signals +{ + [CustomEditor(typeof(SignalAsset))] + class SignalAssetInspector : Editor + { + [MenuItem("Assets/Create/Signal", false, 451)] + [UsedImplicitly] + public static void CreateNewSignal() + { + var icon = EditorGUIUtility.IconContent("SignalAsset Icon").image as Texture2D; + ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, CreateInstance<DoCreateSignalAsset>(), "New Signal.signal", icon, null); + } + + class DoCreateSignalAsset : ProjectWindowCallback.EndNameEditAction + { + public override void Action(int instanceId, string pathName, string resourceFile) + { + var signalAsset = CreateInstance<SignalAsset>(); + AssetDatabase.CreateAsset(signalAsset, pathName); + ProjectWindowUtil.ShowCreatedAsset(signalAsset); + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalAssetInspector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalAssetInspector.cs.meta new file mode 100644 index 0000000..a135f38 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalAssetInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 58004290eb3aab44e9823d1f25c4ed73 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEmitterEditor.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEmitterEditor.cs new file mode 100644 index 0000000..48c5690 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEmitterEditor.cs @@ -0,0 +1,23 @@ +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline.Signals +{ + [CustomTimelineEditor(typeof(SignalEmitter))] + class SignalEmitterEditor : MarkerEditor + { + static readonly string MissingAssetError = LocalizationDatabase.GetLocalizedString("No signal assigned"); + + public override MarkerDrawOptions GetMarkerOptions(IMarker marker) + { + var options = base.GetMarkerOptions(marker); + SignalEmitter emitter = (SignalEmitter)marker; + if (emitter.asset != null) + options.tooltip = emitter.asset.name; + else + options.errorText = MissingAssetError; + + return options; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEmitterEditor.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEmitterEditor.cs.meta new file mode 100644 index 0000000..4f40bf0 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEmitterEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 51a7878f6c989394782db73339e90e46 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEmitterInspector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEmitterInspector.cs new file mode 100644 index 0000000..bea45ad --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEmitterInspector.cs @@ -0,0 +1,377 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Playables; +using UnityEngine.Timeline; +using UnityObject = UnityEngine.Object; + +namespace UnityEditor.Timeline.Signals +{ + [CustomEditor(typeof(SignalEmitter), true)] + [CanEditMultipleObjects] + class SignalEmitterInspector : MarkerInspector, ISignalAssetProvider + { + SerializedProperty m_RetroactiveProperty; + SerializedProperty m_EmitOnceProperty; + + SignalEmitter m_Signal; + GameObject m_BoundGameObject; + PlayableDirector m_AssociatedDirector; + bool m_TargetsHaveTheSameBinding; + + readonly Dictionary<Component, Editor> m_Editors = new Dictionary<Component, Editor>(); + readonly Dictionary<Component, bool> m_Foldouts = new Dictionary<Component, bool>(); + List<Component> m_Receivers = new List<Component>(); + + static GUIStyle s_FoldoutStyle; + internal static GUIStyle foldoutStyle + { + get + { + if (s_FoldoutStyle == null) + { + s_FoldoutStyle = new GUIStyle(EditorStyles.foldout) {fontStyle = FontStyle.Bold}; + } + + return s_FoldoutStyle; + } + } + + public SignalAsset signalAsset + { + get + { + var emitter = target as SignalEmitter; + return signalAssetSameValue ? emitter.asset : null; + } + set + { + AssignSignalAsset(value); + } + } + + bool signalAssetSameValue + { + get + { + var emitters = targets.Cast<SignalEmitter>().ToList(); + return emitters.Select(x => x.asset).Distinct().Count() == 1; + } + } + + void OnEnable() + { + Undo.undoRedoPerformed += OnUndoRedo; // subscribe to the event + m_Signal = target as SignalEmitter; + m_RetroactiveProperty = serializedObject.FindProperty("m_Retroactive"); + m_EmitOnceProperty = serializedObject.FindProperty("m_EmitOnce"); + // In a vast majority of the cases, when this becomes enabled, + // the timeline window will be focused on the correct timeline + // in which case TimelineEditor.inspectedDirector is safe to use + m_AssociatedDirector = TimelineEditor.inspectedDirector; + UpdateState(); + } + + internal override bool IsEnabled() + { + return TimelineUtility.IsCurrentSequenceValid() && !IsCurrentSequenceReadOnly() && base.IsEnabled(); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + using (var changeScope = new EditorGUI.ChangeCheckScope()) + { + var property = serializedObject.GetIterator(); + var expanded = true; + while (property.NextVisible(expanded)) + { + expanded = false; + if (SkipField(property.propertyPath)) + continue; + EditorGUILayout.PropertyField(property, true); + } + + DrawSignalFlags(); + UpdateState(); + DrawNameSelectorAndSignalList(); + + if (changeScope.changed) + { + serializedObject.ApplyModifiedProperties(); + TimelineEditor.Refresh(RefreshReason.ContentsModified | RefreshReason.WindowNeedsRedraw); + } + } + } + + internal override void OnHeaderIconGUI(Rect iconRect) + { + using (new EditorGUI.DisabledScope(!TimelineUtility.IsCurrentSequenceValid() || IsCurrentSequenceReadOnly())) + { + GUI.Label(iconRect, Styles.SignalEmitterIcon); + } + } + + internal override Rect DrawHeaderHelpAndSettingsGUI(Rect r) + { + using (new EditorGUI.DisabledScope(!TimelineUtility.IsCurrentSequenceValid() || IsCurrentSequenceReadOnly())) + { + var helpSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.helpIcon); + const int kTopMargin = 5; + return EditorGUIUtility.DrawEditorHeaderItems(new Rect(r.xMax - helpSize.x, r.y + kTopMargin, helpSize.x, helpSize.y), targets); + } + } + + IEnumerable<SignalAsset> ISignalAssetProvider.AvailableSignalAssets() + { + return SignalManager.assets; + } + + void ISignalAssetProvider.CreateNewSignalAsset(string path) + { + var newSignalAsset = SignalManager.CreateSignalAssetInstance(path); + AssignSignalAsset(newSignalAsset); + var receivers = m_Receivers.OfType<SignalReceiver>().ToList(); + if (signalAsset != null && receivers.Count == 1 && !receivers.Any(r => r.IsSignalAssetHandled(newSignalAsset))) // Only when one receiver is present + { + receivers[0].AddNewReaction(newSignalAsset); // Add reaction on the first receiver from the list + ApplyChangesAndRefreshReceivers(); + } + } + + void UpdateState() + { + m_BoundGameObject = GetBoundGameObject(m_Signal.parent, m_AssociatedDirector); + m_Receivers = m_BoundGameObject == null || m_BoundGameObject.Equals(null) + ? new List<Component>() + : m_BoundGameObject.GetComponents<Component>().Where(t => t is INotificationReceiver).ToList(); + + m_TargetsHaveTheSameBinding = targets.Cast<SignalEmitter>() + .Select(x => GetBoundGameObject(x.parent, m_AssociatedDirector)) + .Distinct().Count() == 1; + } + + Editor GetOrCreateReceiverEditor(Component c) + { + Editor ret; + if (m_Editors.TryGetValue(c, out ret)) + { + return ret; + } + + ret = CreateEditorWithContext(new Object[] {c}, target); + m_Editors[c] = ret; + if (!m_Foldouts.ContainsKey(c)) + { + m_Foldouts[c] = true; + } + + return ret; + } + + void OnDisable() + { + Undo.undoRedoPerformed -= OnUndoRedo; + } + + void OnDestroy() + { + foreach (var editor in m_Editors) + { + DestroyImmediate(editor.Value); + } + m_Editors.Clear(); + } + + void OnUndoRedo() + { + ApplyChangesAndRefreshReceivers(); + } + + void ApplyChangesAndRefreshReceivers() + { + foreach (var receiverInspector in m_Editors.Values.OfType<SignalReceiverInspector>()) + { + receiverInspector.SetAssetContext(signalAsset); + } + } + + void DrawNameSelectorAndSignalList() + { + using (var change = new EditorGUI.ChangeCheckScope()) + { + DrawSignal(); + DrawReceivers(); + + if (change.changed) + { + ApplyChangesAndRefreshReceivers(); + } + } + } + + void DrawReceivers() + { + if (!m_TargetsHaveTheSameBinding) + { + EditorGUILayout.HelpBox(Styles.MultiEditNotSupportedOnDifferentBindings, MessageType.None); + return; + } + + if (targets.OfType<SignalEmitter>().Select(x => x.asset).Distinct().Count() > 1) + { + EditorGUILayout.HelpBox(Styles.MultiEditNotSupportedOnDifferentSignals, MessageType.None); + return; + } + + //do not display the receiver if the current timeline is not the same as the emitter's timeline + //can happen if the inspector is locked + if (m_Signal.parent != null && m_Signal.parent.timelineAsset != TimelineEditor.inspectedAsset) + return; + + if (m_BoundGameObject != null) + { + if (!m_Receivers.Any(x => x is SignalReceiver)) + { + EditorGUILayout.Separator(); + var message = string.Format(Styles.NoSignalReceiverComponent, m_BoundGameObject.name); + SignalUtility.DrawCenteredMessage(message); + if (SignalUtility.DrawCenteredButton(Styles.AddSignalReceiverComponent)) + AddReceiverComponent(); + } + + foreach (var receiver in m_Receivers) + { + var editor = GetOrCreateReceiverEditor(receiver); + if (DrawReceiverHeader(receiver)) + { + editor.OnInspectorGUI(); + } + } + } + else if (m_AssociatedDirector != null) //not in asset mode + { + EditorGUILayout.HelpBox(Styles.NoBoundGO, MessageType.None); + } + } + + void DrawSignalFlags() + { + EditorGUILayout.PropertyField(m_RetroactiveProperty, Styles.RetroactiveLabel); + EditorGUILayout.PropertyField(m_EmitOnceProperty, Styles.EmitOnceLabel); + } + + void DrawSignal() + { + //should show button to create new signal if there are no signals asset in the project + if (!SignalManager.assets.Any()) + { + using (new EditorGUI.DisabledScope(true)) + { + DrawNameSelector(); + } + + EditorGUILayout.Separator(); + SignalUtility.DrawCenteredMessage(Styles.ProjectHasNoSignalAsset); + if (SignalUtility.DrawCenteredButton(Styles.CreateNewSignal)) + CreateNewSignalAsset(SignalUtility.GetNewSignalPath()); + EditorGUILayout.Separator(); + } + else + { + DrawNameSelector(); + } + } + + internal void CreateNewSignalAsset(string path) + { + if (!string.IsNullOrEmpty(path)) + ((ISignalAssetProvider)this).CreateNewSignalAsset(path); + GUIUtility.ExitGUI(); + } + + void AssignSignalAsset(SignalAsset newAsset) + { + foreach (var o in targets) + { + var signalEmitter = (SignalEmitter)o; + TimelineUndo.PushUndo(signalEmitter, Styles.UndoCreateSignalAsset); + signalEmitter.asset = newAsset; + } + } + + void DrawNameSelector() + { + SignalUtility.DrawSignalNames(this, EditorGUILayout.GetControlRect(), Styles.EmitSignalLabel, !signalAssetSameValue); + } + + bool DrawReceiverHeader(Component receiver) + { + EditorGUILayout.Space(); + var lineRect = GUILayoutUtility.GetRect(10, 4, EditorStyles.inspectorTitlebar); + DrawSplitLine(lineRect.y); + + var style = EditorGUIUtility.TrTextContentWithIcon( + ObjectNames.NicifyVariableName(receiver.GetType().Name), + AssetPreview.GetMiniThumbnail(receiver)); + + m_Foldouts[receiver] = + EditorGUILayout.Foldout(m_Foldouts[receiver], style, true, foldoutStyle); + if (m_Foldouts[receiver]) + { + DrawReceiverObjectField(); + } + + return m_Foldouts[receiver]; + } + + void DrawReceiverObjectField() + { + EditorGUI.BeginDisabledGroup(true); + EditorGUILayout.ObjectField(Styles.ObjectLabel, m_BoundGameObject, typeof(GameObject), false); + EditorGUI.EndDisabledGroup(); + } + + void AddReceiverComponent() + { + var receiver = Undo.AddComponent<SignalReceiver>(m_BoundGameObject); + receiver.AddNewReaction(signalAsset); + } + + static bool SkipField(string fieldName) + { + return fieldName == "m_Script" || fieldName == "m_Asset" || fieldName == "m_Retroactive" || fieldName == "m_EmitOnce"; + } + + static void DrawSplitLine(float y) + { + if (Event.current.type != EventType.Repaint) return; + + var width = EditorGUIUtility.currentViewWidth; + var position = new Rect(0, y, width + 1, 1); + + if (EditorStyles.inspectorTitlebar != null) + EditorStyles.inspectorTitlebar.Draw(position, false, false, false, false); + } + + static GameObject GetBoundGameObject(TrackAsset track, PlayableDirector associatedDirector) + { + if (associatedDirector == null || track == null) //if in asset mode, no bound object for you + return null; + + var boundObj = TimelineUtility.GetSceneGameObject(associatedDirector, track); + + //if the signal is on the timeline marker track and user did not set a binding, assume it's bound to PlayableDirector + if (boundObj == null && track.timelineAsset.markerTrack == track) + boundObj = associatedDirector.gameObject; + + return boundObj; + } + + static bool IsCurrentSequenceReadOnly() + { + return TimelineWindow.instance.state.editSequence.isReadOnly; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEmitterInspector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEmitterInspector.cs.meta new file mode 100644 index 0000000..d89a36c --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEmitterInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 970e7735a0864fd40842a36d053d08fe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEventDrawer.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEventDrawer.cs new file mode 100644 index 0000000..021c6c7 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEventDrawer.cs @@ -0,0 +1,39 @@ +using System; +using JetBrains.Annotations; +using UnityEditorInternal; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline.Signals +{ + [CustomPropertyDrawer(typeof(CustomSignalEventDrawer))] + [UsedImplicitly] + class SignalEventDrawer : UnityEventDrawer + { + static GameObject FindBoundObject(SerializedProperty property) + { + var component = property.serializedObject.targetObject as Component; + return component != null ? component.gameObject : null; + } + + protected override void OnAddEvent(ReorderableList list) + { + base.OnAddEvent(list); + var listProperty = list.serializedProperty; + if (listProperty.arraySize > 0) + { + var lastCall = list.serializedProperty.GetArrayElementAtIndex(listProperty.arraySize - 1); + var targetProperty = lastCall.FindPropertyRelative(kInstancePath); + targetProperty.objectReferenceValue = FindBoundObject(listProperty); + } + } + + protected override void DrawEventHeader(Rect headerRect) {} + + protected override void SetupReorderableList(ReorderableList list) + { + base.SetupReorderableList(list); + list.headerHeight = 4; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEventDrawer.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEventDrawer.cs.meta new file mode 100644 index 0000000..26afa8d --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalEventDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6ba7805325c426c43b8e85b5be4eae36 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalManager.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalManager.cs new file mode 100644 index 0000000..4beec0c --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalManager.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.IO; +using UnityEngine; +using UnityEngine.Timeline; +using Object = UnityEngine.Object; + +namespace UnityEditor.Timeline.Signals +{ + class SignalManager : IDisposable + { + static SignalManager m_Instance; + readonly List<SignalAsset> m_assets = new List<SignalAsset>(); + + internal static SignalManager instance + { + get + { + if (m_Instance == null) + { + m_Instance = new SignalManager(); + m_Instance.Refresh(); + } + + return m_Instance; + } + + set { m_Instance = value; } + } + + internal SignalManager() + { + SignalAsset.OnEnableCallback += Register; + } + + public static IEnumerable<SignalAsset> assets + { + get + { + foreach (var asset in instance.m_assets) + { + if (asset != null) + yield return asset; + } + } + } + + public static SignalAsset CreateSignalAssetInstance(string path) + { + var newSignal = ScriptableObject.CreateInstance<SignalAsset>(); + newSignal.name = Path.GetFileNameWithoutExtension(path); + + var asset = AssetDatabase.LoadMainAssetAtPath(path) as SignalAsset; + if (asset != null) + { + TimelineUndo.PushUndo(asset, Styles.UndoCreateSignalAsset); + EditorUtility.CopySerialized(newSignal, asset); + Object.DestroyImmediate(newSignal); + return asset; + } + + AssetDatabase.CreateAsset(newSignal, path); + return newSignal; + } + + public void Dispose() + { + SignalAsset.OnEnableCallback -= Register; + } + + void Register(SignalAsset a) + { + m_assets.Add(a); + } + + void Refresh() + { + var guids = AssetDatabase.FindAssets("t:SignalAsset"); + foreach (var g in guids) + { + var path = AssetDatabase.GUIDToAssetPath(g); + var asset = AssetDatabase.LoadAssetAtPath<SignalAsset>(path); + m_assets.Add(asset); + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalManager.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalManager.cs.meta new file mode 100644 index 0000000..528ec1d --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 255b0c6d400fd964dab3029c8abc53f4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalReceiverHeader.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalReceiverHeader.cs new file mode 100644 index 0000000..55e8d27 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalReceiverHeader.cs @@ -0,0 +1,15 @@ +using UnityEditor.IMGUI.Controls; +using UnityEngine; + +namespace UnityEditor.Timeline.Signals +{ + class SignalReceiverHeader : MultiColumnHeader + { + public SignalReceiverHeader(MultiColumnHeaderState state) : base(state) {} + + protected override void AddColumnHeaderContextMenuItems(GenericMenu menu) + { + menu.AddItem(EditorGUIUtility.TrTextContent("Resize to Fit"), false, ResizeToFit); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalReceiverHeader.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalReceiverHeader.cs.meta new file mode 100644 index 0000000..211c810 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalReceiverHeader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 423cd382a7804414d9bfdb2e7fb7bb62 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalReceiverInspector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalReceiverInspector.cs new file mode 100644 index 0000000..52211e1 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalReceiverInspector.cs @@ -0,0 +1,116 @@ +using UnityEngine; +using UnityObject = UnityEngine.Object; +using UnityEditor.IMGUI.Controls; +using UnityEngine.Events; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline.Signals +{ + [CustomEditor(typeof(SignalReceiver))] + class SignalReceiverInspector : Editor + { + SignalReceiver m_Target; + + [SerializeField] TreeViewState m_TreeState; + [SerializeField] MultiColumnHeaderState m_MultiColumnHeaderState; + internal SignalReceiverTreeView m_TreeView; + + SignalEmitter signalEmitterContext + { + get { return m_Context as SignalEmitter;} + } + + void OnEnable() + { + m_Target = target as SignalReceiver; + InitTreeView(serializedObject); + + Undo.undoRedoPerformed += OnUndoRedo; + } + + void OnDisable() + { + Undo.undoRedoPerformed -= OnUndoRedo; + } + + void OnUndoRedo() + { + m_TreeView.dirty = true; + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + using (var changeCheck = new EditorGUI.ChangeCheckScope()) + { + m_TreeView.RefreshIfDirty(); + DrawEmitterControls(); // Draws buttons coming from the Context (SignalEmitter) + + EditorGUILayout.Space(); + m_TreeView.Draw(); + + if (signalEmitterContext == null) + DrawAddRemoveButtons(); + + if (changeCheck.changed) + { + serializedObject.ApplyModifiedProperties(); + m_TreeView.dirty = true; + } + } + } + + void DrawEmitterControls() + { + var context = signalEmitterContext; + if (context != null) + { + var currentSignal = context.asset; + if (currentSignal != null && !m_Target.IsSignalAssetHandled(currentSignal)) + { + EditorGUILayout.Separator(); + var message = string.Format(Styles.NoReaction, currentSignal.name); + SignalUtility.DrawCenteredMessage(message); + if (SignalUtility.DrawCenteredButton(Styles.AddReactionButton)) + m_Target.AddNewReaction(currentSignal); // Add reaction on the first + EditorGUILayout.Separator(); + } + } + } + + internal void SetAssetContext(SignalAsset asset) + { + m_TreeView.SetSignalContext(asset); + } + + void DrawAddRemoveButtons() + { + using (new GUILayout.HorizontalScope()) + { + GUILayout.FlexibleSpace(); + if (GUILayout.Button(Styles.AddReactionButton)) + { + Undo.RecordObject(m_Target, Styles.UndoAddReaction); + m_Target.AddEmptyReaction(new UnityEvent()); + PrefabUtility.RecordPrefabInstancePropertyModifications(m_Target); + } + GUILayout.Space(18.0f); + } + } + + void InitTreeView(SerializedObject so) + { + m_TreeState = SignalListFactory.CreateViewState(); + m_MultiColumnHeaderState = SignalListFactory.CreateHeaderState(); + var header = SignalListFactory.CreateHeader(m_MultiColumnHeaderState, SignalReceiverUtility.headerHeight); + + var context = signalEmitterContext; + m_TreeView = SignalListFactory.CreateSignalInspectorList(m_TreeState, header, m_Target, so); + m_TreeView.readonlySignals = context != null; + + if (context != null) + m_TreeView.SetSignalContext(context.asset); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalReceiverInspector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalReceiverInspector.cs.meta new file mode 100644 index 0000000..a764c95 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalReceiverInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 70b265ed18dc14041bedc0263d4578ef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalUtility.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalUtility.cs new file mode 100644 index 0000000..663e341 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalUtility.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline.Signals +{ + interface ISignalAssetProvider + { + SignalAsset signalAsset { get; set; } + IEnumerable<SignalAsset> AvailableSignalAssets(); + void CreateNewSignalAsset(string path); + } + + static class SignalUtility + { + const string k_SignalExtension = "signal"; + + public static void DrawSignalNames(ISignalAssetProvider assetProvider, Rect position, GUIContent label, bool multipleValues) + { + var assets = assetProvider.AvailableSignalAssets().ToList(); + var index = assets.IndexOf(assetProvider.signalAsset); + + var availableNames = new List<string>(); + using (new GUIMixedValueScope(multipleValues)) + { + availableNames.Add(Styles.EmptySignalList.text); + + availableNames.AddRange(assets.Select(x => x.name)); + availableNames.Add(Styles.CreateNewSignal.text); + + var curValue = index + 1; + var selected = EditorGUI.Popup(position, label, curValue, availableNames.ToArray()); + + if (selected != curValue) + { + var noneEntryIdx = 0; + if (selected == noneEntryIdx) // None + assetProvider.signalAsset = null; + else if (selected == availableNames.Count - 1) // "Create New Asset" + { + var path = GetNewSignalPath(); + if (!string.IsNullOrEmpty(path)) + assetProvider.CreateNewSignalAsset(path); + GUIUtility.ExitGUI(); + } + else + assetProvider.signalAsset = assets[selected - 1]; + } + } + } + + public static string GetNewSignalPath() + { + return EditorUtility.SaveFilePanelInProject( + Styles.NewSignalWindowTitle.text, + Styles.NewSignalDefaultName.text, + k_SignalExtension, + Styles.NewSignalWindowMessage.text); + } + + public static bool IsSignalAssetHandled(this SignalReceiver receiver, SignalAsset asset) + { + return receiver != null && asset != null && receiver.GetRegisteredSignals().Contains(asset); + } + + public static void AddNewReaction(this SignalReceiver receiver, SignalAsset signalAsset) + { + if (signalAsset != null && receiver != null) + { + Undo.RecordObject(receiver, Styles.UndoAddReaction); + var newEvent = new UnityEvent(); + newEvent.AddPersistentListener(); + var evtIndex = newEvent.GetPersistentEventCount() - 1; + newEvent.RegisterVoidPersistentListenerWithoutValidation(evtIndex, receiver.gameObject, string.Empty); + receiver.AddReaction(signalAsset, newEvent); + PrefabUtility.RecordPrefabInstancePropertyModifications(receiver); + } + } + + public static void DrawCenteredMessage(string message) + { + using (new GUILayout.HorizontalScope()) + { + GUILayout.FlexibleSpace(); + GUILayout.Label(message); + GUILayout.FlexibleSpace(); + } + } + + public static bool DrawCenteredButton(GUIContent buttonLabel) + { + bool buttonClicked; + using (new GUILayout.HorizontalScope()) + { + GUILayout.FlexibleSpace(); + buttonClicked = GUILayout.Button(buttonLabel); + GUILayout.FlexibleSpace(); + } + return buttonClicked; + } + } + + static class SignalReceiverUtility + { + const int k_DefaultTreeviewHeaderHeight = 20; + + public static int headerHeight + { + get { return k_DefaultTreeviewHeaderHeight; } + } + + public static SerializedProperty FindSignalsProperty(SerializedObject obj) + { + return obj.FindProperty("m_Events.m_Signals"); + } + + public static SerializedProperty FindEventsProperty(SerializedObject obj) + { + return obj.FindProperty("m_Events.m_Events"); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalUtility.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalUtility.cs.meta new file mode 100644 index 0000000..f29c92c --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/SignalUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b33687803b08daf418e5315de17658b8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/Styles.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/Styles.cs new file mode 100644 index 0000000..6842081 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/Styles.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +namespace UnityEditor.Timeline.Signals +{ + static class Styles + { + public static readonly GUIContent RetroactiveLabel = EditorGUIUtility.TrTextContent("Retroactive", "Use retroactive to emit this signal even if playback starts afterwards."); + public static readonly GUIContent EmitOnceLabel = EditorGUIUtility.TrTextContent("Emit Once", "Emit the signal once during loops."); + public static readonly GUIContent EmitSignalLabel = EditorGUIUtility.TrTextContent("Emit Signal", "Select which Signal Asset to emit."); + public static readonly GUIContent ObjectLabel = EditorGUIUtility.TrTextContent("Receiver Component on", "The Signal Receiver Component on the bound GameObject."); + + public static readonly GUIContent CreateNewSignal = EditorGUIUtility.TrTextContent("Create Signal…"); + public static readonly GUIContent AddSignalReceiverComponent = EditorGUIUtility.TrTextContent("Add Signal Receiver", "Creates a Signal Receiver component on the track binding and the reaction for the current signal."); + public static readonly GUIContent EmptySignalList = EditorGUIUtility.TrTextContent("None"); + public static readonly GUIContent AddReactionButton = EditorGUIUtility.TrTextContent("Add Reaction"); + + public static readonly GUIContent NewSignalWindowTitle = EditorGUIUtility.TrTextContent("Create Signal Key"); + public static readonly GUIContent NewSignalDefaultName = EditorGUIUtility.TrTextContent("New Signal"); + public static readonly GUIContent NewSignalWindowMessage = EditorGUIUtility.TrTextContent("Create Signal Key"); + + public static readonly string SignalListDuplicateOption = L10n.Tr("Duplicate"); + public static readonly string SignalListDeleteOption = L10n.Tr("Delete"); + public static readonly string NoBoundGO = L10n.Tr("Track has no bound GameObject."); + public static readonly string MultiEditNotSupportedOnDifferentBindings = L10n.Tr("Multi-edit not supported for SignalReceivers on tracks bound to different GameObjects."); + public static readonly string MultiEditNotSupportedOnDifferentSignals = L10n.Tr("Multi-edit not supported for SignalReceivers when SignalEmitters use different Signals."); + + public static readonly string UndoCreateSignalAsset = L10n.Tr("Create New Signal Asset"); + public static readonly string UndoDuplicateRow = L10n.Tr("Duplicate Row"); + public static readonly string UndoDeleteRow = L10n.Tr("Delete Row"); + public static readonly string UndoAddReaction = L10n.Tr("Add Signal Receiver Reaction"); + public static readonly string NoReaction = L10n.Tr("No reaction for {0} has been defined in this receiver"); + public static readonly string NoSignalReceiverComponent = L10n.Tr("There is no Signal Receiver component on {0}"); + public static readonly string ProjectHasNoSignalAsset = L10n.Tr("Your project contains no Signal assets"); + + //Icons + public static readonly GUIStyle OptionsStyle = DirectorStyles.GetGUIStyle("Icon.Options"); + public static readonly GUIContent SignalEmitterIcon = EditorGUIUtility.IconContent("SignalEmitter Icon"); + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/Styles.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/Styles.cs.meta new file mode 100644 index 0000000..da7c028 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/Styles.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 685f63932bebd0c4db02ee14845191e2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView.meta new file mode 100644 index 0000000..d8cac35 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5ba130fc1db953547a50bcf5c162a3e8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalListFactory.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalListFactory.cs new file mode 100644 index 0000000..1b59ec6 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalListFactory.cs @@ -0,0 +1,31 @@ +using System; +using UnityEditor.IMGUI.Controls; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline.Signals +{ + static class SignalListFactory + { + public static SignalReceiverTreeView CreateSignalInspectorList(TreeViewState state, SignalReceiverHeader header, SignalReceiver target, SerializedObject so) + { + return new SignalReceiverTreeView(state, header, target, so); + } + + public static SignalReceiverHeader CreateHeader(MultiColumnHeaderState state, int columnHeight) + { + var header = new SignalReceiverHeader(state) { height = columnHeight }; + header.ResizeToFit(); + return header; + } + + public static MultiColumnHeaderState CreateHeaderState() + { + return new MultiColumnHeaderState(SignalReceiverTreeView.GetColumns()); + } + + public static TreeViewState CreateViewState() + { + return new TreeViewState(); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalListFactory.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalListFactory.cs.meta new file mode 100644 index 0000000..fcc2a87 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalListFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 01cd96d8687272f4898cfd1562079dd7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalReceiverItem.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalReceiverItem.cs new file mode 100644 index 0000000..a58b2fe --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalReceiverItem.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.IMGUI.Controls; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Timeline; +using Object = UnityEngine.Object; + +namespace UnityEditor.Timeline.Signals +{ + class SignalReceiverItem : TreeViewItem, ISignalAssetProvider + { + static readonly SignalEventDrawer k_EvtDrawer = new SignalEventDrawer(); + + readonly SerializedProperty m_Asset; + readonly SerializedProperty m_Evt; + readonly SignalReceiverTreeView m_TreeView; + + int m_CurrentRowIdx; + SignalReceiver m_CurrentReceiver; + + internal readonly bool enabled; + internal readonly bool readonlySignal; + + internal const string SignalName = "SignalName"; + internal const string SignalNameReadOnly = "SignalNameReadOnly"; + internal const string SignalOptions = "SignalOptions"; + + public SignalReceiverItem(SerializedProperty signalAsset, SerializedProperty eventListEntry, int id, bool readonlySignal, bool enabled, SignalReceiverTreeView treeView) + : base(id, 0) + { + m_Asset = signalAsset; + m_Evt = eventListEntry; + this.enabled = enabled; + this.readonlySignal = readonlySignal; + m_TreeView = treeView; + } + + public SignalAsset signalAsset + { + get { return m_CurrentReceiver.GetSignalAssetAtIndex(m_CurrentRowIdx); } + set + { + Undo.RecordObject(m_CurrentReceiver, Styles.UndoCreateSignalAsset); + m_CurrentReceiver.ChangeSignalAtIndex(m_CurrentRowIdx, value); + PrefabUtility.RecordPrefabInstancePropertyModifications(m_CurrentReceiver); + } + } + + public float GetHeight() + { + return k_EvtDrawer.GetPropertyHeight(m_Evt, GUIContent.none); + } + + public void Draw(Rect rect, int colIdx, int rowIdx, float padding, SignalReceiver target) + { + switch (colIdx) + { + case 0: + DrawSignalNameColumn(rect, padding, target, rowIdx); + break; + case 1: + DrawReactionColumn(rect, rowIdx); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + void DrawSignalNameColumn(Rect rect, float padding, SignalReceiver target, int rowIdx) + { + using (new EditorGUI.DisabledScope(!enabled)) + { + if (!readonlySignal) + { + m_CurrentRowIdx = rowIdx; + m_CurrentReceiver = target; + + rect.x += padding; + rect.width -= padding; + rect.height = EditorGUIUtility.singleLineHeight; + GUI.SetNextControlName(SignalName); + SignalUtility.DrawSignalNames(this, rect, GUIContent.none, false); + } + else + { + GUI.SetNextControlName(SignalNameReadOnly); + var signalAsset = m_Asset.objectReferenceValue; + GUI.Label(rect, + signalAsset != null + ? EditorGUIUtility.TempContent(signalAsset.name) + : Styles.EmptySignalList); + } + } + } + + void DrawReactionColumn(Rect rect, int rowIdx) + { + if (!readonlySignal) + { + var optionButtonSize = GetOptionButtonSize(); + rect.width -= optionButtonSize.x; + + var optionButtonRect = new Rect + { + x = rect.xMax, + y = rect.y, + width = optionButtonSize.x, + height = optionButtonSize.y + }; + DrawOptionsButton(optionButtonRect, rowIdx, m_CurrentReceiver); + } + + using (new EditorGUI.DisabledScope(!enabled)) + { + var nameAsString = m_Asset.objectReferenceValue == null ? "Null" : m_Asset.objectReferenceValue.name; + using (var change = new EditorGUI.ChangeCheckScope()) + { + EditorGUI.PropertyField(rect, m_Evt, EditorGUIUtility.TempContent(nameAsString)); + if (change.changed) + m_TreeView.dirty = true; + } + } + } + + static Vector2 GetOptionButtonSize() + { + EditorGUIUtility.SetIconSize(Vector2.zero); + return EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.titleSettingsIcon); + } + + void DrawOptionsButton(Rect rect, int rowIdx, SignalReceiver target) + { + GUI.SetNextControlName(SignalOptions); + if (EditorGUI.DropdownButton(rect, EditorGUI.GUIContents.titleSettingsIcon, FocusType.Passive, EditorStyles.iconButton)) + { + var menu = new GenericMenu(); + menu.AddItem(new GUIContent(Styles.SignalListDuplicateOption), false, () => + { + Undo.RecordObject(target, Styles.UndoDuplicateRow); + var evtCloner = ScriptableObject.CreateInstance<UnityEventCloner>(); + evtCloner.evt = target.GetReactionAtIndex(rowIdx); + var clone = Object.Instantiate(evtCloner); + target.AddEmptyReaction(clone.evt); + m_TreeView.dirty = true; + PrefabUtility.RecordPrefabInstancePropertyModifications(target); + + }); + menu.AddItem(new GUIContent(Styles.SignalListDeleteOption), false, () => + { + Undo.RecordObject(target, Styles.UndoDeleteRow); + target.RemoveAtIndex(rowIdx); + m_TreeView.dirty = true; + PrefabUtility.RecordPrefabInstancePropertyModifications(target); + }); + menu.ShowAsContext(); + } + } + + IEnumerable<SignalAsset> ISignalAssetProvider.AvailableSignalAssets() + { + var ret = SignalManager.assets.Except(m_CurrentReceiver.GetRegisteredSignals()); + return signalAsset == null ? ret : ret.Union(new List<SignalAsset> {signalAsset}).ToList(); + } + + void ISignalAssetProvider.CreateNewSignalAsset(string path) + { + var newSignalAsset = SignalManager.CreateSignalAssetInstance(path); + Undo.RecordObject(m_CurrentReceiver, Styles.UndoCreateSignalAsset); + m_CurrentReceiver.ChangeSignalAtIndex(m_CurrentRowIdx, newSignalAsset); + PrefabUtility.RecordPrefabInstancePropertyModifications(m_CurrentReceiver); + } + + class UnityEventCloner : ScriptableObject + { + public UnityEvent evt; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalReceiverItem.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalReceiverItem.cs.meta new file mode 100644 index 0000000..826e615 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalReceiverItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9bc2b69915879416f8df18971dc98e2e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalReceiverTreeView.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalReceiverTreeView.cs new file mode 100644 index 0000000..abacd72 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalReceiverTreeView.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using UnityEditor.IMGUI.Controls; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline.Signals +{ + class SignalReceiverTreeView : TreeView + { + public bool dirty { private get; set; } + + SerializedProperty signals { get; set; } + SerializedProperty events { get; set; } + + readonly SignalReceiver m_Target; + + const float k_VerticalPadding = 5; + const float k_HorizontalPadding = 5; + + public SignalReceiverTreeView(TreeViewState state, MultiColumnHeader multiColumnHeader, SignalReceiver receiver, SerializedObject serializedObject) + : base(state, multiColumnHeader) + { + m_Target = receiver; + useScrollView = true; + SetSerializedProperties(serializedObject); + getNewSelectionOverride = (item, selection, shift) => new List<int>(); // Disable Selection + } + + SignalAsset signalAssetContext { get; set; } + public bool readonlySignals { get; set; } + + public void SetSignalContext(SignalAsset assetContext = null) + { + signalAssetContext = assetContext; + dirty = true; + } + + void SetSerializedProperties(SerializedObject serializedObject) + { + signals = SignalReceiverUtility.FindSignalsProperty(serializedObject); + events = SignalReceiverUtility.FindEventsProperty(serializedObject); + Reload(); + } + + public void Draw() + { + var rect = EditorGUILayout.GetControlRect(true, GetTotalHeight()); + OnGUI(rect); + } + + public void RefreshIfDirty() + { + var signalsListSizeHasChanged = signals.arraySize != GetRows().Count; + if (dirty || signalsListSizeHasChanged) + Reload(); + dirty = false; + } + + public static MultiColumnHeaderState.Column[] GetColumns() + { + return new[] + { + new MultiColumnHeaderState.Column + { + headerContent = EditorGUIUtility.TrTextContent("Signal"), + contextMenuText = "", + headerTextAlignment = TextAlignment.Center, + width = 50, minWidth = 50, + autoResize = true, + allowToggleVisibility = false, + canSort = false + }, + new MultiColumnHeaderState.Column + { + headerContent = EditorGUIUtility.TrTextContent("Reaction"), + contextMenuText = "", + headerTextAlignment = TextAlignment.Center, + width = 120, minWidth = 120, + autoResize = true, + allowToggleVisibility = false, + canSort = false + } + }; + } + + protected override TreeViewItem BuildRoot() + { + var root = new TreeViewItem(-1, -1) { children = new List<TreeViewItem>() }; + + var matchingId = signalAssetContext != null && readonlySignals ? FindIdForSignal(signals, signalAssetContext) : -1; + if (matchingId >= 0) + AddItem(root, matchingId); + + for (var i = 0; i < signals.arraySize; ++i) + { + if (i == matchingId) continue; + AddItem(root, i, !readonlySignals); + } + + return root; + } + + protected override void RowGUI(RowGUIArgs args) + { + var item = (SignalReceiverItem)args.item; + for (var i = 0; i < args.GetNumVisibleColumns(); ++i) + { + var rect = args.GetCellRect(i); + rect.y += k_VerticalPadding; + item.Draw(rect, args.GetColumn(i), args.row, k_HorizontalPadding, m_Target); + } + } + + protected override float GetCustomRowHeight(int row, TreeViewItem treeItem) + { + var item = treeItem as SignalReceiverItem; + return item.GetHeight() + k_VerticalPadding; + } + + void AddItem(TreeViewItem root, int id, bool enabled = true) + { + var signal = signals.GetArrayElementAtIndex(id); + var evt = events.GetArrayElementAtIndex(id); + root.children.Add(new SignalReceiverItem(signal, evt, id, readonlySignals, enabled, this)); + } + + float GetTotalHeight() + { + var height = 0.0f; + foreach (var item in GetRows()) + { + var signalListItem = item as SignalReceiverItem; + height += signalListItem.GetHeight() + k_VerticalPadding; + } + + var scrollbarPadding = showingHorizontalScrollBar ? GUI.skin.horizontalScrollbar.fixedHeight : k_VerticalPadding; + return height + multiColumnHeader.height + scrollbarPadding; + } + + static int FindIdForSignal(SerializedProperty signals, SignalAsset signalToFind) + { + for (var i = 0; i < signals.arraySize; ++i) + { + //signal in the receiver that matches the current signal asset will be displayed first + var serializedProperty = signals.GetArrayElementAtIndex(i); + var signalReferenceValue = serializedProperty.objectReferenceValue; + var signalToFindRefValue = signalToFind; + if (signalReferenceValue != null && signalReferenceValue == signalToFindRefValue) + return i; + } + return -1; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalReceiverTreeView.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalReceiverTreeView.cs.meta new file mode 100644 index 0000000..7c121bf --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Signals/TreeView/SignalReceiverTreeView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 698b660e9477f4f16abad03ec00ce38c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: |
