From fd806cf4010562b71d0eb920dd8f23885c8723e0 Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Wed, 8 May 2024 20:01:03 -0400 Subject: [PATCH 01/30] cleanup UX layout code. fix alignment for U6 --- .../CinemachineFreeLookModifierEditor.cs | 13 +- .../Editors/CinemachineOrbitalFollowEditor.cs | 2 +- .../CinemachineSequencerCameraEditor.cs | 2 +- .../CinemachineStateDrivenCameraEditor.cs | 2 +- .../Editors/CinemachineStoryboardEditor.cs | 9 +- .../Obsolete/ObsoleteInspectorUtility.cs | 248 ++++++++++ .../Obsolete/ObsoleteInspectorUtility.cs.meta | 11 + .../CameraTargetPropertyDrawer.cs | 2 +- .../DelayedVectorPropertyDrawer.cs | 2 +- .../FoldoutWithEnabledButtonPropertyDrawer.cs | 4 +- .../InputAxisPropertyDrawer.cs | 23 +- .../LensSettingsPropertyDrawer.cs | 7 +- .../MinMaxRangeSliderPropertyDrawer.cs | 5 +- .../OutputChannelsPropertyDrawer.cs | 2 +- .../SensorSizePropertyDrawer.cs | 3 +- .../SplineAutoDollyPropertyDrawer.cs | 2 +- .../PropertyDrawers/TagFieldPropertyDrawer.cs | 2 +- .../Vector2AsRangePropertyDrawer.cs | 1 - .../Editor/Timeline/CinemachineShotEditor.cs | 2 +- .../Utility/CmCameraInspectorUtility.cs | 8 +- .../Editor/Utility/InspectorUtility.cs | 454 ++++-------------- .../Editor/Windows/WaveformWindow.cs | 2 +- .../Behaviours/CinemachineTargetGroup.cs | 2 +- .../Runtime/Components/CinemachineFollow.cs | 6 +- 24 files changed, 403 insertions(+), 411 deletions(-) create mode 100644 com.unity.cinemachine/Editor/Obsolete/ObsoleteInspectorUtility.cs create mode 100644 com.unity.cinemachine/Editor/Obsolete/ObsoleteInspectorUtility.cs.meta diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineFreeLookModifierEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineFreeLookModifierEditor.cs index b613efe0c..c87782962 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineFreeLookModifierEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineFreeLookModifierEditor.cs @@ -17,9 +17,14 @@ public override VisualElement CreateInspectorGUI() { var ux = new VisualElement(); + ux.Add(new HelpBox("This component is optional and can be removed if you don't need it. " + + "The modifiers you add will override settings for the top and bottom portions " + + "of the camera's vertical orbit.", + HelpBoxMessageType.Info)); + var invalidSrcMsg = ux.AddChild( - new HelpBox("This component will be ignored because no applicable target components are present.\n\n" - + "Applicable target components include: " + new HelpBox("Component will be ignored because no modifiable targets are present.\n\n" + + "Modifiable target components include: " + InspectorUtility.GetAssignableBehaviourNames( typeof(CinemachineFreeLookModifier.IModifierValueSource)), HelpBoxMessageType.Warning)); @@ -110,7 +115,9 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) warningSymbol.SetVisible(showWarning); }); - return new InspectorUtility.FoldoutWithOverlay(foldout, overlay, null); + var ux = new InspectorUtility.FoldoutWithOverlay(foldout, overlay, null); + ux.style.marginLeft = 12; + return ux; } } diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineOrbitalFollowEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineOrbitalFollowEditor.cs index 719874872..d4b1a6f0e 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineOrbitalFollowEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineOrbitalFollowEditor.cs @@ -27,8 +27,8 @@ public override VisualElement CreateInspectorGUI() { var ux = new VisualElement(); this.AddMissingCmCameraHelpBox(ux); - ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.TargetOffset))); ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.TrackerSettings))); + ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.TargetOffset))); ux.AddSpace(); var orbitModeProp = serializedObject.FindProperty(() => Target.OrbitStyle); diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs index d11d06bbe..22935aff8 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs @@ -74,7 +74,7 @@ public override VisualElement CreateInspectorGUI() blend.name = "FirstItemBlend"; var hold = row.AddChild( new InspectorUtility.CompactPropertyField(element.FindPropertyRelative(() => def.Hold), " ")); - hold.RemoveFromClassList(InspectorUtility.kAlignFieldClass); + hold.RemoveFromClassList(InspectorUtility.AlignFieldClassName); FormatInstructionElement(false, vcamSel, blend, hold); diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineStateDrivenCameraEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineStateDrivenCameraEditor.cs index ef08d21f7..6ab2f2305 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineStateDrivenCameraEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineStateDrivenCameraEditor.cs @@ -39,7 +39,7 @@ public override VisualElement CreateInspectorGUI() var layerProp = serializedObject.FindProperty(() => Target.LayerIndex); var layerSel = ux.AddChild(new PopupField(layerProp.displayName) { tooltip = layerProp.tooltip }); - layerSel.AddToClassList(InspectorUtility.kAlignFieldClass); + layerSel.AddToClassList(InspectorUtility.AlignFieldClassName); layerSel.RegisterValueChangedCallback((evt) => { layerProp.intValue = Mathf.Max(0, m_LayerNames.FindIndex(v => v == evt.newValue)); diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineStoryboardEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineStoryboardEditor.cs index 9ccf10447..87768fdd2 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineStoryboardEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineStoryboardEditor.cs @@ -24,7 +24,7 @@ public override VisualElement CreateInspectorGUI() tooltip = CinemachineCorePrefs.s_StoryboardGlobalMuteLabel.tooltip, value = CinemachineStoryboard.s_StoryboardGlobalMute }); - muteToggle.AddToClassList(InspectorUtility.kAlignFieldClass); + muteToggle.AddToClassList(InspectorUtility.AlignFieldClassName); muteToggle.RegisterValueChangedCallback((evt) => { CinemachineStoryboard.s_StoryboardGlobalMute = CinemachineCorePrefs.StoryboardGlobalMute.Value = evt.newValue; @@ -35,7 +35,7 @@ public override VisualElement CreateInspectorGUI() var showImageProp = serializedObject.FindProperty(() => Target.ShowImage); var row = ux.AddChild(new InspectorUtility.LabeledRow("Show Image", showImageProp.tooltip)); var imageToggle = row.Contents.AddChild(new Toggle("") - { style = { flexGrow = 0, marginTop = 3, marginLeft = 0, alignSelf = Align.Center }}); + { style = { flexGrow = 0, marginTop = 3, marginLeft = 6, alignSelf = Align.Center }}); imageToggle.BindProperty(showImageProp); var imageField = row.Contents.AddChild(new PropertyField(serializedObject.FindProperty(() => Target.Image), "") { style = { flexGrow = 1, marginLeft = 4 }}); @@ -49,11 +49,10 @@ public override VisualElement CreateInspectorGUI() // Scale var scaleProp = serializedObject.FindProperty(() => Target.Scale); row = ux.AddChild(new InspectorUtility.LabeledRow(scaleProp.displayName, scaleProp.tooltip)); - var scaleField = row.Contents.AddChild(new PropertyField(scaleProp, "") - { style = { flexBasis = 0, flexGrow = 2, marginLeft = -3 }}); + var scaleField = row.Contents.AddChild(new PropertyField(scaleProp, "") { style = { flexBasis = 50, flexGrow = 2 }}); var syncProp = serializedObject.FindProperty(() => Target.SyncScale); var syncField = row.Contents.AddChild(new Toggle("") - { text = " Sync", style = { flexBasis = 0, flexGrow = 1, paddingLeft = 3, paddingTop = 3 }}); + { text = " Sync", style = { flexBasis = 20, flexGrow = 1, paddingLeft = 1, paddingTop = 2 }}); syncField.BindProperty(syncProp); scaleField.TrackPropertyWithInitialCallback(syncProp, (p) => { diff --git a/com.unity.cinemachine/Editor/Obsolete/ObsoleteInspectorUtility.cs b/com.unity.cinemachine/Editor/Obsolete/ObsoleteInspectorUtility.cs new file mode 100644 index 000000000..a61994124 --- /dev/null +++ b/com.unity.cinemachine/Editor/Obsolete/ObsoleteInspectorUtility.cs @@ -0,0 +1,248 @@ +#if !CINEMACHINE_NO_CM2_SUPPORT +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace Unity.Cinemachine.Editor +{ + static partial class InspectorUtility + { + /// Put multiple properties on a single inspector line, with + /// optional label overrides. Passing null as a label (or sublabel) override will + /// cause the property's displayName to be used as a label. For no label at all, + /// pass GUIContent.none. + /// Rect in which to draw + /// Main label + /// Properties to place on the line + /// Sublabels for the properties + public static void MultiPropertyOnLine( + Rect rect, + GUIContent label, + SerializedProperty[] props, GUIContent[] subLabels) + { + if (props == null || props.Length == 0) + return; + + const int hSpace = 2; + int indentLevel = EditorGUI.indentLevel; + float labelWidth = EditorGUIUtility.labelWidth; + + float totalSubLabelWidth = 0; + int numBoolColumns = 0; + List actualLabels = new List(); + for (int i = 0; i < props.Length; ++i) + { + GUIContent sublabel = new GUIContent(props[i].displayName, props[i].tooltip); + if (subLabels != null && subLabels.Length > i && subLabels[i] != null) + sublabel = subLabels[i]; + actualLabels.Add(sublabel); + totalSubLabelWidth += GUI.skin.label.CalcSize(sublabel).x; + if (i > 0) + totalSubLabelWidth += hSpace; + // Special handling for toggles, or it looks stupid + if (props[i].propertyType == SerializedPropertyType.Boolean) + { + totalSubLabelWidth += rect.height + hSpace; + ++numBoolColumns; + } + } + + float subFieldWidth = rect.width - labelWidth - totalSubLabelWidth; + float numCols = props.Length - numBoolColumns; + float colWidth = numCols == 0 ? 0 : subFieldWidth / numCols; + + // Main label. If no first sublabel, then main label must take on that + // role, for mouse dragging value-scrolling support + int subfieldStartIndex = 0; + if (label == null) + label = new GUIContent(props[0].displayName, props[0].tooltip); + if (actualLabels[0] != GUIContent.none) + rect = EditorGUI.PrefixLabel(rect, label); + else + { + rect.width = labelWidth + colWidth; + EditorGUI.PropertyField(rect, props[0], label); + rect.x += rect.width + hSpace; + subfieldStartIndex = 1; + } + + for (int i = subfieldStartIndex; i < props.Length; ++i) + { + EditorGUI.indentLevel = 0; + EditorGUIUtility.labelWidth = GUI.skin.label.CalcSize(actualLabels[i]).x; + if (props[i].propertyType == SerializedPropertyType.Boolean) + { + rect.x += hSpace; + rect.width = EditorGUIUtility.labelWidth + rect.height; + EditorGUI.BeginProperty(rect, actualLabels[i], props[i]); + props[i].boolValue = EditorGUI.ToggleLeft(rect, actualLabels[i], props[i].boolValue); + } + else + { + rect.width = EditorGUIUtility.labelWidth + colWidth; + EditorGUI.BeginProperty(rect, actualLabels[i], props[i]); + EditorGUI.PropertyField(rect, props[i], actualLabels[i]); + } + EditorGUI.EndProperty(); + rect.x += rect.width + hSpace; + } + + EditorGUIUtility.labelWidth = labelWidth; + EditorGUI.indentLevel = indentLevel; + } + + public static float PropertyHeightOfChidren(SerializedProperty property) + { + float height = 0; + var childProperty = property.Copy(); + var endProperty = childProperty.GetEndProperty(); + childProperty.NextVisible(true); + while (!SerializedProperty.EqualContents(childProperty, endProperty)) + { + height += EditorGUI.GetPropertyHeight(childProperty) + + EditorGUIUtility.standardVerticalSpacing; + childProperty.NextVisible(false); + } + return height - EditorGUIUtility.standardVerticalSpacing; + } + + public static void DrawChildProperties(Rect position, SerializedProperty property) + { + var childProperty = property.Copy(); + var endProperty = childProperty.GetEndProperty(); + childProperty.NextVisible(true); + while (!SerializedProperty.EqualContents(childProperty, endProperty)) + { + position.height = EditorGUI.GetPropertyHeight(childProperty); + EditorGUI.PropertyField(position, childProperty, true); + position.y += position.height + EditorGUIUtility.standardVerticalSpacing; + childProperty.NextVisible(false); + } + } + + public static void HelpBoxWithButton( + string message, MessageType messageType, + GUIContent buttonContent, Action onClicked) + { + float lineHeight = EditorGUIUtility.singleLineHeight; + var buttonSize = GUI.skin.label.CalcSize(buttonContent); + buttonSize.x += lineHeight; + + var rect = EditorGUI.IndentedRect(EditorGUILayout.GetControlRect(false, 2)); + + var boxContent = new GUIContent(message + "\n"); // to make room for the button + var boxWidth = rect.width; + var boxHeight = GUI.skin.GetStyle("helpbox").CalcHeight(boxContent, rect.width - 3 * lineHeight) + buttonSize.y; + + rect = EditorGUILayout.GetControlRect(false, boxHeight); + rect = EditorGUI.IndentedRect(rect); + rect.width = boxWidth; rect.height = boxHeight; + EditorGUI.HelpBox(rect, boxContent.text, messageType); + + rect.x += rect.width - buttonSize.x - 6; rect.width = buttonSize.x; + rect.y += rect.height - buttonSize.y - 6; rect.height = buttonSize.y; + if (GUI.Button(rect, buttonContent, EditorStyles.miniButton)) + onClicked(); + } + + public static float EnabledFoldoutHeight(SerializedProperty property, string enabledPropertyName) + { + var enabledProp = property.FindPropertyRelative(enabledPropertyName); + if (enabledProp == null) + return EditorGUI.GetPropertyHeight(property); + if (!enabledProp.boolValue) + return EditorGUIUtility.singleLineHeight; + return PropertyHeightOfChidren(property); + } + + public static bool EnabledFoldout( + Rect rect, SerializedProperty property, string enabledPropertyName, + GUIContent label = null) + { + var enabledProp = property.FindPropertyRelative(enabledPropertyName); + if (enabledProp == null) + { + EditorGUI.PropertyField(rect, property, true); + rect.x += EditorGUIUtility.labelWidth; + EditorGUI.LabelField(rect, new GUIContent($"unknown field `{enabledPropertyName}`")); + return property.isExpanded; + } + rect.height = EditorGUIUtility.singleLineHeight; + label ??= new GUIContent(property.displayName, enabledProp.tooltip); + EditorGUI.PropertyField(rect, enabledProp, label); + if (enabledProp.boolValue) + { + ++EditorGUI.indentLevel; + var childProperty = property.Copy(); + var endProperty = childProperty.GetEndProperty(); + childProperty.NextVisible(true); + while (!SerializedProperty.EqualContents(childProperty, endProperty)) + { + if (!SerializedProperty.EqualContents(childProperty, enabledProp)) + { + rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; + rect.height = EditorGUI.GetPropertyHeight(childProperty); + EditorGUI.PropertyField(rect, childProperty, true); + } + childProperty.NextVisible(false); + } + --EditorGUI.indentLevel; + } + return enabledProp.boolValue; + } + + public static bool EnabledFoldoutSingleLine( + Rect rect, SerializedProperty property, + string enabledPropertyName, string disabledToggleLabel, + GUIContent label = null) + { + var enabledProp = property.FindPropertyRelative(enabledPropertyName); + if (enabledProp == null) + { + EditorGUI.PropertyField(rect, property, true); + rect.x += EditorGUIUtility.labelWidth; + EditorGUI.LabelField(rect, new GUIContent($"unknown field `{enabledPropertyName}`")); + return property.isExpanded; + } + rect.height = EditorGUIUtility.singleLineHeight; + label ??= new GUIContent(property.displayName, enabledProp.tooltip); + EditorGUI.PropertyField(rect, enabledProp, label); + if (!enabledProp.boolValue) + { + if (!string.IsNullOrEmpty(disabledToggleLabel)) + { + var w = EditorGUIUtility.labelWidth + EditorGUIUtility.singleLineHeight + 3; + var r = rect; r.x += w; r.width -= w; + var oldColor = GUI.color; + GUI.color = new(oldColor.r, oldColor.g, oldColor.g, 0.5f); + EditorGUI.LabelField(r, disabledToggleLabel); + GUI.color = oldColor; + } + } + else + { + rect.width -= EditorGUIUtility.labelWidth + EditorGUIUtility.singleLineHeight; + rect.x += EditorGUIUtility.labelWidth + EditorGUIUtility.singleLineHeight; + + var childProperty = property.Copy(); + var endProperty = childProperty.GetEndProperty(); + childProperty.NextVisible(true); + while (!SerializedProperty.EqualContents(childProperty, endProperty)) + { + if (!SerializedProperty.EqualContents(childProperty, enabledProp)) + { + var oldWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 6; // for dragging + EditorGUI.PropertyField(rect, childProperty, new GUIContent(" ")); + EditorGUIUtility.labelWidth = oldWidth; + break; // Draw only the first property + } + childProperty.NextVisible(false); + } + } + return enabledProp.boolValue; + } + } +} +#endif diff --git a/com.unity.cinemachine/Editor/Obsolete/ObsoleteInspectorUtility.cs.meta b/com.unity.cinemachine/Editor/Obsolete/ObsoleteInspectorUtility.cs.meta new file mode 100644 index 000000000..8fcdcebe6 --- /dev/null +++ b/com.unity.cinemachine/Editor/Obsolete/ObsoleteInspectorUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e431aac1b3a84b64e93b38e833c448be +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.cinemachine/Editor/PropertyDrawers/CameraTargetPropertyDrawer.cs b/com.unity.cinemachine/Editor/PropertyDrawers/CameraTargetPropertyDrawer.cs index f6156e9dd..630d032fb 100644 --- a/com.unity.cinemachine/Editor/PropertyDrawers/CameraTargetPropertyDrawer.cs +++ b/com.unity.cinemachine/Editor/PropertyDrawers/CameraTargetPropertyDrawer.cs @@ -23,7 +23,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) VisualElement CreateTargetProperty(SerializedProperty property, SerializedProperty customProp) { var row = InspectorUtility.PropertyRow(property, out _); - row.Add(InspectorUtility.MiniPopupButton(null, new ContextualMenuManipulator((evt) => + row.Contents.Add(InspectorUtility.MiniPopupButton(null, new ContextualMenuManipulator((evt) => { evt.menu.AppendAction("Convert to TargetGroup", (action) => diff --git a/com.unity.cinemachine/Editor/PropertyDrawers/DelayedVectorPropertyDrawer.cs b/com.unity.cinemachine/Editor/PropertyDrawers/DelayedVectorPropertyDrawer.cs index 4bf7e8662..62d723a9a 100644 --- a/com.unity.cinemachine/Editor/PropertyDrawers/DelayedVectorPropertyDrawer.cs +++ b/com.unity.cinemachine/Editor/PropertyDrawers/DelayedVectorPropertyDrawer.cs @@ -21,7 +21,7 @@ VisualElement ChildField(SerializedProperty p) if (p == null) return new VisualElement { style = { flexBasis = 30, flexGrow = 1, marginLeft = 6 } }; var f = new InspectorUtility.CompactPropertyField(p) - { style = { flexBasis = 30, flexGrow = 1, marginLeft = 6 } }; + { style = { flexBasis = 30, flexGrow = 1, marginLeft = 9 } }; f.Label.style.minWidth = 15; f.OnInitialGeometry(() => { diff --git a/com.unity.cinemachine/Editor/PropertyDrawers/FoldoutWithEnabledButtonPropertyDrawer.cs b/com.unity.cinemachine/Editor/PropertyDrawers/FoldoutWithEnabledButtonPropertyDrawer.cs index 2fe3c9783..1436c1a55 100644 --- a/com.unity.cinemachine/Editor/PropertyDrawers/FoldoutWithEnabledButtonPropertyDrawer.cs +++ b/com.unity.cinemachine/Editor/PropertyDrawers/FoldoutWithEnabledButtonPropertyDrawer.cs @@ -75,7 +75,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) var row = new InspectorUtility.LabeledRow(preferredLabel, enabledProp.tooltip); var toggle = row.Contents.AddChild(new Toggle("") - { style = { flexGrow = 0, marginTop = 2, marginLeft = 0, alignSelf = Align.Center }}); + { style = { flexGrow = 0, marginTop = 2, marginLeft = 3, alignSelf = Align.Center }}); toggle.BindProperty(enabledProp); Label disabledText = null; @@ -88,7 +88,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) var childField = row.Contents.AddChild(new PropertyField(childProperty, "") { style = { flexGrow = 1, marginTop = -1, marginLeft = 5, marginBottom = -1 }}); childLabel.AddDelayedFriendlyPropertyDragger(childProperty, childField); - childField.RemoveFromClassList(InspectorUtility.kAlignFieldClass); + childField.RemoveFromClassList(InspectorUtility.AlignFieldClassName); row.TrackPropertyWithInitialCallback(enabledProp, (p) => { diff --git a/com.unity.cinemachine/Editor/PropertyDrawers/InputAxisPropertyDrawer.cs b/com.unity.cinemachine/Editor/PropertyDrawers/InputAxisPropertyDrawer.cs index 0dc7a901d..a497cf089 100644 --- a/com.unity.cinemachine/Editor/PropertyDrawers/InputAxisPropertyDrawer.cs +++ b/com.unity.cinemachine/Editor/PropertyDrawers/InputAxisPropertyDrawer.cs @@ -12,19 +12,12 @@ partial class InputAxisWithNamePropertyDrawer : PropertyDrawer public override VisualElement CreatePropertyGUI(SerializedProperty property) { // When foldout is closed, we display the axis value on the same line, for convenience - var foldout = new Foldout { text = property.displayName, tooltip = property.tooltip, value = property.isExpanded }; - foldout.RegisterValueChangedCallback((evt) => - { - if (evt.target == foldout) - { - property.isExpanded = evt.newValue; - property.serializedObject.ApplyModifiedProperties(); - evt.StopPropagation(); - } - }); + var foldout = new Foldout { text = property.displayName, tooltip = property.tooltip }; + foldout.BindProperty(property); + var valueProp = property.FindPropertyRelative(() => def.Value); var valueLabel = new Label(" ") { style = { minWidth = InspectorUtility.SingleLineHeight * 2}}; - var valueField = new InspectorUtility.CompactPropertyField(valueProp, "") { style = { flexGrow = 1}}; + var valueField = new InspectorUtility.CompactPropertyField(valueProp, "") { style = { flexGrow = 1, marginLeft = 4}}; valueField.OnInitialGeometry(() => valueField.SafeSetIsDelayed()); valueLabel.AddDelayedFriendlyPropertyDragger(valueProp, valueField); @@ -32,12 +25,8 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) // We want dynamic dragging on the value, even if isDelayed is set var valueFieldRow = foldout.AddChild(new InspectorUtility.LabeledRow( - valueProp.displayName, valueProp.tooltip, new PropertyField(valueProp, ""))); - valueFieldRow.Contents.OnInitialGeometry(() => - { - valueFieldRow.Contents.SafeSetIsDelayed(); - valueFieldRow.Contents.Q().style.marginLeft = 0; - }); + valueProp.displayName, valueProp.tooltip, new PropertyField(valueProp, "") { style = { marginLeft = 0 }})); + valueFieldRow.Contents.OnInitialGeometry(() => valueFieldRow.Contents.SafeSetIsDelayed()); valueFieldRow.Label.AddDelayedFriendlyPropertyDragger(valueProp, valueFieldRow.Contents); var centerField = foldout.AddChild(new PropertyField(property.FindPropertyRelative(() => def.Center))); diff --git a/com.unity.cinemachine/Editor/PropertyDrawers/LensSettingsPropertyDrawer.cs b/com.unity.cinemachine/Editor/PropertyDrawers/LensSettingsPropertyDrawer.cs index 7f70f6fb2..945a4fed6 100644 --- a/com.unity.cinemachine/Editor/PropertyDrawers/LensSettingsPropertyDrawer.cs +++ b/com.unity.cinemachine/Editor/PropertyDrawers/LensSettingsPropertyDrawer.cs @@ -86,7 +86,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) var ux = new VisualElement(); // When foldout is closed, we display the FOV on the same line, for convenience - var foldout = new Foldout { text = property.displayName, tooltip = property.tooltip, value = property.isExpanded }; + var foldout = new Foldout { text = property.displayName, tooltip = property.tooltip }; foldout.BindProperty(property); var outerFovControl = new FovPropertyControl(property, true) { style = { flexGrow = 1 }}; @@ -185,7 +185,8 @@ public FovPropertyControl(SerializedProperty property, bool hideLabel) : base(hi var physicalProp = property.FindPropertyRelative(() => s_Def.PhysicalProperties); m_SensorSizeProperty = physicalProp.FindPropertyRelative(() => s_Def.PhysicalProperties.SensorSize); - m_Control = Contents.AddChild(new FloatField("") { style = {flexBasis = 20, flexGrow = 2, marginLeft = 0}}); + m_Control = Contents.AddChild(new FloatField("") + { style = { flexBasis = 20, flexGrow = 2, marginLeft = hideLabel ? -3 : 3 }}); m_Control.RegisterValueChangedCallback(OnControlValueChanged); Label.SetVisible(!hideLabel); Label.AddToClassList("unity-base-field__label--with-dragger"); @@ -193,7 +194,7 @@ public FovPropertyControl(SerializedProperty property, bool hideLabel) : base(hi m_Control.OnInitialGeometry(() => m_Control.SafeSetIsDelayed()); m_Presets = Contents.AddChild(new PopupField - { tooltip = "Customizable Lens Palette", style = {flexBasis = 20, flexGrow = 1}}); + { tooltip = "Customizable Lens Palette", style = { flexBasis = 20, flexGrow = 1 }}); m_Presets.RegisterValueChangedCallback(OnPresetValueChanged); ShortLabel = new Label("X") { style = { alignSelf = Align.Center, opacity = 0.5f }}; diff --git a/com.unity.cinemachine/Editor/PropertyDrawers/MinMaxRangeSliderPropertyDrawer.cs b/com.unity.cinemachine/Editor/PropertyDrawers/MinMaxRangeSliderPropertyDrawer.cs index c252f9489..dd748645b 100644 --- a/com.unity.cinemachine/Editor/PropertyDrawers/MinMaxRangeSliderPropertyDrawer.cs +++ b/com.unity.cinemachine/Editor/PropertyDrawers/MinMaxRangeSliderPropertyDrawer.cs @@ -14,7 +14,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) var minField = new FloatField { value = property.vector2Value.x, isDelayed = true, style = { flexGrow = 1, flexBasis = 0 }}; - minField.AddToClassList(InspectorUtility.kAlignFieldClass); + minField.AddToClassList(InspectorUtility.AlignFieldClassName); minField.TrackPropertyValue(property, (evt) => minField.value = evt.vector2Value.x); minField.RegisterValueChangedCallback((evt) => { @@ -26,6 +26,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) var slider = new MinMaxSlider() { + focusable = false, lowLimit = a.Min, highLimit = a.Max, style = { flexGrow = 3, flexBasis = 0, paddingLeft = 5, paddingRight = 5 } }; @@ -42,7 +43,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) property.serializedObject.ApplyModifiedProperties(); }); - var row = new InspectorUtility.LeftRightRow { style = { flexGrow = 1 }}; + var row = new InspectorUtility.LeftRightRow(); row.Left.Add(new Label { text = property.displayName, tooltip = property.tooltip, style = { alignSelf = Align.Center }}); row.Right.Add(minField); row.Right.Add(slider); diff --git a/com.unity.cinemachine/Editor/PropertyDrawers/OutputChannelsPropertyDrawer.cs b/com.unity.cinemachine/Editor/PropertyDrawers/OutputChannelsPropertyDrawer.cs index 9c31773ef..70c0d7af5 100644 --- a/com.unity.cinemachine/Editor/PropertyDrawers/OutputChannelsPropertyDrawer.cs +++ b/com.unity.cinemachine/Editor/PropertyDrawers/OutputChannelsPropertyDrawer.cs @@ -20,7 +20,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) var row = new InspectorUtility.LabeledRow(preferredLabel, property.tooltip); var selector = row.Contents.AddChild(new MaskField(choices, 1) - { tooltip = property.tooltip, style = { flexBasis = 100, flexGrow = 1, marginLeft = 0 }}); + { tooltip = property.tooltip, style = { flexBasis = 100, flexGrow = 1, marginLeft = 3 }}); selector.BindProperty(property); row.Contents.Add(InspectorUtility.MiniPopupButton(null, new ContextualMenuManipulator((evt) => diff --git a/com.unity.cinemachine/Editor/PropertyDrawers/SensorSizePropertyDrawer.cs b/com.unity.cinemachine/Editor/PropertyDrawers/SensorSizePropertyDrawer.cs index bf2f4fd4b..245e63d4b 100644 --- a/com.unity.cinemachine/Editor/PropertyDrawers/SensorSizePropertyDrawer.cs +++ b/com.unity.cinemachine/Editor/PropertyDrawers/SensorSizePropertyDrawer.cs @@ -75,8 +75,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) property.serializedObject.ApplyModifiedProperties(); // Find matching preset (if any) - var index = s_PresetSizes.FindIndex( - e => Mathf.Approximately(v.x, e.x) && Mathf.Approximately(v.y, e.y)); + var index = s_PresetSizes.FindIndex(e => Mathf.Approximately(v.x, e.x) && Mathf.Approximately(v.y, e.y)); presets.SetValueWithoutNotify(index >= 0 ? s_PresetNames[index] : "Custom"); }); diff --git a/com.unity.cinemachine/Editor/PropertyDrawers/SplineAutoDollyPropertyDrawer.cs b/com.unity.cinemachine/Editor/PropertyDrawers/SplineAutoDollyPropertyDrawer.cs index 5f868676c..f9226f62d 100644 --- a/com.unity.cinemachine/Editor/PropertyDrawers/SplineAutoDollyPropertyDrawer.cs +++ b/com.unity.cinemachine/Editor/PropertyDrawers/SplineAutoDollyPropertyDrawer.cs @@ -27,7 +27,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) choices = AutoDollyMenuItems.s_ItemNames, style = { flexGrow = 1 } }); - dropdown.AddToClassList(InspectorUtility.kAlignFieldClass); + dropdown.AddToClassList(InspectorUtility.AlignFieldClassName); dropdown.RegisterValueChangedCallback((evt) => { var index = AutoDollyMenuItems.GetTypeIndex(evt.newValue); diff --git a/com.unity.cinemachine/Editor/PropertyDrawers/TagFieldPropertyDrawer.cs b/com.unity.cinemachine/Editor/PropertyDrawers/TagFieldPropertyDrawer.cs index 5fc82bac6..d11ded050 100644 --- a/com.unity.cinemachine/Editor/PropertyDrawers/TagFieldPropertyDrawer.cs +++ b/com.unity.cinemachine/Editor/PropertyDrawers/TagFieldPropertyDrawer.cs @@ -11,7 +11,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) { var row = new InspectorUtility.LabeledRow(property.displayName, property.tooltip); - var enabled = row.Contents.AddChild(new Toggle() { style = { marginTop = 2, marginLeft = 0 }}); + var enabled = row.Contents.AddChild(new Toggle() { style = { marginTop = 2, marginLeft = 3 }}); enabled.RegisterValueChangedCallback((evt) => { property.stringValue = evt.newValue ? "Untagged" : string.Empty; diff --git a/com.unity.cinemachine/Editor/PropertyDrawers/Vector2AsRangePropertyDrawer.cs b/com.unity.cinemachine/Editor/PropertyDrawers/Vector2AsRangePropertyDrawer.cs index a0fe66cba..abbece3a9 100644 --- a/com.unity.cinemachine/Editor/PropertyDrawers/Vector2AsRangePropertyDrawer.cs +++ b/com.unity.cinemachine/Editor/PropertyDrawers/Vector2AsRangePropertyDrawer.cs @@ -23,7 +23,6 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) { minField.SafeSetIsDelayed(); maxField.SafeSetIsDelayed(); - minField.Q().style.marginLeft = 2; }); label.AddDelayedFriendlyPropertyDragger(xProp, minField); diff --git a/com.unity.cinemachine/Editor/Timeline/CinemachineShotEditor.cs b/com.unity.cinemachine/Editor/Timeline/CinemachineShotEditor.cs index e79b57610..adb6057a2 100644 --- a/com.unity.cinemachine/Editor/Timeline/CinemachineShotEditor.cs +++ b/com.unity.cinemachine/Editor/Timeline/CinemachineShotEditor.cs @@ -105,7 +105,7 @@ public override VisualElement CreateInspectorGUI() tooltip = CinemachineTimelinePrefs.s_AutoCreateLabel.tooltip, value = CinemachineTimelinePrefs.AutoCreateShotFromSceneView.Value }); - toggle.AddToClassList(InspectorUtility.kAlignFieldClass); + toggle.AddToClassList(InspectorUtility.AlignFieldClassName); toggle.RegisterValueChangedCallback((evt) => CinemachineTimelinePrefs.AutoCreateShotFromSceneView.Value = evt.newValue); // Cached scrubbing diff --git a/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs b/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs index 7a79868b6..3df513a4e 100644 --- a/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs @@ -57,7 +57,7 @@ public static void AddCameraStatus(this UnityEditor.Editor editor, VisualElement { text = "Solo", style = { flexGrow = 1, paddingLeft = 0, paddingRight = 0, - marginLeft = 0, marginRight = 0, borderLeftWidth = 1, borderRightWidth = 1 } + marginLeft = 3, marginRight = 0, borderLeftWidth = 1, borderRightWidth = 1 } }); var updateMode = row.Contents.AddChild(new Label("(Update Mode)") { style = { flexGrow = 0, alignSelf = Align.Center }}); updateMode.SetEnabled(false); @@ -290,7 +290,7 @@ public static void AddExtensionsDropdown(this UnityEditor.Editor editor, VisualE text = "(select)", style = { - flexGrow = 1, marginRight = 0, marginLeft = 3, + flexGrow = 1, marginRight = -2, marginLeft = 3, paddingTop = 0, paddingBottom = 0, paddingLeft = 1, height = InspectorUtility.SingleLineHeight + 2, unityTextAlign = TextAnchor.MiddleLeft @@ -392,7 +392,7 @@ public static void AddGlobalControls(this UnityEditor.Editor editor, VisualEleme tooltip = CinemachineCorePrefs.s_SaveDuringPlayLabel.tooltip, value = SaveDuringPlay.Enabled }); - toggle.AddToClassList(InspectorUtility.kAlignFieldClass); + toggle.AddToClassList(InspectorUtility.AlignFieldClassName); toggle.RegisterValueChangedCallback((evt) => { SaveDuringPlay.Enabled = evt.newValue; @@ -409,7 +409,7 @@ public static void AddGlobalControls(this UnityEditor.Editor editor, VisualEleme index = index, style = { flexGrow = 1 } }); - dropdown.AddToClassList(InspectorUtility.kAlignFieldClass); + dropdown.AddToClassList(InspectorUtility.AlignFieldClassName); dropdown.RegisterValueChangedCallback((evt) => { CinemachineCorePrefs.ShowInGameGuides.Value = evt.newValue != choices[0]; diff --git a/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs b/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs index 1087a861e..091c83005 100644 --- a/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs @@ -13,7 +13,7 @@ namespace Unity.Cinemachine.Editor /// Collection of tools and helpers for drawing inspectors /// [InitializeOnLoad] - static class InspectorUtility + static partial class InspectorUtility { /// /// Callback that happens whenever something undoable happens, either with @@ -31,244 +31,7 @@ static InspectorUtility() static void OnUserDidSomething() => UserDidSomething?.Invoke(); static void OnUserDidSomethingStream(ref ObjectChangeEventStream stream) => UserDidSomething?.Invoke(); } - -#if !CINEMACHINE_NO_CM2_SUPPORT - /// Put multiple properties on a single inspector line, with - /// optional label overrides. Passing null as a label (or sublabel) override will - /// cause the property's displayName to be used as a label. For no label at all, - /// pass GUIContent.none. - /// Rect in which to draw - /// Main label - /// Properties to place on the line - /// Sublabels for the properties - public static void MultiPropertyOnLine( - Rect rect, - GUIContent label, - SerializedProperty[] props, GUIContent[] subLabels) - { - if (props == null || props.Length == 0) - return; - - const int hSpace = 2; - int indentLevel = EditorGUI.indentLevel; - float labelWidth = EditorGUIUtility.labelWidth; - - float totalSubLabelWidth = 0; - int numBoolColumns = 0; - List actualLabels = new List(); - for (int i = 0; i < props.Length; ++i) - { - GUIContent sublabel = new GUIContent(props[i].displayName, props[i].tooltip); - if (subLabels != null && subLabels.Length > i && subLabels[i] != null) - sublabel = subLabels[i]; - actualLabels.Add(sublabel); - totalSubLabelWidth += GUI.skin.label.CalcSize(sublabel).x; - if (i > 0) - totalSubLabelWidth += hSpace; - // Special handling for toggles, or it looks stupid - if (props[i].propertyType == SerializedPropertyType.Boolean) - { - totalSubLabelWidth += rect.height + hSpace; - ++numBoolColumns; - } - } - - float subFieldWidth = rect.width - labelWidth - totalSubLabelWidth; - float numCols = props.Length - numBoolColumns; - float colWidth = numCols == 0 ? 0 : subFieldWidth / numCols; - - // Main label. If no first sublabel, then main label must take on that - // role, for mouse dragging value-scrolling support - int subfieldStartIndex = 0; - if (label == null) - label = new GUIContent(props[0].displayName, props[0].tooltip); - if (actualLabels[0] != GUIContent.none) - rect = EditorGUI.PrefixLabel(rect, label); - else - { - rect.width = labelWidth + colWidth; - EditorGUI.PropertyField(rect, props[0], label); - rect.x += rect.width + hSpace; - subfieldStartIndex = 1; - } - for (int i = subfieldStartIndex; i < props.Length; ++i) - { - EditorGUI.indentLevel = 0; - EditorGUIUtility.labelWidth = GUI.skin.label.CalcSize(actualLabels[i]).x; - if (props[i].propertyType == SerializedPropertyType.Boolean) - { - rect.x += hSpace; - rect.width = EditorGUIUtility.labelWidth + rect.height; - EditorGUI.BeginProperty(rect, actualLabels[i], props[i]); - props[i].boolValue = EditorGUI.ToggleLeft(rect, actualLabels[i], props[i].boolValue); - } - else - { - rect.width = EditorGUIUtility.labelWidth + colWidth; - EditorGUI.BeginProperty(rect, actualLabels[i], props[i]); - EditorGUI.PropertyField(rect, props[i], actualLabels[i]); - } - EditorGUI.EndProperty(); - rect.x += rect.width + hSpace; - } - - EditorGUIUtility.labelWidth = labelWidth; - EditorGUI.indentLevel = indentLevel; - } - - public static float PropertyHeightOfChidren(SerializedProperty property) - { - float height = 0; - var childProperty = property.Copy(); - var endProperty = childProperty.GetEndProperty(); - childProperty.NextVisible(true); - while (!SerializedProperty.EqualContents(childProperty, endProperty)) - { - height += EditorGUI.GetPropertyHeight(childProperty) - + EditorGUIUtility.standardVerticalSpacing; - childProperty.NextVisible(false); - } - return height - EditorGUIUtility.standardVerticalSpacing; - } - - public static void DrawChildProperties(Rect position, SerializedProperty property) - { - var childProperty = property.Copy(); - var endProperty = childProperty.GetEndProperty(); - childProperty.NextVisible(true); - while (!SerializedProperty.EqualContents(childProperty, endProperty)) - { - position.height = EditorGUI.GetPropertyHeight(childProperty); - EditorGUI.PropertyField(position, childProperty, true); - position.y += position.height + EditorGUIUtility.standardVerticalSpacing; - childProperty.NextVisible(false); - } - } - - public static void HelpBoxWithButton( - string message, MessageType messageType, - GUIContent buttonContent, Action onClicked) - { - float lineHeight = EditorGUIUtility.singleLineHeight; - var buttonSize = GUI.skin.label.CalcSize(buttonContent); - buttonSize.x += lineHeight; - - var rect = EditorGUI.IndentedRect(EditorGUILayout.GetControlRect(false, 2)); - - var boxContent = new GUIContent(message + "\n"); // to make room for the button - var boxWidth = rect.width; - var boxHeight = GUI.skin.GetStyle("helpbox").CalcHeight(boxContent, rect.width - 3 * lineHeight) + buttonSize.y; - - rect = EditorGUILayout.GetControlRect(false, boxHeight); - rect = EditorGUI.IndentedRect(rect); - rect.width = boxWidth; rect.height = boxHeight; - EditorGUI.HelpBox(rect, boxContent.text, messageType); - - rect.x += rect.width - buttonSize.x - 6; rect.width = buttonSize.x; - rect.y += rect.height - buttonSize.y - 6; rect.height = buttonSize.y; - if (GUI.Button(rect, buttonContent, EditorStyles.miniButton)) - onClicked(); - } - - public static float EnabledFoldoutHeight(SerializedProperty property, string enabledPropertyName) - { - var enabledProp = property.FindPropertyRelative(enabledPropertyName); - if (enabledProp == null) - return EditorGUI.GetPropertyHeight(property); - if (!enabledProp.boolValue) - return EditorGUIUtility.singleLineHeight; - return PropertyHeightOfChidren(property); - } - - public static bool EnabledFoldout( - Rect rect, SerializedProperty property, string enabledPropertyName, - GUIContent label = null) - { - var enabledProp = property.FindPropertyRelative(enabledPropertyName); - if (enabledProp == null) - { - EditorGUI.PropertyField(rect, property, true); - rect.x += EditorGUIUtility.labelWidth; - EditorGUI.LabelField(rect, new GUIContent($"unknown field `{enabledPropertyName}`")); - return property.isExpanded; - } - rect.height = EditorGUIUtility.singleLineHeight; - label ??= new GUIContent(property.displayName, enabledProp.tooltip); - EditorGUI.PropertyField(rect, enabledProp, label); - if (enabledProp.boolValue) - { - ++EditorGUI.indentLevel; - var childProperty = property.Copy(); - var endProperty = childProperty.GetEndProperty(); - childProperty.NextVisible(true); - while (!SerializedProperty.EqualContents(childProperty, endProperty)) - { - if (!SerializedProperty.EqualContents(childProperty, enabledProp)) - { - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - rect.height = EditorGUI.GetPropertyHeight(childProperty); - EditorGUI.PropertyField(rect, childProperty, true); - } - childProperty.NextVisible(false); - } - --EditorGUI.indentLevel; - } - return enabledProp.boolValue; - } - - public static bool EnabledFoldoutSingleLine( - Rect rect, SerializedProperty property, - string enabledPropertyName, string disabledToggleLabel, - GUIContent label = null) - { - var enabledProp = property.FindPropertyRelative(enabledPropertyName); - if (enabledProp == null) - { - EditorGUI.PropertyField(rect, property, true); - rect.x += EditorGUIUtility.labelWidth; - EditorGUI.LabelField(rect, new GUIContent($"unknown field `{enabledPropertyName}`")); - return property.isExpanded; - } - rect.height = EditorGUIUtility.singleLineHeight; - label ??= new GUIContent(property.displayName, enabledProp.tooltip); - EditorGUI.PropertyField(rect, enabledProp, label); - if (!enabledProp.boolValue) - { - if (!string.IsNullOrEmpty(disabledToggleLabel)) - { - var w = EditorGUIUtility.labelWidth + EditorGUIUtility.singleLineHeight + 3; - var r = rect; r.x += w; r.width -= w; - var oldColor = GUI.color; - GUI.color = new (oldColor.r, oldColor.g, oldColor.g, 0.5f); - EditorGUI.LabelField(r, disabledToggleLabel); - GUI.color = oldColor; - } - } - else - { - rect.width -= EditorGUIUtility.labelWidth + EditorGUIUtility.singleLineHeight; - rect.x += EditorGUIUtility.labelWidth + EditorGUIUtility.singleLineHeight; - - var childProperty = property.Copy(); - var endProperty = childProperty.GetEndProperty(); - childProperty.NextVisible(true); - while (!SerializedProperty.EqualContents(childProperty, endProperty)) - { - if (!SerializedProperty.EqualContents(childProperty, enabledProp)) - { - var oldWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 6; // for dragging - EditorGUI.PropertyField(rect, childProperty, new GUIContent(" ")); - EditorGUIUtility.labelWidth = oldWidth; - break; // Draw only the first property - } - childProperty.NextVisible(false); - } - } - return enabledProp.boolValue; - } -#endif /// /// Add to a list all assets of a given type found in a given location /// @@ -319,7 +82,6 @@ public static string NicifyClassName(string name) { if (name.StartsWith("Cinemachine")) name = name.Substring(11); // Trim the prefix - return ObjectNames.NicifyVariableName(name); } @@ -331,30 +93,11 @@ public static string NicifyClassName(string name) /// The nicified name public static string NicifyClassName(Type type) { - var name = type.Name; - if (name.StartsWith("Cinemachine")) - name = name.Substring(11); // Trim the prefix - - name = ObjectNames.NicifyVariableName(name); - + var name = NicifyClassName(type.Name); if (type.GetCustomAttribute() != null) name += " (Deprecated)"; - return name; } - - // Temporarily here - /// - /// Creates a new GameObject. - /// - /// Name to give the object. - /// Optional components to add. - /// The GameObject that was created. - [Obsolete("Use ObjectFactory.CreateGameObject(string name, params Type[] types) instead.")] - public static GameObject CreateGameObject(string name, params Type[] types) - { - return ObjectFactory.CreateGameObject(name, types); - } private static int m_lastRepaintFrame; @@ -372,7 +115,7 @@ public static void RepaintGameView(UnityEngine.Object unused = null) UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); } - static Dictionary s_AssignableTypes = new Dictionary(); + static Dictionary s_AssignableTypes = new (); public const string s_NoneString = "(none)"; public static string GetAssignableBehaviourNames(Type inputType) @@ -398,14 +141,8 @@ public static string GetAssignableBehaviourNames(Type inputType) return s_AssignableTypes[inputType]; } - ///============================================================================================== - ///============================================================================================== - /// UI Elements utilities - ///============================================================================================== - ///============================================================================================== - /// Aligns fields created by UI toolkit the unity inspector standard way. - public static string kAlignFieldClass => BaseField.alignedFieldUssClassName; + public static string AlignFieldClassName => BaseField.alignedFieldUssClassName; // this is a hack to get around some vertical alignment issues in UITK public static float SingleLineHeight => EditorGUIUtility.singleLineHeight - EditorGUIUtility.standardVerticalSpacing; @@ -515,7 +252,7 @@ public static void AddHeader(this VisualElement ux, string text, string tooltip row.focusable = false; row.Label.style.flexGrow = 1; row.Label.style.paddingTop = verticalPad; - row.Label.style.paddingBottom = EditorGUIUtility.standardVerticalSpacing; + row.Label.style.paddingBottom = EditorGUIUtility.standardVerticalSpacing - 2; } /// @@ -617,34 +354,6 @@ public static Button MiniDropdownButton(string tooltip = null, ContextualMenuMan return button; } - /// - /// This is a hack to get proper layout within th inspector. - /// There seems to be no sanctioned way to get the current inspector label width. - /// This creates a row with a properly-sized label in front of it. - /// - public class LabeledRow : BaseField // bool is just a dummy because it has to be something - { - public Label Label => labelElement; - public VisualElement Contents { get; } - - public LabeledRow(string label, string tooltip = "") - : this (label, tooltip, new VisualElement()) - { - style.flexDirection = FlexDirection.Row; - style.flexGrow = 1; - Contents.style.flexDirection = FlexDirection.Row; - Contents.style.flexGrow = 1; - } - - public LabeledRow(string label, string tooltip, VisualElement contents) : base(label, contents) - { - Contents = contents; - AddToClassList(alignedFieldUssClassName); - this.tooltip = tooltip; - Label.tooltip = tooltip; - } - } - /// /// This is an inspector container with 2 side-by-side rows. The Left row's width is /// locked to the inspector field label size, for proper alignment. @@ -667,22 +376,95 @@ public class LeftRightRow : VisualElement public LeftRightRow() { // This is to peek at the resolved label width - var hack = AddChild(this, new LabeledRow(" ") { style = { height = 1, marginTop = -2 }}); - - var row = AddChild(this, new VisualElement - { style = { flexDirection = FlexDirection.Row }}); - Left = row.AddChild(new VisualElement - { style = { flexDirection = FlexDirection.Row, flexGrow = 0 }}); - Right = row.AddChild(new VisualElement - { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }}); - - hack.Label.RegisterCallback((_) => + Add(new AlignFieldSizer { OnLabelWidthChanged = (w) => { if (KillLeftMargin) - hack.style.marginLeft = 0; - Left.style.width = hack.Label.resolvedStyle.width + DivisionOffset; - row.style.marginLeft = hack.resolvedStyle.marginLeft; - }); + style.marginLeft = 0; + Left.style.width = w + DivisionOffset; + }}); + + style.marginLeft = 3; + var row = AddChild(this, new VisualElement { style = { flexDirection = FlexDirection.Row }}); + Left = row.AddChild(new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 0 }}); + Right = row.AddChild(new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1, marginLeft = 2 }}); + } + + // This is a hacky thing to create custom inspector rows with labels that are the correct size + class AlignFieldSizer : BaseField // bool is just a dummy because it has to be something + { + public Action OnLabelWidthChanged; + public AlignFieldSizer() : base (" ", new VisualElement()) + { + focusable = false; + style.flexDirection = FlexDirection.Row; + style.flexGrow = 1; + style.height = 1; + style.marginTop = -2; + AddToClassList(AlignFieldClassName); + labelElement.RegisterCallback((_) + => OnLabelWidthChanged?.Invoke(labelElement.resolvedStyle.width)); + } + } + } + + /// + /// This creates a row with a properly-sized label in front of it. + /// The label's width is locked to the inspector field label size, for proper alignment. + /// + public class LabeledRow : VisualElement + { + public Label Label { get; private set; } + public VisualElement Contents { get; private set; } + + public LabeledRow(string label, string tooltip, VisualElement contents) + { + var row = this.AddChild(new LeftRightRow() { style = { flexGrow = 1 }}); + Label = row.Left.AddChild(new Label(label) { tooltip = tooltip, style = { alignSelf = Align.Center, flexGrow = 1 }}); + Contents = row.Right.AddChild(contents); + style.marginRight = 0; + Contents.tooltip = tooltip; + Contents.style.marginRight = 0; + Contents.style.flexGrow = 1; + } + + public LabeledRow(string label, string tooltip = "") + : this(label, tooltip, new VisualElement { style = { flexDirection = FlexDirection.Row }}) {} + } + + /// + /// A row containing a property field. Suitable for adding widgets next to the property field. + /// + public static LabeledRow PropertyRow( + SerializedProperty property, out PropertyField propertyField, string label = null) + { + var row = new LabeledRow(label ?? property.displayName, property.tooltip); + propertyField = row.Contents.AddChild(new PropertyField(property, "") + { style = { flexGrow = 1, flexBasis = SingleLineHeight * 5 }}); + AddDelayedFriendlyPropertyDragger(row.Label, property, propertyField); + return row; + } + + /// + /// A property field with a minimally-sized label that does not respect inspector sizing. + /// Suitable for embedding in a row within the right-hand side of the inspector. + /// + public class CompactPropertyField : VisualElement + { + public Label Label; + public PropertyField Field; + + public CompactPropertyField(SerializedProperty property) : this(property, property.displayName) {} + + public CompactPropertyField(SerializedProperty property, string label, float minLabelWidth = 0) + { + style.flexDirection = FlexDirection.Row; + if (!string.IsNullOrEmpty(label)) + Label = AddChild(this, new Label(label) + { tooltip = property?.tooltip, style = { alignSelf = Align.Center, minWidth = minLabelWidth }}); + Field = AddChild(this, new PropertyField(property, "") { style = { flexGrow = 1, flexBasis = 10 } }); + Field.style.marginLeft = Field.style.marginLeft.value.value - 1; + if (Label != null) + AddDelayedFriendlyPropertyDragger(Label, property, Field); } } @@ -756,70 +538,26 @@ public FoldoutWithOverlay(Foldout foldout, VisualElement overlay, Label overlayL } } - /// - /// A property field with a minimally-sized label that does not respect inspector sizing. - /// Suitable for embedding in a row within the right-hand side of the inspector. - /// - public class CompactPropertyField : VisualElement - { - public Label Label; - public PropertyField Field; - - public CompactPropertyField(SerializedProperty property) : this(property, property.displayName) {} - - public CompactPropertyField(SerializedProperty property, string label, float minLabelWidth = 0) - { - style.flexDirection = FlexDirection.Row; - if (!string.IsNullOrEmpty(label)) - Label = AddChild(this, new Label(label) - { tooltip = property?.tooltip, style = { alignSelf = Align.Center, minWidth = minLabelWidth }}); - Field = AddChild(this, new PropertyField(property, "") { style = { flexGrow = 1, flexBasis = 10 } }); - if (Label != null) - AddDelayedFriendlyPropertyDragger(Label, property, Field); - } - } - - /// - /// A row containing a property field. Suitable for adding widgets nest to the property field. - /// - public static LabeledRow PropertyRow( - SerializedProperty property, out PropertyField propertyField, string label = null) - { - var row = new LabeledRow(label ?? property.displayName, property.tooltip); - var field = propertyField = row.Contents.AddChild(new PropertyField(property, "") - { style = { flexGrow = 1, flexBasis = SingleLineHeight * 5 }}); - AddDelayedFriendlyPropertyDragger(row.Label, property, propertyField); - - // Kill any left margin that gets inserted into the property field - field.OnInitialGeometry(() => - { - var children = field.Children().GetEnumerator(); - if (children.MoveNext()) - children.Current.style.marginLeft = 0; - children.Dispose(); - }); - return row; - } - public static VisualElement HelpBoxWithButton( string message, HelpBoxMessageType messageType, string buttonText, Action onClicked, ContextualMenuManipulator contextMenu = null) { var box = new VisualElement { style = { - flexDirection = FlexDirection.Column, + flexDirection = FlexDirection.Row, paddingTop = 8, paddingBottom = 8, paddingLeft = 8, paddingRight = 8 }}; box.AddToClassList("unity-help-box"); + var innerBox = box.AddChild(new VisualElement { style = { flexDirection = FlexDirection.Column, flexGrow = 1 }}); - var row = box.AddChild(new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }}); + var row = innerBox.AddChild(new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }}); var icon = row.AddChild(MiniHelpIcon("", messageType)); icon.style.alignSelf = Align.Auto; icon.style.marginRight = 6; var text = row.AddChild(new Label(message) { style = { flexGrow = 1, flexBasis = 100, alignSelf = Align.Center, whiteSpace = WhiteSpace.Normal }}); - var buttons = box.AddChild(new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1, marginTop = 6 }}); + var buttons = innerBox.AddChild(new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1, marginTop = 6 }}); buttons.Add(new VisualElement { style = { flexGrow = 1 }}); var button = buttons.AddChild(new Button(onClicked) { text = buttonText }); if (contextMenu != null) diff --git a/com.unity.cinemachine/Editor/Windows/WaveformWindow.cs b/com.unity.cinemachine/Editor/Windows/WaveformWindow.cs index 276745167..2f83fac70 100644 --- a/com.unity.cinemachine/Editor/Windows/WaveformWindow.cs +++ b/com.unity.cinemachine/Editor/Windows/WaveformWindow.cs @@ -62,7 +62,7 @@ public void CreateGUI() var ux = rootVisualElement; var exposureField = ux.AddChild(new Slider("Exposure", 0.01f, 2) { value = m_WaveformGenerator.Exposure, showInputField = true }); - exposureField.RemoveFromClassList(InspectorUtility.kAlignFieldClass); + exposureField.RemoveFromClassList(InspectorUtility.AlignFieldClassName); exposureField.RegisterValueChangedCallback((evt) => { m_WaveformGenerator.Exposure = evt.newValue; diff --git a/com.unity.cinemachine/Runtime/Behaviours/CinemachineTargetGroup.cs b/com.unity.cinemachine/Runtime/Behaviours/CinemachineTargetGroup.cs index 296811328..c938cf391 100644 --- a/com.unity.cinemachine/Runtime/Behaviours/CinemachineTargetGroup.cs +++ b/com.unity.cinemachine/Runtime/Behaviours/CinemachineTargetGroup.cs @@ -173,7 +173,7 @@ void Reset() //============================================ // Legacy support - [SerializeField, FormerlySerializedAs("m_Targets")] + [HideInInspector, SerializeField, FormerlySerializedAs("m_Targets")] Target[] m_LegacyTargets; void Awake() diff --git a/com.unity.cinemachine/Runtime/Components/CinemachineFollow.cs b/com.unity.cinemachine/Runtime/Components/CinemachineFollow.cs index c62f9e813..9fa72fdc6 100644 --- a/com.unity.cinemachine/Runtime/Components/CinemachineFollow.cs +++ b/com.unity.cinemachine/Runtime/Components/CinemachineFollow.cs @@ -20,13 +20,13 @@ namespace Unity.Cinemachine [HelpURL(Documentation.BaseURL + "manual/CinemachineFollow.html")] public class CinemachineFollow : CinemachineComponentBase { + /// Settings to control damping for target tracking. + public TrackerSettings TrackerSettings = TrackerSettings.Default; + /// The distance which the camera will attempt to maintain from the tracking target [Tooltip("The distance vector that the camera will attempt to maintain from the tracking target")] public Vector3 FollowOffset = Vector3.back * 10f; - /// Settings to control damping for target tracking. - public TrackerSettings TrackerSettings = TrackerSettings.Default; - Tracker m_TargetTracker; /// Derived classes should call this from their OnValidate() implementation From 691da919079ef12b04e415f35ba11a8176f521d7 Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Thu, 9 May 2024 16:00:25 -0400 Subject: [PATCH 02/30] Update InspectorUtility.cs --- com.unity.cinemachine/Editor/Utility/InspectorUtility.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs b/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs index 091c83005..e27b53fc5 100644 --- a/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs @@ -513,7 +513,7 @@ public FoldoutWithOverlay(Foldout foldout, VisualElement overlay, Label overlayL foldout.SetVisible(true); foldout.value = true; closedFoldout.SetValueWithoutNotify(false); - //foldout.Focus(); // GML why doesn't this work? + foldout.Q().Focus(); } evt.StopPropagation(); } @@ -530,7 +530,7 @@ public FoldoutWithOverlay(Foldout foldout, VisualElement overlay, Label overlayL foldout.SetVisible(false); closedFoldout.SetValueWithoutNotify(false); foldout.value = false; - //closedFoldout.Focus(); // GML why doesn't this work? + closedFoldout.Q().Focus(); } evt.StopPropagation(); } From 5524ac0acdc335005dffa2e379c70a659adc9334 Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Fri, 31 May 2024 07:35:13 -0400 Subject: [PATCH 03/30] merge errors --- .../Editors/CinemachineSplineRollEditor.cs | 2 +- .../Editor/Utility/InspectorUtility.cs | 50 +------------------ 2 files changed, 3 insertions(+), 49 deletions(-) diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs index 76f897214..60931aa5e 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs @@ -196,7 +196,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) InspectorUtility.AddDelayedFriendlyPropertyDragger(label, indexProp, indexField, false); ux.Add(new VisualElement { pickingMode = PickingMode.Ignore, style = { width = 12 }}); // pass-through for selecting row in list - ux.Add(new InspectorUtility.CompactPropertyField(valueProp.FindPropertyRelative(() => def.Value))); + ux.Add(new InspectorUtility.CompactPropertyField(valueProp.FindPropertyRelative(() => def.Value)) { style = { flexGrow = 1 }}); return ux; } } diff --git a/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs b/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs index a5535bbda..7f941995a 100644 --- a/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs @@ -450,7 +450,7 @@ public static LabeledRow PropertyRow( var row = new LabeledRow(label ?? property.displayName, property.tooltip); propertyField = row.Contents.AddChild(new PropertyField(property, "") { style = { flexGrow = 1, flexBasis = SingleLineHeight * 5 }}); - AddDelayedFriendlyPropertyDragger(row.Label, property, propertyField); + AddDelayedFriendlyPropertyDragger(row.Label, property, propertyField, true); return row; } @@ -474,7 +474,7 @@ public CompactPropertyField(SerializedProperty property, string label, float min Field = AddChild(this, new PropertyField(property, "") { style = { flexGrow = 1, flexBasis = 10 } }); Field.style.marginLeft = Field.style.marginLeft.value.value - 1; if (Label != null) - AddDelayedFriendlyPropertyDragger(Label, property, Field); + AddDelayedFriendlyPropertyDragger(Label, property, Field, true); } } @@ -548,52 +548,6 @@ public FoldoutWithOverlay(Foldout foldout, VisualElement overlay, Label overlayL } } - /// - /// A property field with a minimally-sized label that does not respect inspector sizing. - /// Suitable for embedding in a row within the right-hand side of the inspector. - /// - public class CompactPropertyField : VisualElement - { - public Label Label; - public PropertyField Field; - - public CompactPropertyField(SerializedProperty property) : this(property, property.displayName) {} - - public CompactPropertyField(SerializedProperty property, string label, float minLabelWidth = 0) - { - style.flexDirection = FlexDirection.Row; - style.flexGrow = 1; - if (!string.IsNullOrEmpty(label)) - Label = AddChild(this, new Label(label) - { tooltip = property?.tooltip, style = { alignSelf = Align.Center, minWidth = minLabelWidth }}); - Field = AddChild(this, new PropertyField(property, "") { style = { flexGrow = 1, flexBasis = 20 } }); - if (Label != null) - AddDelayedFriendlyPropertyDragger(Label, property, Field, true); - } - } - - /// - /// A row containing a property field. Suitable for adding widgets nest to the property field. - /// - public static LabeledRow PropertyRow( - SerializedProperty property, out PropertyField propertyField, string label = null) - { - var row = new LabeledRow(label ?? property.displayName, property.tooltip); - var field = propertyField = row.Contents.AddChild(new PropertyField(property, "") - { style = { flexGrow = 1, flexBasis = SingleLineHeight * 5 }}); - AddDelayedFriendlyPropertyDragger(row.Label, property, propertyField, true); - - // Kill any left margin that gets inserted into the property field - field.OnInitialGeometry(() => - { - var children = field.Children().GetEnumerator(); - if (children.MoveNext()) - children.Current.style.marginLeft = 0; - children.Dispose(); - }); - return row; - } - public static VisualElement HelpBoxWithButton( string message, HelpBoxMessageType messageType, string buttonText, Action onClicked, ContextualMenuManipulator contextMenu = null) From a3b774a6aad17fdde1e76920e9b079d23f3068fd Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Fri, 31 May 2024 07:40:26 -0400 Subject: [PATCH 04/30] Update CinemachineSplineRollEditor.cs --- .../Editor/Editors/CinemachineSplineRollEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs index 60931aa5e..e563a905f 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs @@ -187,7 +187,7 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property) var indexProp = property.FindPropertyRelative("m_Index"); var valueProp = property.FindPropertyRelative("m_Value"); - var ux = new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }}; + var ux = new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1, marginRight = 2 }}; ux.Add(new VisualElement { pickingMode = PickingMode.Ignore, style = { width = 12 }}); // pass-through for selecting row in list var label = ux.AddChild(new Label(indexProp.displayName) { tooltip = indexTooltip, style = { alignSelf = Align.Center }}); From b25b871eb26c85243b921e6ef4c71d22e88d2807 Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Tue, 4 Jun 2024 15:26:27 -0400 Subject: [PATCH 05/30] merge errors --- .../Editor/Editors/CinemachineSplineRollEditor.cs | 4 ++-- com.unity.cinemachine/Editor/Utility/InspectorUtility.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs index 7491df73b..f6dfb6c1c 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs @@ -59,12 +59,12 @@ public override VisualElement CreateInspectorGUI() ux.Add(new VisualElement { pickingMode = PickingMode.Ignore, style = { width = 12 }}); // pass-through for selecting row in list var label = ux.AddChild(new Label(indexProp.displayName) { tooltip = indexTooltip, style = { alignSelf = Align.Center }}); - var indexField = ux.AddChild(new PropertyField(indexProp, "") { style = { flexGrow = 1, flexBasis = 20 } }); + var indexField = ux.AddChild(new PropertyField(indexProp, "") { style = { flexGrow = 1, flexBasis = 20 }}); indexField.OnInitialGeometry(() => indexField.SafeSetIsDelayed()); label.AddDelayedFriendlyPropertyDragger(indexProp, indexField, (dragger) => dragger.OnStartDrag = () => list.selectedIndex = index); ux.Add(new VisualElement { pickingMode = PickingMode.Ignore, style = { width = 12 }}); // pass-through for selecting row in list - ux.Add(new InspectorUtility.CompactPropertyField(valueProp.FindPropertyRelative(() => def.Value), "Roll")); + ux.Add(new InspectorUtility.CompactPropertyField(valueProp.FindPropertyRelative(() => def.Value), "Roll") { style = { flexGrow = 1 }}); ((BindableElement)ux).BindProperty(element); // bind must be done at the end }; diff --git a/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs b/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs index 47f9a96d7..cd64f753d 100644 --- a/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs @@ -449,7 +449,7 @@ public static LabeledRow PropertyRow( var row = new LabeledRow(label ?? property.displayName, property.tooltip); propertyField = row.Contents.AddChild(new PropertyField(property, "") { style = { flexGrow = 1, flexBasis = SingleLineHeight * 5 }}); - AddDelayedFriendlyPropertyDragger(row.Label, property, propertyField, true); + AddDelayedFriendlyPropertyDragger(row.Label, property, propertyField, (d) => d.CancelDelayedWhenDragging = true); return row; } @@ -473,7 +473,7 @@ public CompactPropertyField(SerializedProperty property, string label, float min Field = AddChild(this, new PropertyField(property, "") { style = { flexGrow = 1, flexBasis = 10 } }); Field.style.marginLeft = Field.style.marginLeft.value.value - 1; if (Label != null) - AddDelayedFriendlyPropertyDragger(Label, property, Field, true); + AddDelayedFriendlyPropertyDragger(Label, property, Field, (d) => d.CancelDelayedWhenDragging = true); } } From 4b1a22d8f219abffeaaa10947459c0c3846e4064 Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Wed, 5 Jun 2024 09:19:41 -0400 Subject: [PATCH 06/30] bugfixes --- .../EmbeddedAssetPropertyDrawer.cs | 2 +- .../Utility/EmbeddedAssetEditorUtility.cs | 25 +++++++++++++------ .../Editor/Utility/InspectorUtility.cs | 1 + .../Editor/Utility/ReflectionHelpers.cs | 2 ++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/com.unity.cinemachine/Editor/PropertyDrawers/EmbeddedAssetPropertyDrawer.cs b/com.unity.cinemachine/Editor/PropertyDrawers/EmbeddedAssetPropertyDrawer.cs index 5b85afa50..1b4b802a9 100644 --- a/com.unity.cinemachine/Editor/PropertyDrawers/EmbeddedAssetPropertyDrawer.cs +++ b/com.unity.cinemachine/Editor/PropertyDrawers/EmbeddedAssetPropertyDrawer.cs @@ -7,7 +7,7 @@ namespace Unity.Cinemachine.Editor { - // GML todo: remove this class, replace with EmbeddedAssetEditorUtility.AddAssetSelectorWithPresets + // GML todo: remove this class, replace with EmbeddedAssetEditorUtility.AssetSelectorWithPresets // Currently only used by CinemachineImpulseDefinition editor [CustomPropertyDrawer(typeof(CinemachineEmbeddedAssetPropertyAttribute))] diff --git a/com.unity.cinemachine/Editor/Utility/EmbeddedAssetEditorUtility.cs b/com.unity.cinemachine/Editor/Utility/EmbeddedAssetEditorUtility.cs index e006aa77d..a6463db1e 100644 --- a/com.unity.cinemachine/Editor/Utility/EmbeddedAssetEditorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/EmbeddedAssetEditorUtility.cs @@ -100,8 +100,7 @@ void OnAssetChanged(SerializedProperty sProp, EmbeddedEditorContext eContext) if (embeddedInspectorParent != null) eContext.Inspector = embeddedInspectorParent.AddChild(new InspectorElement(eContext.Editor)); } - if (unassignedUx != null) - unassignedUx.SetVisible(target == null); + unassignedUx?.SetVisible(target == null); if (assignedUx != null) assignedUx.SetVisible(target != null); } @@ -124,8 +123,21 @@ public static VisualElement AssetSelectorWithPresets( SerializedProperty property, string label = null, string presetsPath = null, string warningTextIfNull = null) where T : ScriptableObject { - var row = InspectorUtility.PropertyRow(property, out var selector, label); - var contents = row.Contents; + VisualElement ux; + VisualElement contents; + if (label == string.Empty) + { + contents = new VisualElement { style = { flexGrow = 1, flexDirection = FlexDirection.Row }}; + ux = contents; + } + else + { + var row = new InspectorUtility.LabeledRow(label ?? property.displayName, property.tooltip); + contents = row.Contents; + ux = row; + } + + var selector = contents.AddChild(new PropertyField(property, "") { style = { flexGrow = 1 }}); Label warningIcon = null; if (!string.IsNullOrEmpty(warningTextIfNull)) @@ -208,7 +220,7 @@ public static VisualElement AssetSelectorWithPresets( } }))); - row.TrackPropertyWithInitialCallback(property, (p) => + ux.TrackPropertyWithInitialCallback(property, (p) => { if (p.serializedObject == null) return; // object deleted @@ -227,12 +239,11 @@ public static VisualElement AssetSelectorWithPresets( selector.SetVisible(presetIndex < 0); }); - return row; + return ux; // Local function static List GetAssetTypes(Type baseType) { - // GML todo: optimize with TypeCache var allTypes = ReflectionHelpers.GetTypesDerivedFrom(baseType, (t) => !t.IsAbstract && t.GetCustomAttribute() == null); var list = new List(); diff --git a/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs b/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs index cd64f753d..96d10a9f8 100644 --- a/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs @@ -431,6 +431,7 @@ public LabeledRow(string label, string tooltip, VisualElement contents) Label = row.Left.AddChild(new Label(label) { tooltip = tooltip, style = { alignSelf = Align.Center, flexGrow = 1 }}); Contents = row.Right.AddChild(contents); style.marginRight = 0; + style.flexGrow = 1; Contents.tooltip = tooltip; Contents.style.marginRight = 0; Contents.style.flexGrow = 1; diff --git a/com.unity.cinemachine/Editor/Utility/ReflectionHelpers.cs b/com.unity.cinemachine/Editor/Utility/ReflectionHelpers.cs index 29747e7e4..50721e7e3 100644 --- a/com.unity.cinemachine/Editor/Utility/ReflectionHelpers.cs +++ b/com.unity.cinemachine/Editor/Utility/ReflectionHelpers.cs @@ -39,6 +39,8 @@ public static void CopyFields( public static IEnumerable GetTypesDerivedFrom(Type type, Predicate predicate) { var list = new List(); + if (predicate(type)) + list.Add(type); var iter = TypeCache.GetTypesDerivedFrom(type).GetEnumerator(); while (iter.MoveNext()) { From 25187a6f3ff3b158e1f1e8088e573b1446ddf093 Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Wed, 5 Jun 2024 12:49:56 -0400 Subject: [PATCH 07/30] Remove bindItem from BlenderSettingsEditor --- .../CinemachineBlenderSettingsEditor.cs | 80 ++++++++----------- 1 file changed, 34 insertions(+), 46 deletions(-) diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineBlenderSettingsEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineBlenderSettingsEditor.cs index 1f3b460ed..928bfe3a0 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineBlenderSettingsEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineBlenderSettingsEditor.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using UnityEngine.UIElements; using UnityEditor.UIElements; +using System; namespace Unity.Cinemachine.Editor { @@ -55,6 +56,7 @@ public override VisualElement CreateInspectorGUI() // Gather the camera candidates var availableCameras = new List(); Dictionary cameraIndexLookup = new(); + Action onCamerasUpdated = null; list.TrackAnyUserActivity(() => { var allCameras = new List(); @@ -65,29 +67,47 @@ public override VisualElement CreateInspectorGUI() for (int i = 0; i < allCameras.Count; ++i) if (allCameras[i] != null && !availableCameras.Contains(allCameras[i].Name)) availableCameras.Add(allCameras[i].Name); - list.RefreshItems(); // rebuild the list + onCamerasUpdated?.Invoke(); }); - list.makeItem = () => new BindableElement { style = { flexDirection = FlexDirection.Row }}; - list.bindItem = (row, index) => + list.makeItem = () => { - // Remove children - items get recycled - for (int i = row.childCount - 1; i >= 0; --i) - row.RemoveAt(i); - var def = new CinemachineBlenderSettings.CustomBlend(); - var element = index < elements.arraySize ? elements.GetArrayElementAtIndex(index) : null; - if (!IsUnityNull(element)) + var row = new BindableElement { style = { flexDirection = FlexDirection.Row }}; + var from = row.AddChild(CreateCameraPopup(SerializedPropertyHelper.PropertyName(() => def.From))); + var to = row.AddChild(CreateCameraPopup(SerializedPropertyHelper.PropertyName(() => def.To))); + var blend = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.Blend)}); + FormatElement(false, from, to, blend); + return row; + + // Local function + VisualElement CreateCameraPopup(string bindingPath) { - var from = row.AddChild(CreateCameraPopup(element.FindPropertyRelative(() => def.From))); - var to = row.AddChild(CreateCameraPopup(element.FindPropertyRelative(() => def.To))); - var blend = row.AddChild(new PropertyField(element.FindPropertyRelative(() => def.Blend), "")); - FormatElement(false, from, to, blend); + var container = new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }}; + var textField = container.AddChild(new TextField { bindingPath = bindingPath, isDelayed = true, style = { flexGrow = 1, flexBasis = 20 }}); - ((BindableElement)row).BindProperty(element); // bind must be done at the end + var warning = container.AddChild(InspectorUtility.MiniHelpIcon($"No in-scene camera matches this name")); + textField.RegisterValueChangedCallback((evt) => OnCameraUpdated()); + onCamerasUpdated += OnCameraUpdated; + void OnCameraUpdated() + { + warning.tooltip = $"No in-scene camera matches \"{textField.value}\""; + warning.SetVisible(availableCameras.FindIndex(x => x == textField.value) < 0); + }; + + var popup = container.AddChild(InspectorUtility.MiniDropdownButton( + "Choose from currently-available cameras", new ContextualMenuManipulator((evt) => + { + for (int i = 0; i < availableCameras.Count; ++i) + evt.menu.AppendAction(availableCameras[i], (action) => textField.value = action.name); + }))); + popup.style.marginRight = 5; + return container; } }; + return ux; + // Local function static void FormatElement(bool isHeader, VisualElement e1, VisualElement e2, VisualElement e3) { @@ -101,38 +121,6 @@ static void FormatElement(bool isHeader, VisualElement e1, VisualElement e2, Vis e3.style.flexBasis = 1; e3.style.flexGrow = 2; } - - // Local function - VisualElement CreateCameraPopup(SerializedProperty p) - { - var row = new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }}; - var textField = row.AddChild(new TextField { isDelayed = true, style = { flexGrow = 1, flexBasis = 20 }}); - textField.BindProperty(p); - if (availableCameras.FindIndex(x => x == p.stringValue) < 0) - row.AddChild(InspectorUtility.MiniHelpIcon("No in-scene camera matches this name")); - var popup = row.AddChild(InspectorUtility.MiniDropdownButton( - "Choose from currently-available cameras", new ContextualMenuManipulator((evt) => - { - for (int i = 0; i < availableCameras.Count; ++i) - evt.menu.AppendAction(availableCameras[i], - (action) => - { - p.stringValue = action.name; - p.serializedObject.ApplyModifiedProperties(); - }); - }))); - popup.style.marginRight = 5; - return row; - } - - // Local function - static bool IsUnityNull(object obj) - { - // Checks whether an object is null or Unity pseudo-null - // without having to cast to UnityEngine.Object manually - return obj == null || ((obj is UnityEngine.Object) && ((UnityEngine.Object)obj) == null); - } - return ux; } } } From 7c43274e8056f15f4167982865570a5ddd484ee7 Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Wed, 5 Jun 2024 12:50:09 -0400 Subject: [PATCH 08/30] Update InspectorUtility.cs --- com.unity.cinemachine/Editor/Utility/InspectorUtility.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs b/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs index 96d10a9f8..87b4c3d70 100644 --- a/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/InspectorUtility.cs @@ -329,7 +329,7 @@ public static Button MiniPopupButton(string tooltip = null, ContextualMenuManipu backgroundImage = (StyleBackground)EditorGUIUtility.IconContent("_Popup").image, width = SingleLineHeight, height = SingleLineHeight, alignSelf = Align.Center, - paddingRight = 0, borderRightWidth = 0, marginRight = 0 + paddingRight = 0, marginRight = 0 }}; if (contextMenu != null) { @@ -352,7 +352,7 @@ public static Button MiniDropdownButton(string tooltip = null, ContextualMenuMan backgroundImage = (StyleBackground)EditorGUIUtility.IconContent("dropdown").image, width = SingleLineHeight, height = SingleLineHeight, alignSelf = Align.Center, - paddingRight = 0, borderRightWidth = 0, marginRight = 0 + paddingRight = 0, marginRight = 0 }}; if (contextMenu != null) { From 09ddd49dbe2d5247d9cdf32c5d8f3ae56fe5d3f2 Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Wed, 5 Jun 2024 15:49:12 -0400 Subject: [PATCH 09/30] get rid of bindItem in SequencerEditor --- .../CinemachineSequencerCameraEditor.cs | 68 +++++++------------ 1 file changed, 23 insertions(+), 45 deletions(-) diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs index 22935aff8..f9efe7a42 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using UnityEditor; using UnityEditor.UIElements; using UnityEngine; @@ -41,7 +42,6 @@ public override VisualElement CreateInspectorGUI() var list = container.AddChild(new ListView() { - name = "InstructionList", reorderable = true, reorderMode = ListViewReorderMode.Animated, showAddRemoveFooter = true, @@ -53,34 +53,28 @@ public override VisualElement CreateInspectorGUI() var instructions = serializedObject.FindProperty(() => Target.Instructions); list.BindProperty(instructions); - list.makeItem = () => new BindableElement { style = { flexDirection = FlexDirection.Row }}; - list.bindItem = (row, index) => + // Available camera candidates + var availableCameras = new List(); + + list.makeItem = () => { - // Remove children - items get recycled - for (int i = row.childCount - 1; i >= 0; --i) - row.RemoveAt(i); + var row = new BindableElement { style = { flexDirection = FlexDirection.Row }}; var def = new CinemachineSequencerCamera.Instruction(); - var element = instructions.GetArrayElementAtIndex(index); - - var vcamSelProp = element.FindPropertyRelative(() => def.Camera); - var vcamSel = row.AddChild(new PopupField { name = $"vcamSelector{index}", choices = new() }); - vcamSel.formatListItemCallback = (obj) => obj == null ? "(null)" : obj.name; - vcamSel.formatSelectedValueCallback = (obj) => obj == null ? "(null)" : obj.name; - vcamSel.TrackPropertyWithInitialCallback(instructions, (p) => UpdateCameraDropdowns()); + var vcamSel = row.AddChild(new PopupField + { + bindingPath = SerializedPropertyHelper.PropertyName(() => def.Camera), + choices = availableCameras, + formatListItemCallback = (obj) => obj == null ? "(null)" : obj.name, + formatSelectedValueCallback = (obj) => obj == null ? "(null)" : obj.name + }); - var blend = row.AddChild(new PropertyField(element.FindPropertyRelative(() => def.Blend), "")); - if (index == 0) - blend.name = "FirstItemBlend"; - var hold = row.AddChild( - new InspectorUtility.CompactPropertyField(element.FindPropertyRelative(() => def.Hold), " ")); + var blend = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.Blend), name = "blendSelector" }); + var hold = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.Hold) }); hold.RemoveFromClassList(InspectorUtility.AlignFieldClassName); FormatInstructionElement(false, vcamSel, blend, hold); - - // Bind must be last - ((BindableElement)row).BindProperty(element); - vcamSel.BindProperty(vcamSelProp); + return row; }; container.AddSpace(); @@ -88,7 +82,7 @@ public override VisualElement CreateInspectorGUI() container.TrackAnyUserActivity(() => { - if (Target == null) + if (Target == null || list.itemsSource == null) return; // object deleted var isMultiSelect = targets.Length > 1; @@ -96,34 +90,18 @@ public override VisualElement CreateInspectorGUI() container.SetVisible(!isMultiSelect); // Hide the first blend if not looped - list.Q("FirstItemBlend")?.SetEnabled(Target.Loop); + var index = 0; + list.Query().Where((e) => e.name == "blendSelector").ForEach((e) + => e.style.visibility = (index++ == 0 && !Target.Loop) ? Visibility.Hidden : Visibility.Visible); - // Update the list items - UpdateCameraDropdowns(); + // Gather the camera candidates + availableCameras.Clear(); + availableCameras.AddRange(Target.ChildCameras); }); this.AddExtensionsDropdown(ux); return ux; - // Local function - void UpdateCameraDropdowns() - { - var children = Target.ChildCameras; - int index = 0; - var iter = list.itemsSource.GetEnumerator(); - while (iter.MoveNext()) - { - var vcamSel = list.Q>($"vcamSelector{index}"); - if (vcamSel != null) - { - vcamSel.choices.Clear(); - for (int i = 0; i < children.Count; ++i) - vcamSel.choices.Add(children[i]); - } - ++index; - } - } - // Local function static void FormatInstructionElement(bool isHeader, VisualElement e1, VisualElement e2, VisualElement e3) { From f7cde1022b61324aaab04868cba319f460964d7b Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Wed, 5 Jun 2024 15:49:40 -0400 Subject: [PATCH 10/30] get rid of bindItem in StateDrivenCamera editor --- .../CinemachineStateDrivenCameraEditor.cs | 101 ++++++++---------- .../CinemachineStateDrivenCamera.cs | 2 +- 2 files changed, 45 insertions(+), 58 deletions(-) diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineStateDrivenCameraEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineStateDrivenCameraEditor.cs index d0b79e52b..20c3c0528 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineStateDrivenCameraEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineStateDrivenCameraEditor.cs @@ -73,7 +73,6 @@ public override VisualElement CreateInspectorGUI() var list = container.AddChild(new ListView() { - name = "InstructionList", reorderable = true, reorderMode = ListViewReorderMode.Animated, showAddRemoveFooter = true, @@ -85,67 +84,71 @@ public override VisualElement CreateInspectorGUI() var instructions = serializedObject.FindProperty(() => Target.Instructions); list.BindProperty(instructions); - list.makeItem = () => new BindableElement { style = { flexDirection = FlexDirection.Row }}; - list.bindItem = (row, index) => + // Available camera candidates + var availableCameras = new List(); + + list.makeItem = () => { - // Remove children - items get recycled - for (int i = row.childCount - 1; i >= 0; --i) - row.RemoveAt(i); + var row = new BindableElement { style = { flexDirection = FlexDirection.Row }}; var def = new CinemachineStateDrivenCamera.Instruction(); - var element = instructions.GetArrayElementAtIndex(index); - var stateSelProp = element.FindPropertyRelative(() => def.FullHash); - int currentState = GetStateHashIndex(stateSelProp.intValue); + // This is the real state field, but it's hiddes + var hashField = row.AddChild(new IntegerField() { bindingPath = SerializedPropertyHelper.PropertyName(() => def.FullHash) }); + hashField.SetVisible(false); + + // Create a state selector popup to drive the state field var stateSel = row.AddChild(new PopupField { - name = $"stateSelector{index}", choices = m_TargetStateNames, - tooltip = "The state that will activate the camera" + tooltip = "The state that will activate the camera" }); - stateSel.RegisterValueChangedCallback((evt) => + + hashField.RegisterValueChangedCallback((evt) => { - if (evt.target == stateSel) + if (evt.target != hashField) + return; + for (int i = 0; i < m_TargetStates.Count; ++i) { - var i = stateSel.index; - if (i >= 0 && i < m_TargetStates.Count) + if (evt.newValue == m_TargetStates[i]) { - stateSelProp.intValue = m_TargetStates[i]; - stateSelProp.serializedObject.ApplyModifiedProperties(); + stateSel.value = m_TargetStateNames[i]; + break; } - evt.StopPropagation(); } + evt.StopPropagation(); }); - stateSel.TrackPropertyWithInitialCallback(stateSelProp, (p) => + + stateSel.RegisterValueChangedCallback((evt) => { - var hash = p.intValue; - for (int i = 0; i < m_TargetStates.Count; ++i) + if (evt.target != stateSel) + return; + + for (int i = 0; i < m_TargetStateNames.Count; ++i) { - if (hash == m_TargetStates[i]) + if (evt.newValue == m_TargetStateNames[i]) { - stateSel.SetValueWithoutNotify(m_TargetStateNames[i]); - return; + hashField.value = m_TargetStates[i]; + break; } } - stateSel.SetValueWithoutNotify(m_TargetStateNames[0]); + evt.StopPropagation(); }); - var vcamSelProp = element.FindPropertyRelative(() => def.Camera); - var vcamSel = row.AddChild(new PopupField { name = $"vcamSelector{index}", choices = new() }); - vcamSel.formatListItemCallback = (obj) => obj == null ? "(null)" : obj.name; - vcamSel.formatSelectedValueCallback = (obj) => obj == null ? "(null)" : obj.name; - vcamSel.TrackPropertyWithInitialCallback(instructions, (p) => UpdateCameraDropdowns()); + var vcamSel = row.AddChild(new PopupField + { + bindingPath = SerializedPropertyHelper.PropertyName(() => def.Camera), + choices = availableCameras, + formatListItemCallback = (obj) => obj == null ? "(null)" : obj.name, + formatSelectedValueCallback = (obj) => obj == null ? "(null)" : obj.name + }); - var wait = row.AddChild( - new InspectorUtility.CompactPropertyField(element.FindPropertyRelative(() => def.ActivateAfter), " ")); - var hold = row.AddChild( - new InspectorUtility.CompactPropertyField(element.FindPropertyRelative(() => def.MinDuration), " ")); + var wait = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.ActivateAfter) }); + var hold = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.MinDuration) }); FormatInstructionElement(false, stateSel, vcamSel, wait, hold); - // Bind must be last - ((BindableElement)row).BindProperty(element); - vcamSel.BindProperty(vcamSelProp); + return row; }; container.TrackAnyUserActivity(() => @@ -156,7 +159,10 @@ public override VisualElement CreateInspectorGUI() var isMultiSelect = targets.Length > 1; multiSelectMsg.SetVisible(isMultiSelect); container.SetVisible(!isMultiSelect); - UpdateCameraDropdowns(); + + // Gather the camera candidates + availableCameras.Clear(); + availableCameras.AddRange(Target.ChildCameras); }); container.AddSpace(); this.AddChildCameras(container, null); @@ -165,25 +171,6 @@ public override VisualElement CreateInspectorGUI() return ux; - // Local function - void UpdateCameraDropdowns() - { - var children = Target.ChildCameras; - int index = 0; - var iter = list.itemsSource.GetEnumerator(); - while (iter.MoveNext()) - { - var vcamSel = list.Q>($"vcamSelector{index}"); - if (vcamSel != null) - { - vcamSel.choices.Clear(); - for (int i = 0; i < children.Count; ++i) - vcamSel.choices.Add(children[i]); - } - ++index; - } - } - // Local function static void FormatInstructionElement( bool isHeader, VisualElement e1, VisualElement e2, VisualElement e3, VisualElement e4) diff --git a/com.unity.cinemachine/Runtime/Behaviours/CinemachineStateDrivenCamera.cs b/com.unity.cinemachine/Runtime/Behaviours/CinemachineStateDrivenCamera.cs index a02b84410..169e2e400 100644 --- a/com.unity.cinemachine/Runtime/Behaviours/CinemachineStateDrivenCamera.cs +++ b/com.unity.cinemachine/Runtime/Behaviours/CinemachineStateDrivenCamera.cs @@ -257,7 +257,7 @@ protected override CinemachineVirtualCameraBase ChooseCurrentCamera(Vector3 worl for (int i = 0; i < instrList.Count; ++i) { var index = instrList[i]; - var cam = Instructions[index].Camera; + var cam = index < Instructions.Length ? Instructions[index].Camera : null; if (cam != null && cam.isActiveAndEnabled && cam.Priority.Value > bestPriority) { newInstrIndex = index; From 8cadc0c38710fdddf171cd7dac0df812f6d27975 Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Wed, 5 Jun 2024 16:47:10 -0400 Subject: [PATCH 11/30] fix bindItem in CameraInspectorUtility --- .../Utility/CmCameraInspectorUtility.cs | 78 +++++++++++-------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs b/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs index c79534728..15a2526d8 100644 --- a/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs @@ -522,50 +522,66 @@ public static void AddChildCameras( }); list.itemsSource = vcam.ChildCameras; - list.makeItem = () => new VisualElement { style = { flexDirection = FlexDirection.Row }}; - list.bindItem = (row, index) => + list.makeItem = () => { - // Remove children - items seem to get recycled - for (int i = row.childCount - 1; i >= 0; --i) - row.RemoveAt(i); + var row = new VisualElement { style = { flexDirection = FlexDirection.Row }}; + + var warningIcon = row.AddChild(InspectorUtility.MiniHelpIcon("Item is null")); + warningIcon.name = "warningIcon"; - var element = list.itemsSource[index] as CinemachineVirtualCameraBase; row.AddChild(new ObjectField { - value = element, + name = "vcamSelector", objectType = typeof(CinemachineVirtualCameraBase), style = { flexBasis = 20, flexGrow = 1 } }).SetEnabled(false); - if (element == null) - return; - - var warningIcon = row.AddChild(InspectorUtility.MiniHelpIcon("Item is null")); - var warningText = getChildWarning == null ? string.Empty : getChildWarning(element); - warningIcon.tooltip = warningText; - warningIcon.SetVisible(!string.IsNullOrEmpty(warningText)); - var dragger = row.AddChild(new Label(" ")); + var dragger = row.AddChild(new Label(" ")); dragger.AddToClassList("unity-base-field__label--with-dragger"); - var so = new SerializedObject(element); - var prop = so.FindProperty("Priority"); - var enabledProp = prop.FindPropertyRelative("Enabled"); - var priorityProp = prop.FindPropertyRelative("m_Value"); - var priorityField = row.AddChild(new IntegerField - { - value = enabledProp.boolValue ? priorityProp.intValue : 0, + var priorityField = row.AddChild(new IntegerField + { + name = "priorityField", + isDelayed = true, style = { flexBasis = floatFieldWidth, flexGrow = 0, marginRight = 4 } }); - new DelayedFriendlyFieldDragger(priorityField) { CancelDelayedWhenDragging = true }.SetDragZone(dragger); - priorityField.RegisterValueChangedCallback((evt) => + new DelayedFriendlyFieldDragger(priorityField).SetDragZone(dragger); + + return row; + }; + + list.bindItem = (row, index) => + { + var element = list.itemsSource[index] as CinemachineVirtualCameraBase; + row.Q("vcamSelector").value = element; + + var warningIcon = row.Q("warningIcon"); + var warningText = getChildWarning == null ? string.Empty : getChildWarning(element); + warningIcon.tooltip = warningText; + warningIcon.SetVisible(!string.IsNullOrEmpty(warningText)); + + if (element != null) { - if (evt.newValue != 0) - enabledProp.boolValue = true; - priorityProp.intValue = evt.newValue; - so.ApplyModifiedProperties(); - }); - priorityField.TrackPropertyValue(priorityProp, (p) => priorityField.value = p.intValue); - priorityField.TrackPropertyValue(enabledProp, (p) => priorityField.value = p.boolValue ? priorityProp.intValue : 0); + var so = new SerializedObject(element); + var prop = so.FindProperty("Priority"); + var enabledProp = prop.FindPropertyRelative("Enabled"); + var priorityProp = prop.FindPropertyRelative("m_Value"); + var priorityField = row.Q("priorityField"); + + priorityField.Unbind(); + priorityField.TrackPropertyWithInitialCallback(priorityProp, (p) => priorityField.value = p.intValue); + priorityField.TrackPropertyWithInitialCallback(enabledProp, (p) => priorityField.value = p.boolValue ? priorityProp.intValue : 0); + + priorityField.UnregisterValueChangedCallback(OnValueChanged); + priorityField.RegisterValueChangedCallback(OnValueChanged); + void OnValueChanged(ChangeEvent evt) + { + if (evt.newValue != 0) + enabledProp.boolValue = true; + priorityProp.intValue = evt.newValue; + so.ApplyModifiedProperties(); + } + } }; list.itemsAdded += (added) => From a4ddbd7b652aeeb51f373cac951f6ec0c1ca4016 Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Wed, 5 Jun 2024 17:19:04 -0400 Subject: [PATCH 12/30] add some missing draggers --- .../CinemachineSequencerCameraEditor.cs | 18 ++++++++++--- .../CinemachineStateDrivenCameraEditor.cs | 26 +++++++++++++++---- .../Utility/CmCameraInspectorUtility.cs | 4 +-- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs index f9efe7a42..81db83687 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs @@ -70,8 +70,17 @@ public override VisualElement CreateInspectorGUI() }); var blend = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.Blend), name = "blendSelector" }); - var hold = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.Hold) }); - hold.RemoveFromClassList(InspectorUtility.AlignFieldClassName); + + + var holdTooltip = "How long to wait (in seconds) before activating the next camera in the list (if any)"; + var holdDragger = row.AddChild(new Label(" ") { tooltip = holdTooltip }); + holdDragger.AddToClassList("unity-base-field__label--with-dragger"); + var hold = row.AddChild(new FloatField + { + tooltip = holdTooltip, + bindingPath = SerializedPropertyHelper.PropertyName(() => def.Hold) + }); + new DelayedFriendlyFieldDragger(hold).SetDragZone(holdDragger); FormatInstructionElement(false, vcamSel, blend, hold); return row; @@ -111,13 +120,14 @@ static void FormatInstructionElement(bool isHeader, VisualElement e1, VisualElem e1.style.flexBasis = floatFieldWidth + InspectorUtility.SingleLineHeight; e1.style.flexGrow = 1; + floatFieldWidth += isHeader ? InspectorUtility.SingleLineHeight/2 - 1 : 0; + e2.style.flexBasis = floatFieldWidth; e2.style.flexGrow = 1; + e2.style.unityTextAlign = TextAnchor.MiddleCenter; - e3.style.marginRight = 4; e3.style.flexBasis = floatFieldWidth; e3.style.flexGrow = 0; - e3.style.unityTextAlign = TextAnchor.MiddleRight; } } } diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineStateDrivenCameraEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineStateDrivenCameraEditor.cs index 20c3c0528..f95eb95a2 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineStateDrivenCameraEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineStateDrivenCameraEditor.cs @@ -143,9 +143,26 @@ public override VisualElement CreateInspectorGUI() formatSelectedValueCallback = (obj) => obj == null ? "(null)" : obj.name }); - var wait = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.ActivateAfter) }); - var hold = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.MinDuration) }); - + var waitTooltip = "How long to wait (in seconds) before activating the camera. This filters out very short state durations"; + var waitDragger = row.AddChild(new Label(" ") { tooltip = waitTooltip }); + waitDragger.AddToClassList("unity-base-field__label--with-dragger"); + var wait = row.AddChild(new FloatField + { + tooltip = waitTooltip, + bindingPath = SerializedPropertyHelper.PropertyName(() => def.ActivateAfter) + }); + new DelayedFriendlyFieldDragger(wait).SetDragZone(waitDragger); + + var holdTooltip = "The minimum length of time (in seconds) to keep a camera active"; + var holdDragger = row.AddChild(new Label(" ") { tooltip = holdTooltip }); + holdDragger.AddToClassList("unity-base-field__label--with-dragger"); + var hold = row.AddChild(new FloatField + { + tooltip = holdTooltip, + bindingPath = SerializedPropertyHelper.PropertyName(() => def.MinDuration) + }); + new DelayedFriendlyFieldDragger(hold).SetDragZone(holdDragger); + FormatInstructionElement(false, stateSel, vcamSel, wait, hold); return row; @@ -184,13 +201,12 @@ static void FormatInstructionElement( e2.style.flexBasis = floatFieldWidth + InspectorUtility.SingleLineHeight; e2.style.flexGrow = 1; + floatFieldWidth += isHeader ? InspectorUtility.SingleLineHeight/2 - 1 : 0; e3.style.flexBasis = floatFieldWidth; e3.style.flexGrow = 0; - e4.style.marginRight = 4; e4.style.flexBasis = floatFieldWidth; e4.style.flexGrow = 0; - e4.style.unityTextAlign = TextAnchor.MiddleRight; } } diff --git a/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs b/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs index 15a2526d8..1ed87d703 100644 --- a/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs @@ -497,7 +497,7 @@ public static void AddChildCameras( if (vcam == null) return; - var floatFieldWidth = EditorGUIUtility.singleLineHeight * 2.5f; + var floatFieldWidth = EditorGUIUtility.singleLineHeight * 3f; var helpBox = ux.AddChild(new HelpBox( "Child Cameras cannot be displayed when multiple objects are selected.", @@ -536,7 +536,7 @@ public static void AddChildCameras( style = { flexBasis = 20, flexGrow = 1 } }).SetEnabled(false); - var dragger = row.AddChild(new Label(" ")); + var dragger = row.AddChild(new Label(" ")); dragger.AddToClassList("unity-base-field__label--with-dragger"); var priorityField = row.AddChild(new IntegerField From 4b4e069946d2c4af43f562bf48494b1bc69aab4f Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Wed, 5 Jun 2024 17:31:36 -0400 Subject: [PATCH 13/30] layout tweaking --- .../Editor/Editors/CinemachineSequencerCameraEditor.cs | 8 +++----- .../Editor/Utility/CmCameraInspectorUtility.cs | 4 +--- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs index 81db83687..3df11ee33 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineSequencerCameraEditor.cs @@ -71,7 +71,6 @@ public override VisualElement CreateInspectorGUI() var blend = row.AddChild(new PropertyField(null, "") { bindingPath = SerializedPropertyHelper.PropertyName(() => def.Blend), name = "blendSelector" }); - var holdTooltip = "How long to wait (in seconds) before activating the next camera in the list (if any)"; var holdDragger = row.AddChild(new Label(" ") { tooltip = holdTooltip }); holdDragger.AddToClassList("unity-base-field__label--with-dragger"); @@ -120,12 +119,11 @@ static void FormatInstructionElement(bool isHeader, VisualElement e1, VisualElem e1.style.flexBasis = floatFieldWidth + InspectorUtility.SingleLineHeight; e1.style.flexGrow = 1; - floatFieldWidth += isHeader ? InspectorUtility.SingleLineHeight/2 - 1 : 0; - - e2.style.flexBasis = floatFieldWidth; + e2.style.marginLeft = isHeader ? 4 * InspectorUtility.SingleLineHeight - 3 : 0; + e2.style.flexBasis = floatFieldWidth + InspectorUtility.SingleLineHeight; e2.style.flexGrow = 1; - e2.style.unityTextAlign = TextAnchor.MiddleCenter; + floatFieldWidth += isHeader ? InspectorUtility.SingleLineHeight/2 - 1 : 0; e3.style.flexBasis = floatFieldWidth; e3.style.flexGrow = 0; } diff --git a/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs b/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs index 1ed87d703..87781cd43 100644 --- a/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/CmCameraInspectorUtility.cs @@ -508,8 +508,7 @@ public static void AddChildCameras( var header = container.AddChild(new VisualElement { style = { flexDirection = FlexDirection.Row, marginBottom = -2 } }); header.AddToClassList("unity-collection-view--with-border"); header.AddChild(new Label("Child Cameras") { style = { marginLeft = 3, flexGrow = 1, flexBasis = 10 }}); - header.AddChild(new Label("Priority") - { style = { marginRight = 4, flexGrow = 1, flexBasis = floatFieldWidth, unityTextAlign = TextAnchor.MiddleRight }}); + header.AddChild(new Label("Priority") { style = { flexGrow = 0, flexBasis = floatFieldWidth + 4}}); var list = container.AddChild(new ListView() { @@ -538,7 +537,6 @@ public static void AddChildCameras( var dragger = row.AddChild(new Label(" ")); dragger.AddToClassList("unity-base-field__label--with-dragger"); - var priorityField = row.AddChild(new IntegerField { name = "priorityField", From 85253214e09c697785767fcb8dd3f8c7d4abcec0 Mon Sep 17 00:00:00 2001 From: Gregory Labute Date: Thu, 6 Jun 2024 07:49:47 -0400 Subject: [PATCH 14/30] Simplify SplineDataInspectorUtility.CreateDataListField --- ...nemachineSplineDollyLookAtTargetsEditor.cs | 179 +++++++++--------- .../Editors/CinemachineSplineRollEditor.cs | 78 ++++---- .../Utility/SplineDataInspectorUtility.cs | 103 +++++----- 3 files changed, 177 insertions(+), 183 deletions(-) diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineSplineDollyLookAtTargetsEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineSplineDollyLookAtTargetsEditor.cs index b5b8f8400..addaafe40 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineSplineDollyLookAtTargetsEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineSplineDollyLookAtTargetsEditor.cs @@ -96,7 +96,7 @@ public override VisualElement CreateInspectorGUI() => splineData.GetGetSplineAndDolly(out var spline, out _) ? spline : null)); ux.AddHeader("Data Points"); - var listField = ux.AddChild(SplineDataInspectorUtility.CreateDataListField( + var list = ux.AddChild(SplineDataInspectorUtility.CreateDataListField( splineData.Targets, targetsProp, () => splineData.GetGetSplineAndDolly(out var spline, out _) ? spline : null, () => @@ -113,116 +113,113 @@ public override VisualElement CreateInspectorGUI() } return item; })); + var arrayProp = targetsProp.FindPropertyRelative("m_DataPoints"); - listField.OnInitialGeometry(() => + list.makeItem = () => new BindableElement() { style = { marginRight = 4 }}; + list.bindItem = (ux, index) => { - var list = listField.Q(); - list.makeItem = () => new BindableElement() { style = { marginRight = 4 }}; - list.bindItem = (ux, index) => - { - // Remove children - items get recycled - for (int i = ux.childCount - 1; i >= 0; --i) - ux.RemoveAt(i); - - const string indexTooltip = "The position on the Spline at which this data point will take effect. " - + "The value is interpreted according to the Index Unit setting."; - - var element = index < arrayProp.arraySize ? arrayProp.GetArrayElementAtIndex(index) : null; - CinemachineSplineDollyLookAtTargets.Item def = new (); - var indexProp = element.FindPropertyRelative("m_Index"); - var valueProp = element.FindPropertyRelative("m_Value"); - var lookAtProp = valueProp.FindPropertyRelative(() => def.LookAt); - var offsetProp = valueProp.FindPropertyRelative(() => def.Offset); - - var overlay = new VisualElement () { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }}; - var indexField1 = overlay.AddChild(new PropertyField(indexProp, "") { tooltip = indexTooltip, style = { flexGrow = 1, flexBasis = 50 }}); - indexField1.OnInitialGeometry(() => indexField1.SafeSetIsDelayed()); - - var lookAtField1 = overlay.AddChild(new PropertyField(lookAtProp, "") { style = { flexGrow = 4, flexBasis = 50, marginLeft = 3 }}); - var overlayLabel = new Label(indexProp.displayName) { tooltip = indexTooltip, style = { alignSelf = Align.Center }}; - overlayLabel.AddDelayedFriendlyPropertyDragger(indexProp, overlay, OnIndexDraggerCreated); + // Remove children - items get recycled + for (int i = ux.childCount - 1; i >= 0; --i) + ux.RemoveAt(i); + + const string indexTooltip = "The position on the Spline at which this data point will take effect. " + + "The value is interpreted according to the Index Unit setting."; + + var element = index < arrayProp.arraySize ? arrayProp.GetArrayElementAtIndex(index) : null; + CinemachineSplineDollyLookAtTargets.Item def = new (); + var indexProp = element.FindPropertyRelative("m_Index"); + var valueProp = element.FindPropertyRelative("m_Value"); + var lookAtProp = valueProp.FindPropertyRelative(() => def.LookAt); + var offsetProp = valueProp.FindPropertyRelative(() => def.Offset); + + var overlay = new VisualElement () { style = { flexDirection = FlexDirection.Row, flexGrow = 1 }}; + var indexField1 = overlay.AddChild(new PropertyField(indexProp, "") { tooltip = indexTooltip, style = { flexGrow = 1, flexBasis = 50 }}); + indexField1.OnInitialGeometry(() => indexField1.SafeSetIsDelayed()); + + var lookAtField1 = overlay.AddChild(new PropertyField(lookAtProp, "") { style = { flexGrow = 4, flexBasis = 50, marginLeft = 3 }}); + var overlayLabel = new Label(indexProp.displayName) { tooltip = indexTooltip, style = { alignSelf = Align.Center }}; + overlayLabel.AddDelayedFriendlyPropertyDragger(indexProp, overlay, OnIndexDraggerCreated); - var foldout = new Foldout() { text = $"Target {index}" }; - foldout.BindProperty(element); - var row = foldout.AddChild(new InspectorUtility.LabeledRow(indexProp.displayName, indexTooltip)); - var indexField2 = row.Contents.AddChild(new PropertyField(indexProp, "") { style = { flexGrow = 1 }}); - indexField2.OnInitialGeometry(() => indexField2.SafeSetIsDelayed()); - row.Label.AddDelayedFriendlyPropertyDragger(indexProp, indexField2, OnIndexDraggerCreated); + var foldout = new Foldout() { text = $"Target {index}" }; + foldout.BindProperty(element); + var row = foldout.AddChild(new InspectorUtility.LabeledRow(indexProp.displayName, indexTooltip)); + var indexField2 = row.Contents.AddChild(new PropertyField(indexProp, "") { style = { flexGrow = 1 }}); + indexField2.OnInitialGeometry(() => indexField2.SafeSetIsDelayed()); + row.Label.AddDelayedFriendlyPropertyDragger(indexProp, indexField2, OnIndexDraggerCreated); + + var lookAtField2 = foldout.AddChild(new PropertyField(lookAtProp)); + foldout.Add(new PropertyField(offsetProp)); + foldout.Add(new PropertyField(valueProp.FindPropertyRelative(() => def.Easing))); - var lookAtField2 = foldout.AddChild(new PropertyField(lookAtProp)); - foldout.Add(new PropertyField(offsetProp)); - foldout.Add(new PropertyField(valueProp.FindPropertyRelative(() => def.Easing))); + ux.Add(new InspectorUtility.FoldoutWithOverlay(foldout, overlay, overlayLabel) { style = { marginLeft = 12 }}); - ux.Add(new InspectorUtility.FoldoutWithOverlay(foldout, overlay, overlayLabel) { style = { marginLeft = 12 }}); + ux.TrackPropertyValue(lookAtProp, (p) => + { + // Don't mess with the offset if change was a result of undo/redo + if (m_UndoRedoMonitor.IsUndoRedo) + return; - ux.TrackPropertyValue(lookAtProp, (p) => + // if lookAt target was set to null, preserve the worldspace location + if (GetInspectorStateCache(splineData).GetCachedValue(index, out var previous)) { - // Don't mess with the offset if change was a result of undo/redo - if (m_UndoRedoMonitor.IsUndoRedo) - return; + var newData = p.objectReferenceValue; + if (newData == null && previous.Value.LookAt != null) + SetOffset(previous.Value.WorldLookAt); - // if lookAt target was set to null, preserve the worldspace location - if (GetInspectorStateCache(splineData).GetCachedValue(index, out var previous)) + // if lookAt target was changed, zero the offset + else if (newData != null && newData != previous.Value.LookAt) + SetOffset(Vector3.zero); + + // local function + void SetOffset(Vector3 offset) { - var newData = p.objectReferenceValue; - if (newData == null && previous.Value.LookAt != null) - SetOffset(previous.Value.WorldLookAt); - - // if lookAt target was changed, zero the offset - else if (newData != null && newData != previous.Value.LookAt) - SetOffset(Vector3.zero); - - // local function - void SetOffset(Vector3 offset) - { - offsetProp.vector3Value = offset; - p.serializedObject.ApplyModifiedProperties(); - } + offsetProp.vector3Value = offset; + p.serializedObject.ApplyModifiedProperties(); } - }); - - ((BindableElement)ux).BindProperty(element); // bind must be done at the end - - // local function - void OnIndexDraggerCreated(IDelayedFriendlyDragger dragger) - { - dragger.OnStartDrag = () => list.selectedIndex = index; - dragger.OnDragValueChangedFloat = (v) => BringCameraToCustomSplinePoint(splineData, v); } - }; + }); - list.TrackPropertyValue(arrayProp, (p) => EditorApplication.delayCall += () => GetInspectorStateCache(splineData).Reset(splineData)); + ((BindableElement)ux).BindProperty(element); // bind must be done at the end - // When the list selection changes, cache the index and put the camera at that point on the dolly track - list.selectedIndicesChanged += (indices) => + // local function + void OnIndexDraggerCreated(IDelayedFriendlyDragger dragger) { - var it = indices.GetEnumerator(); - var cache = GetInspectorStateCache(splineData); - cache.CurrentSelection = it.MoveNext() ? it.Current : -1; - BringCameraToSplinePoint(splineData, cache.CurrentSelection); - }; + dragger.OnStartDrag = () => list.selectedIndex = index; + dragger.OnDragValueChangedFloat = (v) => BringCameraToCustomSplinePoint(splineData, v); + } + }; - LookAtDataOnSplineTool.s_OnDataLookAtDragged += OnToolDragged; - LookAtDataOnSplineTool.s_OnDataIndexDragged += OnToolDragged; - void OnToolDragged(CinemachineSplineDollyLookAtTargets data, int index) + list.TrackPropertyValue(arrayProp, (p) => EditorApplication.delayCall += () => GetInspectorStateCache(splineData).Reset(splineData)); + + // When the list selection changes, cache the index and put the camera at that point on the dolly track + list.selectedIndicesChanged += (indices) => + { + var it = indices.GetEnumerator(); + var cache = GetInspectorStateCache(splineData); + cache.CurrentSelection = it.MoveNext() ? it.Current : -1; + BringCameraToSplinePoint(splineData, cache.CurrentSelection); + }; + + LookAtDataOnSplineTool.s_OnDataLookAtDragged += OnToolDragged; + LookAtDataOnSplineTool.s_OnDataIndexDragged += OnToolDragged; + void OnToolDragged(CinemachineSplineDollyLookAtTargets data, int index) + { + EditorApplication.delayCall += () => { - EditorApplication.delayCall += () => + // GML This is a hack to avoid spurious exceptions thrown by uitoolkit! + // GML TODO: Remove when they fix it + try { - // GML This is a hack to avoid spurious exceptions thrown by uitoolkit! - // GML TODO: Remove when they fix it - try + if (data == splineData) { - if (data == splineData) - { - list.selectedIndex = index; - BringCameraToSplinePoint(data, index); - } + list.selectedIndex = index; + BringCameraToSplinePoint(data, index); } - catch {} // Ignore exceptions - }; - } - }); + } + catch {} // Ignore exceptions + }; + } return ux; } diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs index f6dfb6c1c..9b5ed69ea 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineSplineRollEditor.cs @@ -35,57 +35,53 @@ public override VisualElement CreateInspectorGUI() ux.Add(SplineDataInspectorUtility.CreatePathUnitField(rollProp, () => splineData == null ? null : splineData.SplineContainer)); ux.AddHeader("Data Points"); - var listField = ux.AddChild(SplineDataInspectorUtility.CreateDataListField( - splineData.Roll, rollProp, () => splineData?.SplineContainer)); + var list = ux.AddChild(SplineDataInspectorUtility.CreateDataListField(splineData.Roll, rollProp, () => splineData?.SplineContainer)); + var arrayProp = rollProp.FindPropertyRelative("m_DataPoints"); - listField.OnInitialGeometry(() => - { - var list = listField.Q(); - list.makeItem = () => new BindableElement() { style = { flexDirection = FlexDirection.Row, marginRight = 4 }}; - list.bindItem = (ux, index) => - { - // Remove children - items get recycled - for (int i = ux.childCount - 1; i >= 0; --i) - ux.RemoveAt(i); + list.makeItem = () => new BindableElement() { style = { flexDirection = FlexDirection.Row, marginRight = 4 }}; + list.bindItem = (ux, index) => + { + // Remove children - items get recycled + for (int i = ux.childCount - 1; i >= 0; --i) + ux.RemoveAt(i); - const string indexTooltip = "The position on the Spline at which this data point will take effect. " - + "The value is interpreted according to the Index Unit setting."; + const string indexTooltip = "The position on the Spline at which this data point will take effect. " + + "The value is interpreted according to the Index Unit setting."; - var element = index < arrayProp.arraySize ? arrayProp.GetArrayElementAtIndex(index) : null; - var def = new CinemachineSplineRoll.RollData(); - var indexProp = element.FindPropertyRelative("m_Index"); - var valueProp = element.FindPropertyRelative("m_Value"); + var element = index < arrayProp.arraySize ? arrayProp.GetArrayElementAtIndex(index) : null; + var def = new CinemachineSplineRoll.RollData(); + var indexProp = element.FindPropertyRelative("m_Index"); + var valueProp = element.FindPropertyRelative("m_Value"); - ux.Add(new VisualElement { pickingMode = PickingMode.Ignore, style = { width = 12 }}); // pass-through for selecting row in list - var label = ux.AddChild(new Label(indexProp.displayName) { tooltip = indexTooltip, style = { alignSelf = Align.Center }}); - var indexField = ux.AddChild(new PropertyField(indexProp, "") { style = { flexGrow = 1, flexBasis = 20 }}); - indexField.OnInitialGeometry(() => indexField.SafeSetIsDelayed()); - label.AddDelayedFriendlyPropertyDragger(indexProp, indexField, (dragger) => dragger.OnStartDrag = () => list.selectedIndex = index); + ux.Add(new VisualElement { pickingMode = PickingMode.Ignore, style = { width = 12 }}); // pass-through for selecting row in list + var label = ux.AddChild(new Label(indexProp.displayName) { tooltip = indexTooltip, style = { alignSelf = Align.Center }}); + var indexField = ux.AddChild(new PropertyField(indexProp, "") { style = { flexGrow = 1, flexBasis = 20 }}); + indexField.OnInitialGeometry(() => indexField.SafeSetIsDelayed()); + label.AddDelayedFriendlyPropertyDragger(indexProp, indexField, (dragger) => dragger.OnStartDrag = () => list.selectedIndex = index); - ux.Add(new VisualElement { pickingMode = PickingMode.Ignore, style = { width = 12 }}); // pass-through for selecting row in list - ux.Add(new InspectorUtility.CompactPropertyField(valueProp.FindPropertyRelative(() => def.Value), "Roll") { style = { flexGrow = 1 }}); + ux.Add(new VisualElement { pickingMode = PickingMode.Ignore, style = { width = 12 }}); // pass-through for selecting row in list + ux.Add(new InspectorUtility.CompactPropertyField(valueProp.FindPropertyRelative(() => def.Value), "Roll") { style = { flexGrow = 1 }}); - ((BindableElement)ux).BindProperty(element); // bind must be done at the end - }; + ((BindableElement)ux).BindProperty(element); // bind must be done at the end + }; - SplineRollTool.s_OnDataLookAtDragged += OnToolDragged; - SplineRollTool.s_OnDataIndexDragged += OnToolDragged; - void OnToolDragged(CinemachineSplineRoll data, int index) + SplineRollTool.s_OnDataLookAtDragged += OnToolDragged; + SplineRollTool.s_OnDataIndexDragged += OnToolDragged; + void OnToolDragged(CinemachineSplineRoll data, int index) + { + EditorApplication.delayCall += () => { - EditorApplication.delayCall += () => + // This is a hack to avoid spurious exceptions thrown by uitoolkit! + // GML TODO: Remove when they fix it + try { - // This is a hack to avoid spurious exceptions thrown by uitoolkit! - // GML TODO: Remove when they fix it - try - { - if (data == splineData) - list.selectedIndex = index; - } - catch {} // Ignore exceptions - }; - } - }); + if (data == splineData) + list.selectedIndex = index; + } + catch {} // Ignore exceptions + }; + } ux.TrackPropertyValue(rollProp, (p) => { diff --git a/com.unity.cinemachine/Editor/Utility/SplineDataInspectorUtility.cs b/com.unity.cinemachine/Editor/Utility/SplineDataInspectorUtility.cs index 1086ac41b..4baa77583 100644 --- a/com.unity.cinemachine/Editor/Utility/SplineDataInspectorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/SplineDataInspectorUtility.cs @@ -59,7 +59,7 @@ static void ConvertPathUnit( pathUnitProp.enumValueIndex = (int)newIndexUnit; } - public static PropertyField CreateDataListField( + public static ListView CreateDataListField( SplineData splineData, SerializedProperty splineDataProp, GetSplineDelegate getSpline, @@ -71,67 +71,68 @@ public static PropertyField CreateDataListField( var pathUnitProp = splineDataProp.FindPropertyRelative("m_IndexUnit"); var arrayProp = splineDataProp.FindPropertyRelative("m_DataPoints"); - var list = new PropertyField(arrayProp); - list.OnInitialGeometry(() => + var list = new ListView { - var listView = list.Q(); - listView.reorderable = false; - listView.showFoldoutHeader = false; - listView.showBoundCollectionSize = false; - listView.showAddRemoveFooter = true; - listView.showAlternatingRowBackgrounds = AlternatingRowBackground.None; - - // When we add the first item, make sure to use the default value - var button = list.Q