diff --git a/Editor.Extras/Drawers/AnimatorParameterAttributeDrawer.cs b/Editor.Extras/Drawers/AnimatorParameterAttributeDrawer.cs index fe653e90..b1739dc6 100644 --- a/Editor.Extras/Drawers/AnimatorParameterAttributeDrawer.cs +++ b/Editor.Extras/Drawers/AnimatorParameterAttributeDrawer.cs @@ -6,8 +6,10 @@ using TriInspector; using TriInspector.Drawers; using TriInspector.Resolvers; +using TriInspector.VisualElements; using UnityEditor; using UnityEngine; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(AnimatorParameterAttributeDrawer), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] @@ -34,17 +36,20 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override void OnGUI(Rect position, TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) + { + var imgui = new IMGUIContainer(() => DrawImgui(property)); + return new TriAlignedLabelVisualElement(property, imgui); + } + + private void DrawImgui(TriProperty property) { var animator = _resolvedParams.AnimatorResolver.GetValue(property); - var label = property.DisplayNameContent; var (allParameters, allFilteredParameters) = AnimatorParameterHelper.GetParameters(animator, Attribute.ParameterType); if (property.ValueType == typeof(string)) { DrawPopup( - position, - label, property, animator, (string)property.Value, @@ -58,8 +63,6 @@ public override void OnGUI(Rect position, TriProperty property, TriElement next) else if (property.ValueType == typeof(int)) { DrawPopup( - position, - label, property, animator, (int)property.Value, @@ -72,8 +75,6 @@ public override void OnGUI(Rect position, TriProperty property, TriElement next) } } private void DrawPopup( - Rect position, - GUIContent label, TriProperty property, Animator animator, T currentValue, @@ -106,7 +107,7 @@ private void DrawPopup( } EditorGUI.BeginChangeCheck(); - int newIndex = EditorGUI.Popup(position, label, currentIndex, displayList.ToArray()); + int newIndex = EditorGUILayout.Popup(currentIndex, displayList.ToArray()); if (EditorGUI.EndChangeCheck()) { diff --git a/Editor.Extras/Drawers/AssetDropdownDrawer.cs b/Editor.Extras/Drawers/AssetDropdownDrawer.cs index 65da07f4..56a7517b 100644 --- a/Editor.Extras/Drawers/AssetDropdownDrawer.cs +++ b/Editor.Extras/Drawers/AssetDropdownDrawer.cs @@ -2,10 +2,11 @@ using System.Linq; using TriInspector; using TriInspector.Drawers; -using TriInspector.Elements; using TriInspector.Utilities; +using TriInspector.VisualElements; using UnityEditor; -using UnityEngine; +using UnityEngine.UIElements; +using Object = UnityEngine.Object; [assembly: RegisterTriAttributeDrawer(typeof(AssetDropdownDrawer<>), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] @@ -14,7 +15,7 @@ namespace TriInspector.Drawers { public class AssetDropdownDrawer : TriAttributeDrawer { - private bool showNoneElement; + private bool _showNoneElement; public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { @@ -24,23 +25,25 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return "AssetDropdown attribute can only be used on field with UnityEngine.Object type"; } - showNoneElement = !propertyDefinition.Attributes.TryGet(out _); + _showNoneElement = !propertyDefinition.Attributes.TryGet(out _); return base.Initialize(propertyDefinition); } - public override TriElement CreateElement(TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - var dropdownElement = new TriDropdownElement(property, EnumerateAssets, Attribute.Advanced); + var dropdownElement = new TriDropdownVisualElement(property, EnumerateAssets, Attribute.Advanced); if (Attribute.HideNextDrawer) { return dropdownElement; } - var line = new TriHorizontalGroupElement(); - line.AddChild(dropdownElement); - line.AddChild(base.CreateElement(property, next)); + var line = new VisualElement(); + line.style.flexDirection = FlexDirection.Row; + dropdownElement.style.flexGrow = 1; + line.Add(dropdownElement); + line.Add(next); return line; } @@ -56,7 +59,7 @@ private IEnumerable EnumerateAssets(TriProperty property) Value = (T) (object) asset, }); - if (showNoneElement) + if (_showNoneElement) { assets = assets.Prepend(new TriDropdownItem {Text = "None", Value = default,}); } diff --git a/Editor.Extras/Drawers/BuiltinDrawerBase.cs b/Editor.Extras/Drawers/BuiltinDrawerBase.cs index baafe310..b11beb88 100644 --- a/Editor.Extras/Drawers/BuiltinDrawerBase.cs +++ b/Editor.Extras/Drawers/BuiltinDrawerBase.cs @@ -1,45 +1,29 @@ -using UnityEditor; -using UnityEngine; +using TriInspector.VisualElements; +using UnityEngine.UIElements; namespace TriInspector.Drawers { public abstract class BuiltinDrawerBase : TriValueDrawer { - public sealed override TriElement CreateElement(TriValue propertyValue, TriElement next) + public override VisualElement CreateVisualElement(TriValue propertyValue, VisualElement next) { if (propertyValue.Property.TryGetSerializedProperty(out _)) { return next; } - return base.CreateElement(propertyValue, next); - } - - public virtual int CompactModeLines => 1; - public virtual int WideModeLines => 1; + var field = CreateField(); + if (field == null) + { + return next; + } - public sealed override float GetHeight(float width, TriValue propertyValue, TriElement next) - { - var lineHeight = EditorGUIUtility.singleLineHeight; - var spacing = EditorGUIUtility.standardVerticalSpacing; - var lines = EditorGUIUtility.wideMode ? WideModeLines : CompactModeLines; - return lineHeight * lines + spacing * (lines - 1); + return TriBuiltinFieldFactory.Create(propertyValue, field); } - public sealed override void OnGUI(Rect position, TriValue propertyValue, TriElement next) + protected virtual BaseField CreateField() { - var value = propertyValue.SmartValue; - - EditorGUI.BeginChangeCheck(); - - value = OnValueGUI(position, propertyValue.Property.DisplayNameContent, value); - - if (EditorGUI.EndChangeCheck()) - { - propertyValue.SetValue(value); - } + return null; } - - protected abstract T OnValueGUI(Rect position, GUIContent label, T value); } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/BuiltinDrawers.cs b/Editor.Extras/Drawers/BuiltinDrawers.cs index a303a11c..fbdfd6a0 100644 --- a/Editor.Extras/Drawers/BuiltinDrawers.cs +++ b/Editor.Extras/Drawers/BuiltinDrawers.cs @@ -1,9 +1,12 @@ using System; using TriInspector; using TriInspector.Drawers; +using TriInspector.VisualElements; using UnityEditor; +using UnityEditor.UIElements; using UnityEditorInternal; using UnityEngine; +using UnityEngine.UIElements; [assembly: RegisterTriValueDrawer(typeof(IntegerDrawer), TriDrawerOrder.Fallback)] [assembly: RegisterTriValueDrawer(typeof(LongDrawer), TriDrawerOrder.Fallback)] @@ -30,195 +33,132 @@ namespace TriInspector.Drawers { public class StringDrawer : BuiltinDrawerBase { - protected override string OnValueGUI(Rect position, GUIContent label, string value) - { - return EditorGUI.TextField(position, label, value); - } + protected override BaseField CreateField() => new TextField(); } public class BooleanDrawer : BuiltinDrawerBase { - protected override bool OnValueGUI(Rect position, GUIContent label, bool value) - { - return EditorGUI.Toggle(position, label, value); - } + protected override BaseField CreateField() => new Toggle(); } public class IntegerDrawer : BuiltinDrawerBase { - protected override int OnValueGUI(Rect position, GUIContent label, int value) - { - return EditorGUI.IntField(position, label, value); - } + protected override BaseField CreateField() => new IntegerField(); } public class LongDrawer : BuiltinDrawerBase { - protected override long OnValueGUI(Rect position, GUIContent label, long value) - { - return EditorGUI.LongField(position, label, value); - } + protected override BaseField CreateField() => new LongField(); } public class FloatDrawer : BuiltinDrawerBase { - protected override float OnValueGUI(Rect position, GUIContent label, float value) - { - return EditorGUI.FloatField(position, label, value); - } + protected override BaseField CreateField() => new FloatField(); } public class ColorDrawer : BuiltinDrawerBase { - protected override Color OnValueGUI(Rect position, GUIContent label, Color value) - { - return EditorGUI.ColorField(position, label, value); - } + protected override BaseField CreateField() => new ColorField(); } public class Color32Drawer : BuiltinDrawerBase { - protected override Color32 OnValueGUI(Rect position, GUIContent label, Color32 value) + public override VisualElement CreateVisualElement(TriValue propertyValue, VisualElement next) { - return EditorGUI.ColorField(position, label, value); + if (propertyValue.Property.TryGetSerializedProperty(out _)) + { + return next; + } + + return TriBuiltinFieldFactory.Create(propertyValue, new ColorField(), v => v, v => v); } } public class LayerMaskDrawer : BuiltinDrawerBase { - protected override LayerMask OnValueGUI(Rect position, GUIContent label, LayerMask value) + public override VisualElement CreateVisualElement(TriValue propertyValue, VisualElement next) { - var mask = InternalEditorUtility.LayerMaskToConcatenatedLayersMask(value); - var layers = InternalEditorUtility.layers; + if (propertyValue.Property.TryGetSerializedProperty(out _)) + { + return next; + } - position = EditorGUI.PrefixLabel(position, label); - return EditorGUI.MaskField(position, mask, layers); + return TriBuiltinFieldFactory.Create(propertyValue, new LayerMaskField(), v => v.value, v => v); } } public class EnumDrawer : BuiltinDrawerBase { - protected override Enum OnValueGUI(Rect position, GUIContent label, Enum value) + public override VisualElement CreateVisualElement(TriValue propertyValue, VisualElement next) { - return EditorGUI.EnumPopup(position, label, value); + if (propertyValue.Property.TryGetSerializedProperty(out _)) + { + return next; + } + + var enumType = propertyValue.Property.FieldType; + var current = propertyValue.SmartValue ?? (Enum) Enum.ToObject(enumType, 0); + + BaseField field = enumType.IsDefined(typeof(FlagsAttribute), false) + ? new EnumFlagsField(current) + : new EnumField(current); + + return TriBuiltinFieldFactory.Create(propertyValue, field); } } public class Vector2Drawer : BuiltinDrawerBase { - public override int CompactModeLines => 2; - - protected override Vector2 OnValueGUI(Rect position, GUIContent label, Vector2 value) - { - return EditorGUI.Vector2Field(position, label, value); - } + protected override BaseField CreateField() => new Vector2Field(); } public class Vector3Drawer : BuiltinDrawerBase { - public override int CompactModeLines => 2; - - protected override Vector3 OnValueGUI(Rect position, GUIContent label, Vector3 value) - { - return EditorGUI.Vector3Field(position, label, value); - } + protected override BaseField CreateField() => new Vector3Field(); } public class Vector4Drawer : BuiltinDrawerBase { - public override int CompactModeLines => 2; - - protected override Vector4 OnValueGUI(Rect position, GUIContent label, Vector4 value) - { - return EditorGUI.Vector4Field(position, label, value); - } + protected override BaseField CreateField() => new Vector4Field(); } public class RectDrawer : BuiltinDrawerBase { - public override int CompactModeLines => 3; - public override int WideModeLines => 2; - - protected override Rect OnValueGUI(Rect position, GUIContent label, Rect value) - { - return EditorGUI.RectField(position, label, value); - } + protected override BaseField CreateField() => new RectField(); } public class AnimationCurveDrawer : BuiltinDrawerBase { - protected override AnimationCurve OnValueGUI(Rect position, GUIContent label, AnimationCurve value) - { - return EditorGUI.CurveField(position, label, value); - } + protected override BaseField CreateField() => new CurveField(); } public class BoundsDrawer : BuiltinDrawerBase { - public override int CompactModeLines => 3; - public override int WideModeLines => 3; - - protected override Bounds OnValueGUI(Rect position, GUIContent label, Bounds value) - { - return EditorGUI.BoundsField(position, label, value); - } + protected override BaseField CreateField() => new BoundsField(); } public class GradientDrawer : BuiltinDrawerBase { - private static readonly GUIContent NullLabel = new GUIContent("Gradient is null"); - - protected override Gradient OnValueGUI(Rect position, GUIContent label, Gradient value) - { - if (value == null) - { - EditorGUI.LabelField(position, label, NullLabel); - return null; - } - - return EditorGUI.GradientField(position, label, value); - } + protected override BaseField CreateField() => new GradientField(); } public class Vector2IntDrawer : BuiltinDrawerBase { - public override int CompactModeLines => 2; - - protected override Vector2Int OnValueGUI(Rect position, GUIContent label, Vector2Int value) - { - return EditorGUI.Vector2IntField(position, label, value); - } + protected override BaseField CreateField() => new Vector2IntField(); } public class Vector3IntDrawer : BuiltinDrawerBase { - public override int CompactModeLines => 2; - - protected override Vector3Int OnValueGUI(Rect position, GUIContent label, Vector3Int value) - { - return EditorGUI.Vector3IntField(position, label, value); - } + protected override BaseField CreateField() => new Vector3IntField(); } public class RectIntDrawer : BuiltinDrawerBase { - public override int CompactModeLines => 3; - public override int WideModeLines => 2; - - protected override RectInt OnValueGUI(Rect position, GUIContent label, RectInt value) - { - return EditorGUI.RectIntField(position, label, value); - } + protected override BaseField CreateField() => new RectIntField(); } public class BoundsIntDrawer : BuiltinDrawerBase { - public override int CompactModeLines => 3; - public override int WideModeLines => 3; - - protected override BoundsInt OnValueGUI(Rect position, GUIContent label, BoundsInt value) - { - return EditorGUI.BoundsIntField(position, label, value); - } + protected override BaseField CreateField() => new BoundsIntField(); } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/ButtonDrawer.TriStyleSheet.uss b/Editor.Extras/Drawers/ButtonDrawer.TriStyleSheet.uss new file mode 100644 index 00000000..1fd4d77b --- /dev/null +++ b/Editor.Extras/Drawers/ButtonDrawer.TriStyleSheet.uss @@ -0,0 +1,16 @@ +.tri-button { + margin: 1px -2px 1px 3px; + white-space: normal; +} + +.tri-button__box { + margin: 1px -2px 1px 3px; + padding: 2px 5px 2px 2px; + border-width: 1px; + border-color: var(--tri-color-border); + border-radius: 3px; +} + +.tri-button__box > .tri-button { + margin: -3px -6px 3px -3px; +} diff --git a/Editor.Extras/Drawers/ButtonDrawer.TriStyleSheet.uss.meta b/Editor.Extras/Drawers/ButtonDrawer.TriStyleSheet.uss.meta new file mode 100644 index 00000000..8888300d --- /dev/null +++ b/Editor.Extras/Drawers/ButtonDrawer.TriStyleSheet.uss.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 19ae24a4b64d4652874338186e537aa9 +timeCreated: 1786096698 \ No newline at end of file diff --git a/Editor.Extras/Drawers/ButtonDrawer.cs b/Editor.Extras/Drawers/ButtonDrawer.cs index ef9b418b..aa7fbe6c 100644 --- a/Editor.Extras/Drawers/ButtonDrawer.cs +++ b/Editor.Extras/Drawers/ButtonDrawer.cs @@ -1,12 +1,11 @@ -using System; +using System; using System.Reflection; using TriInspector; using TriInspector.Drawers; -using TriInspector.Elements; using TriInspector.Resolvers; -using TriInspector.Utilities; -using UnityEditor; +using TriInspector.VisualElements; using UnityEngine; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(ButtonDrawer), TriDrawerOrder.Drawer)] @@ -33,94 +32,98 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override TriElement CreateElement(TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - return new TriButtonElement(property, Attribute, _nameResolver); + return new TriButtonVisualElement(property, Attribute, _nameResolver); } - private class TriButtonElement : TriHeaderGroupBaseElement + private class TriButtonVisualElement : VisualElement { private readonly TriProperty _property; - private readonly ButtonAttribute _attribute; private readonly ValueResolver _nameResolver; private readonly object[] _invocationArgs; - public TriButtonElement(TriProperty property, ButtonAttribute attribute, + public TriButtonVisualElement(TriProperty property, ButtonAttribute attribute, ValueResolver nameResolver) { _property = property; - _attribute = attribute; _nameResolver = nameResolver; var mi = property.TryGetMemberInfo(out var memberInfo) ? (MethodInfo) memberInfo - : throw new Exception("TriButtonElement requires MethodInfo"); + : throw new Exception("TriButtonVisualElement requires MethodInfo"); var parameters = mi.GetParameters(); _invocationArgs = new object[parameters.Length]; - for (var i = 0; i < parameters.Length; i++) + var button = new Button(OnButtonClicked) { - var pIndex = i; - var pInfo = parameters[pIndex]; + text = ResolveName(), + }; + button.AddToClassList(Styles.Button); + + if (attribute.ButtonSize != 0) + { + button.style.height = attribute.ButtonSize; + } - if (pInfo.HasDefaultValue) + if (parameters.Length == 0) + { + Add(button); + } + else + { + var box = new VisualElement(); + box.AddToClassList(Styles.ButtonBox); + Add(box); + + box.Add(button); + + for (var i = 0; i < parameters.Length; i++) { - _invocationArgs[pIndex] = pInfo.DefaultValue; - } + var pIndex = i; + var pInfo = parameters[pIndex]; - var pTriDefinition = TriPropertyDefinition.CreateForGetterSetter( - pIndex, pInfo.Name, pInfo.ParameterType, - ((self, targetIndex) => _invocationArgs[pIndex]), - ((self, targetIndex, value) => _invocationArgs[pIndex] = value)); + if (pInfo.HasDefaultValue) + { + _invocationArgs[pIndex] = pInfo.DefaultValue; + } - var pTriProperty = new TriProperty(_property.PropertyTree, _property, pTriDefinition, null); + var pTriDefinition = TriPropertyDefinition.CreateForGetterSetter( + pIndex, pInfo.Name, pInfo.ParameterType, + ((self, targetIndex) => _invocationArgs[pIndex]), + ((self, targetIndex, value) => _invocationArgs[pIndex] = value)); - AddChild(new TriPropertyElement(pTriProperty)); + var pTriProperty = new TriProperty(_property.PropertyTree, _property, pTriDefinition, null); + + box.Add(new TriPropertyVisualElement(pTriProperty)); + } } - } - protected override float GetHeaderHeight(float width) - { - return GetButtonHeight(); + this.PeriodicRun(() => button.text = ResolveName()); } - protected override void DrawHeader(Rect position) + private string ResolveName() { - if (_invocationArgs.Length > 0) - { - TriEditorGUI.DrawBox(position, TriEditorStyles.TabOnlyOne); - } + var buttonName = _nameResolver.GetValue(_property); - var name = _nameResolver.GetValue(_property); - - if (string.IsNullOrEmpty(name)) + if (string.IsNullOrEmpty(buttonName)) { - name = _property.DisplayName; + buttonName = _property.DisplayName; } - if (string.IsNullOrEmpty(name)) + if (string.IsNullOrEmpty(buttonName)) { - name = _property.RawName; + buttonName = _property.RawName; } - var buttonRect = new Rect(position) - { - height = GetButtonHeight(), - }; - - if (GUI.Button(buttonRect, name)) - { - InvokeButton(_property, _invocationArgs); - } + return buttonName; } - private float GetButtonHeight() + private void OnButtonClicked() { - return _attribute.ButtonSize != 0 - ? _attribute.ButtonSize - : EditorGUIUtility.singleLineHeight; + InvokeButton(_property, _invocationArgs); } } @@ -142,5 +145,11 @@ private static void InvokeButton(TriProperty property, object[] parameters) }); } } + + private static class Styles + { + public const string Button = "tri-button"; + public const string ButtonBox = "tri-button__box"; + } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/CustomBuiltInDrawer.cs b/Editor.Extras/Drawers/CustomBuiltInDrawer.cs index c4514ade..799cb9b3 100644 --- a/Editor.Extras/Drawers/CustomBuiltInDrawer.cs +++ b/Editor.Extras/Drawers/CustomBuiltInDrawer.cs @@ -1,9 +1,9 @@ using TriInspector; using TriInspector.Drawers; -using TriInspector.Editors; -using TriInspector.Elements; using TriInspector.Utilities; +using TriInspector.VisualElements; using TriInspectorUnityInternalBridge; +using UnityEngine.UIElements; [assembly: RegisterTriValueDrawer(typeof(CustomBuiltInDrawer), TriDrawerOrder.Fallback - 999)] @@ -11,8 +11,13 @@ namespace TriInspector.Drawers { public class CustomBuiltInDrawer : TriValueDrawer { - public override TriElement CreateElement(TriValue propertyValue, TriElement next) + public override VisualElement CreateVisualElement(TriValue propertyValue, VisualElement next) { + if (propertyValue.Property.IsRootProperty) + { + return next; + } + var property = propertyValue.Property; if (property.TryGetSerializedProperty(out var serializedProperty)) @@ -25,26 +30,11 @@ public override TriElement CreateElement(TriValue propertyValue, TriElem if (drawWithHandler) { - if (property.TryGetAttribute(out DrawWithUnityAttribute withUnityAttribute) && - withUnityAttribute.WithUiToolkit) - { - handler.SetPreferredLabel(property.DisplayName); - - var visualElement = handler.CreatePropertyGUI(serializedProperty); - - if (visualElement != null && - TriEditorCore.UiElementsRoots.TryGetValue(property.PropertyTree, out var rootElement)) - { - return new TriUiToolkitPropertyElement(property, serializedProperty, - visualElement, rootElement); - } - } - - return new TriBuiltInPropertyElement(property, serializedProperty, handler); + return new TriBuiltInPropertyVisualElement(property, serializedProperty); } } - return base.CreateElement(propertyValue, next); + return next; } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/DisplayAsStringDrawer.cs b/Editor.Extras/Drawers/DisplayAsStringDrawer.cs index 4775df0c..489f87eb 100644 --- a/Editor.Extras/Drawers/DisplayAsStringDrawer.cs +++ b/Editor.Extras/Drawers/DisplayAsStringDrawer.cs @@ -1,27 +1,41 @@ -using TriInspector; +using TriInspector; using TriInspector.Drawers; -using UnityEditor; -using UnityEngine; +using TriInspector.VisualElements; +using UnityEditor.UIElements; +using UnityEngine.UIElements; -[assembly: RegisterTriAttributeDrawer(typeof(DisplayAsStringDrawer), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] +[assembly: + RegisterTriAttributeDrawer(typeof(DisplayAsStringDrawer), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] namespace TriInspector.Drawers { public class DisplayAsStringDrawer : TriAttributeDrawer { - public override float GetHeight(float width, TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - return EditorGUIUtility.singleLineHeight; + return new TriAlignedLabelVisualElement(property, new TriDisplayAsString(property)); } - public override void OnGUI(Rect position, TriProperty property, TriElement next) + private class TriDisplayAsString : Label { - var value = property.Value; - var text = value != null ? value.ToString() : "Null"; + public TriDisplayAsString(TriProperty property) + { + void Sync() + { + text = property.Value?.ToString() ?? "Null"; + } - var controlId = GUIUtility.GetControlID(FocusType.Passive); - position = EditorGUI.PrefixLabel(position, controlId, property.DisplayNameContent); - GUI.Label(position, text); + if (property.TryGetSerializedProperty(out var serializedProperty)) + { + this.TrackPropertyValue(serializedProperty, _ => Sync()); + } + else + { + this.PeriodicRun(Sync); + } + + Sync(); + } } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/DropdownDrawer.cs b/Editor.Extras/Drawers/DropdownDrawer.cs index 7a4eb1fa..eda19ad9 100644 --- a/Editor.Extras/Drawers/DropdownDrawer.cs +++ b/Editor.Extras/Drawers/DropdownDrawer.cs @@ -1,8 +1,8 @@ using TriInspector; using TriInspector.Drawers; -using TriInspector.Elements; using TriInspector.Resolvers; -using UnityEngine; +using TriInspector.VisualElements; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(DropdownDrawer<>), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] @@ -24,9 +24,9 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override TriElement CreateElement(TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - return new TriDropdownElement(property, _valuesResolver.GetDropdownItems, Attribute.Advanced); + return new TriDropdownVisualElement(property, _valuesResolver.GetDropdownItems, Attribute.Advanced); } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/EnumToggleButtonsDrawer.cs b/Editor.Extras/Drawers/EnumToggleButtonsDrawer.cs index 0c76633c..6605090b 100644 --- a/Editor.Extras/Drawers/EnumToggleButtonsDrawer.cs +++ b/Editor.Extras/Drawers/EnumToggleButtonsDrawer.cs @@ -1,11 +1,13 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using TriInspector; using TriInspector.Drawers; +using TriInspector.VisualElements; using UnityEditor; using UnityEngine; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(EnumToggleButtonsDrawer), TriDrawerOrder.Drawer, ApplyOnArrayElement = true)] @@ -24,26 +26,27 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override TriElement CreateElement(TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - return new EnumToggleButtonsElement(property); + var buttons = new EnumToggleButtonsVisualElement(property); + return new TriAlignedLabelVisualElement(property, buttons); } - private sealed class EnumToggleButtonsElement : TriElement + private sealed class EnumToggleButtonsVisualElement : ToggleButtonGroup { private readonly TriProperty _property; private readonly List _enumValues; private readonly bool _isFlags; - public EnumToggleButtonsElement(TriProperty property) + public EnumToggleButtonsVisualElement(TriProperty property) { _property = property; _enumValues = Enum.GetNames(property.FieldType) - .Zip(Enum.GetValues(property.FieldType).OfType(), (name, value) => new EnumEntry + .Zip(Enum.GetValues(property.FieldType).OfType(), (key, val) => new EnumEntry { - name = name, - value = value, - displayName = ObjectNames.NicifyVariableName(name), + name = key, + value = val, + displayName = ObjectNames.NicifyVariableName(key), }) .ToList(); _isFlags = property.FieldType.GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0; @@ -61,80 +64,81 @@ public EnumToggleButtonsElement(TriProperty property) } _enumValues.Sort(new DeclarationOrderComparer(enumFields)); - } - - public override float GetHeight(float width) - { - return EditorGUIUtility.singleLineHeight; - } - - public override void OnGUI(Rect position) - { - var value = _property.TryGetSerializedProperty(out var serializedProperty) - ? (Enum) Enum.ToObject(_property.FieldType, serializedProperty.longValue) - : (Enum) _property.Value; - var controlId = GUIUtility.GetControlID(FocusType.Passive); - position = EditorGUI.PrefixLabel(position, controlId, _property.DisplayNameContent); + isMultipleSelection = _isFlags; + allowEmptySelection = _isFlags; - for (var i = 0; i < _enumValues.Count; i++) + foreach (var entry in _enumValues) { - var itemRect = SplitRectWidth(position, _enumValues.Count, i); - var itemStyle = GetButtonStyle(_enumValues.Count, i); - var itemDisplayName = _enumValues[i].displayName; - var itemValue = _enumValues[i].value; - - var oldSelected = value != null && (_isFlags ? value.HasFlag(itemValue) : value.Equals(itemValue)); - var newSelected = GUI.Toggle(itemRect, oldSelected, itemDisplayName, itemStyle); - - if (oldSelected != newSelected) + Add(new Button { - if (_isFlags) - { - var newValue = newSelected - ? (Convert.ToInt64(value) | Convert.ToInt64(itemValue)) - : (Convert.ToInt64(value) & ~Convert.ToInt64(itemValue)); - - _property.SetValue((Enum) Enum.ToObject(_property.FieldType, newValue)); - } - else + text = entry.displayName, + style = { - _property.SetValue(itemValue); - } - } + flexGrow = 1, + }, + }); } + + this.RegisterValueChangedCallback(OnValueChanged); + this.PeriodicRun(RefreshFromProperty); } - private static GUIStyle GetButtonStyle(int total, int current) + private Enum GetCurrentValue() { - if (total <= 1) - { - return EditorStyles.miniButton; - } + return _property.TryGetSerializedProperty(out var serializedProperty) + ? (Enum) Enum.ToObject(_property.FieldType, serializedProperty.longValue) + : (Enum) _property.Value; + } - if (current == 0) + private void RefreshFromProperty() + { + showMixedValue = _property.IsValueMixed; + if (_property.IsValueMixed) { - return EditorStyles.miniButtonLeft; + return; } - if (current == total - 1) + var current = GetCurrentValue(); + + var state = new ToggleButtonGroupState(0UL, _enumValues.Count); + for (var i = 0; i < _enumValues.Count; i++) { - return EditorStyles.miniButtonRight; + var itemValue = _enumValues[i].value; + state[i] = current != null && (_isFlags ? current.HasFlag(itemValue) : current.Equals(itemValue)); } - return EditorStyles.miniButtonMid; + SetValueWithoutNotify(state); } - private static Rect SplitRectWidth(Rect rect, int total, int current) + private void OnValueChanged(ChangeEvent evt) { - if (total == 0) + var state = evt.newValue; + + if (_isFlags) { - return rect; - } + long newValue = 0; + for (var i = 0; i < _enumValues.Count; i++) + { + if (state[i]) + { + newValue |= Convert.ToInt64(_enumValues[i].value); + } + } - rect.width /= total; - rect.x += rect.width * current; - return rect; + _property.SetValue((Enum) Enum.ToObject(_property.FieldType, newValue)); + } + else + { + for (var i = 0; i < _enumValues.Count; i++) + { + if (state[i]) + { + _property.SetValue(_enumValues[i].value); + break; + } + } + } } private class EnumEntry diff --git a/Editor.Extras/Drawers/GUIColorDrawer.cs b/Editor.Extras/Drawers/GUIColorDrawer.cs index 991c2be0..306217fe 100644 --- a/Editor.Extras/Drawers/GUIColorDrawer.cs +++ b/Editor.Extras/Drawers/GUIColorDrawer.cs @@ -1,8 +1,9 @@ -using JetBrains.Annotations; +using JetBrains.Annotations; using TriInspector; using TriInspector.Drawers; using TriInspector.Resolvers; using UnityEngine; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(GUIColorDrawer), TriDrawerOrder.Decorator)] @@ -27,18 +28,23 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override void OnGUI(Rect position, TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - var oldColor = GUI.color; - var newColor = _colorResolver?.GetValue(property, Color.white) ?? Attribute.Color; - - GUI.color = Attribute.Multiply ? oldColor * newColor : newColor; - GUI.contentColor = newColor; + void SetColor(Color value) + { + next.style.backgroundColor = value; + } - next.OnGUI(position); + if (_colorResolver != null) + { + next.TrackResolvedValue(property, _colorResolver, Attribute.Color, SetColor); + } + else + { + SetColor(Attribute.Color); + } - GUI.color = oldColor; - GUI.contentColor = oldColor; + return next; } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/IndentDrawer.cs b/Editor.Extras/Drawers/IndentDrawer.cs index 33fbac86..0ed90ea7 100644 --- a/Editor.Extras/Drawers/IndentDrawer.cs +++ b/Editor.Extras/Drawers/IndentDrawer.cs @@ -1,7 +1,6 @@ -using TriInspector; +using TriInspector; using TriInspector.Drawers; -using TriInspector.Utilities; -using UnityEngine; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(IndentDrawer), TriDrawerOrder.Decorator)] @@ -9,12 +8,12 @@ namespace TriInspector.Drawers { public class IndentDrawer : TriAttributeDrawer { - public override void OnGUI(Rect position, TriProperty property, TriElement next) + private const float IndentWidth = 15f; + + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - using (var indentedRectScope = TriGuiHelper.PushIndentedRect(position, Attribute.Indent)) - { - next.OnGUI(indentedRectScope.IndentedRect); - } + next.style.marginLeft = Attribute.Indent * IndentWidth - 1; + return next; } } -} \ No newline at end of file +} diff --git a/Editor.Extras/Drawers/InlineButtonDrawer.TriStyleSheet.uss b/Editor.Extras/Drawers/InlineButtonDrawer.TriStyleSheet.uss new file mode 100644 index 00000000..78235171 --- /dev/null +++ b/Editor.Extras/Drawers/InlineButtonDrawer.TriStyleSheet.uss @@ -0,0 +1,15 @@ +.tri-inline-button__row { + flex-direction: row; + align-items: center; +} + +.tri-inline-button__field { + flex-grow: 1; + flex-shrink: 0; +} + +.tri-inline-button__button { + margin-left: 4px; + margin-right: -2px; + flex-shrink: 0; +} diff --git a/Editor.Extras/Drawers/InlineButtonDrawer.TriStyleSheet.uss.meta b/Editor.Extras/Drawers/InlineButtonDrawer.TriStyleSheet.uss.meta new file mode 100644 index 00000000..79fe858b --- /dev/null +++ b/Editor.Extras/Drawers/InlineButtonDrawer.TriStyleSheet.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f9e41f116e9b57489820f8c1c7bae48 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Editor.Extras/Drawers/InlineButtonDrawer.cs b/Editor.Extras/Drawers/InlineButtonDrawer.cs index 19648f2f..c9c0f00b 100644 --- a/Editor.Extras/Drawers/InlineButtonDrawer.cs +++ b/Editor.Extras/Drawers/InlineButtonDrawer.cs @@ -1,101 +1,66 @@ -using System; -using System.Reflection; using TriInspector; using TriInspector.Drawers; -using UnityEngine; +using TriInspector.Resolvers; +using UnityEngine.UIElements; -[assembly: RegisterTriAttributeDrawer(typeof(InlineButtonDrawer), TriDrawerOrder.Drawer)] +[assembly: RegisterTriAttributeDrawer(typeof(InlineButtonDrawer), TriDrawerOrder.Decorator - 100)] namespace TriInspector.Drawers { public class InlineButtonDrawer : TriAttributeDrawer { - private const float MinButtonWidth = 28f; - private const float ButtonSpacing = 4f; - private const float ButtonPadding = 12f; - private const float MaxButtonWidthRatio = 0.25f; + private ActionResolver _actionResolver; public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { - if (string.IsNullOrEmpty(Attribute.Name)) + _actionResolver = ActionResolver.Resolve(propertyDefinition, Attribute.Name); + if (_actionResolver.TryGetErrorString(out var error)) { - return "[InlineButton] method name cannot be empty"; + return error; } return TriExtensionInitializationResult.Ok; } - public override float GetHeight(float width, TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - return next.GetHeight(width); + return new TriInlineButtonRow(property, next, Attribute, _actionResolver); } - public override void OnGUI(Rect position, TriProperty property, TriElement next) + private class TriInlineButtonRow : VisualElement { - var buttonText = !string.IsNullOrEmpty(Attribute.ButtonLabel) - ? Attribute.ButtonLabel - : Attribute.Name; + public TriInlineButtonRow(TriProperty property, VisualElement next, + InlineButtonAttribute attribute, ActionResolver actionResolver) + { + var buttonText = !string.IsNullOrEmpty(attribute.ButtonLabel) + ? attribute.ButtonLabel + : attribute.Name; - var buttonContent = new GUIContent(buttonText); - var maxButtonWidth = position.width * MaxButtonWidthRatio; - var buttonWidth = Attribute.ButtonWidth > 0f - ? Attribute.ButtonWidth - : Mathf.Clamp(GUI.skin.button.CalcSize(buttonContent).x + ButtonPadding, MinButtonWidth, maxButtonWidth); + AddToClassList(Styles.Row); - var propertyRect = new Rect(position) - { - width = position.width - buttonWidth - ButtonSpacing, - }; + next.AddToClassList(Styles.Field); + Add(next); - var buttonRect = new Rect(position) - { - x = position.x + position.width - buttonWidth, - width = buttonWidth, - }; + var button = new Button(() => actionResolver.InvokeForAllTargets(property)) + { + text = buttonText, + }; + button.AddToClassList(Styles.Button); - next.OnGUI(propertyRect); + if (attribute.ButtonWidth > 0f) + { + button.style.width = attribute.ButtonWidth; + } - if (GUI.Button(buttonRect, buttonContent)) - { - InvokeMethod(property); + Add(button); } } - private void InvokeMethod(TriProperty property) + private static class Styles { - var methodName = Attribute.Name; - - property.ModifyAndRecordForUndo(targetIndex => - { - try - { - var parentValue = property.Parent.GetValue(targetIndex); - var targetType = parentValue?.GetType() ?? property.Parent.FieldType; - - var methodInfo = targetType.GetMethod( - methodName, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - - if (methodInfo == null) - { - Debug.LogError($"[InlineButton] Method '{methodName}' not found on type '{targetType.Name}'"); - return; - } - - var parameters = methodInfo.GetParameters(); - if (parameters.Length > 0) - { - Debug.LogError($"[InlineButton] Method '{methodName}' must have no parameters"); - return; - } - - methodInfo.Invoke(parentValue, null); - } - catch (Exception e) - { - Debug.LogException(e); - } - }); + public const string Row = "tri-inline-button__row"; + public const string Field = "tri-inline-button__field"; + public const string Button = "tri-inline-button__button"; } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/InlineEditorDrawer.cs b/Editor.Extras/Drawers/InlineEditorDrawer.cs index b98ccc9a..04ae8641 100644 --- a/Editor.Extras/Drawers/InlineEditorDrawer.cs +++ b/Editor.Extras/Drawers/InlineEditorDrawer.cs @@ -1,9 +1,7 @@ using TriInspector; using TriInspector.Drawers; -using TriInspector.Elements; -using TriInspector.Utilities; -using UnityEditor; -using UnityEngine; +using TriInspector.VisualElements; +using UnityEngine.UIElements; using Object = UnityEngine.Object; [assembly: RegisterTriAttributeDrawer(typeof(InlineEditorDrawer), TriDrawerOrder.Decorator, @@ -23,63 +21,13 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override TriElement CreateElement(TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - var element = new TriBoxGroupElement(new TriBoxGroupElement.Props - { - titleMode = TriBoxGroupElement.TitleMode.Hidden, - }); - element.AddChild(new ObjectReferenceFoldoutDrawerElement(property)); - element.AddChild(new InlineEditorElement(property, new InlineEditorElement.Props + return new TriInlineEditorVisualElement(property, new TriInlineEditorVisualElement.Props { mode = Attribute.Mode, previewHeight = Attribute.PreviewHeight, - })); - return element; - } - - private class ObjectReferenceFoldoutDrawerElement : TriElement - { - private readonly TriProperty _property; - - public ObjectReferenceFoldoutDrawerElement(TriProperty property) - { - _property = property; - } - - public override float GetHeight(float width) - { - return EditorGUIUtility.singleLineHeight; - } - - public override void OnGUI(Rect position) - { - var prefixRect = new Rect(position) - { - height = EditorGUIUtility.singleLineHeight, - xMax = position.xMin + EditorGUIUtility.labelWidth, - }; - var pickerRect = new Rect(position) - { - height = EditorGUIUtility.singleLineHeight, - xMin = prefixRect.xMax, - }; - - TriEditorGUI.Foldout(prefixRect, _property); - - EditorGUI.BeginChangeCheck(); - - var allowSceneObjects = _property.PropertyTree.TargetIsPersistent == false; - - var value = (Object) _property.Value; - value = EditorGUI.ObjectField(pickerRect, GUIContent.none, value, - _property.FieldType, allowSceneObjects); - - if (EditorGUI.EndChangeCheck()) - { - _property.SetValue(value); - } - } + }); } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/LabelWidthDrawer.cs b/Editor.Extras/Drawers/LabelWidthDrawer.cs index 5c813b8d..5f64e67c 100644 --- a/Editor.Extras/Drawers/LabelWidthDrawer.cs +++ b/Editor.Extras/Drawers/LabelWidthDrawer.cs @@ -1,7 +1,7 @@ -using TriInspector; +using TriInspector; using TriInspector.Drawers; -using UnityEditor; -using UnityEngine; +using TriInspector.VisualElements; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(LabelWidthDrawer), TriDrawerOrder.Decorator)] @@ -9,13 +9,9 @@ namespace TriInspector.Drawers { public class LabelWidthDrawer : TriAttributeDrawer { - public override void OnGUI(Rect position, TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - var oldLabelWidth = EditorGUIUtility.labelWidth; - - EditorGUIUtility.labelWidth = Attribute.Width; - next.OnGUI(position); - EditorGUIUtility.labelWidth = oldLabelWidth; + return new TriLabelWidthContextVisualElement(Attribute.Width, next); } } -} \ No newline at end of file +} diff --git a/Editor.Extras/Drawers/LayerDrawer.cs b/Editor.Extras/Drawers/LayerDrawer.cs index 024f8bd8..a1403b95 100644 --- a/Editor.Extras/Drawers/LayerDrawer.cs +++ b/Editor.Extras/Drawers/LayerDrawer.cs @@ -1,7 +1,8 @@ using TriInspector; using TriInspector.Drawers; -using UnityEditor; -using UnityEngine; +using TriInspector.VisualElements; +using UnityEditor.UIElements; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(LayerDrawer), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] @@ -20,38 +21,13 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return base.Initialize(propertyDefinition); } - public override TriElement CreateElement(TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - return new LayerElement(property); - } - - private class LayerElement : TriElement - { - private readonly TriProperty _property; - - public LayerElement(TriProperty property) - { - _property = property; - } - - public override float GetHeight(float width) - { - return EditorGUIUtility.singleLineHeight; - } - - public override void OnGUI(Rect position) - { - EditorGUI.BeginChangeCheck(); + var field = new LayerField(); - var currentValue = (int)_property.Value; - var newValue = EditorGUI.LayerField(position, _property.DisplayName, currentValue); - - if (EditorGUI.EndChangeCheck()) - { - _property.SetValue(newValue); - } - } + return TriBuiltinFieldFactory.CreateForProperty(property, field, + () => (int) property.Value, + value => property.SetValue(value)); } } } - diff --git a/Editor.Extras/Drawers/MaterialPropertyAttributeDrawer.cs b/Editor.Extras/Drawers/MaterialPropertyAttributeDrawer.cs index 49fdd226..56dc3ba7 100644 --- a/Editor.Extras/Drawers/MaterialPropertyAttributeDrawer.cs +++ b/Editor.Extras/Drawers/MaterialPropertyAttributeDrawer.cs @@ -4,9 +4,11 @@ using TriInspector; using TriInspector.Drawers; using TriInspector.Resolvers; +using TriInspector.VisualElements; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(MaterialPropertyAttributeDrawer), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] @@ -30,17 +32,20 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override void OnGUI(Rect position, TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) + { + var imgui = new IMGUIContainer(() => DrawImgui(property)); + return new TriAlignedLabelVisualElement(property, imgui); + } + + private void DrawImgui(TriProperty property) { var material = _resolvedParams.MaterialResolver.GetValue(property); - var label = property.DisplayNameContent; var (allProperties, filteredProperties) = MaterialPropertyHelper.GetProperties(material, Attribute.PropertyType); if (property.ValueType == typeof(string)) { DrawPopup( - position, - label, property, material, (string)property.Value, @@ -54,8 +59,6 @@ public override void OnGUI(Rect position, TriProperty property, TriElement next) else if (property.ValueType == typeof(int)) { DrawPopup( - position, - label, property, material, (int)property.Value, @@ -69,8 +72,6 @@ public override void OnGUI(Rect position, TriProperty property, TriElement next) } private void DrawPopup( - Rect position, - GUIContent label, TriProperty property, Material material, T currentValue, @@ -103,7 +104,7 @@ private void DrawPopup( } EditorGUI.BeginChangeCheck(); - int newIndex = EditorGUI.Popup(position, label, currentIndex, displayList.ToArray()); + int newIndex = EditorGUILayout.Popup(currentIndex, displayList.ToArray()); if (EditorGUI.EndChangeCheck()) { diff --git a/Editor.Extras/Drawers/MinMaxSliderDrawer.TriStyleSheet.uss b/Editor.Extras/Drawers/MinMaxSliderDrawer.TriStyleSheet.uss new file mode 100644 index 00000000..25a5a5ab --- /dev/null +++ b/Editor.Extras/Drawers/MinMaxSliderDrawer.TriStyleSheet.uss @@ -0,0 +1,16 @@ +.tri-min-max-slider { + flex-direction: row; + flex-grow: 1; +} + +.tri-min-max-slider__field { + width: 48px; + margin-left: 0; + margin-right: 0; +} + +.tri-min-max-slider__slider { + flex-grow: 1; + margin-left: 5px; + margin-right: 5px; +} diff --git a/Editor.Extras/Drawers/MinMaxSliderDrawer.TriStyleSheet.uss.meta b/Editor.Extras/Drawers/MinMaxSliderDrawer.TriStyleSheet.uss.meta new file mode 100644 index 00000000..ecf205ea --- /dev/null +++ b/Editor.Extras/Drawers/MinMaxSliderDrawer.TriStyleSheet.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0fea8891cfe4c58479b391991c483ded +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Editor.Extras/Drawers/MinMaxSliderDrawer.cs b/Editor.Extras/Drawers/MinMaxSliderDrawer.cs index 1d6e1397..dc2f2a0c 100644 --- a/Editor.Extras/Drawers/MinMaxSliderDrawer.cs +++ b/Editor.Extras/Drawers/MinMaxSliderDrawer.cs @@ -2,12 +2,13 @@ using System.Collections.Generic; using TriInspector; using TriInspector.Drawers; -using TriInspector.Resolvers; -using TriInspector.Utilities; -using UnityEditor; +using TriInspector.VisualElements; using UnityEngine; +using UnityEngine.UIElements; -[assembly: RegisterTriAttributeDrawer(typeof(MinMaxSliderAttributeDrawer), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] +[assembly: + RegisterTriAttributeDrawer(typeof(MinMaxSliderAttributeDrawer), TriDrawerOrder.Decorator, + ApplyOnArrayElement = true)] namespace TriInspector.Drawers { @@ -15,7 +16,6 @@ public class MinMaxSliderAttributeDrawer : TriAttributeDrawer ApplyValue(evt.newValue, CurrentValue().y)); + + _slider = new MinMaxSlider(); + _slider.AddToClassList(Styles.Slider); + _slider.RegisterValueChangedCallback(evt => ApplyValue(evt.newValue.x, evt.newValue.y)); + + _maxField = new FloatField(); + _maxField.AddToClassList(Styles.Field); + _maxField.RegisterValueChangedCallback(evt => ApplyValue(CurrentValue().x, evt.newValue)); + + Add(_minField); + Add(_slider); + Add(_maxField); + + this.PeriodicRun(RefreshFromProperty); + } + + private (double min, double max) GetLimits() { - var val = (Vector2Int) property.Value; - xValue = val.x; - yValue = val.y; + return MinMaxSliderAttributeHelpers.GetLimits(_property, _attribute, _resolvers); } - else + + private Vector2 CurrentValue() { - var val = (Vector2) property.Value; - xValue = val.x; - yValue = val.y; + switch (_property.Value) + { + case Vector2Int vi: return new Vector2(vi.x, vi.y); + case Vector2 v: return v; + default: return Vector2.zero; + } } - if (Attribute.AutoClamp) + private void ApplyValue(float x, float y) { - float clampedX = xValue; - float clampedY = yValue; + var (minLimit, maxLimit) = GetLimits(); - if (clampedX > clampedY) (clampedX, clampedY) = (clampedY, clampedX); - clampedX = Mathf.Clamp(clampedX, (float)minLimit, clampedY); - clampedY = Mathf.Clamp(clampedY, clampedX, (float)maxLimit); + x = Mathf.Clamp(x, (float) minLimit, Mathf.Min((float) maxLimit, y)); + y = Mathf.Clamp(y, Mathf.Max((float) minLimit, x), (float) maxLimit); - const float epsilon = 1e-5f; - if (Math.Abs(clampedX - xValue) > epsilon || Math.Abs(clampedY - yValue) > epsilon) + MinMaxSliderAttributeHelpers.SetValue(_property, x, y); + RefreshFromProperty(); + } + + private void RefreshFromProperty() + { + var (minLimit, maxLimit) = GetLimits(); + + _slider.lowLimit = (float) minLimit; + _slider.highLimit = (float) maxLimit; + + var mixed = _property.IsValueMixed; + _minField.showMixedValue = mixed; + _maxField.showMixedValue = mixed; + _slider.showMixedValue = mixed; + + if (mixed) { - xValue = clampedX; - yValue = clampedY; + return; + } - MinMaxSliderAttributeHelpers.SetValue(property, xValue, yValue); + var value = CurrentValue(); + var x = value.x; + var y = value.y; + + if (_attribute.AutoClamp) + { + if (x > y) + { + (x, y) = (y, x); + } + + x = Mathf.Clamp(x, (float) minLimit, y); + y = Mathf.Clamp(y, x, (float) maxLimit); + + const float epsilon = 1e-5f; + if (Mathf.Abs(x - value.x) > epsilon || Mathf.Abs(y - value.y) > epsilon) + { + MinMaxSliderAttributeHelpers.SetValue(_property, x, y); + } } - } - var label = property.DisplayNameContent; - var controlRect = EditorGUI.PrefixLabel(position, label); + _minField.SetValueWithoutNotify(x); + _maxField.SetValueWithoutNotify(y); + _slider.SetValueWithoutNotify(new Vector2(x, y)); + } - EditorGUI.BeginChangeCheck(); - TriEditorGUI.DrawMinMaxSlider(controlRect, ref xValue, ref yValue, (float)minLimit, (float)maxLimit); - if (EditorGUI.EndChangeCheck()) + private static class Styles { - MinMaxSliderAttributeHelpers.SetValue(property, xValue, yValue); + public const string Root = "tri-min-max-slider"; + public const string Field = "tri-min-max-slider__field"; + public const string Slider = "tri-min-max-slider__slider"; } } - public override float GetHeight(float width, TriProperty property, TriElement next) - { - return EditorGUIUtility.singleLineHeight; - } } internal static class MinMaxSliderAttributeHelpers { internal class SliderResolvers : SliderAttributeHelpers.SliderResolvers { - internal SliderResolvers(ref HashSet errors, TriPropertyDefinition propertyDefinition, MinMaxSliderAttribute attribute) - : base(ref errors, propertyDefinition, attribute.MinMemberName, attribute.MaxMemberName, attribute.MinMaxMemberName) + internal SliderResolvers(ref HashSet errors, TriPropertyDefinition propertyDefinition, + MinMaxSliderAttribute attribute) + : base(ref errors, propertyDefinition, attribute.MinMemberName, attribute.MaxMemberName, + attribute.MinMaxMemberName) { } } + public static SliderResolvers Initialize(MinMaxSliderAttribute attribute, TriPropertyDefinition propertyDefinition, out TriExtensionInitializationResult errorResult) { @@ -110,10 +184,13 @@ public static SliderResolvers Initialize(MinMaxSliderAttribute attribute, errorResult = TriExtensionInitializationResult.Ok; return resolvers; } - public static (double min, double max) GetLimits(TriProperty property, MinMaxSliderAttribute attribute, SliderResolvers resolvers) + + public static (double min, double max) GetLimits(TriProperty property, MinMaxSliderAttribute attribute, + SliderResolvers resolvers) { return SliderAttributeHelpers.GetLimits(property, attribute.MinFixed, attribute.MaxFixed, resolvers); } + public static void SetValue(TriProperty property, float x, float y) { if (property.ValueType == typeof(Vector2Int)) diff --git a/Editor.Extras/Drawers/ObjectReferenceDrawer.cs b/Editor.Extras/Drawers/ObjectReferenceDrawer.cs index e77dc1ec..6def2865 100644 --- a/Editor.Extras/Drawers/ObjectReferenceDrawer.cs +++ b/Editor.Extras/Drawers/ObjectReferenceDrawer.cs @@ -1,7 +1,9 @@ -using TriInspector; +using TriInspector; using TriInspector.Drawers; -using UnityEditor; +using TriInspector.VisualElements; +using UnityEditor.UIElements; using UnityEngine; +using UnityEngine.UIElements; [assembly: RegisterTriValueDrawer(typeof(ObjectReferenceDrawer), TriDrawerOrder.Fallback)] @@ -9,45 +11,25 @@ namespace TriInspector.Drawers { public class ObjectReferenceDrawer : TriValueDrawer { - public override TriElement CreateElement(TriValue value, TriElement next) + public override VisualElement CreateVisualElement(TriValue value, VisualElement next) { if (value.Property.IsRootProperty || value.Property.TryGetSerializedProperty(out _)) { return next; } - return new ObjectReferenceDrawerElement(value); + return new TriAlignedLabelVisualElement(value.Property, new TriObjectReference(value)); } - private class ObjectReferenceDrawerElement : TriElement + private class TriObjectReference : ObjectField { - private TriValue _propertyValue; - private readonly bool _allowSceneObjects; - - public ObjectReferenceDrawerElement(TriValue propertyValue) + public TriObjectReference(TriValue value) { - _propertyValue = propertyValue; - _allowSceneObjects = propertyValue.Property.PropertyTree.TargetIsPersistent == false; - } - - public override float GetHeight(float width) - { - return EditorGUIUtility.singleLineHeight; - } - - public override void OnGUI(Rect position) - { - var value = _propertyValue.SmartValue; - - EditorGUI.BeginChangeCheck(); - - value = EditorGUI.ObjectField(position, _propertyValue.Property.DisplayNameContent, value, - _propertyValue.Property.FieldType, _allowSceneObjects); + objectType = value.Property.FieldType; + allowSceneObjects = value.Property.PropertyTree.TargetIsPersistent == false; - if (EditorGUI.EndChangeCheck()) - { - _propertyValue.SetValue(value); - } + this.RegisterValueChangedCallback(evt => value.SetValue(evt.newValue)); + this.AutoSyncValueFromProperty(value.Property); } } } diff --git a/Editor.Extras/Drawers/OnValueChangedDrawer.cs b/Editor.Extras/Drawers/OnValueChangedDrawer.cs index e98aa5f6..c06825be 100644 --- a/Editor.Extras/Drawers/OnValueChangedDrawer.cs +++ b/Editor.Extras/Drawers/OnValueChangedDrawer.cs @@ -1,6 +1,7 @@ -using TriInspector; +using TriInspector; using TriInspector.Drawers; using TriInspector.Resolvers; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(OnValueChangedDrawer), TriDrawerOrder.System)] @@ -23,46 +24,28 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override TriElement CreateElement(TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - return new OnValueChangedListenerElement(property, next, _actionResolver); - } - - private class OnValueChangedListenerElement : TriElement - { - private readonly TriProperty _property; - private readonly ActionResolver _actionResolver; - - public OnValueChangedListenerElement(TriProperty property, TriElement next, ActionResolver actionResolver) + void OnValueChanged(TriProperty _) { - _property = property; - _actionResolver = actionResolver; - - AddChild(next); + property.PropertyTree.ApplyChanges(); + _actionResolver.InvokeForAllTargets(property); + property.PropertyTree.Update(); } - protected override void OnAttachToPanel() + next.RegisterCallback(_ => { - base.OnAttachToPanel(); + property.ValueChanged += OnValueChanged; + property.ChildValueChanged += OnValueChanged; + }); - _property.ValueChanged += OnValueChanged; - _property.ChildValueChanged += OnValueChanged; - } - - protected override void OnDetachFromPanel() + next.RegisterCallback(_ => { - _property.ChildValueChanged -= OnValueChanged; - _property.ValueChanged -= OnValueChanged; - - base.OnDetachFromPanel(); - } + property.ChildValueChanged -= OnValueChanged; + property.ValueChanged -= OnValueChanged; + }); - private void OnValueChanged(TriProperty obj) - { - _property.PropertyTree.ApplyChanges(); - _actionResolver.InvokeForAllTargets(_property); - _property.PropertyTree.Update(); - } + return next; } } -} \ No newline at end of file +} diff --git a/Editor.Extras/Drawers/PreviewMeshDrawer.cs b/Editor.Extras/Drawers/PreviewMeshDrawer.cs index 59c60154..fd5e7760 100644 --- a/Editor.Extras/Drawers/PreviewMeshDrawer.cs +++ b/Editor.Extras/Drawers/PreviewMeshDrawer.cs @@ -1,77 +1,70 @@ -using System; using System.Linq; using TriInspector; using TriInspector.Drawers; -using TriInspector.Elements; -using TriInspector.Utilities; +using TriInspector.VisualElements; using UnityEditor; +using UnityEditor.UIElements; using UnityEngine; +using UnityEngine.UIElements; using Object = UnityEngine.Object; [assembly: RegisterTriAttributeDrawer(typeof(PreviewMeshDrawer), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] - + namespace TriInspector.Drawers { public class PreviewMeshDrawer : TriAttributeDrawer { - private class PreviewMeshPicker : TriElement + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - private readonly TriProperty _property; - private readonly bool _useFoldout; + return new PreviewMeshVisualElement(property, Attribute); + } + + private class PreviewMeshVisualElement : TriHeaderBoxedVisualElement + { + private readonly MeshPreviewVisualElement _preview; - public PreviewMeshPicker(TriProperty property, bool useFoldout) + public PreviewMeshVisualElement(TriProperty property, PreviewMeshAttribute attribute) + : base(property, attribute.UseFoldout, BuildObjectField(property)) { - _property = property; - _useFoldout = useFoldout; + _preview = new MeshPreviewVisualElement(property, attribute.Height, attribute.Width, + attribute.UseFoldout, attribute.RotationMethod); + + Content.Add(_preview); } - public override float GetHeight(float width) + protected override void OnExpandedChanged(bool expanded) { - return EditorGUIUtility.singleLineHeight; + _preview.RefreshVisibility(); } - public override void OnGUI(Rect position) - { - var pickerRect = position; - GUIContent label = new(_property.DisplayName); - if (_useFoldout) + private static ObjectField BuildObjectField(TriProperty property) + { + var field = new ObjectField { - var prefixRect = new Rect(position) - { - height = EditorGUIUtility.singleLineHeight, - xMax = position.xMin + EditorGUIUtility.labelWidth, - }; - pickerRect = new Rect(position) - { - height = EditorGUIUtility.singleLineHeight, - xMin = prefixRect.xMax, - }; + objectType = typeof(GameObject), + allowSceneObjects = property.PropertyTree.TargetIsPersistent == false, + }; - TriEditorGUI.Foldout(prefixRect, _property); - label = GUIContent.none; - } + field.RegisterValueChangedCallback(evt => property.SetValue(evt.newValue)); + field.AutoSyncValueFromProperty(property); - EditorGUI.BeginChangeCheck(); - Object obj = _property.Value as Object; - var asset = EditorGUI.ObjectField(pickerRect, label, obj, typeof(GameObject), true); - if (EditorGUI.EndChangeCheck()) - { - _property.SetValue(asset); - } + return field; } } - private class PreviewMesh : TriElement + private class MeshPreviewVisualElement : VisualElement { private readonly int _height; private readonly int _width; private readonly TriProperty _property; private readonly bool _useFoldout; private readonly PreviewMeshRotationMethod _rotationMethod; + private readonly IMGUIContainer _imgui; private PreviewRenderUtility _previewUtility; private static Material _mat; + private Material GetMat { get @@ -93,6 +86,7 @@ private Material GetMat color = new Color(0.4f, 0.7f, 0.4f), }; } + return _mat; } } @@ -111,16 +105,29 @@ private Material GetMat private Vector2 _previewDir = new(-20f, 0f); #region Initialization - public PreviewMesh(TriProperty property, int size, int width, bool useFoldout, PreviewMeshRotationMethod rotationMethod) + + public MeshPreviewVisualElement(TriProperty property, int height, int width, bool useFoldout, + PreviewMeshRotationMethod rotationMethod) { _property = property; - _height = size; + _height = height; _width = width; _useFoldout = useFoldout; _rotationMethod = rotationMethod; + + _imgui = new IMGUIContainer(OnPreviewGUI); + _imgui.style.height = _height; + Add(_imgui); + + style.display = DisplayStyle.None; + style.width = width; + style.height = height; + + RegisterCallback(OnAttachToPanel); + RegisterCallback(OnDetachFromPanel); } - protected override void OnAttachToPanel() + private void OnAttachToPanel(AttachToPanelEvent evt) { _previewUtility = new(); _property.ValueChanged += OnValueChanged; @@ -137,64 +144,59 @@ protected override void OnAttachToPanel() _previewUtility.camera.backgroundColor = Color.black; _previewUtility.camera.clearFlags = CameraClearFlags.Color; - base.OnAttachToPanel(); - GetMeshObject(); + RefreshVisibility(); } - protected override void OnDetachFromPanel() + private void OnDetachFromPanel(DetachFromPanelEvent evt) { - _previewUtility.Cleanup(); + _previewUtility?.Cleanup(); _previewUtility = null; _property.ValueChanged -= OnValueChanged; - - base.OnDetachFromPanel(); } private void OnValueChanged(TriProperty property) { GetMeshObject(); + RefreshVisibility(); } - public override float GetHeight(float width) + public void RefreshVisibility() { - if (_sharedMesh == null) - { - return 0f; - } - if (!_useFoldout || _property.IsExpanded) - { - return _height; - } - return 0f; + var shouldShow = _sharedMesh != null && (!_useFoldout || _property.IsExpanded); + style.display = shouldShow ? DisplayStyle.Flex : DisplayStyle.None; } - public override void OnGUI(Rect position) + private void OnPreviewGUI() { - if (_sharedMesh == null) + if (_sharedMesh == null || _previewUtility == null) { return; } - float currentWidth = _width == -1 ? (int) position.width : _width; - currentWidth = Math.Max(currentWidth, _c_MIN_WIDTH); - if (position.height == 0f) + var containerWidth = _imgui.contentRect.width; + var currentWidth = _width == -1 ? containerWidth : _width; + currentWidth = Mathf.Max(currentWidth, _c_MIN_WIDTH); + + if (containerWidth <= 0f) { return; } - position = new Rect(position.x, position.y, currentWidth, _height); + var position = new Rect(0f, 0f, currentWidth, _height); _previewUtility.BeginPreview(position, GUIStyle.none); - _previewUtility.DrawMesh(_sharedMesh, Matrix4x4.TRS(Vector3.zero, _previewQuaternion, Vector3.one), GetMat, 0); + _previewUtility.DrawMesh(_sharedMesh, Matrix4x4.TRS(Vector3.zero, _previewQuaternion, Vector3.one), + GetMat, 0); _previewUtility.camera.Render(); Texture result = _previewUtility.EndPreview(); - + if (result) { GUI.DrawTexture(position, result, ScaleMode.ScaleToFit, false); } + if (position.Contains(Event.current.mousePosition)) { HandleMouseEvent(Event.current); @@ -268,15 +270,19 @@ private void HandleMouseEvent(Event mouseEvent) var cameraMovement = mouseEvent.delta * _c_ROTATION_SENSITIVITY; HandlePreviewCameraRotation(cameraMovement); mouseEvent.Use(); + _imgui.MarkDirtyRepaint(); break; case EventType.ScrollWheel: - _distance = Mathf.Clamp(_distance + mouseEvent.delta.x * _c_ZOOM_SENSITIVITY, _c_ZOOM_SENSITIVITY_MIN, _c_ZOOM_SENSITIVITY_MAX); + _distance = Mathf.Clamp(_distance + mouseEvent.delta.x * _c_ZOOM_SENSITIVITY, + _c_ZOOM_SENSITIVITY_MIN, _c_ZOOM_SENSITIVITY_MAX); if (shift) { UpdatePreviewCamera(); mouseEvent.Use(); + _imgui.MarkDirtyRepaint(); } + break; default: @@ -294,28 +300,18 @@ private void HandlePreviewCameraRotation(Vector2 movement) case PreviewMeshRotationMethod.Clamped: _previewDir.x = Mathf.Clamp(pitch + _previewDir.x, -90f, 90); _previewDir.y += yaw; - _previewQuaternion = Quaternion.Euler(_previewDir.x, 0, 0) * Quaternion.Euler(0, _previewDir.y, 0); + _previewQuaternion = Quaternion.Euler(_previewDir.x, 0, 0) * + Quaternion.Euler(0, _previewDir.y, 0); break; case PreviewMeshRotationMethod.Freeform: _previewQuaternion = Quaternion.Euler(pitch, yaw, 0) * _previewQuaternion; break; } + _previewQuaternion = Quaternion.Normalize(_previewQuaternion); } #endregion } - - public override TriElement CreateElement(TriProperty property, TriElement next) - { - var root = new TriBoxGroupElement(new TriBoxGroupElement.Props - { - titleMode = TriBoxGroupElement.TitleMode.Hidden, - }); - root.AddChild(new PreviewMeshPicker(property, Attribute.UseFoldout)); - root.AddChild(new PreviewMesh(property, Attribute.Height, Attribute.Width, Attribute.UseFoldout, Attribute.RotationMethod)); - return root; - } - } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/PreviewObjectDrawer.cs b/Editor.Extras/Drawers/PreviewObjectDrawer.cs index 746fc5d5..477a90c8 100644 --- a/Editor.Extras/Drawers/PreviewObjectDrawer.cs +++ b/Editor.Extras/Drawers/PreviewObjectDrawer.cs @@ -2,6 +2,7 @@ using TriInspector.Drawers; using UnityEditor; using UnityEngine; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(PreviewObjectDrawer), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] @@ -20,54 +21,45 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override float GetHeight(float width, TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { var previewSize = GetPreviewSize(); - if (!Attribute.DrawDefaultField) - { - return previewSize; - } - - var contentWidth = width - previewSize; - var contentHeight = base.GetHeight(contentWidth, property, next); - - return Mathf.Max(contentHeight, previewSize); - } - - public override void OnGUI(Rect position, TriProperty property, TriElement next) - { - var previewSize = GetPreviewSize(); - - if (Attribute.DrawDefaultField) + var preview = new IMGUIContainer { - var contentRect = new Rect(position) - { - xMax = position.xMax - previewSize, - height = base.GetHeight(position.width - previewSize, property, next), - }; - var previewRect = new Rect(position) + style = { - xMin = contentRect.xMax, + width = previewSize, height = previewSize, - }; + flexShrink = 0, + }, + }; + + preview.onGUIHandler = () => DrawPreview(new Rect(0, 0, previewSize, previewSize), property, preview); - base.OnGUI(contentRect, property, next); - DrawPreview(previewRect, property); + if (!Attribute.DrawDefaultField) + { + return preview; } - else + + var row = new VisualElement { - var previewRect = new Rect(position) + style = { - width = previewSize, - height = previewSize, - }; + flexDirection = FlexDirection.Row, + }, + }; - DrawPreview(previewRect, property); - } + next.style.flexGrow = 1; + next.style.flexShrink = 1; + + row.Add(next); + row.Add(preview); + + return row; } - private void DrawPreview(Rect previewRect, TriProperty property) + private void DrawPreview(Rect previewRect, TriProperty property, IMGUIContainer preview) { var assetToPreview = (Object) property.Value; @@ -97,10 +89,10 @@ private void DrawPreview(Rect previewRect, TriProperty property) return; } - DrawAssetPreview(previewContentRect, assetToPreview, property); + DrawAssetPreview(previewContentRect, assetToPreview, preview); } - private void DrawAssetPreview(Rect position, Object assetToPreview, TriProperty property) + private void DrawAssetPreview(Rect position, Object assetToPreview, IMGUIContainer preview) { var previewTexture = AssetPreview.GetAssetPreview(assetToPreview); @@ -115,7 +107,7 @@ private void DrawAssetPreview(Rect position, Object assetToPreview, TriProperty if (AssetPreview.IsLoadingAssetPreview(assetToPreview.GetInstanceID())) #endif { - property.PropertyTree.RequestRepaint(); + preview.MarkDirtyRepaint(); } } diff --git a/Editor.Extras/Drawers/PropertySpaceDrawer.cs b/Editor.Extras/Drawers/PropertySpaceDrawer.cs index bc5cf3ec..8c56ed12 100644 --- a/Editor.Extras/Drawers/PropertySpaceDrawer.cs +++ b/Editor.Extras/Drawers/PropertySpaceDrawer.cs @@ -1,6 +1,6 @@ -using TriInspector; +using TriInspector; using TriInspector.Drawers; -using UnityEngine; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(PropertySpaceDrawer), TriDrawerOrder.Inspector)] @@ -8,22 +8,24 @@ namespace TriInspector.Drawers { public class PropertySpaceDrawer : TriAttributeDrawer { - public override float GetHeight(float width, TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - var totalSpace = Attribute.SpaceBefore + Attribute.SpaceAfter; - - return next.GetHeight(width) + totalSpace; + return new TriPropertySpace(next) + { + style = + { + marginTop = Attribute.SpaceBefore, + marginBottom = Attribute.SpaceAfter, + }, + }; } - public override void OnGUI(Rect position, TriProperty property, TriElement next) + private class TriPropertySpace : VisualElement { - var contentPosition = new Rect(position) + public TriPropertySpace(VisualElement next) { - yMin = position.yMin + Attribute.SpaceBefore, - yMax = position.yMax - Attribute.SpaceAfter, - }; - - next.OnGUI(contentPosition); + Add(next); + } } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/PropertyTextAreaDrawer.cs b/Editor.Extras/Drawers/PropertyTextAreaDrawer.cs index fbbc142d..51537500 100644 --- a/Editor.Extras/Drawers/PropertyTextAreaDrawer.cs +++ b/Editor.Extras/Drawers/PropertyTextAreaDrawer.cs @@ -1,7 +1,7 @@ -using TriInspector; +using TriInspector; using TriInspector.Drawers; -using UnityEditor; -using UnityEngine; +using TriInspector.VisualElements; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(PropertyTextAreaDrawer), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] @@ -21,35 +21,16 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override TriElement CreateElement(TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - return new TextAreaElement(property); - } - - private class TextAreaElement : TriElement - { - private readonly TriProperty _property; - - public TextAreaElement(TriProperty property) - { - _property = property; - } - - public override float GetHeight(float width) - { - var text = _property.Value as string ?? ""; - return GUI.skin.textArea.CalcHeight(EditorGUIUtility.TrTempContent(text), width); - } - - public override void OnGUI(Rect position) + var field = new TextField { - var text = _property.Value as string ?? ""; - - var controlId = GUIUtility.GetControlID(FocusType.Passive); - position = EditorGUI.PrefixLabel(position, controlId, _property.DisplayNameContent); + multiline = true, + }; - EditorGUI.TextArea(position, text); - } + return TriBuiltinFieldFactory.CreateForProperty(property, field, + () => (string) property.Value ?? "", + value => property.SetValue(value)); } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/SceneDrawer.cs b/Editor.Extras/Drawers/SceneDrawer.cs index 45bdd47c..c20f8e12 100644 --- a/Editor.Extras/Drawers/SceneDrawer.cs +++ b/Editor.Extras/Drawers/SceneDrawer.cs @@ -1,7 +1,10 @@ -using TriInspector; +using TriInspector; using TriInspector.Drawers; +using TriInspector.VisualElements; using UnityEditor; -using UnityEngine; +using UnityEditor.UIElements; +using UnityEngine.UIElements; +using Object = UnityEngine.Object; [assembly: RegisterTriAttributeDrawer(typeof(SceneDrawer), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] @@ -20,66 +23,17 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return base.Initialize(propertyDefinition); } - public override TriElement CreateElement(TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - return new SceneElement(property); - } - - private class SceneElement : TriElement - { - private readonly TriProperty _property; - - private SceneAsset _sceneAsset; - - public SceneElement(TriProperty property) - { - _property = property; - } - - protected override void OnAttachToPanel() - { - base.OnAttachToPanel(); - - _property.ValueChanged += OnValueChanged; - - RefreshSceneAsset(); - } - - protected override void OnDetachFromPanel() - { - _property.ValueChanged -= OnValueChanged; - - base.OnDetachFromPanel(); - } - - public override float GetHeight(float width) - { - return EditorGUIUtility.singleLineHeight; - } - - public override void OnGUI(Rect position) - { - EditorGUI.BeginChangeCheck(); - - var asset = EditorGUI.ObjectField(position, _property.DisplayName, _sceneAsset, - typeof(SceneAsset), false); - - if (EditorGUI.EndChangeCheck()) - { - var path = AssetDatabase.GetAssetPath(asset); - _property.SetValue(path); - } - } - - private void OnValueChanged(TriProperty property) + var field = new ObjectField { - RefreshSceneAsset(); - } + objectType = typeof(SceneAsset), + allowSceneObjects = false, + }; - private void RefreshSceneAsset() - { - _sceneAsset = AssetDatabase.LoadAssetAtPath(_property.Value as string); - } + return TriBuiltinFieldFactory.CreateForProperty(property, field, + () => AssetDatabase.LoadAssetAtPath(property.Value as string), + asset => property.SetValue(AssetDatabase.GetAssetPath(asset))); } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/ShowDrawerChainDrawer.cs b/Editor.Extras/Drawers/ShowDrawerChainDrawer.cs index c0b15bd9..66444fc0 100644 --- a/Editor.Extras/Drawers/ShowDrawerChainDrawer.cs +++ b/Editor.Extras/Drawers/ShowDrawerChainDrawer.cs @@ -2,7 +2,8 @@ using System.Text; using TriInspector; using TriInspector.Drawers; -using TriInspector.Elements; +using TriInspector.VisualElements; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(ShowDrawerChainDrawer), TriDrawerOrder.System)] @@ -10,15 +11,15 @@ namespace TriInspector.Drawers { public class ShowDrawerChainDrawer : TriAttributeDrawer { - public override TriElement CreateElement(TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - return new TriDrawerChainInfoElement(property.AllDrawers, next); + var container = new VisualElement(); + container.Add(new TriInfoBoxVisualElement(BuildInfo(property.AllDrawers), TriMessageType.None)); + container.Add(next); + return container; } - } - public class TriDrawerChainInfoElement : TriElement - { - public TriDrawerChainInfoElement(IReadOnlyList drawers, TriElement next) + private static string BuildInfo(IReadOnlyList drawers) { var info = new StringBuilder(); @@ -31,8 +32,7 @@ public TriDrawerChainInfoElement(IReadOnlyList drawers, TriElem info.Append(i).Append(": ").Append(drawer.GetType().Name); } - AddChild(new TriInfoBoxElement(info.ToString())); - AddChild(next); + return info.ToString(); } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/SliderDrawer.cs b/Editor.Extras/Drawers/SliderDrawer.cs index 6b62da03..6eba9c65 100644 --- a/Editor.Extras/Drawers/SliderDrawer.cs +++ b/Editor.Extras/Drawers/SliderDrawer.cs @@ -3,10 +3,12 @@ using TriInspector; using TriInspector.Drawers; using TriInspector.Resolvers; -using UnityEditor; +using TriInspector.VisualElements; using UnityEngine; +using UnityEngine.UIElements; -[assembly: RegisterTriAttributeDrawer(typeof(SliderAttributeDrawer), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] +[assembly: + RegisterTriAttributeDrawer(typeof(SliderAttributeDrawer), TriDrawerOrder.Decorator, ApplyOnArrayElement = true)] namespace TriInspector.Drawers { @@ -14,7 +16,6 @@ public class SliderAttributeDrawer : TriAttributeDrawer { private SliderAttributeHelpers.SliderResolvers _resolvers; - public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { _resolvers = SliderAttributeHelpers.Initialize(Attribute, propertyDefinition, out var errorResult); @@ -24,47 +25,80 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio { return TriExtensionInitializationResult.Skip; } + return TriExtensionInitializationResult.Ok; } - public override void OnGUI(Rect position, TriProperty property, TriElement next) + + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - var label = property.DisplayNameContent; - double currentValue; - try + return new TriAlignedLabelVisualElement(property, new TriSlider(property, Attribute, _resolvers) { - currentValue = Convert.ToDouble(property.Value); - } - catch (Exception) + showInputField = true, + }); + } + + private class TriSlider : Slider + { + private readonly TriProperty _property; + private readonly SliderAttribute _attribute; + private readonly SliderAttributeHelpers.SliderResolvers _resolvers; + + public TriSlider(TriProperty property, SliderAttribute attribute, + SliderAttributeHelpers.SliderResolvers resolvers) { - EditorGUI.LabelField(position, label.text, "Cannot convert value to a number."); - return; + _property = property; + _attribute = attribute; + _resolvers = resolvers; + + this.RegisterValueChangedCallback(evt => ApplyValue(evt.newValue)); + + this.PeriodicRun(RefreshFromProperty); } - var (minLimit, maxLimit) = SliderAttributeHelpers.GetLimits(property, Attribute, _resolvers); + private void ApplyValue(double sliderValue) + { + var finalValue = Convert.ChangeType(sliderValue, _property.Definition.FieldType); + _property.SetValue(finalValue); + } - if (Attribute.AutoClamp) + private void RefreshFromProperty() { - double clampedValue = Math.Clamp(currentValue, minLimit, maxLimit); - const double epsilon = 1e-9; - if (Math.Abs(clampedValue - currentValue) > epsilon) + var (minLimit, maxLimit) = SliderAttributeHelpers.GetLimits(_property, _attribute, _resolvers); + + lowValue = (float) minLimit; + highValue = (float) maxLimit; + showMixedValue = _property.IsValueMixed; + + if (_property.IsValueMixed) { - property.SetValue(Convert.ChangeType(clampedValue, property.ValueType)); - currentValue = clampedValue; + return; } - } - EditorGUI.BeginChangeCheck(); - float sliderValue = EditorGUI.Slider(position, label, (float) currentValue, (float) minLimit, (float) maxLimit); - if (EditorGUI.EndChangeCheck()) - { - var finalValue = Convert.ChangeType(sliderValue, property.ValueType); - property.SetValue(finalValue); + double currentValue; + try + { + currentValue = Convert.ToDouble(_property.Value); + } + catch (Exception) + { + return; + } + + if (_attribute.AutoClamp) + { + var clampedValue = Math.Clamp(currentValue, minLimit, maxLimit); + + const double epsilon = 1e-9; + if (Math.Abs(clampedValue - currentValue) > epsilon) + { + ApplyValue(clampedValue); + currentValue = clampedValue; + } + } + + SetValueWithoutNotify((float) currentValue); } } - public override float GetHeight(float width, TriProperty property, TriElement next) - { - return EditorGUIUtility.singleLineHeight; - } } internal static class SliderAttributeHelpers @@ -78,14 +112,16 @@ internal class SliderResolvers public ValueResolver minMaxVector2Resolver; public ValueResolver minMaxVector2IntResolver; - internal SliderResolvers(ref HashSet errors, TriPropertyDefinition propertyDefinition, SliderAttribute attribute) - : this(ref errors, propertyDefinition, attribute.MinMemberName, attribute.MaxMemberName, attribute.MinMaxMemberName) + internal SliderResolvers(ref HashSet errors, TriPropertyDefinition propertyDefinition, + SliderAttribute attribute) + : this(ref errors, propertyDefinition, attribute.MinMemberName, attribute.MaxMemberName, + attribute.MinMaxMemberName) { } - protected SliderResolvers(ref HashSet errors, TriPropertyDefinition propertyDefinition, string minMemberName, string maxMemberName, string minMaxMemberName) - { - var resolverErrors = new HashSet(); + protected SliderResolvers(ref HashSet errors, TriPropertyDefinition propertyDefinition, + string minMemberName, string maxMemberName, string minMaxMemberName) + { bool hasMinMaxMember = !string.IsNullOrEmpty(minMaxMemberName); if (hasMinMaxMember) { @@ -93,7 +129,8 @@ protected SliderResolvers(ref HashSet errors, TriPropertyDefinition prop if (minMaxVector2Resolver.TryGetErrorString(out var vector2Error)) { minMaxVector2Resolver = null; - minMaxVector2IntResolver = ValueResolver.Resolve(propertyDefinition, minMaxMemberName); + minMaxVector2IntResolver = + ValueResolver.Resolve(propertyDefinition, minMaxMemberName); if (minMaxVector2IntResolver.TryGetErrorString(out var vector2IntError)) { errors.Add(vector2Error); @@ -135,6 +172,7 @@ protected SliderResolvers(ref HashSet errors, TriPropertyDefinition prop } } } + private static bool IsNumericType(Type type) { if (type == null) return false; @@ -143,6 +181,7 @@ private static bool IsNumericType(Type type) type != typeof(bool) && type != typeof(char); } + public static SliderResolvers Initialize(SliderAttribute attribute, TriPropertyDefinition propertyDefinition, out TriExtensionInitializationResult errorResult) { @@ -164,11 +203,15 @@ public static SliderResolvers Initialize(SliderAttribute attribute, errorResult = TriExtensionInitializationResult.Ok; return resolvers; } - public static (double min, double max) GetLimits(TriProperty property, SliderAttribute attribute, SliderResolvers resolvers) + + public static (double min, double max) GetLimits(TriProperty property, SliderAttribute attribute, + SliderResolvers resolvers) { return GetLimits(property, attribute.MinFixed, attribute.MaxFixed, resolvers); } - public static (double min, double max) GetLimits(TriProperty property, float minFixed, float maxFixed, SliderResolvers resolvers) + + public static (double min, double max) GetLimits(TriProperty property, float minFixed, float maxFixed, + SliderResolvers resolvers) { double minLimit = resolvers.minMaxVector2Resolver?.GetValue(property, Vector2.zero).x ?? resolvers.minMaxVector2IntResolver?.GetValue(property, Vector2Int.zero).x ?? diff --git a/Editor.Extras/Drawers/TableListDrawer.cs b/Editor.Extras/Drawers/TableListDrawer.cs index 963c8ce7..7ee16194 100644 --- a/Editor.Extras/Drawers/TableListDrawer.cs +++ b/Editor.Extras/Drawers/TableListDrawer.cs @@ -2,19 +2,14 @@ using System.Collections.Generic; using TriInspector; using TriInspector.Drawers; -using TriInspector.Elements; using TriInspector.Utilities; +using TriInspector.VisualElements; using TriInspectorUnityInternalBridge; using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEditorInternal; using UnityEngine; - -#if UNITY_6000_2_OR_NEWER -using TreeView = UnityEditor.IMGUI.Controls.TreeView; -using TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState; -using TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem; -#endif +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(TableListDrawer), TriDrawerOrder.Drawer)] @@ -32,420 +27,9 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override TriElement CreateElement(TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - return new TableElement(property); - } - - private class TableElement : TriListElement - { - private const float FooterExtraSpace = 4; - - private readonly TriProperty _property; - private readonly TableMultiColumnTreeView _treeView; - private readonly bool _alwaysExpanded; - - private bool _reloadRequired; - private bool _heightDirty; - private bool _isExpanded; - private int _arraySize; - - public TableElement(TriProperty property) : base(property) - { - _property = property; - _treeView = new TableMultiColumnTreeView(property, this, ListGui) - { - SelectionChangedCallback = SelectionChangedCallback, - }; - _reloadRequired = true; - } - - public override bool Update() - { - var dirty = base.Update(); - - dirty |= ReloadIfRequired(); - - if (dirty) - { - _heightDirty = true; - _treeView.multiColumnHeader.ResizeToFit(); - } - - return dirty; - } - - public override float GetHeight(float width) - { - _treeView.Width = width; - - if (_heightDirty) - { - _heightDirty = false; - _treeView.RefreshHeight(); - } - - var height = 0f; - height += ListGui.headerHeight; - - if (_property.IsExpanded) - { - height += _treeView.totalHeight; - height += ListGui.footerHeight; - height += FooterExtraSpace; - } - - return height; - } - - public override void OnGUI(Rect position) - { - var headerRect = new Rect(position) - { - height = ListGui.headerHeight, - }; - var elementsRect = new Rect(position) - { - yMin = headerRect.yMax, - height = _treeView.totalHeight + FooterExtraSpace, - }; - var elementsContentRect = new Rect(elementsRect) - { - xMin = elementsRect.xMin + 1, - xMax = elementsRect.xMax - 1, - yMax = elementsRect.yMax - FooterExtraSpace, - }; - var footerRect = new Rect(position) - { - yMin = elementsRect.yMax, - }; - - if (!_property.IsExpanded) - { - ReorderableListProxy.DoListHeader(ListGui, headerRect); - return; - } - - if (Event.current.isMouse && Event.current.type == EventType.MouseDrag) - { - _heightDirty = true; - _treeView.multiColumnHeader.ResizeToFit(); - } - - if (Event.current.type == EventType.Repaint) - { - ReorderableListProxy.defaultBehaviours.boxBackground.Draw(elementsRect, - false, false, false, false); - } - - ReorderableListProxy.DoListHeader(ListGui, headerRect); - - EditorGUI.BeginChangeCheck(); - - _treeView.OnGUI(elementsContentRect); - - if (EditorGUI.EndChangeCheck()) - { - _heightDirty = true; - _property.PropertyTree.RequestRepaint(); - } - - ReorderableListProxy.defaultBehaviours.DrawFooter(footerRect, ListGui); - } - - private bool ReloadIfRequired() - { - if (!_reloadRequired && - _property.IsExpanded == _isExpanded && - _property.ArrayElementProperties.Count == _arraySize) - { - return false; - } - - _reloadRequired = false; - _isExpanded = _property.IsExpanded; - _arraySize = _property.ArrayElementProperties.Count; - - _treeView.Reload(); - - return true; - } - - protected override TriElement CreateItemElement(TriProperty property) - { - return new TableRowElement(property); - } - - private void SelectionChangedCallback(int index) - { - ListGui.index = index; - } - } - - [Serializable] - private class TableMultiColumnTreeView : TreeView - { - private readonly TriProperty _property; - private readonly TriElement _cellElementContainer; - private readonly ReorderableList _listGui; - private readonly TableListPropertyOverrideContext _propertyOverrideContext; - private readonly bool _showAlternatingBackground; - - private bool _wasRendered; - - public Action SelectionChangedCallback; - - public TableMultiColumnTreeView(TriProperty property, TriElement container, ReorderableList listGui) - : base(new TreeViewState(), new TableColumnHeader()) - { - property.TryGetAttribute(out ListDrawerSettingsAttribute listSettings); - - _property = property; - _cellElementContainer = container; - _listGui = listGui; - _showAlternatingBackground = listSettings?.ShowAlternatingBackground ?? true; - _propertyOverrideContext = new TableListPropertyOverrideContext(property); - - showAlternatingRowBackgrounds = true; - showBorder = false; - useScrollView = false; - - multiColumnHeader.ResizeToFit(); - multiColumnHeader.visibleColumnsChanged += header => header.ResizeToFit(); - } - - public float Width { get; set; } - - public void RefreshHeight() - { - RefreshCustomRowHeights(); - } - - protected override void SelectionChanged(IList selectedIds) - { - base.SelectionChanged(selectedIds); - - if (SelectionChangedCallback != null && selectedIds.Count == 1) - { - SelectionChangedCallback.Invoke(selectedIds[0]); - } - } - - protected override TreeViewItem BuildRoot() - { - var root = new TreeViewItem(0, -1, string.Empty); - var columns = new List - { - new MultiColumnHeaderState.Column - { - width = 16, autoResize = false, canSort = false, allowToggleVisibility = false, - }, - }; - - if (_property.IsExpanded) - { - for (var index = 0; index < _property.ArrayElementProperties.Count; index++) - { - var rowChildProperty = _property.ArrayElementProperties[index]; - root.AddChild(new TableTreeItem(index, rowChildProperty)); - - if (index == 0) - { - foreach (var kvp in ((TableRowElement) (_cellElementContainer.GetChild(0))).Elements) - { - columns.Add(new MultiColumnHeaderState.Column - { - headerContent = kvp.Value, - headerTextAlignment = TextAlignment.Center, - autoResize = true, - canSort = false, - }); - } - } - } - } - - if (root.children == null) - { - root.AddChild(new TableTreeEmptyItem()); - } - - if (multiColumnHeader.state == null || - multiColumnHeader.state.columns.Length == 1) - { - multiColumnHeader.state = new MultiColumnHeaderState(columns.ToArray()); - } - - return root; - } - - protected override float GetCustomRowHeight(int row, TreeViewItem item) - { - if (item is TableTreeEmptyItem) - { - return EditorGUIUtility.singleLineHeight; - } - - var height = 0f; - var rowElement = (TableRowElement) _cellElementContainer.GetChild(row); - - foreach (var visibleColumnIndex in multiColumnHeader.state.visibleColumns) - { - var cellWidth = _wasRendered - ? multiColumnHeader.GetColumnRect(visibleColumnIndex).width - : Width / Mathf.Max(1, multiColumnHeader.state.visibleColumns.Length); - - var cellHeight = visibleColumnIndex == 0 - ? EditorGUIUtility.singleLineHeight - : rowElement.Elements[visibleColumnIndex - 1].Key.GetHeight(cellWidth); - - height = Math.Max(height, cellHeight); - } - - return height + EditorGUIUtility.standardVerticalSpacing * 2; - } - - protected override void RowGUI(RowGUIArgs args) - { - if (args.item is TableTreeEmptyItem) - { - base.RowGUI(args); - return; - } - - if (_showAlternatingBackground && args.row % 2 != 0) - { - EditorGUI.DrawRect(args.rowRect, new Color(0.1f, 0.1f, 0.1f, 0.15f)); - } - - var rowElement = (TableRowElement) _cellElementContainer.GetChild(args.row); - - for (var i = 0; i < multiColumnHeader.state.visibleColumns.Length; i++) - { - var visibleColumnIndex = multiColumnHeader.state.visibleColumns[i]; - var rowIndex = args.row; - - var cellRect = args.GetCellRect(i); - cellRect.yMin += EditorGUIUtility.standardVerticalSpacing; - - if (visibleColumnIndex == 0) - { - ReorderableListProxy.defaultBehaviours.DrawElementDraggingHandle(cellRect, rowIndex, - _listGui.index == rowIndex, _listGui.index == rowIndex, _listGui.draggable); - continue; - } - - var cellElement = rowElement.Elements[visibleColumnIndex - 1].Key; - cellRect.height = cellElement.GetHeight(cellRect.width); - - using (TriGuiHelper.PushLabelWidth(EditorGUIUtility.labelWidth / rowElement.ChildrenCount)) - using (TriPropertyOverrideContext.BeginOverride(_propertyOverrideContext)) - { - cellElement.OnGUI(cellRect); - } - } - - _wasRendered = true; - } - } - - public class TableRowElement : TriPropertyCollectionBaseElement - { - public TableRowElement(TriProperty property) - { - DeclareGroups(property.ValueType); - - Elements = new List>(); - - if (property.PropertyType == TriPropertyType.Generic) - { - foreach (var childProperty in property.ChildrenProperties) - { - var oldChildrenCount = ChildrenCount; - - var props = new TriPropertyElement.Props - { - forceInline = true, - }; - AddProperty(childProperty, props, out var group); - - if (oldChildrenCount != ChildrenCount) - { - var element = GetChild(ChildrenCount - 1); - var headerContent = new GUIContent(group ?? childProperty.DisplayName); - - Elements.Add(new KeyValuePair(element, headerContent)); - } - } - } - else - { - var element = new TriPropertyElement(property, new TriPropertyElement.Props - { - forceInline = true, - }); - var headerContent = new GUIContent("Element"); - - AddChild(element); - Elements.Add(new KeyValuePair(element, headerContent)); - } - } - - public List> Elements { get; } - } - - [Serializable] - private class TableColumnHeader : MultiColumnHeader - { - public TableColumnHeader() : base(null) - { - canSort = false; - height = DefaultGUI.minimumHeight; - } - } - - [Serializable] - private class TableTreeEmptyItem : TreeViewItem - { - public TableTreeEmptyItem() : base(0, 0, "Table is Empty") - { - } - } - - [Serializable] - private class TableTreeItem : TreeViewItem - { - public TableTreeItem(int id, TriProperty property) : base(id, 0) - { - Property = property; - } - - public TriProperty Property { get; } - } - - private class TableListPropertyOverrideContext : TriPropertyOverrideContext - { - private readonly TriProperty _grandParentProperty; - private readonly GUIContent _noneLabel = GUIContent.none; - - public TableListPropertyOverrideContext(TriProperty grandParentProperty) - { - _grandParentProperty = grandParentProperty; - } - - public override bool TryGetDisplayName(TriProperty property, out GUIContent displayName) - { - if (property.PropertyType == TriPropertyType.Primitive && - property.Parent?.Parent == _grandParentProperty && - !property.TryGetAttribute(out GroupAttribute _)) - { - displayName = _noneLabel; - return true; - } - - displayName = default; - return false; - } + return new TriTableListVisualElement(property); } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/TitleDrawer.TriStyleSheet.uss b/Editor.Extras/Drawers/TitleDrawer.TriStyleSheet.uss new file mode 100644 index 00000000..83d54c31 --- /dev/null +++ b/Editor.Extras/Drawers/TitleDrawer.TriStyleSheet.uss @@ -0,0 +1,11 @@ +.tri-title { + -unity-font-style: bold; + margin: 7px -2px 2px 3px; + font-size: 13px; +} + +.tri-title__line { + height: 2px; + margin: 0 -5px 2px 0px; + background-color: var(--tri-color-border); +} \ No newline at end of file diff --git a/Editor.Extras/Drawers/TitleDrawer.TriStyleSheet.uss.meta b/Editor.Extras/Drawers/TitleDrawer.TriStyleSheet.uss.meta new file mode 100644 index 00000000..628779f0 --- /dev/null +++ b/Editor.Extras/Drawers/TitleDrawer.TriStyleSheet.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b43b87fba77dc5c48bb2c821f096d415 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Editor.Extras/Drawers/TitleDrawer.cs b/Editor.Extras/Drawers/TitleDrawer.cs index 678f02a2..7d411278 100644 --- a/Editor.Extras/Drawers/TitleDrawer.cs +++ b/Editor.Extras/Drawers/TitleDrawer.cs @@ -1,8 +1,7 @@ -using TriInspector; +using TriInspector; using TriInspector.Drawers; using TriInspector.Resolvers; -using UnityEditor; -using UnityEngine; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(TitleDrawer), TriDrawerOrder.Inspector)] @@ -10,11 +9,6 @@ namespace TriInspector.Drawers { public class TitleDrawer : TriAttributeDrawer { - private const int SpaceBeforeTitle = 9; - private const int SpaceBeforeLine = 2; - private const int LineHeight = 2; - private const int SpaceBeforeContent = 3; - private ValueResolver _titleResolver; public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) @@ -31,45 +25,37 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override float GetHeight(float width, TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - var extraHeight = SpaceBeforeTitle + - EditorGUIUtility.singleLineHeight + - SpaceBeforeLine + - LineHeight - + SpaceBeforeContent; - - return next.GetHeight(width) + extraHeight; + return new TriTitle(property, next, Attribute, _titleResolver); } - public override void OnGUI(Rect position, TriProperty property, TriElement next) + private class TriTitle : VisualElement { - var titleRect = new Rect(position) - { - y = position.y + SpaceBeforeTitle, - height = EditorGUIUtility.singleLineHeight, - }; - - var lineRect = new Rect(position) + public TriTitle(TriProperty property, VisualElement next, + TitleAttribute attribute, ValueResolver titleResolver) { - y = titleRect.yMax + SpaceBeforeLine, - height = LineHeight, - }; + var title = new Label(); + title.AddToClassList(Styles.Title); + Add(title); - var contentRect = new Rect(position) - { - yMin = lineRect.yMax + SpaceBeforeContent, - }; + if (attribute.HorizontalLine) + { + var line = new VisualElement(); + line.AddToClassList(Styles.Line); + Add(line); + } - var title = _titleResolver.GetValue(property, "Error"); - GUI.Label(titleRect, title, EditorStyles.boldLabel); + Add(next); - if (Attribute.HorizontalLine) - { - EditorGUI.DrawRect(lineRect, Color.gray); + this.TrackResolvedValue(property, titleResolver, "", value => title.text = value); } + } - next.OnGUI(contentRect); + private static class Styles + { + public const string Title = "tri-title"; + public const string Line = "tri-title__line"; } } } \ No newline at end of file diff --git a/Editor.Extras/Drawers/UnitDrawer.cs b/Editor.Extras/Drawers/UnitDrawer.cs index b601acd0..5b289130 100644 --- a/Editor.Extras/Drawers/UnitDrawer.cs +++ b/Editor.Extras/Drawers/UnitDrawer.cs @@ -1,9 +1,8 @@ -using TriInspector; +using TriInspector; using TriInspector.Drawers; using TriInspector.Resolvers; -using TriInspector.Utilities; -using UnityEditor; using UnityEngine; +using UnityEngine.UIElements; [assembly: RegisterTriAttributeDrawer(typeof(UnitDrawer), TriDrawerOrder.Decorator)] @@ -11,11 +10,6 @@ namespace TriInspector.Drawers { public class UnitDrawer : TriAttributeDrawer { - /// - /// Defines the padding to the right of the unit label towards the editable input field - /// - private const int PaddingRight = 5; - private ValueResolver _unitResolver; public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) @@ -32,32 +26,35 @@ public override TriExtensionInitializationResult Initialize(TriPropertyDefinitio return TriExtensionInitializationResult.Ok; } - public override void OnGUI(Rect position, TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - var unit = _unitResolver.GetValue(property, ""); - var size = Styles.UnitStyle.CalcSize(TriGuiHelper.TempContent(unit)); - - var unitRect = new Rect(position.xMax - size.x - PaddingRight, position.y, size.x, position.height); - - // Render the editable input field - next.OnGUI(position); - - //Change color to grey - using (TriGuiHelper.PushColor(Color.grey)) + var container = new VisualElement { - // Render the unit as a suffix in the unitRect - EditorGUI.LabelField(unitRect, unit); - } - } - - private static class Styles - { - public static readonly GUIStyle UnitStyle; - - static Styles() + style = + { + position = Position.Relative, + }, + }; + container.Add(next); + + var unitLabel = new Label { - UnitStyle = new GUIStyle(EditorStyles.label); - } + pickingMode = PickingMode.Ignore, + style = + { + position = Position.Absolute, + right = 0, + top = 0, + bottom = 0, + unityTextAlign = TextAnchor.MiddleRight, + color = Color.grey, + }, + }; + container.Add(unitLabel); + + container.TrackResolvedValue(property, _unitResolver, "", value => unitLabel.text = value); + + return container; } } } \ No newline at end of file diff --git a/Editor.Extras/GroupDrawers/TriBoxGroupDrawer.cs b/Editor.Extras/GroupDrawers/TriBoxGroupDrawer.cs index a1afbeca..ff8c53e9 100644 --- a/Editor.Extras/GroupDrawers/TriBoxGroupDrawer.cs +++ b/Editor.Extras/GroupDrawers/TriBoxGroupDrawer.cs @@ -1,6 +1,7 @@ using TriInspector; -using TriInspector.Elements; using TriInspector.GroupDrawers; +using TriInspector.VisualElements; +using TriInspector.VisualElements.Groups; [assembly: RegisterTriGroupDrawer(typeof(TriBoxGroupDrawer))] @@ -8,16 +9,14 @@ namespace TriInspector.GroupDrawers { public class TriBoxGroupDrawer : TriGroupDrawer { - public override TriPropertyCollectionBaseElement CreateElement(DeclareBoxGroupAttribute attribute) + public override TriPropertyCollectionVisualElement CreateVisualElement(DeclareBoxGroupAttribute attribute) { - return new TriBoxGroupElement(new TriBoxGroupElement.Props + if (attribute.HideTitle) { - title = attribute.Title, - titleMode = attribute.HideTitle - ? TriBoxGroupElement.TitleMode.Hidden - : TriBoxGroupElement.TitleMode.Normal, - hideIfChildrenInvisible = true, - }); + return new TriBoxGroupVisualElement(hideIfChildrenInvisible: true); + } + + return new TriHeaderBoxGroupVisualElement(attribute.Title, hideIfChildrenInvisible: true); } } } \ No newline at end of file diff --git a/Editor.Extras/GroupDrawers/TriFoldoutGroupDrawer.cs b/Editor.Extras/GroupDrawers/TriFoldoutGroupDrawer.cs index 0ca815c5..d7aeda81 100644 --- a/Editor.Extras/GroupDrawers/TriFoldoutGroupDrawer.cs +++ b/Editor.Extras/GroupDrawers/TriFoldoutGroupDrawer.cs @@ -1,6 +1,7 @@ using TriInspector; -using TriInspector.Elements; using TriInspector.GroupDrawers; +using TriInspector.VisualElements; +using TriInspector.VisualElements.Groups; [assembly: RegisterTriGroupDrawer(typeof(TriFoldoutGroupDrawer))] @@ -8,15 +9,9 @@ namespace TriInspector.GroupDrawers { public class TriFoldoutGroupDrawer : TriGroupDrawer { - public override TriPropertyCollectionBaseElement CreateElement(DeclareFoldoutGroupAttribute attribute) + public override TriPropertyCollectionVisualElement CreateVisualElement(DeclareFoldoutGroupAttribute attribute) { - return new TriBoxGroupElement(new TriBoxGroupElement.Props - { - title = attribute.Title, - titleMode = TriBoxGroupElement.TitleMode.Foldout, - expandedByDefault = attribute.Expanded, - hideIfChildrenInvisible = true, - }); + return new TriFoldoutGroupVisualElement(attribute.Title, attribute.Expanded, hideIfChildrenInvisible: true); } } } \ No newline at end of file diff --git a/Editor.Extras/GroupDrawers/TriHorizontalGroupDrawer.cs b/Editor.Extras/GroupDrawers/TriHorizontalGroupDrawer.cs index 5c033149..a5c8913a 100644 --- a/Editor.Extras/GroupDrawers/TriHorizontalGroupDrawer.cs +++ b/Editor.Extras/GroupDrawers/TriHorizontalGroupDrawer.cs @@ -1,7 +1,7 @@ using TriInspector; -using TriInspector.Elements; using TriInspector.GroupDrawers; -using UnityEngine; +using TriInspector.VisualElements; +using TriInspector.VisualElements.Groups; [assembly: RegisterTriGroupDrawer(typeof(TriHorizontalGroupDrawer))] @@ -9,9 +9,9 @@ namespace TriInspector.GroupDrawers { public class TriHorizontalGroupDrawer : TriGroupDrawer { - public override TriPropertyCollectionBaseElement CreateElement(DeclareHorizontalGroupAttribute attribute) + public override TriPropertyCollectionVisualElement CreateVisualElement(DeclareHorizontalGroupAttribute attribute) { - return new TriHorizontalGroupElement(attribute.Sizes); + return new TriHorizontalGroupVisualElement(attribute.Sizes); } } } \ No newline at end of file diff --git a/Editor.Extras/GroupDrawers/TriTabGroupDrawer.cs b/Editor.Extras/GroupDrawers/TriTabGroupDrawer.cs index 1a757ff0..99af933b 100644 --- a/Editor.Extras/GroupDrawers/TriTabGroupDrawer.cs +++ b/Editor.Extras/GroupDrawers/TriTabGroupDrawer.cs @@ -1,6 +1,7 @@ using TriInspector; -using TriInspector.Elements; using TriInspector.GroupDrawers; +using TriInspector.VisualElements; +using TriInspector.VisualElements.Groups; [assembly: RegisterTriGroupDrawer(typeof(TriTabGroupDrawer))] @@ -8,9 +9,9 @@ namespace TriInspector.GroupDrawers { public class TriTabGroupDrawer : TriGroupDrawer { - public override TriPropertyCollectionBaseElement CreateElement(DeclareTabGroupAttribute attribute) + public override TriPropertyCollectionVisualElement CreateVisualElement(DeclareTabGroupAttribute attribute) { - return new TriTabGroupElement(); + return new TriTabGroupVisualElement(); } } } \ No newline at end of file diff --git a/Editor.Extras/GroupDrawers/TriToggleGroupDrawer.cs b/Editor.Extras/GroupDrawers/TriToggleGroupDrawer.cs index e78e22cf..a3b8a4fd 100644 --- a/Editor.Extras/GroupDrawers/TriToggleGroupDrawer.cs +++ b/Editor.Extras/GroupDrawers/TriToggleGroupDrawer.cs @@ -1,6 +1,7 @@ using TriInspector; -using TriInspector.Elements; using TriInspector.GroupDrawers; +using TriInspector.VisualElements; +using TriInspector.VisualElements.Groups; [assembly: RegisterTriGroupDrawer(typeof(TriToggleGroupDrawer))] @@ -8,15 +9,10 @@ namespace TriInspector.GroupDrawers { public class TriToggleGroupDrawer : TriGroupDrawer { - public override TriPropertyCollectionBaseElement CreateElement(DeclareToggleGroupAttribute attribute) + public override TriPropertyCollectionVisualElement CreateVisualElement(DeclareToggleGroupAttribute attribute) { - return new TriBoxGroupElement(new TriBoxGroupElement.Props - { - title = attribute.Title, - titleMode = TriBoxGroupElement.TitleMode.Toggle, - expandedByDefault = attribute.Collapsible, - hideIfChildrenInvisible = true, - }); + return new TriToggleGroupVisualElement(attribute.Title, attribute.Collapsible, + hideIfChildrenInvisible: true); } } } \ No newline at end of file diff --git a/Editor.Extras/GroupDrawers/TriVerticalGroupDrawer.cs b/Editor.Extras/GroupDrawers/TriVerticalGroupDrawer.cs index dff669b2..d1337917 100644 --- a/Editor.Extras/GroupDrawers/TriVerticalGroupDrawer.cs +++ b/Editor.Extras/GroupDrawers/TriVerticalGroupDrawer.cs @@ -1,6 +1,7 @@ using TriInspector; -using TriInspector.Elements; using TriInspector.GroupDrawers; +using TriInspector.VisualElements; +using TriInspector.VisualElements.Groups; [assembly: RegisterTriGroupDrawer(typeof(TriVerticalGroupDrawer))] @@ -8,9 +9,9 @@ namespace TriInspector.GroupDrawers { public class TriVerticalGroupDrawer : TriGroupDrawer { - public override TriPropertyCollectionBaseElement CreateElement(DeclareVerticalGroupAttribute attribute) + public override TriPropertyCollectionVisualElement CreateVisualElement(DeclareVerticalGroupAttribute attribute) { - return new TriVerticalGroupElement(); + return new TriVerticalGroupVisualElement(); } } } \ No newline at end of file diff --git a/Editor.Integrations/Odin/OdinFieldDrawer.cs b/Editor.Integrations/Odin/OdinFieldDrawer.cs index ad86df1c..270c3fba 100644 --- a/Editor.Integrations/Odin/OdinFieldDrawer.cs +++ b/Editor.Integrations/Odin/OdinFieldDrawer.cs @@ -1,5 +1,6 @@ using System; using Sirenix.OdinInspector.Editor; +using Sirenix.OdinInspector.Editor.Internal.UIToolkitIntegration; using Sirenix.Utilities.Editor; using UnityEngine; @@ -13,6 +14,7 @@ public class OdinFieldDrawer : OdinValueDrawer, IDisposable private bool _initialized; private TriPropertyTree _propertyTree; private LabelOverrideContext _labelOverrideContext; + private OdinImGuiElement _element; public override bool CanDrawTypeFilter(Type type) { @@ -70,6 +72,11 @@ protected override void DrawPropertyLayout(GUIContent label) _initialized = true; _propertyTree = new TriPropertyTreeForOdin(ValueEntry); _labelOverrideContext = new LabelOverrideContext(_propertyTree); + + // Scoped to the root property, so it is safe to keep registered for the tree's whole lifetime. + _propertyTree.AddPropertyOverride(_labelOverrideContext); + + _element = new OdinImGuiElement(_propertyTree.GetRootElement()); } _propertyTree.Update(); @@ -77,15 +84,9 @@ protected override void DrawPropertyLayout(GUIContent label) _labelOverrideContext.Label = label ?? GUIContent.none; - using (TriPropertyOverrideContext.BeginOverride(_labelOverrideContext)) - { - _propertyTree.Draw(); - } - - if (_propertyTree.RepaintRequired) - { - GUIHelper.RequestRepaint(); - } + GUILayout.BeginVertical(); + ImguiElementUtils.EmbedVisualElementAndDrawItHere(_element); + GUILayout.EndVertical(); } private class LabelOverrideContext : TriPropertyOverrideContext diff --git a/Editor.Integrations/Odin/OdinObjectDrawer.cs b/Editor.Integrations/Odin/OdinObjectDrawer.cs index 9c6a207c..2d3a7098 100644 --- a/Editor.Integrations/Odin/OdinObjectDrawer.cs +++ b/Editor.Integrations/Odin/OdinObjectDrawer.cs @@ -1,6 +1,7 @@ using System; using Sirenix.Utilities; using Sirenix.OdinInspector.Editor; +using Sirenix.OdinInspector.Editor.Internal.UIToolkitIntegration; using Sirenix.Utilities.Editor; using TriInspector.Utilities; using UnityEngine; @@ -13,6 +14,7 @@ public class OdinObjectDrawer : OdinValueDrawer, IDisposable { private bool _initialized; private TriPropertyTree _propertyTree; + private OdinImGuiElement _element; public override bool CanDrawTypeFilter(Type type) { @@ -51,31 +53,20 @@ public void Dispose() protected override void DrawPropertyLayout(GUIContent label) { - if (TriGuiHelper.IsEditorTargetPushed(ValueEntry.SmartValue)) - { - GUILayout.Label("Recursive inline editors not supported"); - return; - } - if (!_initialized) { _initialized = true; var serializedObject = Property.Tree.UnitySerializedObject; _propertyTree = new TriPropertyTreeForSerializedObject(serializedObject); + _element = new OdinImGuiElement(_propertyTree.GetRootElement()); } _propertyTree.Update(); _propertyTree.RunValidationIfRequired(); - using (TriGuiHelper.PushEditorTarget(ValueEntry.SmartValue)) - { - _propertyTree.Draw(); - } - - if (_propertyTree.RepaintRequired) - { - GUIHelper.RequestRepaint(); - } + GUILayout.BeginVertical(); + ImguiElementUtils.EmbedVisualElementAndDrawItHere(_element); + GUILayout.EndVertical(); } } } \ No newline at end of file diff --git a/Editor.Samples/SampleWindowStyles.cs b/Editor.Samples/SampleWindowStyles.cs deleted file mode 100644 index 24d3103e..00000000 --- a/Editor.Samples/SampleWindowStyles.cs +++ /dev/null @@ -1,32 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Editor.Samples -{ - internal static class SampleWindowStyles - { - public static readonly GUIStyle Padding; - public static readonly GUIStyle BoxWithPadding; - public static readonly GUIStyle HeaderDisplayNameLabel; - - static SampleWindowStyles() - { - Padding = new GUIStyle(GUI.skin.label) - { - padding = new RectOffset(5, 5, 5, 5), - }; - - BoxWithPadding = new GUIStyle(TriEditorStyles.Box) - { - padding = new RectOffset(5, 5, 5, 5), - }; - - HeaderDisplayNameLabel = new GUIStyle(EditorStyles.largeLabel) - { - fontStyle = FontStyle.Bold, - fontSize = 17, - margin = new RectOffset(5, 5, 5, 0), - }; - } - } -} \ No newline at end of file diff --git a/Editor.Samples/SampleWindowStyles.cs.meta b/Editor.Samples/SampleWindowStyles.cs.meta deleted file mode 100644 index 91833f1f..00000000 --- a/Editor.Samples/SampleWindowStyles.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: ddb081b7f73a4b58aca6d24aaefbc50e -timeCreated: 1656858907 \ No newline at end of file diff --git a/Editor.Samples/TriSamplesWindiw.TriStyleSheet.uss b/Editor.Samples/TriSamplesWindiw.TriStyleSheet.uss new file mode 100644 index 00000000..2f663ade --- /dev/null +++ b/Editor.Samples/TriSamplesWindiw.TriStyleSheet.uss @@ -0,0 +1,52 @@ +/* ---- Samples window ---- */ + +.tri-samples { + flex-direction: row; + flex-grow: 1; +} + +.tri-samples__menu { + width: 200px; + flex-shrink: 0; + border-right-width: 1px; + border-color: var(--tri-color-border); +} + +.tri-samples__search { + width: 100%; +} + +.tri-samples__tree { + flex-grow: 1; +} + +.tri-samples__detail-scroll { + flex-grow: 1; +} + +.tri-samples__detail { + padding-left: 5px; + padding-right: 5px; +} + +.tri-samples__header { + -unity-font-style: bold; + font-size: 17px; + margin: 20px 0 5px 5px; +} + +.tri-samples__section { + -unity-font-style: bold; + margin: 10px 0 2px 5px; +} + +.tri-samples__box { + padding: 5px; + margin: 0 5px; + border-width: 1px; + border-color: var(--tri-color-border); +} + +.tri-samples__tree-item { + -unity-text-align: middle-left; +} diff --git a/Editor.Samples/TriSamplesWindiw.TriStyleSheet.uss.meta b/Editor.Samples/TriSamplesWindiw.TriStyleSheet.uss.meta new file mode 100644 index 00000000..5348e242 --- /dev/null +++ b/Editor.Samples/TriSamplesWindiw.TriStyleSheet.uss.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 99b0417144dc4513a5b52dbd62861219 +timeCreated: 1786096863 \ No newline at end of file diff --git a/Editor.Samples/TriSamplesWindow.cs b/Editor.Samples/TriSamplesWindow.cs index 7a19c7aa..e13bfedd 100644 --- a/Editor.Samples/TriSamplesWindow.cs +++ b/Editor.Samples/TriSamplesWindow.cs @@ -2,27 +2,24 @@ using System.Collections.Generic; using System.Linq; using TriInspector.Editors; +using TriInspector.VisualElements; using UnityEditor; -using UnityEditor.IMGUI.Controls; +using UnityEditor.UIElements; using UnityEngine; - -#if UNITY_6000_2_OR_NEWER -using TreeView = UnityEditor.IMGUI.Controls.TreeView; -using TreeViewState = UnityEditor.IMGUI.Controls.TreeViewState; -using TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem; -#endif +using UnityEngine.UIElements; namespace TriInspector.Editor.Samples { internal class TriSamplesWindow : EditorWindow { - private MenuTree _menuTree; - private SearchField _searchField; + private readonly List _sampleTypes = new List(); private ScriptableObject _current; private UnityEditor.Editor _currentEditor; private MonoScript _currentMonoScript; - private Vector2 _currentScroll; + + private TreeView _menuTree; + private VisualElement _detailContainer; [MenuItem("Tools/Tri Inspector/Samples")] public static void Open() @@ -32,15 +29,52 @@ public static void Open() window.Show(); } - private void OnEnable() + private void CreateGUI() { - _menuTree = new MenuTree(new TreeViewState()); - _menuTree.SelectedTypeChanged += ChangeCurrentSample; + CollectSampleTypes(); + + var root = rootVisualElement; + TriStyleSheet.ApplyTo(root); + root.AddToClassList(EditorGUIUtility.isProSkin ? "tri-dark" : "tri-light"); + root.AddToClassList(TriStyles.Samples); - _searchField = new SearchField(); - _searchField.downOrUpArrowKeyPressed += _menuTree.SetFocusAndEnsureSelectedItem; + var leftPane = new VisualElement(); + leftPane.AddToClassList(TriStyles.SamplesMenu); + root.Add(leftPane); - _menuTree.Reload(); + var searchField = new ToolbarSearchField(); + searchField.AddToClassList(TriStyles.SamplesSearch); + searchField.RegisterValueChangedCallback(evt => RebuildMenu(evt.newValue)); + leftPane.Add(searchField); + + _menuTree = new TreeView + { + fixedItemHeight = 20, + selectionType = SelectionType.Single, + makeItem = MakeTreeItem, + }; + _menuTree.AddToClassList(TriStyles.SamplesTree); + _menuTree.bindItem = (element, index) => + ((Label) element).text = _menuTree.GetItemDataForIndex(index).Name; + _menuTree.selectionChanged += OnMenuSelectionChanged; + leftPane.Add(_menuTree); + + var rightPane = new ScrollView(); + rightPane.AddToClassList(TriStyles.SamplesDetailScroll); + root.Add(rightPane); + + _detailContainer = new VisualElement(); + _detailContainer.AddToClassList(TriStyles.SamplesDetail); + rightPane.Add(_detailContainer); + + RebuildMenu(string.Empty); + } + + private static VisualElement MakeTreeItem() + { + var label = new Label(); + label.AddToClassList(TriStyles.SamplesTreeItem); + return label; } private void OnDisable() @@ -48,79 +82,67 @@ private void OnDisable() ChangeCurrentSample(null); } - private void OnGUI() + private void CollectSampleTypes() + { + _sampleTypes.Clear(); + _sampleTypes.AddRange(typeof(TriSamplesWindow).Assembly.GetTypes() + .Where(type => type.BaseType == typeof(ScriptableObject) && type.Name.EndsWith("Sample")) + .OrderBy(type => type.Name)); + } + + private void RebuildMenu(string search) { - using (new GUILayout.HorizontalScope()) + var hasSearch = !string.IsNullOrEmpty(search); + + var groups = new List>>(); + var groupLookup = new Dictionary>(); + + foreach (var type in _sampleTypes) { - using (new GUILayout.VerticalScope(GUILayout.Width(200))) + if (hasSearch && + GetTypeNiceName(type).IndexOf(search, StringComparison.OrdinalIgnoreCase) < 0) { - DrawMenu(); + continue; } - var separatorRect = GUILayoutUtility.GetLastRect(); - separatorRect.xMin = separatorRect.xMax; - separatorRect.xMax += 1; - GUI.Box(separatorRect, ""); - - using (new GUILayout.VerticalScope()) + var group = type.Name.Split('_')[0]; + if (!groupLookup.TryGetValue(group, out var list)) { - DrawElement(); + groupLookup[group] = list = new List(); + groups.Add(new KeyValuePair>(group, list)); } + + list.Add(type); } - } - private void DrawMenu() - { - using (new GUILayout.HorizontalScope(EditorStyles.toolbar, GUILayout.ExpandWidth(true))) + var id = 0; + var roots = new List>(); + foreach (var group in groups) { - GUILayout.Space(5); - _menuTree.searchString = _searchField.OnToolbarGUI(_menuTree.searchString, GUILayout.ExpandWidth(true)); - GUILayout.Space(5); + var children = new List>(); + foreach (var type in group.Value) + { + children.Add(new TreeViewItemData( + id++, new MenuEntry(GetTypeNiceName(type), type))); + } + + roots.Add(new TreeViewItemData( + id++, new MenuEntry(group.Key, null), children)); } - var menuRect = GUILayoutUtility.GetRect(0, 100000, 0, 100000); - _menuTree.OnGUI(menuRect); - } + _menuTree.SetRootItems(roots); + _menuTree.Rebuild(); - private void DrawElement() - { - if (_currentEditor == null || _currentMonoScript == null) + if (hasSearch) { - return; + _menuTree.ExpandAll(); } + } - using (var scrollScope = new GUILayout.ScrollViewScope(_currentScroll)) - { - _currentScroll = scrollScope.scrollPosition; - - using (new GUILayout.VerticalScope(SampleWindowStyles.Padding)) - { - GUILayout.Label(_current.name, SampleWindowStyles.HeaderDisplayNameLabel); - - if (_currentEditor.GetType() != typeof(TriScriptableObjectEditor)) - { - EditorGUILayout.HelpBox( - "Detected third party asset that overrides all inspectors. Tri-Inspector's attributes might not work\n" + - _currentEditor.GetType().FullName, MessageType.Error); - } - - GUILayout.Space(10); - GUILayout.Label("Preview", EditorStyles.boldLabel); - - using (new GUILayout.VerticalScope(SampleWindowStyles.BoxWithPadding)) - { - _currentEditor.OnInspectorGUI(); - } - - GUILayout.Space(10); - GUILayout.Label("Code", EditorStyles.boldLabel); - - using (new GUILayout.VerticalScope(SampleWindowStyles.BoxWithPadding)) - { - GUILayout.TextField(_currentMonoScript.text); - } - } - } + private void OnMenuSelectionChanged(IEnumerable selection) + { + var type = selection.OfType().Select(entry => entry.Type).FirstOrDefault(); + ChangeCurrentSample(type); } private void ChangeCurrentSample(Type type) @@ -131,19 +153,73 @@ private void ChangeCurrentSample(Type type) _current = null; } - DestroyImmediate(_currentEditor); + if (_currentEditor != null) + { + DestroyImmediate(_currentEditor); + _currentEditor = null; + } + + _currentMonoScript = null; - _currentScroll = Vector2.zero; + _detailContainer?.Clear(); - if (type != null) + if (type == null) { - _current = CreateInstance(type); - _current.name = GetTypeNiceName(type); - _current.hideFlags = HideFlags.DontSave; + return; + } + + _current = CreateInstance(type); + _current.name = GetTypeNiceName(type); + _current.hideFlags = HideFlags.DontSave; + + _currentEditor = UnityEditor.Editor.CreateEditor(_current); + _currentMonoScript = MonoScript.FromScriptableObject(_current); + + BuildDetail(); + } + + private void BuildDetail() + { + var header = new Label(_current.name); + header.AddToClassList(TriStyles.SamplesHeader); + _detailContainer.Add(header); - _currentEditor = UnityEditor.Editor.CreateEditor(_current); - _currentMonoScript = MonoScript.FromScriptableObject(_current); + if (_currentEditor.GetType() != typeof(TriScriptableObjectEditor)) + { + _detailContainer.Add(new HelpBox( + "Detected third party asset that overrides all inspectors. " + + "Tri-Inspector's attributes might not work\n" + + _currentEditor.GetType().FullName, HelpBoxMessageType.Error)); } + + _detailContainer.Add(CreateSectionLabel("Preview")); + var previewBox = CreateBox(); + previewBox.Add(new InspectorElement(_currentEditor)); + _detailContainer.Add(previewBox); + + _detailContainer.Add(CreateSectionLabel("Code")); + var codeBox = CreateBox(); + codeBox.Add(new TextField + { + multiline = true, + isReadOnly = true, + value = _currentMonoScript.text, + }); + _detailContainer.Add(codeBox); + } + + private static Label CreateSectionLabel(string text) + { + var label = new Label(text); + label.AddToClassList(TriStyles.SamplesSection); + return label; + } + + private static VisualElement CreateBox() + { + var box = new VisualElement(); + box.AddToClassList(TriStyles.SamplesBox); + return box; } private static string GetTypeNiceName(Type type) @@ -164,75 +240,16 @@ private static string GetTypeNiceName(Type type) return name; } - private class MenuTree : TreeView + private readonly struct MenuEntry { - private readonly Dictionary _groups = new Dictionary(); - - public event Action SelectedTypeChanged; + public readonly string Name; + public readonly Type Type; - public MenuTree(TreeViewState state) : base(state) + public MenuEntry(string name, Type type) { - } - - protected override bool CanMultiSelect(TreeViewItem item) - { - return false; - } - - protected override void SelectionChanged(IList selectedIds) - { - base.SelectionChanged(selectedIds); - - var type = selectedIds.Count > 0 && FindItem(selectedIds[0], rootItem) is SampleItem sampleItem - ? sampleItem.Type - : null; - - SelectedTypeChanged?.Invoke(type); - } - - protected override TreeViewItem BuildRoot() - { - var root = new TreeViewItem(-1, -1); - - var sampleTypes = typeof(TriSamplesWindow).Assembly.GetTypes() - .Where(type => type.BaseType == typeof(ScriptableObject) && type.Name.EndsWith("Sample")) - .OrderBy(type => type.Name) - .ToList(); - - var id = 0; - foreach (var sampleType in sampleTypes) - { - var group = sampleType.Name.Split('_')[0]; - - if (!_groups.TryGetValue(group, out var groupItem)) - { - _groups[group] = groupItem = new GroupItem(++id, group); - - root.AddChild(groupItem); - } - - groupItem.AddChild(new SampleItem(++id, sampleType)); - } - - return root; - } - - private class GroupItem : TreeViewItem - { - public GroupItem(int id, string name) : base(id, 0, name) - { - } - } - - private class SampleItem : TreeViewItem - { - public Type Type { get; } - - public SampleItem(int id, Type type) : base(id, 1, GetTypeNiceName(type)) - { - Type = type; - } + Name = name; + Type = type; } } } -} \ No newline at end of file +} diff --git a/Editor/Editors/TriEditor.cs b/Editor/Editors/TriEditor.cs index 668e7829..e49a35ce 100644 --- a/Editor/Editors/TriEditor.cs +++ b/Editor/Editors/TriEditor.cs @@ -17,12 +17,6 @@ protected virtual void OnDisable() _core.Dispose(); } - - public override void OnInspectorGUI() - { - _core.OnInspectorGUI(); - } - public override VisualElement CreateInspectorGUI() { return _core.CreateVisualElement(); diff --git a/Editor/Editors/TriEditorCore.cs b/Editor/Editors/TriEditorCore.cs index dc7334d7..a83d8dc4 100644 --- a/Editor/Editors/TriEditorCore.cs +++ b/Editor/Editors/TriEditorCore.cs @@ -1,16 +1,12 @@ -using System.Collections.Generic; -using TriInspector.Utilities; +using TriInspector.VisualElements; using UnityEditor; -using UnityEngine; +using UnityEditor.UIElements; using UnityEngine.UIElements; namespace TriInspector.Editors { public class TriEditorCore { - internal static readonly Dictionary UiElementsRoots - = new Dictionary(); - private readonly Editor _editor; private TriPropertyTreeForSerializedObject _inspector; @@ -24,36 +20,22 @@ public void Dispose() { if (_inspector != null) { - UiElementsRoots.Remove(_inspector); - _inspector.Dispose(); } _inspector = null; } - public void OnInspectorGUI(VisualElement visualRoot = null) + public VisualElement CreateVisualElement() { var serializedObject = _editor.serializedObject; - if (serializedObject.targetObjects.Length == 0) - { - return; - } - - if (serializedObject.targetObject == null) - { - EditorGUILayout.HelpBox("Script is missing", MessageType.Warning); - return; - } + var container = new VisualElement(); - foreach (var targetObject in serializedObject.targetObjects) + if (serializedObject.targetObjects.Length == 0 || serializedObject.targetObject == null) { - if (TriGuiHelper.IsEditorTargetPushed(targetObject)) - { - GUILayout.Label("Recursive inline editors not supported"); - return; - } + container.Add(new HelpBox("Script is missing", HelpBoxMessageType.Warning)); + return container; } if (_inspector == null) @@ -61,84 +43,30 @@ public void OnInspectorGUI(VisualElement visualRoot = null) _inspector = new TriPropertyTreeForSerializedObject(serializedObject); } - if (visualRoot != null) + if (!_inspector.RootProperty.TryGetAttribute(out HideMonoScriptAttribute _)) { - UiElementsRoots[_inspector] = visualRoot; + var scriptProperty = serializedObject.FindProperty("m_Script"); + if (scriptProperty != null) + { + var scriptField = new PropertyField(scriptProperty); + scriptField.SetEnabled(false); + scriptField.Bind(serializedObject); + container.Add(scriptField); + } } serializedObject.UpdateIfRequiredOrScript(); - _inspector.Update(); - _inspector.RunValidationIfRequired(); - EditorGUIUtility.hierarchyMode = false; - - using (TriGuiHelper.PushEditorTarget(serializedObject.targetObject)) - { - _inspector.Draw(); - } + container.Add(_inspector.GetRootElement()); - if (serializedObject.ApplyModifiedProperties()) + container.schedule.Execute(() => { - _inspector.RequestValidation(); - } - - if (_inspector.RepaintRequired) - { - _editor.Repaint(); - } - } - - public VisualElement CreateVisualElement() - { - var container = new VisualElement(); - var root = new VisualElement() - { - style = - { - position = Position.Absolute, - }, - }; - - container.Add(new IMGUIContainer(() => - { - const float labelExtraPadding = 2; - const float labelWidthRatio = 0.45f; - const float labelMinWidth = 120; - - var space = container.resolvedStyle.left + container.resolvedStyle.right + labelExtraPadding; - - EditorGUIUtility.wideMode = true; - EditorGUIUtility.hierarchyMode = false; - EditorGUIUtility.labelWidth = Mathf.Max(labelMinWidth, - container.resolvedStyle.width * labelWidthRatio - space); - - GUILayout.BeginVertical(Styles.RootLayout); - OnInspectorGUI(root); - GUILayout.EndVertical(); - }) - { - style = - { - marginLeft = -Styles.RootMarginLeft, - marginRight = -Styles.RootMarginRight, - }, - }); - - container.Add(root); + _inspector.Update(); + _inspector.RunValidationIfRequired(); + }).Every(0); return container; } - - private static class Styles - { - public const int RootMarginLeft = 15; - public const int RootMarginRight = 6; - - public static readonly GUIStyle RootLayout = new GUIStyle - { - padding = new RectOffset(RootMarginLeft, RootMarginRight, 0, 0), - }; - } } } \ No newline at end of file diff --git a/Editor/Editors/TriScriptedImporterEditor.cs b/Editor/Editors/TriScriptedImporterEditor.cs index de4f90fe..f5a977f8 100644 --- a/Editor/Editors/TriScriptedImporterEditor.cs +++ b/Editor/Editors/TriScriptedImporterEditor.cs @@ -30,13 +30,6 @@ public override void OnDisable() base.OnDisable(); } - public override void OnInspectorGUI() - { - _core.OnInspectorGUI(); - - ApplyRevertGUI(); - } - public override VisualElement CreateInspectorGUI() { var root = new VisualElement(); diff --git a/Editor/Elements.meta b/Editor/Elements.meta deleted file mode 100644 index a98609e5..00000000 --- a/Editor/Elements.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 99d0fe2f9d1c4cb88cf46ba5813c091f -timeCreated: 1638772919 \ No newline at end of file diff --git a/Editor/Elements/InlineEditorElement.cs b/Editor/Elements/InlineEditorElement.cs deleted file mode 100644 index 3ad1de90..00000000 --- a/Editor/Elements/InlineEditorElement.cs +++ /dev/null @@ -1,161 +0,0 @@ -using TriInspectorUnityInternalBridge; -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - public class InlineEditorElement : TriElement - { - private readonly TriProperty _property; - private readonly Props _props; - private Editor _editor; - private Rect _editorPosition; - private bool _dirty; - - [System.Serializable] - public struct Props - { - public InlineEditorModes mode; - public float previewHeight; - - public bool DrawGUI => (mode & InlineEditorModes.GUIOnly) != 0; - public bool DrawHeader => (mode & InlineEditorModes.Header) != 0; - public bool DrawPreview => (mode & InlineEditorModes.Preview) != 0; - } - - public InlineEditorElement(TriProperty property, Props props = default) - { - _property = property; - _props = props; - _editorPosition = Rect.zero; - } - - protected override void OnDetachFromPanel() - { - if (_editor != null) - { - Object.DestroyImmediate(_editor); - } - - base.OnDetachFromPanel(); - } - - public override bool Update() - { - if (_editor == null || _editor.target != (Object) _property.Value) - { - if (_editor != null) - { - Object.DestroyImmediate(_editor); - } - - _dirty = true; - } - - if (_dirty) - { - _dirty = false; - return true; - } - - return false; - } - - public override float GetHeight(float width) - { - if (_property.IsExpanded && !_property.IsValueMixed) - { - return _editorPosition.height; - } - - return 0f; - } - - public override void OnGUI(Rect position) - { - if (Event.current.type == EventType.Repaint) - { - _editorPosition = position; - } - - var lastEditorRect = Rect.zero; - var shouldDrawEditor = _property.IsExpanded && !_property.IsValueMixed; - - if (_editor == null && shouldDrawEditor && _property.Value is Object obj && obj != null) - { - _editor = Editor.CreateEditor(obj); - - if (!InternalEditorUtilityProxy.GetIsInspectorExpanded(obj)) - { - InternalEditorUtilityProxy.SetIsInspectorExpanded(obj, true); - } - } - - if (_editor != null && shouldDrawEditor) - { - GUILayout.BeginArea(_editorPosition); - GUILayout.BeginVertical(); - - if (_props.DrawHeader || _props.DrawGUI) - { - GUILayout.BeginVertical(); - - if (_props.DrawHeader) - { - GUILayout.BeginVertical(); - _editor.DrawHeader(); - GUILayout.EndVertical(); - } - - if (_props.DrawGUI) - { - GUILayout.BeginVertical(); - _editor.OnInspectorGUI(); - GUILayout.EndVertical(); - } - - GUILayout.EndVertical(); - } - - if (_props.DrawPreview && _editor.HasPreviewGUI()) - { - GUILayout.BeginVertical(); - - var previewOpts = new[] {GUILayout.ExpandWidth(true), GUILayout.Height(_props.previewHeight),}; - var previewRect = EditorGUILayout.GetControlRect(false, _props.previewHeight, previewOpts); - - previewRect.width = Mathf.Max(previewRect.width, 10); - previewRect.height = Mathf.Max(previewRect.height, 10); - - var guiEnabled = GUI.enabled; - GUI.enabled = true; - - _editor.DrawPreview(previewRect); - - GUI.enabled = guiEnabled; - - GUILayout.EndVertical(); - } - - GUILayout.EndVertical(); - lastEditorRect = GUILayoutUtility.GetLastRect(); - GUILayout.EndArea(); - } - else - { - if (_editor != null) - { - Object.DestroyImmediate(_editor); - } - } - - if (Event.current.type == EventType.Repaint && - !Mathf.Approximately(_editorPosition.height, lastEditorRect.height)) - { - _editorPosition.height = lastEditorRect.height; - _dirty = true; - _property.PropertyTree.RequestRepaint(); - } - } - } -} \ No newline at end of file diff --git a/Editor/Elements/InlineEditorElement.cs.meta b/Editor/Elements/InlineEditorElement.cs.meta deleted file mode 100644 index 4a6d9c3b..00000000 --- a/Editor/Elements/InlineEditorElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: e5abb7004e824b6d87bae69c80c8df1d -timeCreated: 1641802293 \ No newline at end of file diff --git a/Editor/Elements/TriBoxGroupElement.cs b/Editor/Elements/TriBoxGroupElement.cs deleted file mode 100644 index 7b61199c..00000000 --- a/Editor/Elements/TriBoxGroupElement.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System; -using JetBrains.Annotations; -using TriInspector.Resolvers; -using TriInspector.Utilities; -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - public class TriBoxGroupElement : TriHeaderGroupBaseElement - { - private readonly Props _props; - - private ValueResolver _headerResolver; - [CanBeNull] private TriProperty _firstProperty; - [CanBeNull] private TriProperty _toggleProperty; - - private bool _expanded; - - [Serializable] - public new struct Props - { - public string title; - public TitleMode titleMode; - public bool expandedByDefault; - public bool hideIfChildrenInvisible; - } - - public TriBoxGroupElement(Props props = default) : base(new TriHeaderGroupBaseElement.Props - { - hideIfChildrenInvisible = props.hideIfChildrenInvisible, - }) - { - _props = props; - _expanded = _props.expandedByDefault; - } - - protected override void AddPropertyChild(TriElement element, TriProperty property) - { - _firstProperty = property; - _headerResolver = ValueResolver.ResolveString(property.Definition, _props.title ?? ""); - - if (_headerResolver.TryGetErrorString(out var error)) - { - AddChild(new TriInfoBoxElement(error, TriMessageType.Error)); - } - - if (_props.titleMode == TitleMode.Toggle) - { - if (_toggleProperty == null) - { - if (property.ValueType == typeof(bool)) - { - _toggleProperty = property; - - return; - } - - if (property.ChildrenProperties?.Count > 0) - { - var childrenProperty = property.ChildrenProperties[0]; - - if (childrenProperty.ValueType == typeof(bool)) - { - _toggleProperty = childrenProperty; - } - } - } - } - - base.AddPropertyChild(element, property); - } - - protected override float GetHeaderHeight(float width) - { - if (_props.titleMode == TitleMode.Hidden) - { - return 0f; - } - - return base.GetHeaderHeight(width); - } - - protected override float GetContentHeight(float width) - { - if (((_props.titleMode == TitleMode.Toggle && _props.expandedByDefault) || - _props.titleMode == TitleMode.Foldout) && !_expanded) - { - return 0f; - } - - return base.GetContentHeight(width); - } - - protected override void DrawHeader(Rect position) - { - TriEditorGUI.DrawBox(position, TriEditorStyles.TabOnlyOne); - - var headerLabelRect = new Rect(position) - { - xMin = position.xMin + 6, - xMax = position.xMax - 6, - yMin = position.yMin + 2, - yMax = position.yMax - 2, - }; - - var headerContent = _headerResolver.GetValue(_firstProperty); - - switch (_props.titleMode) - { - case TitleMode.Foldout: - _expanded = EditorGUI.Foldout(headerLabelRect, _expanded, headerContent, true); - break; - case TitleMode.Toggle: - { - if (_toggleProperty?.Value is bool cachedValue) - { - EditorGUI.BeginChangeCheck(); - - var newValue = EditorGUI.ToggleLeft(headerLabelRect, headerContent, cachedValue); - - if (EditorGUI.EndChangeCheck()) - { - _toggleProperty.SetValue(newValue); - } - - _expanded = newValue; - } - else - { - EditorGUI.LabelField(headerLabelRect, $"The first property in the group must be of bool."); - } - break; - } - default: - EditorGUI.LabelField(headerLabelRect, headerContent); - break; - } - } - - protected override void DrawContent(Rect position) - { - if (_props.titleMode == TitleMode.Foldout && !_expanded) - { - return; - } - - if (_props.titleMode == TitleMode.Toggle && !_props.expandedByDefault && !_expanded) - { - EditorGUI.BeginDisabledGroup(true); - base.DrawContent(position); - EditorGUI.EndDisabledGroup(); - - return; - - } - - base.DrawContent(position); - } - - public enum TitleMode - { - Normal, - Hidden, - Foldout, - Toggle, - } - } -} diff --git a/Editor/Elements/TriBoxGroupElement.cs.meta b/Editor/Elements/TriBoxGroupElement.cs.meta deleted file mode 100644 index 4d289e0a..00000000 --- a/Editor/Elements/TriBoxGroupElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: c7a787b7a5e844a2a12192a9d52984b0 -timeCreated: 1641802243 \ No newline at end of file diff --git a/Editor/Elements/TriBuiltInPropertyElement.cs b/Editor/Elements/TriBuiltInPropertyElement.cs deleted file mode 100644 index 0233c459..00000000 --- a/Editor/Elements/TriBuiltInPropertyElement.cs +++ /dev/null @@ -1,47 +0,0 @@ -using TriInspectorUnityInternalBridge; -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - internal class TriBuiltInPropertyElement : TriElement - { - private readonly TriProperty _property; - private readonly PropertyHandlerProxy _propertyHandler; - private readonly SerializedProperty _serializedProperty; - - public TriBuiltInPropertyElement( - TriProperty property, - SerializedProperty serializedProperty, - PropertyHandlerProxy propertyHandler) - { - _property = property; - _serializedProperty = serializedProperty; - _propertyHandler = propertyHandler; - } - - public override float GetHeight(float width) - { - return _propertyHandler.GetHeight(_serializedProperty, _property.DisplayNameContent, true); - } - - public override void OnGUI(Rect position) - { - EditorGUI.BeginChangeCheck(); - - if (_property.IsArrayElement && - _serializedProperty.propertyType == SerializedPropertyType.Generic && - _serializedProperty.hasVisibleChildren) - { - position.xMin += 12; - } - - _propertyHandler.OnGUI(position, _serializedProperty, _property.DisplayNameContent, true); - - if (EditorGUI.EndChangeCheck()) - { - _property.NotifyValueChanged(); - } - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriBuiltInPropertyElement.cs.meta b/Editor/Elements/TriBuiltInPropertyElement.cs.meta deleted file mode 100644 index 17ec3681..00000000 --- a/Editor/Elements/TriBuiltInPropertyElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: cb76597978d84d19a27f6e8596e1a4bf -timeCreated: 1638774260 \ No newline at end of file diff --git a/Editor/Elements/TriDropdownElement.cs.meta b/Editor/Elements/TriDropdownElement.cs.meta deleted file mode 100644 index a03b9750..00000000 --- a/Editor/Elements/TriDropdownElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 0bfe47c1836e47c48920fb74982c89cb -timeCreated: 1657812638 \ No newline at end of file diff --git a/Editor/Elements/TriFoldoutElement.cs b/Editor/Elements/TriFoldoutElement.cs deleted file mode 100644 index d2d92071..00000000 --- a/Editor/Elements/TriFoldoutElement.cs +++ /dev/null @@ -1,101 +0,0 @@ -using TriInspector.Utilities; -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - internal class TriFoldoutElement : TriPropertyCollectionBaseElement - { - private readonly TriProperty _property; - - public TriFoldoutElement(TriProperty property) - { - _property = property; - - DeclareGroups(property.ValueType); - } - - public override bool Update() - { - var dirty = false; - - if (_property.IsExpanded) - { - dirty |= GenerateChildren(); - } - else - { - dirty |= ClearChildren(); - } - - dirty |= base.Update(); - - return dirty; - } - - public override float GetHeight(float width) - { - var height = EditorGUIUtility.singleLineHeight; - - if (!_property.IsExpanded) - { - return height; - } - - height += base.GetHeight(width); - - return height; - } - - public override void OnGUI(Rect position) - { - var headerRect = new Rect(position) - { - height = EditorGUIUtility.singleLineHeight, - }; - var contentRect = new Rect(position) - { - yMin = position.yMin + headerRect.height, - }; - - TriEditorGUI.Foldout(headerRect, _property); - - if (!_property.IsExpanded) - { - return; - } - - using (var indentedRectScope = TriGuiHelper.PushIndentedRect(contentRect, 1)) - { - base.OnGUI(indentedRectScope.IndentedRect); - } - } - - private bool GenerateChildren() - { - if (ChildrenCount != 0) - { - return false; - } - - foreach (var childProperty in _property.ChildrenProperties) - { - AddProperty(childProperty); - } - - return true; - } - - private bool ClearChildren() - { - if (ChildrenCount == 0) - { - return false; - } - - RemoveAllChildren(); - - return true; - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriFoldoutElement.cs.meta b/Editor/Elements/TriFoldoutElement.cs.meta deleted file mode 100644 index abdd1c25..00000000 --- a/Editor/Elements/TriFoldoutElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 90b64b1805694cf8999a0380d4ca70b6 -timeCreated: 1638772042 \ No newline at end of file diff --git a/Editor/Elements/TriHeaderGroupBaseElement.cs b/Editor/Elements/TriHeaderGroupBaseElement.cs deleted file mode 100644 index 0122b80c..00000000 --- a/Editor/Elements/TriHeaderGroupBaseElement.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using TriInspector.Utilities; -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - public abstract class TriHeaderGroupBaseElement : TriPropertyCollectionBaseElement - { - private readonly Props _props; - private const float InsetTop = 4; - private const float InsetBottom = 4; - private const float InsetLeft = 4; - private const float InsetRight = 4; - - private readonly List _properties = new List(); - - private bool IsAnyPropertyVisible => _properties.Any(it => it.IsVisible); - - [Serializable] - public struct Props - { - public bool hideIfChildrenInvisible; - } - - protected TriHeaderGroupBaseElement(Props props = default) - { - _props = props; - } - - protected override void AddPropertyChild(TriElement element, TriProperty property) - { - _properties.Add(property); - - base.AddPropertyChild(element, property); - } - - protected virtual float GetHeaderHeight(float width) - { - return 22; - } - - protected virtual float GetContentHeight(float width) - { - return base.GetHeight(width); - } - - protected virtual void DrawHeader(Rect position) - { - } - - protected virtual void DrawContent(Rect position) - { - base.OnGUI(position); - } - - public sealed override float GetHeight(float width) - { - if (_props.hideIfChildrenInvisible && !IsAnyPropertyVisible) - { - return -EditorGUIUtility.standardVerticalSpacing; - } - - var headerHeight = GetHeaderHeight(width); - var contentHeight = GetContentHeight(width); - - var height = headerHeight + contentHeight; - - if (contentHeight > 0) - { - height += InsetTop + InsetBottom; - } - - return height; - } - - public sealed override void OnGUI(Rect position) - { - if (_props.hideIfChildrenInvisible && !IsAnyPropertyVisible) - { - return; - } - - var headerHeight = GetHeaderHeight(position.width); - var contentHeight = GetContentHeight(position.width); - - var headerBgRect = new Rect(position) - { - height = headerHeight, - }; - var contentBgRect = new Rect(position) - { - yMin = headerBgRect.yMax, - }; - var contentRect = new Rect(contentBgRect) - { - xMin = contentBgRect.xMin + InsetLeft, - xMax = contentBgRect.xMax - InsetRight, - yMin = contentBgRect.yMin + InsetTop, - yMax = contentBgRect.yMax - InsetBottom, - height = contentHeight, - }; - - if (headerHeight > 0f) - { - DrawHeader(headerBgRect); - } - - if (contentHeight > 0) - { - TriEditorGUI.DrawBox(contentBgRect, headerHeight > 0f - ? TriEditorStyles.ContentBox - : TriEditorStyles.Box); - - using (TriGuiHelper.PushLabelWidth(EditorGUIUtility.labelWidth - InsetLeft)) - { - DrawContent(contentRect); - } - } - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriHeaderGroupBaseElement.cs.meta b/Editor/Elements/TriHeaderGroupBaseElement.cs.meta deleted file mode 100644 index c807edb4..00000000 --- a/Editor/Elements/TriHeaderGroupBaseElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 7406688f5ef349a3ae0acee7ea9ec935 -timeCreated: 1642760804 \ No newline at end of file diff --git a/Editor/Elements/TriHorizontalGroupElement.cs b/Editor/Elements/TriHorizontalGroupElement.cs deleted file mode 100644 index eef40c1b..00000000 --- a/Editor/Elements/TriHorizontalGroupElement.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System; -using TriInspector.Utilities; -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - public class TriHorizontalGroupElement : TriPropertyCollectionBaseElement - { - private readonly float[] _sizes; - private readonly float _totalFixedSize; - - public TriHorizontalGroupElement(float[] sizes = null) - { - _sizes = sizes ?? Array.Empty(); - _totalFixedSize = 0f; - - for (var index = 0; index < _sizes.Length; index++) - { - if (TryGetFixedSizeByIndex(index, out var fixedSize)) - { - _totalFixedSize += fixedSize; - } - } - } - - public override float GetHeight(float width) - { - if (ChildrenCount == 0) - { - return 0f; - } - - var spacing = EditorGUIUtility.standardVerticalSpacing; - var totalSpacing = spacing * (ChildrenCount - 1); - var totalDynamic = width - totalSpacing - _totalFixedSize; - var dynamicChildCount = GetDynamicChildCount(); - - var height = 0f; - - for (var i = 0; i < ChildrenCount; i++) - { - var childWidth = GetChildWidth(i, totalDynamic, dynamicChildCount); - var child = GetChild(i); - var childHeight = child.GetHeight(childWidth); - - height = Mathf.Max(height, childHeight); - } - - return height; - } - - public override void OnGUI(Rect position) - { - if (ChildrenCount == 0) - { - return; - } - - var spacing = EditorGUIUtility.standardVerticalSpacing; - var totalSpacing = spacing * (ChildrenCount - 1); - var totalDynamic = position.width - totalSpacing - _totalFixedSize; - var dynamicChildCount = GetDynamicChildCount(); - - var xOffset = 0f; - for (var i = 0; i < ChildrenCount; i++) - { - var childWidth = GetChildWidth(i, totalDynamic, dynamicChildCount); - var child = GetChild(i); - var childRect = new Rect(position) - { - width = childWidth, - height = child.GetHeight(childWidth), - x = position.xMin + xOffset, - }; - - using (TriGuiHelper.PushLabelWidth(EditorGUIUtility.labelWidth / ChildrenCount)) - { - child.OnGUI(childRect); - } - - xOffset += childWidth + spacing; - } - } - - private float GetDynamicChildCount() - { - var count = 0f; - - for (var i = 0; i < ChildrenCount; i++) - { - if (TryGetFixedSizeByIndex(i, out _)) - { - continue; - } - - count++; - } - - return count; - } - - private float GetChildWidth(int i, float totalDynamic, float dynamicChildCount) - { - if (TryGetFixedSizeByIndex(i, out var fixedSize)) - { - return fixedSize; - } - - return totalDynamic / dynamicChildCount; - } - - private bool TryGetFixedSizeByIndex(int index, out float fixedSize) - { - if (index < _sizes.Length && _sizes[index] > 0f) - { - fixedSize = _sizes[index]; - return true; - } - - fixedSize = 0f; - return false; - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriHorizontalGroupElement.cs.meta b/Editor/Elements/TriHorizontalGroupElement.cs.meta deleted file mode 100644 index 26a83946..00000000 --- a/Editor/Elements/TriHorizontalGroupElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: e609cf56a7e242d8b9cb5813178a7e69 -timeCreated: 1642259149 \ No newline at end of file diff --git a/Editor/Elements/TriInfoBoxElement.cs b/Editor/Elements/TriInfoBoxElement.cs deleted file mode 100644 index bcce49ae..00000000 --- a/Editor/Elements/TriInfoBoxElement.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System; -using TriInspector.Utilities; -using TriInspectorUnityInternalBridge; -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - public class TriInfoBoxElement : TriElement - { - private const int ActionSpacing = 5; - private const int ActionWidth = 100; - private const int ActionWidthWithSpacing = ActionWidth + ActionSpacing * 2; - - private readonly GUIContent _message; - private readonly Texture2D _icon; - private readonly Color _color; - private readonly Action _inlineAction; - private readonly GUIContent _inlineActionContent; - - public TriInfoBoxElement(string message, TriMessageType type = TriMessageType.None, Color? color = null, - Action inlineAction = null, GUIContent inlineActionContent = null) - { - var messageType = GetMessageType(type); - _icon = EditorGUIUtilityProxy.GetHelpIcon(messageType); - _message = new GUIContent(message); - _color = color ?? GetColor(type); - _inlineAction = inlineAction; - _inlineActionContent = inlineActionContent ?? GUIContent.none; - } - - public override float GetHeight(float width) - { - var labelWidth = width; - - if (_inlineAction != null) - { - labelWidth -= ActionWidthWithSpacing; - } - - var style = _icon == null ? Styles.InfoBoxContentNone : Styles.InfoBoxContent; - var height = style.CalcHeight(_message, labelWidth); - - if (_inlineAction != null) - { - height = Mathf.Max(height, CalcActionHeight() + ActionSpacing * 2); - } - - return Mathf.Max(26, height); - } - - public override void OnGUI(Rect position) - { - using (TriGuiHelper.PushColor(_color)) - { - GUI.Label(position, string.Empty, Styles.InfoBoxBg); - } - - var labelWidth = position.width; - - if (_inlineAction != null) - { - labelWidth -= ActionWidthWithSpacing; - } - - if (_icon != null) - { - var labelRect = new Rect(position) - { - width = labelWidth, - }; - - var iconRect = new Rect(position) - { - xMin = position.xMin + 4, - width = 20, - }; - - GUI.Label(labelRect, _message, Styles.InfoBoxContent); - GUI.DrawTexture(iconRect, _icon, ScaleMode.ScaleToFit); - } - else - { - GUI.Label(position, _message, Styles.InfoBoxContentNone); - } - - if (_inlineAction != null) - { - var fixHeight = CalcActionHeight(); - - var actionRect = new Rect(position) - { - xMax = position.xMax - ActionSpacing, - xMin = position.xMax - ActionWidth - ActionSpacing, - yMin = position.center.y - fixHeight / 2, - yMax = position.center.y + fixHeight / 2, - }; - - if (GUI.Button(actionRect, _inlineActionContent, Styles.InfoBoxInlineAction)) - { - _inlineAction?.Invoke(); - } - } - } - - - private float CalcActionHeight() - { - return Styles.InfoBoxInlineAction.CalcHeight(_inlineActionContent, ActionWidth); - } - - private static Color GetColor(TriMessageType type) - { - switch (type) - { - case TriMessageType.Error: - return new Color(1f, 0.4f, 0.4f); - - case TriMessageType.Warning: - return new Color(1f, 0.8f, 0.2f); - - default: - return Color.white; - } - } - - private static MessageType GetMessageType(TriMessageType type) - { - switch (type) - { - case TriMessageType.None: return MessageType.None; - case TriMessageType.Info: return MessageType.Info; - case TriMessageType.Warning: return MessageType.Warning; - case TriMessageType.Error: return MessageType.Error; - default: return MessageType.None; - } - } - - private static class Styles - { - public static readonly GUIStyle InfoBoxBg; - public static readonly GUIStyle InfoBoxContent; - public static readonly GUIStyle InfoBoxContentNone; - public static readonly GUIStyle InfoBoxInlineAction; - - static Styles() - { - InfoBoxBg = new GUIStyle(EditorStyles.helpBox); - InfoBoxContentNone = new GUIStyle(EditorStyles.label) - { - padding = new RectOffset(4, 4, 4, 4), - fontSize = InfoBoxBg.fontSize, - alignment = TextAnchor.MiddleLeft, - wordWrap = true, - }; - InfoBoxContent = new GUIStyle(InfoBoxContentNone) - { - padding = new RectOffset(26, 4, 4, 4), - }; - InfoBoxInlineAction = new GUIStyle(GUI.skin.button) - { - wordWrap = true, - }; - } - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriInfoBoxElement.cs.meta b/Editor/Elements/TriInfoBoxElement.cs.meta deleted file mode 100644 index 420392a0..00000000 --- a/Editor/Elements/TriInfoBoxElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: f64a66d501c34a808686c834530dd9a9 -timeCreated: 1638860979 \ No newline at end of file diff --git a/Editor/Elements/TriInlineGenericElement.cs b/Editor/Elements/TriInlineGenericElement.cs deleted file mode 100644 index d3fff047..00000000 --- a/Editor/Elements/TriInlineGenericElement.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using TriInspector.Utilities; -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - internal class TriInlineGenericElement : TriPropertyCollectionBaseElement - { - private readonly Props _props; - private readonly TriProperty _property; - - [Serializable] - public struct Props - { - public bool drawPrefixLabel; - public float labelWidth; - } - - public TriInlineGenericElement(TriProperty property, Props props = default) - { - _property = property; - _props = props; - - DeclareGroups(property.ValueType); - - foreach (var childProperty in property.ChildrenProperties) - { - AddProperty(childProperty); - } - } - - public override void OnGUI(Rect position) - { - if (_props.drawPrefixLabel) - { - var controlId = GUIUtility.GetControlID(FocusType.Passive); - position = EditorGUI.PrefixLabel(position, controlId, _property.DisplayNameContent); - } - - using (TriGuiHelper.PushLabelWidth(_props.labelWidth)) - { - base.OnGUI(position); - } - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriInlineGenericElement.cs.meta b/Editor/Elements/TriInlineGenericElement.cs.meta deleted file mode 100644 index e59f8506..00000000 --- a/Editor/Elements/TriInlineGenericElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: a5124d0a8d93488a858723d80fe69e69 -timeCreated: 1638788657 \ No newline at end of file diff --git a/Editor/Elements/TriLabelElement.cs b/Editor/Elements/TriLabelElement.cs deleted file mode 100644 index 6c028c18..00000000 --- a/Editor/Elements/TriLabelElement.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UnityEngine; - -namespace TriInspector.Elements -{ - public class TriLabelElement : TriElement - { - private readonly GUIContent _label; - - public TriLabelElement(string label, string tooltip = "") - { - _label = new GUIContent(label, tooltip); - } - - public TriLabelElement(GUIContent label) - { - _label = label; - } - - public override float GetHeight(float width) - { - return GUI.skin.label.CalcHeight(_label, width); - } - - public override void OnGUI(Rect position) - { - GUI.Label(position, _label); - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriLabelElement.cs.meta b/Editor/Elements/TriLabelElement.cs.meta deleted file mode 100644 index 19226339..00000000 --- a/Editor/Elements/TriLabelElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: a193f4236257483a8d5a10f0025b3d4f -timeCreated: 1638771650 \ No newline at end of file diff --git a/Editor/Elements/TriListElement.cs b/Editor/Elements/TriListElement.cs deleted file mode 100644 index 43e03425..00000000 --- a/Editor/Elements/TriListElement.cs +++ /dev/null @@ -1,593 +0,0 @@ -using System; -using System.Collections; -using System.Linq; -using TriInspectorUnityInternalBridge; -using TriInspector.Utilities; -using UnityEditor; -using UnityEditorInternal; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace TriInspector.Elements -{ - public class TriListElement : TriElement - { - private const int MinElementsForVirtualization = 25; - - private const float ListExtraWidth = 7f; - private const float DraggableAreaExtraWidth = 14f; - - private readonly TriProperty _property; - private readonly ReorderableList _reorderableListGui; - private readonly bool _alwaysExpanded; - private readonly bool _showElementLabels; - private readonly bool _showAlternatingBackground; - - private float _lastContentWidth; - private int? _lastInvisibleElement; - private int? _lastVisibleElement; - - protected ReorderableList ListGui => _reorderableListGui; - - public TriListElement(TriProperty property) - { - property.TryGetAttribute(out ListDrawerSettingsAttribute settings); - - _property = property; - _alwaysExpanded = settings?.AlwaysExpanded ?? false; - _showElementLabels = settings?.ShowElementLabels ?? false; - _showAlternatingBackground = settings?.ShowAlternatingBackground ?? true; - _reorderableListGui = new ReorderableList(null, _property.ArrayElementType) - { - showDefaultBackground = settings?.ShowDefaultBackground ?? true, - draggable = settings?.Draggable ?? true, - displayAdd = settings == null || !settings.HideAddButton, - displayRemove = settings == null || !settings.HideRemoveButton, - drawHeaderCallback = DrawHeaderCallback, - elementHeightCallback = ElementHeightCallback, - drawElementBackgroundCallback = DrawElementBackgroundCallback, - drawElementCallback = DrawElementCallback, - onAddCallback = AddElementCallback, - onRemoveCallback = RemoveElementCallback, - onReorderCallbackWithDetails = ReorderCallback, - }; - - if (!_reorderableListGui.displayAdd && !_reorderableListGui.displayRemove) - { - _reorderableListGui.footerHeight = 0f; - } - } - - public override bool Update() - { - var dirty = false; - - if (_property.TryGetSerializedProperty(out var serializedProperty) && serializedProperty.isArray) - { - _reorderableListGui.serializedProperty = serializedProperty; - } - else if (_property.Value != null) - { - _reorderableListGui.list = (IList) _property.Value; - } - else if (_reorderableListGui.list == null) - { - _reorderableListGui.list = (IList) (_property.FieldType.IsArray - ? Array.CreateInstance(_property.ArrayElementType, 0) - : Activator.CreateInstance(_property.FieldType)); - } - - if (_alwaysExpanded && !_property.IsExpanded) - { - _property.IsExpanded = true; - } - - if (_property.IsExpanded) - { - dirty |= GenerateChildren(); - } - else - { - dirty |= ClearChildren(); - } - - dirty |= base.Update(); - - if (dirty) - { - ReorderableListProxy.ClearCacheRecursive(_reorderableListGui); - } - - return dirty; - } - - public override float GetHeight(float width) - { - if (!_property.IsExpanded) - { - return _reorderableListGui.headerHeight + 4f; - } - - _lastContentWidth = width; - - return _reorderableListGui.GetHeight(); - } - - public override void OnGUI(Rect position) - { - if (!_property.IsExpanded) - { - _lastInvisibleElement = null; - _lastVisibleElement = null; - - ReorderableListProxy.DoListHeader(_reorderableListGui, new Rect(position) - { - yMax = position.yMax - 4, - }); - return; - } - - if (_reorderableListGui.count < MinElementsForVirtualization) - { - _lastInvisibleElement = null; - _lastVisibleElement = null; - } - - var labelWidthExtra = ListExtraWidth + DraggableAreaExtraWidth; - - using (TriGuiHelper.PushLabelWidth(EditorGUIUtility.labelWidth - labelWidthExtra)) - { - _reorderableListGui.DoList(position); - } - } - - private void AddElementCallback(ReorderableList reorderableList) - { - AddElementCallback(reorderableList, null); - } - - private void AddElementCallback(ReorderableList reorderableList, Object addedReferenceValue) - { - if (_property.TryGetSerializedProperty(out _)) - { - ReorderableListProxy.DoAddButton(reorderableList, addedReferenceValue); - _property.NotifyValueChanged(); - return; - } - - var template = CloneValue(_property); - - _property.SetValues(targetIndex => - { - var value = (IList) _property.GetValue(targetIndex); - - if (_property.FieldType.IsArray) - { - var array = Array.CreateInstance(_property.ArrayElementType, template.Length + 1); - Array.Copy(template, array, template.Length); - - if (addedReferenceValue != null) - { - array.SetValue(addedReferenceValue, array.Length - 1); - } - - value = array; - } - else - { - if (value == null) - { - value = (IList) Activator.CreateInstance(_property.FieldType); - } - - var newElement = addedReferenceValue != null - ? addedReferenceValue - : CreateDefaultElementValue(_property); - - value.Add(newElement); - } - - return value; - }); - } - - private void RemoveElementCallback(ReorderableList reorderableList) - { - if (_property.TryGetSerializedProperty(out _)) - { - ReorderableListProxy.defaultBehaviours.DoRemoveButton(reorderableList); - _property.NotifyValueChanged(); - return; - } - - var template = CloneValue(_property); - var ind = reorderableList.index; - - _property.SetValues(targetIndex => - { - var value = (IList) _property.GetValue(targetIndex); - - if (_property.FieldType.IsArray) - { - var array = Array.CreateInstance(_property.ArrayElementType, template.Length - 1); - Array.Copy(template, 0, array, 0, ind); - Array.Copy(template, ind + 1, array, ind, array.Length - ind); - value = array; - } - else - { - value?.RemoveAt(ind); - } - - return value; - }); - } - - private void ReorderCallback(ReorderableList list, int oldIndex, int newIndex) - { - if (_property.TryGetSerializedProperty(out _)) - { - _property.NotifyValueChanged(); - return; - } - - var mainValue = _property.Value; - - _property.SetValues(targetIndex => - { - var value = (IList) _property.GetValue(targetIndex); - - if (value == mainValue) - { - return value; - } - - var element = value[oldIndex]; - for (var index = 0; index < value.Count - 1; ++index) - { - if (index >= oldIndex) - { - value[index] = value[index + 1]; - } - } - - for (var index = value.Count - 1; index > 0; --index) - { - if (index > newIndex) - { - value[index] = value[index - 1]; - } - } - - value[newIndex] = element; - - return value; - }); - } - - private void SetArraySizeCallback(int arraySize) - { - if (arraySize < 0) - { - return; - } - - if (_property.TryGetSerializedProperty(out var serializedProperty)) - { - serializedProperty.arraySize = arraySize; - _property.NotifyValueChanged(); - return; - } - - var template = CloneValue(_property); - - _property.SetValues(targetIndex => - { - var value = (IList) _property.GetValue(targetIndex); - - if (_property.FieldType.IsArray) - { - var array = Array.CreateInstance(_property.ArrayElementType, arraySize); - Array.Copy(template, array, Math.Min(arraySize, template.Length)); - - value = array; - } - else - { - if (value == null) - { - value = (IList) Activator.CreateInstance(_property.FieldType); - } - - while (value.Count > arraySize) - { - value.RemoveAt(value.Count - 1); - } - - while (value.Count < arraySize) - { - var newElement = CreateDefaultElementValue(_property); - value.Add(newElement); - } - } - - return value; - }); - } - - private bool GenerateChildren() - { - var count = _reorderableListGui.count; - - if (ChildrenCount == count) - { - return false; - } - - while (ChildrenCount < count) - { - var property = _property.ArrayElementProperties[ChildrenCount]; - AddChild(CreateItemElement(property)); - } - - while (ChildrenCount > count) - { - RemoveChildAt(ChildrenCount - 1); - } - - return true; - } - - private bool ClearChildren() - { - if (ChildrenCount == 0) - { - return false; - } - - RemoveAllChildren(); - - return true; - } - - protected virtual TriElement CreateItemElement(TriProperty property) - { - return new TriPropertyElement(property, new TriPropertyElement.Props - { - forceInline = !_showElementLabels, - }); - } - - private void DrawHeaderCallback(Rect rect) - { - var labelRect = new Rect(rect) - { - xMax = rect.xMax - 50, - }; - var arraySizeRect = new Rect(rect) - { - xMin = labelRect.xMax, - }; - - if (_alwaysExpanded) - { - EditorGUI.LabelField(labelRect, _property.DisplayNameContent); - } - else - { - TriEditorGUI.Foldout(labelRect, _property); - } - - EditorGUI.BeginChangeCheck(); - - var newArraySize = EditorGUI.DelayedIntField(arraySizeRect, _reorderableListGui.count); - - if (EditorGUI.EndChangeCheck()) - { - SetArraySizeCallback(newArraySize); - return; - } - - if (Event.current.type == EventType.DragUpdated && rect.Contains(Event.current.mousePosition)) - { - DragAndDrop.visualMode = DragAndDrop.objectReferences.All(obj => TryGetDragAndDropObject(obj, out _)) - ? DragAndDropVisualMode.Copy - : DragAndDropVisualMode.Rejected; - - Event.current.Use(); - } - else if (Event.current.type == EventType.DragPerform && rect.Contains(Event.current.mousePosition)) - { - DragAndDrop.AcceptDrag(); - - foreach (var obj in DragAndDrop.objectReferences) - { - if (TryGetDragAndDropObject(obj, out var addedReferenceValue)) - { - AddElementCallback(_reorderableListGui, addedReferenceValue); - } - } - - Event.current.Use(); - } - } - - private void DrawElementBackgroundCallback(Rect rect, int index, bool isActive, bool isFocused) - { - if (_lastInvisibleElement.HasValue && index + 1 < _lastInvisibleElement.Value || - _lastVisibleElement.HasValue && index - 1 > _lastVisibleElement.Value) - { - if (index != _reorderableListGui.index) - { - return; - } - } - - if (_showAlternatingBackground && index % 2 != 0) - { - EditorGUI.DrawRect(rect, new Color(0.1f, 0.1f, 0.1f, 0.15f)); - } - - ReorderableList.defaultBehaviours.DrawElementBackground(rect, index, isActive, isFocused, - _reorderableListGui.draggable); - } - - private void DrawElementCallback(Rect rect, int index, bool isActive, bool isFocused) - { - if (index >= ChildrenCount) - { - return; - } - - if (_lastInvisibleElement.HasValue && index + 1 < _lastInvisibleElement.Value || - _lastVisibleElement.HasValue && index - 1 > _lastVisibleElement.Value) - { - if (index != _reorderableListGui.index) - { - return; - } - } - - if (_reorderableListGui.count > MinElementsForVirtualization) - { - if (Event.current.type == EventType.Repaint) - { - var windowRect = GUIClipProxy.VisibleRect; - var rectInWindow = GUIClipProxy.UnClipToWindow(rect); - - if (rectInWindow.yMax < 0) - { - _lastInvisibleElement = index; - } else if (_lastInvisibleElement == index) - { - _lastInvisibleElement = index / 2; - _lastVisibleElement = index / 2 + 1; - _property.PropertyTree.RequestRepaint(); - } - - if (rectInWindow.y < windowRect.height) - { - if (!_lastVisibleElement.HasValue || index > _lastVisibleElement.Value) - { - _lastVisibleElement = index; - } - } - } - } - - if (!_reorderableListGui.draggable) - { - rect.xMin += DraggableAreaExtraWidth; - } - - using (TriPropertyOverrideContext.BeginOverride(ListPropertyOverrideContext.Instance)) - { - GetChild(index).OnGUI(rect); - } - } - - private float ElementHeightCallback(int index) - { - if (index >= ChildrenCount) - { - return EditorGUIUtility.singleLineHeight; - } - - if (_lastInvisibleElement.HasValue && index + 1 < _lastInvisibleElement.Value || - _lastVisibleElement.HasValue && index - 1 > _lastVisibleElement.Value) - { - if (index != _reorderableListGui.index) - { - return Mathf.Max(EditorGUIUtility.singleLineHeight, GetChild(index).CachedHeight); - } - } - - return GetChild(index).GetHeight(_lastContentWidth); - } - - private static object CreateDefaultElementValue(TriProperty property) - { - var canActivate = property.ArrayElementType.IsValueType || - property.ArrayElementType.GetConstructor(Type.EmptyTypes) != null; - - return canActivate ? Activator.CreateInstance(property.ArrayElementType) : null; - } - - private static Array CloneValue(TriProperty property) - { - var list = (IList) property.Value; - var template = Array.CreateInstance(property.ArrayElementType, list?.Count ?? 0); - list?.CopyTo(template, 0); - return template; - } - - private bool TryGetDragAndDropObject(Object obj, out Object result) - { - if (obj == null) - { - result = null; - return false; - } - - var elementType = _property.ArrayElementType; - var objType = obj.GetType(); - - if (elementType == objType || elementType.IsAssignableFrom(objType)) - { - result = obj; - return true; - } - - if (obj is GameObject go && typeof(Component).IsAssignableFrom(elementType) && - go.TryGetComponent(elementType, out var component)) - { - result = component; - return true; - } - - result = null; - return false; - } - - private class ListPropertyOverrideContext : TriPropertyOverrideContext - { - public static readonly ListPropertyOverrideContext Instance = new ListPropertyOverrideContext(); - - private readonly GUIContent _noneLabel = GUIContent.none; - - public override bool TryGetDisplayName(TriProperty property, out GUIContent displayName) - { - var showLabels = property.TryGetAttribute(out ListDrawerSettingsAttribute settings) && - settings.ShowElementLabels; - - if (!showLabels) - { - displayName = _noneLabel; - return true; - } - - displayName = default; - return false; - } - } - - private static class Styles - { - public static readonly GUIStyle ItemsCount; - - static Styles() - { - ItemsCount = new GUIStyle(GUI.skin.label) - { - alignment = TextAnchor.MiddleRight, - normal = - { - textColor = EditorGUIUtility.isProSkin - ? new Color(0.6f, 0.6f, 0.6f) - : new Color(0.3f, 0.3f, 0.3f), - }, - }; - } - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriListElement.cs.meta b/Editor/Elements/TriListElement.cs.meta deleted file mode 100644 index 44881ae6..00000000 --- a/Editor/Elements/TriListElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: c9ed87465ed54b039d11e455c4aa3efc -timeCreated: 1638776402 \ No newline at end of file diff --git a/Editor/Elements/TriMultiEditNotSupportedElement.cs b/Editor/Elements/TriMultiEditNotSupportedElement.cs deleted file mode 100644 index 2bb99061..00000000 --- a/Editor/Elements/TriMultiEditNotSupportedElement.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - public class TriMultiEditNotSupportedElement : TriElement - { - private readonly TriProperty _property; - private readonly GUIContent _message; - - public TriMultiEditNotSupportedElement(TriProperty property) - { - _property = property; - _message = new GUIContent("Multi edit not supported"); - } - - public override float GetHeight(float width) - { - return EditorGUIUtility.singleLineHeight; - } - - public override void OnGUI(Rect position) - { - EditorGUI.LabelField(position, _property.DisplayNameContent, _message); - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriMultiEditNotSupportedElement.cs.meta b/Editor/Elements/TriMultiEditNotSupportedElement.cs.meta deleted file mode 100644 index 9b8c48e4..00000000 --- a/Editor/Elements/TriMultiEditNotSupportedElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 575bf0dafd7f459fb09451ec5a83c427 -timeCreated: 1641382168 \ No newline at end of file diff --git a/Editor/Elements/TriNoDrawerElement.cs b/Editor/Elements/TriNoDrawerElement.cs deleted file mode 100644 index ed0f4219..00000000 --- a/Editor/Elements/TriNoDrawerElement.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - public class TriNoDrawerElement : TriElement - { - private readonly GUIContent _message; - private readonly TriProperty _property; - - public TriNoDrawerElement(TriProperty property) - { - _property = property; - _message = new GUIContent($"No drawer for {property.FieldType}"); - } - - public override float GetHeight(float width) - { - return EditorGUIUtility.singleLineHeight; - } - - public override void OnGUI(Rect position) - { - EditorGUI.LabelField(position, _property.DisplayNameContent, _message); - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriNoDrawerElement.cs.meta b/Editor/Elements/TriNoDrawerElement.cs.meta deleted file mode 100644 index 6afb7960..00000000 --- a/Editor/Elements/TriNoDrawerElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: e6cc0cc1449a4af4b8d435b87ef20378 -timeCreated: 1639319113 \ No newline at end of file diff --git a/Editor/Elements/TriPropertyCollectionBaseElement.cs b/Editor/Elements/TriPropertyCollectionBaseElement.cs deleted file mode 100644 index 5cb79c79..00000000 --- a/Editor/Elements/TriPropertyCollectionBaseElement.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using JetBrains.Annotations; -using TriInspector.Utilities; - -namespace TriInspector.Elements -{ - public abstract class TriPropertyCollectionBaseElement : TriElement - { - private List _declarations = new List(); - - private Dictionary _groups; - - internal void ClearGroups() - { - _declarations.Clear(); - } - - [PublicAPI] - public void DeclareGroups([CanBeNull] Type type) - { - if (type == null) - { - return; - } - - foreach (var attribute in TriReflectionUtilities.GetAttributesCached(type)) - { - if (attribute is DeclareGroupBaseAttribute declareAttribute) - { - _declarations.Add(declareAttribute); - } - } - } - - [PublicAPI] - public void AddProperty(TriProperty property) - { - AddProperty(property, default, out _); - } - - [PublicAPI] - public void AddProperty(TriProperty property, TriPropertyElement.Props props, out string group) - { - var propertyElement = new TriPropertyElement(property, props); - - if (property.TryGetAttribute(out GroupAttribute groupAttribute)) - { - IEnumerable path = groupAttribute.Path.Split('/'); - - var remaining = path.GetEnumerator(); - if (remaining.MoveNext()) - { - group = remaining.Current; - AddGroupedChild(propertyElement, property, remaining.Current, remaining.Current, remaining); - } - else - { - group = null; - AddPropertyChild(propertyElement, property); - } - } - else - { - group = null; - AddPropertyChild(propertyElement, property); - } - } - - private void AddGroupedChild(TriElement child, TriProperty property, string currentPath, string currentName, - IEnumerator remainingPath) - { - if (_groups == null) - { - _groups = new Dictionary(); - } - - var groupElement = CreateSubGroup(property, currentPath, currentName); - - if (remainingPath.MoveNext()) - { - var nextPath = currentPath + "/" + remainingPath.Current; - var nextName = remainingPath.Current; - - groupElement.AddGroupedChild(child, property, nextPath, nextName, remainingPath); - } - else - { - groupElement.AddPropertyChild(child, property); - } - } - - private TriPropertyCollectionBaseElement CreateSubGroup(TriProperty property, - string groupPath, string groupName) - { - if (!_groups.TryGetValue(groupName, out var groupElement)) - { - var declaration = _declarations.FirstOrDefault(it => it.Path == groupPath); - - if (declaration != null) - { - groupElement = TriDrawersUtilities.TryCreateGroupElementFor(declaration); - } - - if (groupElement == null) - { - groupElement = new DefaultGroupElement(); - } - - groupElement._declarations = _declarations; - - _groups.Add(groupName, groupElement); - - AddPropertyChild(groupElement, property); - } - else - { - bool found = false; - for (var i = 0; i < ChildrenCount; ++i) - { - if (GetChild(i) == groupElement) - { - found = true; - break; - } - } - if (!found) - { - groupElement.RemoveAllChildren(); - AddPropertyChild(groupElement, property); - } - } - return groupElement; - } - - protected virtual void AddPropertyChild(TriElement element, TriProperty property) - { - AddChild(element); - } - - private class DefaultGroupElement : TriPropertyCollectionBaseElement - { - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriPropertyCollectionBaseElement.cs.meta b/Editor/Elements/TriPropertyCollectionBaseElement.cs.meta deleted file mode 100644 index f9f02d33..00000000 --- a/Editor/Elements/TriPropertyCollectionBaseElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 1373b681c88a425c943ea5e6d149a217 -timeCreated: 1639412705 \ No newline at end of file diff --git a/Editor/Elements/TriPropertyElement.cs b/Editor/Elements/TriPropertyElement.cs deleted file mode 100644 index 7cb33c1f..00000000 --- a/Editor/Elements/TriPropertyElement.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System; -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - public class TriPropertyElement : TriElement - { - private readonly TriProperty _property; - - [Serializable] - public struct Props - { - public bool forceInline; - } - - public TriPropertyElement(TriProperty property, Props props = default) - { - _property = property; - - foreach (var error in _property.ExtensionErrors) - { - AddChild(new TriInfoBoxElement(error, TriMessageType.Error)); - } - - var element = CreateElement(property, props); - - var drawers = property.AllDrawers; - for (var index = drawers.Count - 1; index >= 0; index--) - { - element = drawers[index].CreateElementInternal(property, element); - } - - AddChild(element); - } - - public override float GetHeight(float width) - { - if (!_property.IsVisible) - { - return -EditorGUIUtility.standardVerticalSpacing; - } - - return base.GetHeight(width); - } - - public override void OnGUI(Rect position) - { - if (!_property.IsVisible) - { - return; - } - - var oldShowMixedValue = EditorGUI.showMixedValue; - var oldEnabled = GUI.enabled; - - GUI.enabled &= _property.IsEnabled; - EditorGUI.showMixedValue = _property.IsValueMixed; - var overrideCtx = TriPropertyOverrideContext.BeginProperty(); - - if (_property.TryGetSerializedProperty(out var serializedProperty)) - { - EditorGUI.BeginProperty(position, null, serializedProperty); - } - - base.OnGUI(position); - - if (_property.TryGetSerializedProperty(out _)) - { - EditorGUI.EndProperty(); - } - - overrideCtx.EndProperty(); - EditorGUI.showMixedValue = oldShowMixedValue; - GUI.enabled = oldEnabled; - } - - private static TriElement CreateElement(TriProperty property, Props props) - { - switch (property.PropertyType) - { - case TriPropertyType.Array: - { - return CreateArrayElement(property); - } - - case TriPropertyType.Reference: - { - return CreateReferenceElement(property, props); - } - - case TriPropertyType.Generic: - { - return CreateGenericElement(property, props); - } - - default: - { - return new TriNoDrawerElement(property); - } - } - } - - private static TriElement CreateArrayElement(TriProperty property) - { - return new TriListElement(property); - } - - private static TriElement CreateReferenceElement(TriProperty property, Props props) - { - if (property.TryGetAttribute(out InlinePropertyAttribute inlineAttribute)) - { - return new TriReferenceElement(property, new TriReferenceElement.Props - { - inline = true, - drawPrefixLabel = !props.forceInline, - labelWidth = inlineAttribute.LabelWidth, - }); - } - - if (props.forceInline) - { - return new TriReferenceElement(property, new TriReferenceElement.Props - { - inline = true, - drawPrefixLabel = false, - }); - } - - return new TriReferenceElement(property, new TriReferenceElement.Props - { - inline = false, - drawPrefixLabel = false, - }); - } - - private static TriElement CreateGenericElement(TriProperty property, Props props) - { - if (property.TryGetAttribute(out InlinePropertyAttribute inlineAttribute)) - { - return new TriInlineGenericElement(property, new TriInlineGenericElement.Props - { - drawPrefixLabel = !props.forceInline, - labelWidth = inlineAttribute.LabelWidth, - }); - } - - if (props.forceInline) - { - return new TriInlineGenericElement(property, new TriInlineGenericElement.Props - { - drawPrefixLabel = false, - }); - } - - return new TriFoldoutElement(property); - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriPropertyElement.cs.meta b/Editor/Elements/TriPropertyElement.cs.meta deleted file mode 100644 index 44bfd980..00000000 --- a/Editor/Elements/TriPropertyElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: f57a61ef6fe34b51939950c6b9597f88 -timeCreated: 1638776439 \ No newline at end of file diff --git a/Editor/Elements/TriReferenceElement.cs b/Editor/Elements/TriReferenceElement.cs deleted file mode 100644 index 7ae29b62..00000000 --- a/Editor/Elements/TriReferenceElement.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System; -using TriInspector.Utilities; -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - internal class TriReferenceElement : TriPropertyCollectionBaseElement - { - private readonly Props _props; - private readonly TriProperty _property; - private readonly bool _showReferencePicker; - private readonly bool _skipReferencePickerExtraLine; - - private Type _referenceType; - - [Serializable] - public struct Props - { - public bool inline; - public bool drawPrefixLabel; - public float labelWidth; - } - - public TriReferenceElement(TriProperty property, Props props = default) - { - _property = property; - _props = props; - _showReferencePicker = !property.TryGetAttribute(out HideReferencePickerAttribute _); - _skipReferencePickerExtraLine = !_showReferencePicker && _props.inline; - } - - public override bool Update() - { - var dirty = false; - - if (_props.inline || _property.IsExpanded) - { - dirty |= GenerateChildren(); - } - else - { - dirty |= ClearChildren(); - } - - dirty |= base.Update(); - - return dirty; - } - - public override float GetHeight(float width) - { - var height = _skipReferencePickerExtraLine ? 0f : EditorGUIUtility.singleLineHeight; - - if (_props.inline || _property.IsExpanded) - { - height += base.GetHeight(width); - } - - return height; - } - - public override void OnGUI(Rect position) - { - if (_props.drawPrefixLabel) - { - var controlId = GUIUtility.GetControlID(FocusType.Passive); - position = EditorGUI.PrefixLabel(position, controlId, _property.DisplayNameContent); - } - - var headerRect = new Rect(position) - { - height = _skipReferencePickerExtraLine ? 0f : EditorGUIUtility.singleLineHeight, - }; - var headerLabelRect = new Rect(position) - { - height = headerRect.height, - width = EditorGUIUtility.labelWidth, - }; - var headerFieldRect = new Rect(position) - { - height = headerRect.height, - xMin = headerRect.xMin + EditorGUIUtility.labelWidth, - }; - var contentRect = new Rect(position) - { - yMin = position.yMin + headerRect.height, - }; - - if (_props.inline) - { - if (_showReferencePicker) - { - TriManagedReferenceGui.DrawTypeSelector(headerRect, _property); - } - - using (TriGuiHelper.PushLabelWidth(_props.labelWidth)) - { - base.OnGUI(contentRect); - } - } - else - { - TriEditorGUI.Foldout(headerLabelRect, _property); - - if (_showReferencePicker) - { - TriManagedReferenceGui.DrawTypeSelector(headerFieldRect, _property); - } - - if (_property.IsExpanded) - { - using (var indentedRectScope = TriGuiHelper.PushIndentedRect(contentRect, 1)) - using (TriGuiHelper.PushLabelWidth(_props.labelWidth)) - { - base.OnGUI(indentedRectScope.IndentedRect); - } - } - } - } - - private bool GenerateChildren() - { - if (_property.ValueType == _referenceType) - { - return false; - } - - _referenceType = _property.ValueType; - - RemoveAllChildren(); - - ClearGroups(); - DeclareGroups(_property.ValueType); - - foreach (var childProperty in _property.ChildrenProperties) - { - AddProperty(childProperty); - } - - return true; - } - - private bool ClearChildren() - { - if (ChildrenCount == 0) - { - return false; - } - - _referenceType = null; - RemoveAllChildren(); - - return true; - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriReferenceElement.cs.meta b/Editor/Elements/TriReferenceElement.cs.meta deleted file mode 100644 index e8c6ae8e..00000000 --- a/Editor/Elements/TriReferenceElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 7dd13898e07a45afacca03cc86c0e24c -timeCreated: 1638789498 \ No newline at end of file diff --git a/Editor/Elements/TriTabGroupElement.cs b/Editor/Elements/TriTabGroupElement.cs deleted file mode 100644 index 1492bb60..00000000 --- a/Editor/Elements/TriTabGroupElement.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using TriInspector.Resolvers; -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Elements -{ - public class TriTabGroupElement : TriHeaderGroupBaseElement - { - private const string DefaultTabName = "Main"; - - private readonly List _tabs; - private readonly Dictionary _tabElements; - private string _activeTabNameKey; - private string _activeTabName; - private Dictionary _rowToInfo; - private int[] _rowCounts; - - private struct TabInfo - { - public string name; - public int row; - public ValueResolver titleResolver; - public TriProperty property; - } - - public TriTabGroupElement() - { - _tabs = new List(); - _tabElements = new Dictionary(); - _activeTabName = null; - } - - protected override void DrawHeader(Rect position) - { - if (_tabs.Count == 0) - { - return; - } - - if (_tabs.Count == 1) - { - var tab = _tabs[0]; - var content = tab.titleResolver.GetValue(tab.property); - GUI.Toggle(position, true, content, TriEditorStyles.TabOnlyOne); - } - else - { - if (_rowToInfo == null) - { - _rowToInfo = _tabs - .GroupBy(t => t.row) - .OrderBy(g => g.Key) - .Select((g, index) => ( - row: g.Key, - realRow: index, - rowCount: g.Count() - )) - .ToDictionary( - x => x.row, - x => (x.realRow, x.rowCount) - ); - _rowCounts = new int[_rowToInfo.Count]; - foreach (var (_, (realRow, count)) in _rowToInfo) - _rowCounts[realRow] = count; - } - - Span tab_rects = stackalloc Rect[_rowToInfo.Count]; - for (int i = 0; i < tab_rects.Length; i++) - { - tab_rects[i] = new Rect( - position.x, - position.y + base.GetHeaderHeight(0) * i, - position.width / _rowCounts[i], - base.GetHeaderHeight(0) - ); - } - - for (int index = 0, tabCount = _tabs.Count; index < tabCount; index++) - { - var tab = _tabs[index]; - var (realRow, rowCount) = _rowToInfo[tab.row]; - var content = tab.titleResolver.GetValue(tab.property); - var tabStyle = index == 0 ? TriEditorStyles.TabFirst - : index == rowCount - 1 ? TriEditorStyles.TabLast - : TriEditorStyles.TabMiddle; - - var isTabActive = GUI.Toggle(tab_rects[realRow], _activeTabName == tab.name, content, tabStyle); - if (isTabActive && _activeTabName != tab.name) - { - SetActiveTab(tab.name); - } - - tab_rects[realRow].x += tab_rects[realRow].width; - } - } - } - - protected override float GetHeaderHeight(float width) - { - return base.GetHeaderHeight(width) * _rowToInfo?.Count ?? 1; - } - - protected override void AddPropertyChild(TriElement element, TriProperty property) - { - var tabName = DefaultTabName; - - if (property.TryGetAttribute(out TabAttribute tab)) - { - tabName = tab.TabName ?? tabName; - } - - if (!_tabElements.TryGetValue(tabName, out var tabElement)) - { - tabElement = new TriElement(); - - var info = new TabInfo - { - name = tabName, - row = tab.Row, - titleResolver = ValueResolver.ResolveString(property.Definition, tabName), - property = property, - }; - - _tabElements[tabName] = tabElement; - _tabs.Add(info); - - if (info.titleResolver.TryGetErrorString(out var error)) - { - tabElement.AddChild(new TriInfoBoxElement(error, TriMessageType.Error)); - } - - if (_activeTabNameKey == null && info.property.TryGetAttribute(out GroupAttribute groupAttribute)) - { - _activeTabNameKey = $"TriInspector.tab_grouop.{info.property.PropertyTree.TargetObjectType}.{groupAttribute.Path}.active"; - _activeTabName = SessionState.GetString(_activeTabNameKey, null); - } - if (string.IsNullOrEmpty(_activeTabName) || _activeTabName == tabName) - { - SetActiveTab(tabName); - } - } - - tabElement.AddChild(element); - } - - private void SetActiveTab(string tabName) - { - _activeTabName = tabName; - if (_activeTabNameKey != null) - SessionState.SetString(_activeTabNameKey, tabName); - - RemoveAllChildren(); - - AddChild(_tabElements[_activeTabName]); - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriTabGroupElement.cs.meta b/Editor/Elements/TriTabGroupElement.cs.meta deleted file mode 100644 index f62a3150..00000000 --- a/Editor/Elements/TriTabGroupElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: deb5a57d2d0a4476a3e396a49b9f44da -timeCreated: 1642759023 \ No newline at end of file diff --git a/Editor/Elements/TriUiToolkitPropertyElemenet.cs b/Editor/Elements/TriUiToolkitPropertyElemenet.cs deleted file mode 100644 index 8499415a..00000000 --- a/Editor/Elements/TriUiToolkitPropertyElemenet.cs +++ /dev/null @@ -1,91 +0,0 @@ -using TriInspectorUnityInternalBridge; -using UnityEditor; -using UnityEditor.UIElements; -using UnityEngine; -using UnityEngine.UIElements; - -namespace TriInspector.Elements -{ - internal class TriUiToolkitPropertyElement : TriElement - { - private readonly SerializedProperty _serializedProperty; - - private readonly VisualElement _rootElement; - private readonly VisualElement _selfElement; - - private bool _heightDirty; - - public TriUiToolkitPropertyElement( - TriProperty property, - SerializedProperty serializedProperty, - VisualElement selfElement, - VisualElement rootElement) - { - _serializedProperty = serializedProperty; - _selfElement = selfElement; - _rootElement = rootElement; - - _selfElement.style.position = Position.Absolute; - } - - protected override void OnAttachToPanel() - { - base.OnAttachToPanel(); - - _rootElement.schedule.Execute(() => - { - _rootElement.Add(_selfElement); - _selfElement.Bind(_serializedProperty.serializedObject); - }); - } - - protected override void OnDetachFromPanel() - { - _rootElement.schedule.Execute(() => - { - _selfElement.Unbind(); - _rootElement.Remove(_selfElement); - }); - - base.OnDetachFromPanel(); - } - - public override bool Update() - { - var dirty = base.Update(); - - if (_heightDirty) - { - _heightDirty = false; - dirty = true; - } - - return dirty; - } - - public override float GetHeight(float width) - { - var height = _selfElement.resolvedStyle.height; - - if (float.IsNaN(height)) - { - _heightDirty = true; - return 0f; - } - - return height; - } - - public override void OnGUI(Rect position) - { - if (Event.current.type == EventType.Repaint) - { - var pos = GUIClipProxy.UnClip(position.position); - - _selfElement.style.width = position.width; - _selfElement.style.left = pos.x; - _selfElement.style.top = pos.y; - } - } - } -} \ No newline at end of file diff --git a/Editor/Elements/TriUiToolkitPropertyElemenet.cs.meta b/Editor/Elements/TriUiToolkitPropertyElemenet.cs.meta deleted file mode 100644 index a43f1c8a..00000000 --- a/Editor/Elements/TriUiToolkitPropertyElemenet.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 535ce5f65f424a8c9e83943eda845fc6 -timeCreated: 1690621289 \ No newline at end of file diff --git a/Editor/Elements/TriVerticalGroupElement.cs b/Editor/Elements/TriVerticalGroupElement.cs deleted file mode 100644 index adc12527..00000000 --- a/Editor/Elements/TriVerticalGroupElement.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace TriInspector.Elements -{ - public class TriVerticalGroupElement : TriPropertyCollectionBaseElement - { - } -} \ No newline at end of file diff --git a/Editor/Elements/TriVerticalGroupElement.cs.meta b/Editor/Elements/TriVerticalGroupElement.cs.meta deleted file mode 100644 index 2ec8f8b9..00000000 --- a/Editor/Elements/TriVerticalGroupElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: ec0e2c38af6f4830b3eca87e63c3248c -timeCreated: 1643558785 \ No newline at end of file diff --git a/Editor/Resources.meta b/Editor/Resources.meta deleted file mode 100644 index 6ae5eb56..00000000 --- a/Editor/Resources.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: d8d4d0876dcc071428509b59e2f78e29 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Editor/Resources/TriInspector_Box_Bg.png b/Editor/Resources/TriInspector_Box_Bg.png deleted file mode 100644 index 18745960..00000000 Binary files a/Editor/Resources/TriInspector_Box_Bg.png and /dev/null differ diff --git a/Editor/Resources/TriInspector_Box_Bg.png.meta b/Editor/Resources/TriInspector_Box_Bg.png.meta deleted file mode 100644 index 1dc183c4..00000000 --- a/Editor/Resources/TriInspector_Box_Bg.png.meta +++ /dev/null @@ -1,108 +0,0 @@ -fileFormatVersion: 2 -guid: 7a524300faaf5aa40a2ff59c25b28b71 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 11 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 0 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 0 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: 3 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: 3 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - spritePackingTag: - pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Editor/Resources/TriInspector_Box_Bg_Dark.png b/Editor/Resources/TriInspector_Box_Bg_Dark.png deleted file mode 100644 index 618cbcb3..00000000 Binary files a/Editor/Resources/TriInspector_Box_Bg_Dark.png and /dev/null differ diff --git a/Editor/Resources/TriInspector_Box_Bg_Dark.png.meta b/Editor/Resources/TriInspector_Box_Bg_Dark.png.meta deleted file mode 100644 index 81688800..00000000 --- a/Editor/Resources/TriInspector_Box_Bg_Dark.png.meta +++ /dev/null @@ -1,108 +0,0 @@ -fileFormatVersion: 2 -guid: 6c3f6c6cd431e8e4e87094572f59d524 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 11 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 0 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 0 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: 3 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: 3 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - spritePackingTag: - pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Editor/Resources/TriInspector_Content_Bg.png b/Editor/Resources/TriInspector_Content_Bg.png deleted file mode 100644 index 8c56155c..00000000 Binary files a/Editor/Resources/TriInspector_Content_Bg.png and /dev/null differ diff --git a/Editor/Resources/TriInspector_Content_Bg.png.meta b/Editor/Resources/TriInspector_Content_Bg.png.meta deleted file mode 100644 index 2802077e..00000000 --- a/Editor/Resources/TriInspector_Content_Bg.png.meta +++ /dev/null @@ -1,108 +0,0 @@ -fileFormatVersion: 2 -guid: 372e4831c9374244aafdd096c36bb645 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 11 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 0 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 0 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: 3 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: 3 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - spritePackingTag: - pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Editor/Resources/TriInspector_Content_Bg_Dark.png b/Editor/Resources/TriInspector_Content_Bg_Dark.png deleted file mode 100644 index 5436eec8..00000000 Binary files a/Editor/Resources/TriInspector_Content_Bg_Dark.png and /dev/null differ diff --git a/Editor/Resources/TriInspector_Content_Bg_Dark.png.meta b/Editor/Resources/TriInspector_Content_Bg_Dark.png.meta deleted file mode 100644 index 333176fb..00000000 --- a/Editor/Resources/TriInspector_Content_Bg_Dark.png.meta +++ /dev/null @@ -1,108 +0,0 @@ -fileFormatVersion: 2 -guid: d73be6aba60ae5b41887b4116facc353 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 11 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 0 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 0 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: 3 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: 3 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - spritePackingTag: - pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Editor/TriAttributeDrawer.cs b/Editor/TriAttributeDrawer.cs index e4afcefd..7792418a 100644 --- a/Editor/TriAttributeDrawer.cs +++ b/Editor/TriAttributeDrawer.cs @@ -1,6 +1,5 @@ using System; using JetBrains.Annotations; -using UnityEngine; namespace TriInspector { @@ -14,55 +13,5 @@ public abstract class TriAttributeDrawer : TriAttributeDrawer { [PublicAPI] public TAttribute Attribute => (TAttribute) RawAttribute; - - public sealed override TriElement CreateElementInternal(TriProperty property, TriElement next) - { - return CreateElement(property, next); - } - - [PublicAPI] - public virtual TriElement CreateElement(TriProperty property, TriElement next) - { - return new DefaultAttributeDrawerElement(this, property, next); - } - - [PublicAPI] - public virtual float GetHeight(float width, TriProperty property, TriElement next) - { - return next.GetHeight(width); - } - - [PublicAPI] - public virtual void OnGUI(Rect position, TriProperty property, TriElement next) - { - next.OnGUI(position); - } - - internal class DefaultAttributeDrawerElement : TriElement - { - private readonly TriAttributeDrawer _drawer; - private readonly TriElement _next; - private readonly TriProperty _property; - - public DefaultAttributeDrawerElement(TriAttributeDrawer drawer, TriProperty property, - TriElement next) - { - _drawer = drawer; - _property = property; - _next = next; - - AddChild(next); - } - - public override float GetHeight(float width) - { - return _drawer.GetHeight(width, _property, _next); - } - - public override void OnGUI(Rect position) - { - _drawer.OnGUI(position, _property, _next); - } - } } } \ No newline at end of file diff --git a/Editor/TriCustomDrawer.cs b/Editor/TriCustomDrawer.cs index 910bea5b..03cb29ec 100644 --- a/Editor/TriCustomDrawer.cs +++ b/Editor/TriCustomDrawer.cs @@ -1,9 +1,14 @@ -namespace TriInspector +using UnityEngine.UIElements; + +namespace TriInspector { public abstract class TriCustomDrawer : TriPropertyExtension { internal int Order { get; set; } - public abstract TriElement CreateElementInternal(TriProperty property, TriElement next); + public virtual VisualElement CreateVisualElement(TriProperty property, VisualElement next) + { + return null; + } } } \ No newline at end of file diff --git a/Editor/TriEditorStyles.cs b/Editor/TriEditorStyles.cs deleted file mode 100644 index 471f6b45..00000000 --- a/Editor/TriEditorStyles.cs +++ /dev/null @@ -1,92 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace TriInspector -{ - public static class TriEditorStyles - { - private static GUIStyle _contentBox; - private static GUIStyle _box; - - public static GUIStyle TabOnlyOne { get; } = "Tab onlyOne"; - public static GUIStyle TabFirst { get; } = "Tab first"; - public static GUIStyle TabMiddle { get; } = "Tab middle"; - public static GUIStyle TabLast { get; } = "Tab last"; - - private static GUIStyle FallbackContentBox { get; } = "HelpBox"; - private static GUIStyle FallbackBox { get; } = "HelpBox"; - - public static GUIStyle ContentBox - { - get - { - if (_contentBox == null) - { - var backgroundTexture = LoadTexture("TriInspector_Content_Bg"); - - if (backgroundTexture == null) - { - _contentBox = new GUIStyle(FallbackContentBox); - } - else - { - _contentBox = new GUIStyle - { - normal = - { - background = backgroundTexture, - }, - }; - } - - _contentBox.border = new RectOffset(2, 2, 2, 2); - } - - return _contentBox; - } - } - - public static GUIStyle Box - { - get - { - if (_box == null) - { - var backgroundTexture = LoadTexture("TriInspector_Box_Bg"); - - if (backgroundTexture == null) - { - _box = new GUIStyle(FallbackBox); - } - else - { - _box = new GUIStyle - { - normal = - { - background = backgroundTexture, - }, - }; - } - - _box.border = new RectOffset(2, 2, 2, 2); - } - - return _box; - } - } - - private static Texture2D LoadTexture(string name) - { - name = EditorGUIUtility.isProSkin ? $"{name}_Dark" : name; - - var results = AssetDatabase.FindAssets($"{name} t:texture2D"); - - if (results.Length == 0) return null; - - var path = AssetDatabase.GUIDToAssetPath(results[0]); - - return (Texture2D) EditorGUIUtility.Load(path); - } - } -} \ No newline at end of file diff --git a/Editor/TriEditorStyles.cs.meta b/Editor/TriEditorStyles.cs.meta deleted file mode 100644 index 73b75fed..00000000 --- a/Editor/TriEditorStyles.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 6f23eb6fd2f644a0a718543287192636 -timeCreated: 1639462144 \ No newline at end of file diff --git a/Editor/TriElement.cs b/Editor/TriElement.cs deleted file mode 100644 index 2034e6f1..00000000 --- a/Editor/TriElement.cs +++ /dev/null @@ -1,215 +0,0 @@ -using System.Collections.Generic; -using JetBrains.Annotations; -using UnityEditor; -using UnityEngine; - -namespace TriInspector -{ - public class TriElement - { - private static readonly List Empty = new List(); - - private float _cachedHeight; - private bool _cachedheightDirty; - private bool _attached; - private List _children = Empty; - - [PublicAPI] - public int ChildrenCount => _children.Count; - - public bool IsAttached => _attached; - - internal float CachedHeight => _cachedHeight; - - [PublicAPI] - public virtual bool Update() - { - if (!_attached) - { - Debug.LogError($"{GetType().Name} not attached"); - } - - var dirty = false; - - foreach (var child in _children) - { - dirty |= child.Update(); - } - - return dirty; - } - - [PublicAPI] - public virtual float GetHeight(float width) - { - if (!_attached) - { - Debug.LogError($"{GetType().Name} not attached"); - } - - if (Event.current.type != EventType.Layout && !_cachedheightDirty) - { - return _cachedHeight; - } - - _cachedheightDirty = false; - - switch (_children.Count) - { - case 0: - return _cachedHeight = 0f; - - case 1: - return _cachedHeight = _children[0].GetHeight(width); - - default: - { - _cachedHeight = (_children.Count - 1) * EditorGUIUtility.standardVerticalSpacing; - - foreach (var child in _children) - { - _cachedHeight += child.GetHeight(width); - } - - return _cachedHeight; - } - } - } - - [PublicAPI] - public virtual void OnGUI(Rect position) - { - if (!_attached) - { - Debug.LogError($"{GetType().Name} not attached"); - } - - switch (_children.Count) - { - case 0: - break; - - case 1: - _children[0].OnGUI(position); - break; - - default: - { - var offset = 0f; - var spacing = EditorGUIUtility.standardVerticalSpacing; - - foreach (var child in _children) - { - var childHeight = child.GetHeight(position.width); - - child.OnGUI(new Rect(position.x, position.y + offset, position.width, childHeight)); - - offset += childHeight + spacing; - } - - break; - } - } - } - - [PublicAPI] - public TriElement GetChild(int index) - { - return _children[index]; - } - - [PublicAPI] - public void RemoveChildAt(int index) - { - if (_children.Count < index) - { - return; - } - - var child = _children[index]; - _children.RemoveAt(index); - _cachedheightDirty = true; - - if (_attached) - { - child.DetachInternal(); - } - } - - [PublicAPI] - public void RemoveAllChildren() - { - if (_attached) - { - foreach (var child in _children) - { - child.DetachInternal(); - } - } - - _children.Clear(); - _cachedheightDirty = true; - } - - [PublicAPI] - public void AddChild(TriElement child) - { - if (_children == Empty) - { - _children = new List(); - } - - _children.Add(child); - _cachedheightDirty = true; - - if (_attached) - { - child.AttachInternal(); - child.Update(); - } - } - - internal void AttachInternal() - { - if (_attached) - { - Debug.LogError($"{GetType().Name} already attached"); - } - - _attached = true; - - OnAttachToPanel(); - - foreach (var child in _children) - { - child.AttachInternal(); - child.Update(); - } - } - - internal void DetachInternal() - { - if (!_attached) - { - Debug.LogError($"{GetType().Name} not attached"); - } - - _attached = false; - - foreach (var child in _children) - { - child.DetachInternal(); - } - - OnDetachFromPanel(); - } - - protected virtual void OnAttachToPanel() - { - } - - protected virtual void OnDetachFromPanel() - { - } - } -} \ No newline at end of file diff --git a/Editor/TriElement.cs.meta b/Editor/TriElement.cs.meta deleted file mode 100644 index 92d39140..00000000 --- a/Editor/TriElement.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 543813bc0e9e4045904a35ef56ea6abe -timeCreated: 1638771508 \ No newline at end of file diff --git a/Editor/TriGroupDrawer.cs b/Editor/TriGroupDrawer.cs index dc87a4d5..ded2caca 100644 --- a/Editor/TriGroupDrawer.cs +++ b/Editor/TriGroupDrawer.cs @@ -1,23 +1,28 @@ using System; using JetBrains.Annotations; -using TriInspector.Elements; +using TriInspector.VisualElements; namespace TriInspector { public abstract class TriGroupDrawer { - public abstract TriPropertyCollectionBaseElement CreateElementInternal(Attribute attribute); + public virtual TriPropertyCollectionVisualElement CreateVisualElementInternal(Attribute attribute) + { + return null; + } } public abstract class TriGroupDrawer : TriGroupDrawer where TAttribute : Attribute { - public sealed override TriPropertyCollectionBaseElement CreateElementInternal(Attribute attribute) + public sealed override TriPropertyCollectionVisualElement CreateVisualElementInternal(Attribute attribute) { - return CreateElement((TAttribute) attribute); + return CreateVisualElement((TAttribute) attribute); } - [PublicAPI] - public abstract TriPropertyCollectionBaseElement CreateElement(TAttribute attribute); + public virtual TriPropertyCollectionVisualElement CreateVisualElement(TAttribute attribute) + { + return null; + } } } \ No newline at end of file diff --git a/Editor/TriProperty.cs b/Editor/TriProperty.cs index 4c3f1413..5b9e8813 100644 --- a/Editor/TriProperty.cs +++ b/Editor/TriProperty.cs @@ -29,12 +29,13 @@ public sealed class TriProperty private string _propertyPath; private string _isExpandedPrefsKey; - private int _lastUpdateFrame; + private int _lastUpdateFrame = -1; private bool _isUpdating; [CanBeNull] private object _value; [CanBeNull] private Type _valueType; private bool _isValueMixed; + private int _arrayHash; public event Action ValueChanged; public event Action ChildValueChanged; @@ -103,8 +104,7 @@ public GUIContent DisplayNameContent { get { - if (TriPropertyOverrideContext.Current != null && - TriPropertyOverrideContext.Current.TryGetDisplayName(this, out var overrideName)) + if (PropertyTree.TryGetOverrideDisplayName(this, out var overrideName)) { return overrideName; } @@ -377,15 +377,16 @@ public void ModifyAndRecordForUndo(Action call) PropertyTree.Update(forceUpdate: true); - NotifyValueChanged(); - + UpdateIfRequired(forceUpdate: true); PropertyTree.RequestValidation(); - PropertyTree.RequestRepaint(); } - public void NotifyValueChanged() + // Re-reads the value and fires ValueChanged if it actually changed. Use this when the value + // may have been mutated outside of TriProperty.SetValue (e.g. by a bound native field or a + // script), so the change is detected once rather than announced blindly. + public void RefreshValue() { - NotifyValueChanged(this); + UpdateIfRequired(forceUpdate: true); } private void NotifyValueChanged(TriProperty property) @@ -416,8 +417,11 @@ private void UpdateIfRequired(bool forceUpdate = false) _isUpdating = true; + var valueChanged = false; + try { + var isFirstUpdate = _lastUpdateFrame < 0; _lastUpdateFrame = PropertyTree.RepaintFrame; ReadValue(this, out var newValue, out var newValueIsMixed); @@ -427,6 +431,23 @@ private void UpdateIfRequired(bool forceUpdate = false) : newValue?.GetType(); var valueTypeChanged = _valueType != newValueType; + bool contentChanged; + if (PropertyType == TriPropertyType.Array) + { + // Arrays are mutated in place, so the cached reference would be compared against + // itself. Snapshot an order-sensitive hash of the element hashes instead, which + // detects add/remove/reorder as well as element value changes. + var newArrayHash = ComputeArrayHash(newValue as IList); + contentChanged = newArrayHash != _arrayHash; + _arrayHash = newArrayHash; + } + else + { + contentChanged = valueTypeChanged || !ValuesEqual(_value, newValue, newValueType); + } + + valueChanged = !isFirstUpdate && (contentChanged || _isValueMixed != newValueIsMixed); + _value = newValue; _valueType = newValueType; _isValueMixed = newValueIsMixed; @@ -496,6 +517,48 @@ private void UpdateIfRequired(bool forceUpdate = false) { _isUpdating = false; } + + // Value may change outside of TriInspector (e.g. from a script or Undo), and internal + // edits route through here too. Notify listeners and re-run validation reactively. + if (valueChanged) + { + PropertyTree.RequestValidation(); + NotifyValueChanged(this); + } + } + + private static bool ValuesEqual(object a, object b, Type valueType) + { + if (ReferenceEquals(a, b)) + { + return true; + } + + if (a == null || b == null || valueType == null) + { + return false; + } + + return TriEqualityComparer.Of(valueType).Equals(a, b); + } + + private int ComputeArrayHash(IList list) + { + if (list == null) + { + return 0; + } + + var comparer = TriEqualityComparer.Of(ArrayElementType); + + var hash = list.Count; + foreach (var element in list) + { + var elementHash = element != null ? comparer.GetHashCode(element) : 0; + hash = unchecked(hash * 31 + elementHash); + } + + return hash; } internal void RunValidation() diff --git a/Editor/TriPropertyOverrideContext.cs b/Editor/TriPropertyOverrideContext.cs index 5aad6f63..83e6806d 100644 --- a/Editor/TriPropertyOverrideContext.cs +++ b/Editor/TriPropertyOverrideContext.cs @@ -1,60 +1,9 @@ -using System; using UnityEngine; namespace TriInspector { public abstract class TriPropertyOverrideContext { - private static TriPropertyOverrideContext Override { get; set; } - public static TriPropertyOverrideContext Current { get; private set; } - public abstract bool TryGetDisplayName(TriProperty property, out GUIContent displayName); - - public static EnterPropertyScope BeginProperty() - { - return new EnterPropertyScope().Init(); - } - - public static OverrideScope BeginOverride(TriPropertyOverrideContext overrideContext) - { - return new OverrideScope(overrideContext); - } - - public struct EnterPropertyScope - { - private TriPropertyOverrideContext _previousContext; - - public EnterPropertyScope Init() - { - _previousContext = Current; - Current = Override; - Override = null; - return this; - } - - public void EndProperty() - { - Override = Current; - Current = _previousContext; - } - } - - public readonly struct OverrideScope : IDisposable - { - public OverrideScope(TriPropertyOverrideContext context) - { - if (Override != null) - { - Debug.LogError($"TriPropertyContext already overriden with {Override.GetType()}"); - } - - Override = context; - } - - public void Dispose() - { - Override = null; - } - } } -} \ No newline at end of file +} diff --git a/Editor/TriPropertyTree.cs b/Editor/TriPropertyTree.cs index 5763e9cd..7fa66f51 100644 --- a/Editor/TriPropertyTree.cs +++ b/Editor/TriPropertyTree.cs @@ -1,15 +1,19 @@ using System; -using TriInspector.Elements; +using System.Collections.Generic; +using TriInspector.VisualElements; using UnityEditor; using UnityEngine; using UnityEngine.Profiling; +using UnityEngine.UIElements; namespace TriInspector { public abstract class TriPropertyTree : IDisposable { - private TriPropertyElement _rootPropertyElement; - private Rect _cachedOuterRect = new Rect(0, 0, 0, 0); + private readonly List _propertyOverrides = + new List(); + + private TriPropertyVisualElement _rootPropertyElement; public TriPropertyDefinition RootPropertyDefinition { get; protected set; } public TriProperty RootProperty { get; protected set; } @@ -19,16 +23,11 @@ public abstract class TriPropertyTree : IDisposable public bool TargetIsPersistent { get; protected set; } public bool ValidationRequired { get; private set; } = true; - public bool RepaintRequired { get; private set; } = true; public int RepaintFrame { get; private set; } = 0; public virtual void Dispose() { - if (_rootPropertyElement != null && _rootPropertyElement.IsAttached) - { - _rootPropertyElement.DetachInternal(); - } } public virtual void Update(bool forceUpdate = false) @@ -62,40 +61,20 @@ public void RunValidation() RequestRepaint(); } - public virtual void Draw() + public VisualElement GetRootElement() { - RepaintRequired = false; - if (_rootPropertyElement == null) { - _rootPropertyElement = new TriPropertyElement(RootProperty, new TriPropertyElement.Props + _rootPropertyElement = new TriPropertyVisualElement(RootProperty, new TriPropertyVisualElement.Props { forceInline = !RootProperty.TryGetMemberInfo(out _), }); - _rootPropertyElement.AttachInternal(); + + TriStyleSheet.ApplyTo(_rootPropertyElement); + _rootPropertyElement.AddToClassList(EditorGUIUtility.isProSkin ? "tri-dark" : "tri-light"); } - Profiler.BeginSample("TriInspector.UpdateRootPropertyElement"); - _rootPropertyElement.Update(); - Profiler.EndSample(); - - var rectOuter = GUILayoutUtility.GetRect(0, 9999, 0, 0); - _cachedOuterRect = Event.current.type == EventType.Layout ? _cachedOuterRect : rectOuter; - - var rect = new Rect(_cachedOuterRect); - rect = EditorGUI.IndentedRect(rect); - rect.height = _rootPropertyElement.GetHeight(rect.width); - - var oldIndent = EditorGUI.indentLevel; - EditorGUI.indentLevel = 0; - - GUILayoutUtility.GetRect(_cachedOuterRect.width, rect.height); - - Profiler.BeginSample("TriInspector.DrawRootPropertyElement"); - _rootPropertyElement.OnGUI(rect); - Profiler.EndSample(); - - EditorGUI.indentLevel = oldIndent; + return _rootPropertyElement; } public void EnumerateValidationResults(Action call) @@ -103,18 +82,40 @@ public void EnumerateValidationResults(Action RootProperty.EnumerateValidationResults(call); } + [Obsolete("Legacy from IMGUI")] public void RequestRepaint() { - RepaintRequired = true; } public void RequestValidation() { ValidationRequired = true; - - RequestRepaint(); } public abstract void ForceCreateUndoGroup(); + + public void AddPropertyOverride(TriPropertyOverrideContext context) + { + _propertyOverrides.Add(context); + } + + public void RemovePropertyOverride(TriPropertyOverrideContext context) + { + _propertyOverrides.Remove(context); + } + + internal bool TryGetOverrideDisplayName(TriProperty property, out GUIContent displayName) + { + for (var i = _propertyOverrides.Count - 1; i >= 0; i--) + { + if (_propertyOverrides[i].TryGetDisplayName(property, out displayName)) + { + return true; + } + } + + displayName = default; + return false; + } } } \ No newline at end of file diff --git a/Editor/TriPropertyTreeForSerializedObject.cs b/Editor/TriPropertyTreeForSerializedObject.cs index f31fbf6d..574f390e 100644 --- a/Editor/TriPropertyTreeForSerializedObject.cs +++ b/Editor/TriPropertyTreeForSerializedObject.cs @@ -56,13 +56,6 @@ public override void Update(bool forceUpdate = false) base.Update(forceUpdate); } - public override void Draw() - { - DrawMonoScriptProperty(); - - base.Draw(); - } - public override bool ApplyChanges() { var changed = base.ApplyChanges(); @@ -86,19 +79,5 @@ private void OnPropertyChanged(TriProperty changedProperty) RequestValidation(); RequestRepaint(); } - - private void DrawMonoScriptProperty() - { - if (RootProperty.TryGetAttribute(out HideMonoScriptAttribute _)) - { - return; - } - - EditorGUI.BeginDisabledGroup(true); - var scriptRect = EditorGUILayout.GetControlRect(true); - scriptRect.xMin += 3; - EditorGUI.PropertyField(scriptRect, _scriptProperty); - EditorGUI.EndDisabledGroup(); - } } } \ No newline at end of file diff --git a/Editor/TriValueDrawer.cs b/Editor/TriValueDrawer.cs index 930c5797..a23eb3e3 100644 --- a/Editor/TriValueDrawer.cs +++ b/Editor/TriValueDrawer.cs @@ -1,5 +1,4 @@ -using JetBrains.Annotations; -using UnityEngine; +using UnityEngine.UIElements; namespace TriInspector { @@ -9,53 +8,14 @@ public abstract class TriValueDrawer : TriCustomDrawer public abstract class TriValueDrawer : TriValueDrawer { - public sealed override TriElement CreateElementInternal(TriProperty property, TriElement next) + public sealed override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { - return CreateElement(new TriValue(property), next); + return CreateVisualElement(new TriValue(property), next); } - [PublicAPI] - public virtual TriElement CreateElement(TriValue propertyValue, TriElement next) + public virtual VisualElement CreateVisualElement(TriValue propertyValue, VisualElement next) { - return new DefaultValueDrawerElement(this, propertyValue, next); - } - - [PublicAPI] - public virtual float GetHeight(float width, TriValue propertyValue, TriElement next) - { - return next.GetHeight(width); - } - - [PublicAPI] - public virtual void OnGUI(Rect position, TriValue propertyValue, TriElement next) - { - next.OnGUI(position); - } - - internal class DefaultValueDrawerElement : TriElement - { - private readonly TriValueDrawer _drawer; - private readonly TriElement _next; - private readonly TriValue _propertyValue; - - public DefaultValueDrawerElement(TriValueDrawer drawer, TriValue propertyValue, TriElement next) - { - _drawer = drawer; - _propertyValue = propertyValue; - _next = next; - - AddChild(next); - } - - public override float GetHeight(float width) - { - return _drawer.GetHeight(width, _propertyValue, _next); - } - - public override void OnGUI(Rect position) - { - _drawer.OnGUI(position, _propertyValue, _next); - } + return null; } } } \ No newline at end of file diff --git a/Editor/Utilities/TriDrawersUtilities.cs b/Editor/Utilities/TriDrawersUtilities.cs index 96632074..b9d0a2ca 100644 --- a/Editor/Utilities/TriDrawersUtilities.cs +++ b/Editor/Utilities/TriDrawersUtilities.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using TriInspector.Elements; +using TriInspector.VisualElements; using UnityEngine; namespace TriInspector.Utilities @@ -174,14 +174,15 @@ select attr } } - public static TriPropertyCollectionBaseElement TryCreateGroupElementFor(DeclareGroupBaseAttribute attribute) + public static TriPropertyCollectionVisualElement TryCreateGroupVisualElementFor( + DeclareGroupBaseAttribute attribute) { if (!AllGroupDrawersCache.TryGetValue(attribute.GetType(), out var attr)) { return null; } - return attr.CreateElementInternal(attribute); + return attr.CreateVisualElementInternal(attribute); } public static IEnumerable CreateValueDrawersFor(Type valueType) diff --git a/Editor/Utilities/TriEditorGUI.MinMaxSlider.cs b/Editor/Utilities/TriEditorGUI.MinMaxSlider.cs deleted file mode 100644 index 1e2c3dc2..00000000 --- a/Editor/Utilities/TriEditorGUI.MinMaxSlider.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2018-2022 A. R. (arimger) -// -// This code was originally sourced from: -// https://github.com/arimger/Unity-Editor-Toolbox/blob/master/Assets/Editor%20Toolbox/Editor/ToolboxEditorGui.cs -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Utilities -{ - public static partial class TriEditorGUI - { - public static void DrawMinMaxSlider(Rect rect, ref float xValue, ref float yValue, float minValue, float maxValue) - { - var fieldWidth = EditorGUIUtility.fieldWidth; - var minFieldRect = new Rect(rect.xMin, rect.y, fieldWidth, rect.height); - var maxFieldRect = new Rect(rect.xMax - fieldWidth, rect.y, fieldWidth, rect.height); - - //set slider rect between min and max fields + additional padding - const float spacing = 8.0f; - var sliderRect = Rect.MinMaxRect(minFieldRect.xMax + spacing, - rect.yMin, - maxFieldRect.xMin - spacing, - rect.yMax); - - xValue = EditorGUI.FloatField(minFieldRect, xValue); - yValue = EditorGUI.FloatField(maxFieldRect, yValue); - EditorGUI.MinMaxSlider(sliderRect, ref xValue, ref yValue, minValue, maxValue); - - //values validation (xValue can't be higher than yValue etc.) - xValue = Mathf.Clamp(xValue, minValue, Mathf.Min(maxValue, yValue)); - yValue = Mathf.Clamp(yValue, Mathf.Max(minValue, xValue), maxValue); - } - public static void DrawMinMaxSlider(Rect rect, string label, ref float xValue, ref float yValue, float minValue, float maxValue) - { - DrawMinMaxSlider(rect, new GUIContent(label), ref xValue, ref yValue, minValue, maxValue); - } - public static void DrawMinMaxSlider(Rect rect, GUIContent label, ref float xValue, ref float yValue, float minValue, float maxValue) - { - rect = EditorGUI.PrefixLabel(rect, label); - DrawMinMaxSlider(rect, ref xValue, ref yValue, minValue, maxValue); - } - } -} diff --git a/Editor/Utilities/TriEditorGUI.MinMaxSlider.cs.meta b/Editor/Utilities/TriEditorGUI.MinMaxSlider.cs.meta deleted file mode 100644 index 3cd88176..00000000 --- a/Editor/Utilities/TriEditorGUI.MinMaxSlider.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 547d2e05782b5f849b6bea8585320d7e \ No newline at end of file diff --git a/Editor/Utilities/TriEditorGUI.cs b/Editor/Utilities/TriEditorGUI.cs deleted file mode 100644 index d9d19636..00000000 --- a/Editor/Utilities/TriEditorGUI.cs +++ /dev/null @@ -1,32 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace TriInspector.Utilities -{ - public static partial class TriEditorGUI - { - public static void Foldout(Rect rect, TriProperty property) - { - var content = property.DisplayNameContent; - if (property.TryGetSerializedProperty(out var serializedProperty)) - { - EditorGUI.BeginProperty(rect, content, serializedProperty); - property.IsExpanded = EditorGUI.Foldout(rect, property.IsExpanded, content, true); - EditorGUI.EndProperty(); - } - else - { - property.IsExpanded = EditorGUI.Foldout(rect, property.IsExpanded, content, true); - } - } - - public static void DrawBox(Rect position, GUIStyle style, - bool isHover = false, bool isActive = false, bool on = false, bool hasKeyboardFocus = false) - { - if (Event.current.type == EventType.Repaint) - { - style.Draw(position, GUIContent.none, isHover, isActive, on, hasKeyboardFocus); - } - } - } -} \ No newline at end of file diff --git a/Editor/Utilities/TriEditorGUI.cs.meta b/Editor/Utilities/TriEditorGUI.cs.meta deleted file mode 100644 index fd97d814..00000000 --- a/Editor/Utilities/TriEditorGUI.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 59bc827ebe19464ea936ff5cf8ae1b7f -timeCreated: 1638864333 \ No newline at end of file diff --git a/Editor/Utilities/TriGuiHelper.cs b/Editor/Utilities/TriGuiHelper.cs deleted file mode 100644 index f96d73a8..00000000 --- a/Editor/Utilities/TriGuiHelper.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace TriInspector.Utilities -{ - public static class TriGuiHelper - { - private static readonly GUIContent TempContentShared = new GUIContent(); - private static readonly Stack TargetObjects = new Stack(); - - internal static GUIContent TempContent(string text) - { - TempContentShared.text = text; - return TempContentShared; - } - - internal static bool IsAnyEditorPushed() - { - return TargetObjects.Count > 0; - } - - internal static bool IsEditorTargetPushed(Object obj) - { - foreach (var targetObject in TargetObjects) - { - if (targetObject == obj) - { - return true; - } - } - - return false; - } - - internal static EditorScope PushEditorTarget(Object obj) - { - return new EditorScope(obj); - } - - public static LabelWidthScope PushLabelWidth(float labelWidth) - { - return new LabelWidthScope(labelWidth); - } - - public static IndentedRectScope PushIndentedRect(Rect source, int indentLevel) - { - return new IndentedRectScope(source, indentLevel); - } - - public static GuiColorScope PushColor(Color color) - { - return new GuiColorScope(color); - } - - public readonly struct EditorScope : IDisposable - { - public EditorScope(Object obj) - { - TargetObjects.Push(obj); - } - - public void Dispose() - { - TargetObjects.Pop(); - } - } - - public readonly struct LabelWidthScope : IDisposable - { - private readonly float _oldLabelWidth; - - public LabelWidthScope(float labelWidth) - { - _oldLabelWidth = EditorGUIUtility.labelWidth; - - if (labelWidth > 0) - { - EditorGUIUtility.labelWidth = labelWidth; - } - } - - public void Dispose() - { - EditorGUIUtility.labelWidth = _oldLabelWidth; - } - } - - public readonly struct IndentedRectScope : IDisposable - { - private readonly float _indent; - - public Rect IndentedRect { get; } - - public IndentedRectScope(Rect source, int indentLevel) - { - _indent = indentLevel * 15; - - IndentedRect = new Rect(source.x + _indent, source.y, source.width - _indent, source.height); - EditorGUIUtility.labelWidth -= _indent; - } - - public void Dispose() - { - EditorGUIUtility.labelWidth += _indent; - } - } - - public readonly struct GuiColorScope : IDisposable - { - private readonly Color _oldColor; - - public GuiColorScope(Color color) - { - _oldColor = GUI.color; - - GUI.color = color; - } - - public void Dispose() - { - GUI.color = _oldColor; - } - } - } -} \ No newline at end of file diff --git a/Editor/Utilities/TriGuiHelper.cs.meta b/Editor/Utilities/TriGuiHelper.cs.meta deleted file mode 100644 index 87a00669..00000000 --- a/Editor/Utilities/TriGuiHelper.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 787c857ae9a64fdbb01e6ced9309a09e -timeCreated: 1639377094 \ No newline at end of file diff --git a/Editor/ValidatorsDrawer.cs b/Editor/ValidatorsDrawer.cs index a78f98af..d16ef1bc 100644 --- a/Editor/ValidatorsDrawer.cs +++ b/Editor/ValidatorsDrawer.cs @@ -1,83 +1,18 @@ -using System; -using System.Collections.Generic; -using TriInspector.Elements; -using UnityEditor; +using TriInspector.VisualElements; +using UnityEngine.UIElements; namespace TriInspector { internal class ValidatorsDrawer : TriCustomDrawer { - public override TriElement CreateElementInternal(TriProperty property, TriElement next) + public override VisualElement CreateVisualElement(TriProperty property, VisualElement next) { if (!property.HasValidators) { return next; } - var element = new TriElement(); - element.AddChild(new TriPropertyValidationResultElement(property)); - element.AddChild(next); - return element; - } - - public class TriPropertyValidationResultElement : TriElement - { - private readonly TriProperty _property; - private IReadOnlyList _validationResults; - - public TriPropertyValidationResultElement(TriProperty property) - { - _property = property; - } - - public override float GetHeight(float width) - { - if (ChildrenCount == 0) - { - return -EditorGUIUtility.standardVerticalSpacing; - } - - return base.GetHeight(width); - } - - public override bool Update() - { - var dirty = base.Update(); - - dirty |= GenerateValidationResults(); - - return dirty; - } - - private bool GenerateValidationResults() - { - if (ReferenceEquals(_property.ValidationResults, _validationResults)) - { - return false; - } - - _validationResults = _property.ValidationResults; - - RemoveAllChildren(); - - foreach (var result in _validationResults) - { - var infoBox = result.FixAction != null - ? new TriInfoBoxElement(result.Message, result.MessageType, - inlineAction: () => ExecuteFix(result.FixAction), - inlineActionContent: result.FixActionContent) - : new TriInfoBoxElement(result.Message, result.MessageType); - - AddChild(infoBox); - } - - return true; - } - - private void ExecuteFix(Action fixAction) - { - _property.ModifyAndRecordForUndo(targetIndex => fixAction?.Invoke()); - } + return new TriValidationResultsVisualElement(property, next); } } } \ No newline at end of file diff --git a/Editor/VisualElementExtensions.cs b/Editor/VisualElementExtensions.cs new file mode 100644 index 00000000..8225af79 --- /dev/null +++ b/Editor/VisualElementExtensions.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using TriInspector.Resolvers; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; + +namespace TriInspector +{ + public static class VisualElementExtensions + { + private static readonly FieldInfo ToggleClickable; + private static readonly PropertyInfo ClickableSetAcceptClicksIfDisabled; + + public const int PollIntervalMs = 100; + + static VisualElementExtensions() + { + ToggleClickable = typeof(Toggle).GetField("m_Clickable", BindingFlags.Instance | BindingFlags.NonPublic); + ClickableSetAcceptClicksIfDisabled = typeof(Clickable).GetProperty("acceptClicksIfDisabled", + BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); + } + + public static T FindAncestor(this VisualElement element) where T : VisualElement + { + for (var current = element; current != null; current = current.parent) + { + if (current is T result) + { + return result; + } + } + + return null; + } + + public static void PeriodicRun(this VisualElement element, Action action) + { + element.schedule.Execute(action).Every(PollIntervalMs); + } + + public static void TrackResolvedValue(this VisualElement el, + TriProperty property, ValueResolver resolver, T defaultValue, Action callback) + { + el.PeriodicRun(() => + { + try + { + callback(resolver.GetValue(property, defaultValue)); + } + catch (Exception ex) + { + Debug.LogException(ex); + } + }); + } + + public static void AutoSyncLabelFromProperty(this Foldout foldout, TriProperty property) + { + AutoSyncLabelFromProperty(foldout, property, text => foldout.text = text); + } + + public static void AutoSyncLabelFromProperty(this BaseField field, TriProperty property) + { + AutoSyncLabelFromProperty(field, property, text => field.label = text); + } + + public static void AutoSyncLabelFromProperty(this PropertyField field, TriProperty property) + { + AutoSyncLabelFromProperty(field, property, text => field.label = text); + } + + private static void AutoSyncLabelFromProperty(VisualElement el, TriProperty property, Action setText) + { + void Sync() + { + var name = property.DisplayNameContent; + try + { + setText(name.text); + } + catch (Exception ex) + { + Debug.LogException(ex); + } + } + + PeriodicRun(el, Sync); + } + + public static void AutoSyncValueFromProperty(this BaseField field, TriProperty property) + { + field.AutoSyncValueFromProperty(property, () => (T) property.Value); + } + + public static void AutoSyncValueFromProperty(this BaseField field, TriProperty property, Func getValue) + { + void Sync(TriProperty _) + { + field.showMixedValue = property.IsValueMixed; + + // Don't clobber the value while the user is editing it. + if (field.IsBeingEdited()) + { + return; + } + + var current = getValue(); + if (!EqualityComparer.Default.Equals(field.value, current)) + { + field.SetValueWithoutNotify(current); + } + } + + field.RegisterCallback(_ => + { + property.ValueChanged += Sync; + Sync(property); + }); + + field.RegisterCallback(_ => + { + property.ValueChanged -= Sync; + }); + } + + private static bool IsBeingEdited(this VisualElement field) + { + var focused = field.focusController?.focusedElement as VisualElement; + return focused != null && (focused == field || field.Contains(focused)); + } + + + public static void SetAcceptClicksIfDisabled(this Foldout foldout, bool value) + { + if (foldout != null) + { + SetAcceptClicksIfDisabled(foldout.Q(), value); + } + } + + public static void SetAcceptClicksIfDisabled(this Toggle toggle, bool value) + { + if (toggle != null) + { + SetAcceptClicksIfDisabled(ToggleClickable.GetValue(toggle) as Clickable, value); + } + } + + public static void SetAcceptClicksIfDisabled(this Clickable clickable, bool value) + { + if (clickable != null) + { + ClickableSetAcceptClicksIfDisabled?.SetValue(clickable, value); + } + } + } +} \ No newline at end of file diff --git a/Editor/VisualElementExtensions.cs.meta b/Editor/VisualElementExtensions.cs.meta new file mode 100644 index 00000000..217b3c34 --- /dev/null +++ b/Editor/VisualElementExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ef4c7a36921f445a9a611f44d0e8cbac +timeCreated: 1785849248 \ No newline at end of file diff --git a/Editor/VisualElements.meta b/Editor/VisualElements.meta new file mode 100644 index 00000000..ddb911df --- /dev/null +++ b/Editor/VisualElements.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2ae05fdff25a47f7af9fdc1345f19f7b +timeCreated: 1785837702 \ No newline at end of file diff --git a/Editor/VisualElements/Core.TriStyleSheet.uss b/Editor/VisualElements/Core.TriStyleSheet.uss new file mode 100644 index 00000000..320d5771 --- /dev/null +++ b/Editor/VisualElements/Core.TriStyleSheet.uss @@ -0,0 +1,465 @@ +/* ---- Palette ---- */ + +.tri-dark { + --tri-color-border: #141414; + --tri-color-header-background: #353535; + --tri-color-content-background: #464646; + --tri-color-hover: #585858; + --tri-color-foldout-line: #6C6C6C; + + --tri-color-validation-background: #2A2A2A; + + --tri-color-validation-info-background: rgba(92, 92, 92, 0.3); + --tri-color-validation-warning-background: rgba(108, 86, 18, 0.3); + --tri-color-validation-error-background: rgba(122, 35, 35, 0.4); + + --tri-color-validation-info-icon: #D2D2D2; + --tri-color-validation-warning-icon: #FFC107; + --tri-color-validation-error-icon: #FF534A; + + --tri-color-validation-info-text: #D2D2D2; + --tri-color-validation-warning-text: #FFC107; + --tri-color-validation-error-text: #FF534A; +} + +.tri-light { + --tri-color-border: #7E7E7E; + --tri-color-header-background: #B6B6B6; + --tri-color-content-background: #DCDCDC; + --tri-color-hover: #ECECEC; + --tri-color-foldout-line: #929292; + + --tri-color-validation-background: #ECECEC; + + --tri-color-validation-info-background: rgba(255, 255, 255, 0.3); + --tri-color-validation-warning-background: rgba(230, 184, 46, 0.3); + --tri-color-validation-error-background: rgba(230, 92, 92, 0.3); + + --tri-color-validation-info-icon: #F0F0F0; + --tri-color-validation-warning-icon: #C99700; + --tri-color-validation-error-icon: #B10C0C; + + --tri-color-validation-info-text: #090909; + --tri-color-validation-warning-text: #333308; + --tri-color-validation-error-text: #5A0000; +} + +/* +unity-label + padding: 0 2px 0 1px + +unity-base-field + margin: 3px 1px + +unity-base-field__inspector-field + margin-right: -2px + +unity-base-field__label + margin-right: 2px + padding-left: 2px + padding-top: 2px + +unity-property-field__label + padding-left: 1px + */ + +.tri-inspector-element { + overflow: visible; + + /* We need to reset the minimum size, sometimes it looks bad, + but it's the only way I found to make the content fit correctly, + especially in a horizontal group */ + min-width: 0; +} + +.tri-aligned-label--contains-inlined { + overflow: visible; + margin-right: 0; /* Fix default -2px margin */ +} + +.tri-aligned-label__content { + margin-left: 0; /* Fix default 3px margin */ +} + +/* ---- Foldout ---- */ + +.tri-foldout > .unity-foldout__toggle { + margin-left: 3px; /* Fix default -12px, we want the arrow to be aligned with the text and not moved outward to the left. */ + margin-bottom: 1px; /* Fix default 3px, we make the foldout look like a regular field. */ +} + +.tri-foldout > .unity-foldout__content { + border-left-width: 1px; + border-left-color: var(--tri-color-foldout-line); + + margin-bottom: 3px; /* Additional indentation so that it is clearly visible where the foldout ends */ + + margin-left: 8px; /* Move the margin to the left and the padding to the right.. */ + padding-left: 6px; /* ..so that our foldout line is centered under the arrow */ +} + +/* ---- Box group ---- */ + +.tri-box-group { + margin: 1px -2px 1px 3px; + border-width: 1px; + border-color: var(--tri-color-border); + border-top-left-radius: 3px; + border-top-right-radius: 3px; + background-color: var(--tri-color-content-background); +} + +.tri-box-group__header { + flex-direction: row; + align-items: center; + padding: 3px 5px; + background-color: var(--tri-color-header-background); + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} + +.tri-box-group__header > .unity-toggle { + margin: 0; +} + +.tri-box-group__title { +} + +.tri-box-group__content { + padding: 0; + margin: 2px 5px 2px 0; +} + +.tri-box-group > .unity-foldout > .unity-foldout__toggle { + margin: 0; + padding: 2px 0 3px 4px; + background-color: var(--tri-color-header-background); + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} + +.tri-box-group > .unity-foldout > .unity-foldout__toggle:hover { + background-color: var(--tri-color-hover); +} + +/* ---- Tab group ---- */ + +.tri-tab-group { + margin: 1px -2px 1px 3px; + background-color: var(--tri-color-content-background); + border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-width: 1px; + border-color: var(--tri-color-border); +} + +.tri-tab-group__row { + flex-direction: row; +} + +.tri-tab-group__button { + flex-grow: 1; + margin: 0; + padding: 3px 4px 2px 4px; + border-radius: 0; + border-width: 0 1px 1px 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-color: var(--tri-color-border); + background-color: var(--tri-color-header-background); +} + +.tri-tab-group__button--non-active:hover { + border-bottom-width: 0; + background-color: var(--tri-color-hover); +} + +.tri-tab-group__button--active { + padding-bottom: 3px; + border-width: 0 1px 0 0; + background-color: var(--tri-color-content-background); +} + +.tri-tab-group__button--first { +} + +.tri-tab-group__button--last { + border-right-width: 0; +} + +.tri-tab-group__content { + padding: 0; + margin: 2px 5px 2px 0; +} + +/* ---- Horizontal group ---- */ + +.tri-horizontal-group { + flex-direction: row; +} + +.tri-horizontal-group__column { + overflow: visible; +} + +/* ---- List ---- */ + +.tri-list, +.tri-table { + margin: 1px -2px 1px 3px; + border-width: 1px; + border-color: var(--tri-color-border); + border-top-left-radius: 3px; + border-top-right-radius: 3px; + align-self: stretch; +} + +.tri-list .unity-list-view__reorderable-item__container { + padding-left: 0; +} + +.tri-list .unity-list-view__reorderable-handle { + justify-content: center; + align-items: center; + min-width: 20px; + padding-right: 2px; +} + +.tri-list__header { + flex-direction: row; + align-items: center; + background-color: var(--tri-color-header-background); + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} + +.tri-list__header .unity-toggle { + margin: 0; +} + +.tri-list__header-foldout { + margin: 0; + padding: 2px 0 3px 4px; + flex-grow: 1; +} + +.tri-list__header-foldout-collapsible:hover { + background-color: var(--tri-color-hover); +} + +.tri-list__header-foldout-non-collapsible .unity-foldout__checkmark { + opacity: 0; + width: 0; + margin-right: 4px; +} + +.tri-list__header-size { + width: 48px; + margin: 0 1px; +} + +.tri-list__header-button { + width: 24px; + height: 20px; + -unity-text-align: middle-center; + font-size: 20px; + border-left-width: 1px; + border-color: var(--tri-color-border); +} + +.tri-list__header-button:hover { + background-color: var(--tri-color-hover); +} + +.tri-list__header-button:disabled { + opacity: 0.5; +} + +.tri-list__element { + flex-direction: row; + align-items: flex-start; +} + +.tri-list__element-content { + flex-grow: 1; + flex-shrink: 1; +} + +.tri-list__element-remove { + align-self: stretch; + width: 24px; + margin: 0 -5px 0 4px; + -unity-text-align: middle-center; + font-size: 12px; + background-color: rgba(0, 0, 0, 0); + border-left-width: 1px; + border-color: var(--tri-color-border); +} + +.tri-list__element-remove:hover { + background-color: var(--tri-color-hover); +} + +/* ---- Table list ---- */ + +.tri-table .unity-inspector-main-container { + min-width: 10px; +} + +.tri-table__header-remove-spacer { + width: 24px; + border-left-width: 1px; + border-color: var(--tri-color-border); +} + +.tri-table__header-columns { + flex-direction: row; + background-color: var(--tri-color-content-background); + border-bottom-width: 1px; + border-color: var(--tri-color-border); +} + +.tri-table__header--reorderable { + margin-left: 20px; +} + +.tri-table__header-cell { + flex-grow: 1; + flex-basis: 0; + flex-shrink: 1; + -unity-text-align: middle-center; + white-space: normal; + padding: 2px 4px; + border-left-width: 1px; + border-color: var(--tri-color-border); +} + +.tri-table__row { + flex-direction: row; +} + +.tri-table__cell { + flex-grow: 1; + flex-basis: 0; + flex-shrink: 1; + justify-content: center; + padding: 0 5px 0 0; + border-left-width: 1px; + border-color: var(--tri-color-border); + overflow: visible; +} + +.tri-table__cell .unity-base-field__label { + min-width: 0; +} + +/* ---- Info box ---- */ + +.tri-validation-results { + margin: 3px 0 1px 0; +} + +.tri-validation-results__bg { + position: absolute; + left: 1px; + right: -3px; + top: 0; + bottom: 0; + border-width: 1px 0 0 2px; + border-radius: 5px 5px 4px 4px; +} + +.tri-info-box { + flex-direction: row; + align-items: center; + margin: 0 -2px 0 2px; + padding: 3px 3px 3px 2px; + border-left-width: 1px; + background-color: var(--tri-color-validation-background); +} + +.tri-info-box--first { + border-top-left-radius: 5px; +} + +.tri-info-box__icon { + width: 16px; + height: 16px; + flex-shrink: 0; + margin-left: 1px; +} + +.tri-info-box__label { + margin-left: 1px; + flex-grow: 1; + flex-shrink: 1; + flex-basis: 0; + min-width: 0; + white-space: normal; + -unity-text-align: middle-left; +} + +.tri-info-box__action { + font-size: var(--unity-metrics-default-font_semi_small_size); + padding: 1px 6px; + margin: 1px; + min-width: 70px; + max-width: 150px; + flex-grow: 0; + flex-shrink: 0; + margin-left: 5px; + white-space: normal; +} + +.tri-info-box--info { + border-color: var(--tri-color-validation-info-icon); +} + +.tri-info-box--warning { + border-color: var(--tri-color-validation-warning-icon); +} + +.tri-info-box--error { + border-color: var(--tri-color-validation-error-icon); +} + +.tri-info-box.tri-info-box--info { + background-color: var(--tri-color-validation-info-background); +} + +.tri-info-box.tri-info-box--warning { + background-color: var(--tri-color-validation-warning-background); +} + +.tri-info-box.tri-info-box--error { + background-color: var(--tri-color-validation-error-background); +} + +.tri-info-box--info > .tri-info-box__label { + color: var(--tri-color-validation-info-text); +} + +.tri-info-box--warning > .tri-info-box__label { + color: var(--tri-color-validation-warning-text); +} + +.tri-info-box--error > .tri-info-box__label { + color: var(--tri-color-validation-error-text); +} + +/* ---- No drawer ---- */ + +.tri-no-drawer__label { + flex-grow: 1; + -unity-text-align: middle-left; +} + +/* ---- Reference ---- */ + +.tri-reference__type-overlay { + position: absolute; + left: 2px; + right: 4px; + top: 0; + bottom: 0; +} \ No newline at end of file diff --git a/Editor/VisualElements/Core.TriStyleSheet.uss.meta b/Editor/VisualElements/Core.TriStyleSheet.uss.meta new file mode 100644 index 00000000..8a494008 --- /dev/null +++ b/Editor/VisualElements/Core.TriStyleSheet.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 99d0944bc09379e42b2720d0ec796645 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Editor/VisualElements/Groups.meta b/Editor/VisualElements/Groups.meta new file mode 100644 index 00000000..ffd9e9aa --- /dev/null +++ b/Editor/VisualElements/Groups.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9514fff6d56e44d396989ff103c20769 +timeCreated: 1785996966 \ No newline at end of file diff --git a/Editor/VisualElements/Groups/TriBoxGroupBaseVisualElement.cs b/Editor/VisualElements/Groups/TriBoxGroupBaseVisualElement.cs new file mode 100644 index 00000000..b420c9e5 --- /dev/null +++ b/Editor/VisualElements/Groups/TriBoxGroupBaseVisualElement.cs @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using TriInspector.Resolvers; +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements.Groups +{ + public abstract class TriBoxGroupBaseVisualElement : TriPropertyCollectionVisualElement + { + private readonly bool _hideIfChildrenInvisible; + private readonly string _titleExpression; + private readonly List _properties = new List(); + + private ValueResolver _titleResolver; + private TriProperty _firstProperty; + + protected TriBoxGroupBaseVisualElement(string titleExpression, bool hideIfChildrenInvisible) + { + _titleExpression = titleExpression; + _hideIfChildrenInvisible = hideIfChildrenInvisible; + + AddToClassList(TriStyles.BoxGroup); + + RegisterCallback(_ => Sync()); + this.PeriodicRun(Sync); + } + + protected VisualElement Content { get; private set; } + + protected void UseContent(VisualElement content) + { + Content = content; + Content.AddToClassList(TriStyles.BoxGroupContent); + } + + protected virtual bool TryConsumeProperty(TriProperty property) + { + return false; + } + + protected virtual void OnSync(string title) + { + } + + protected override void AddPropertyChild(VisualElement child, TriProperty property) + { + _properties.Add(property); + + if (_firstProperty == null) + { + _firstProperty = property; + _titleResolver = ValueResolver.ResolveString(property.Definition, _titleExpression ?? ""); + + if (_titleResolver.TryGetErrorString(out var error)) + { + Content.Add(new TriInfoBoxVisualElement(error, TriMessageType.Error)); + } + } + + if (TryConsumeProperty(property)) + { + return; + } + + Content.Add(child); + } + + private void Sync() + { + if (_hideIfChildrenInvisible) + { + var anyVisible = false; + for (var i = 0; i < _properties.Count; i++) + { + if (_properties[i].IsVisible) + { + anyVisible = true; + break; + } + } + + style.display = anyVisible ? DisplayStyle.Flex : DisplayStyle.None; + } + + var title = _titleResolver != null && _firstProperty != null + ? _titleResolver.GetValue(_firstProperty) + : _titleExpression; + + OnSync(title); + } + } +} diff --git a/Editor/VisualElements/Groups/TriBoxGroupBaseVisualElement.cs.meta b/Editor/VisualElements/Groups/TriBoxGroupBaseVisualElement.cs.meta new file mode 100644 index 00000000..36fc02fa --- /dev/null +++ b/Editor/VisualElements/Groups/TriBoxGroupBaseVisualElement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 27c7641694e54ac40981de0d36684509 \ No newline at end of file diff --git a/Editor/VisualElements/Groups/TriBoxGroupVisualElement.cs b/Editor/VisualElements/Groups/TriBoxGroupVisualElement.cs new file mode 100644 index 00000000..de8460e2 --- /dev/null +++ b/Editor/VisualElements/Groups/TriBoxGroupVisualElement.cs @@ -0,0 +1,15 @@ +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements.Groups +{ + public class TriBoxGroupVisualElement : TriBoxGroupBaseVisualElement + { + public TriBoxGroupVisualElement(bool hideIfChildrenInvisible) + : base(null, hideIfChildrenInvisible) + { + var content = new VisualElement(); + Add(content); + UseContent(content); + } + } +} diff --git a/Editor/VisualElements/Groups/TriBoxGroupVisualElement.cs.meta b/Editor/VisualElements/Groups/TriBoxGroupVisualElement.cs.meta new file mode 100644 index 00000000..543d9ad3 --- /dev/null +++ b/Editor/VisualElements/Groups/TriBoxGroupVisualElement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b90a5bd3826044347824e462e522bdd3 \ No newline at end of file diff --git a/Editor/VisualElements/Groups/TriFoldoutGroupVisualElement.cs b/Editor/VisualElements/Groups/TriFoldoutGroupVisualElement.cs new file mode 100644 index 00000000..7c5d3350 --- /dev/null +++ b/Editor/VisualElements/Groups/TriFoldoutGroupVisualElement.cs @@ -0,0 +1,28 @@ +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements.Groups +{ + public class TriFoldoutGroupVisualElement : TriBoxGroupBaseVisualElement + { + private readonly Foldout _foldout; + + public TriFoldoutGroupVisualElement(string title, bool expandedByDefault, bool hideIfChildrenInvisible) + : base(title, hideIfChildrenInvisible) + { + _foldout = new Foldout + { + text = title, + value = expandedByDefault, + }; + _foldout.SetAcceptClicksIfDisabled(true); + + Add(_foldout); + UseContent(_foldout.contentContainer); + } + + protected override void OnSync(string title) + { + _foldout.text = title; + } + } +} diff --git a/Editor/VisualElements/Groups/TriFoldoutGroupVisualElement.cs.meta b/Editor/VisualElements/Groups/TriFoldoutGroupVisualElement.cs.meta new file mode 100644 index 00000000..e41a4740 --- /dev/null +++ b/Editor/VisualElements/Groups/TriFoldoutGroupVisualElement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a9ae8e77c7803864a94b342414dda095 \ No newline at end of file diff --git a/Editor/VisualElements/Groups/TriHeaderBoxGroupVisualElement.cs b/Editor/VisualElements/Groups/TriHeaderBoxGroupVisualElement.cs new file mode 100644 index 00000000..5761c8d5 --- /dev/null +++ b/Editor/VisualElements/Groups/TriHeaderBoxGroupVisualElement.cs @@ -0,0 +1,31 @@ +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements.Groups +{ + public class TriHeaderBoxGroupVisualElement : TriBoxGroupBaseVisualElement + { + private readonly Label _titleLabel; + + public TriHeaderBoxGroupVisualElement(string title, bool hideIfChildrenInvisible) + : base(title, hideIfChildrenInvisible) + { + var header = new VisualElement(); + header.AddToClassList(TriStyles.BoxGroupHeader); + + _titleLabel = new Label(); + _titleLabel.AddToClassList(TriStyles.BoxGroupTitle); + header.Add(_titleLabel); + + Add(header); + + var content = new VisualElement(); + Add(content); + UseContent(content); + } + + protected override void OnSync(string title) + { + _titleLabel.text = title; + } + } +} diff --git a/Editor/VisualElements/Groups/TriHeaderBoxGroupVisualElement.cs.meta b/Editor/VisualElements/Groups/TriHeaderBoxGroupVisualElement.cs.meta new file mode 100644 index 00000000..c66169aa --- /dev/null +++ b/Editor/VisualElements/Groups/TriHeaderBoxGroupVisualElement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5a11816796877c34f8f7c66c0dc646c9 \ No newline at end of file diff --git a/Editor/VisualElements/Groups/TriHorizontalGroupVisualElement.cs b/Editor/VisualElements/Groups/TriHorizontalGroupVisualElement.cs new file mode 100644 index 00000000..3a17596c --- /dev/null +++ b/Editor/VisualElements/Groups/TriHorizontalGroupVisualElement.cs @@ -0,0 +1,51 @@ +using System; +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements.Groups +{ + public class TriHorizontalGroupVisualElement : TriPropertyCollectionVisualElement + { + private readonly float[] _sizes; + private int _childIndex; + + public TriHorizontalGroupVisualElement(float[] sizes = null) + { + _sizes = sizes ?? Array.Empty(); + + AddToClassList(TriStyles.HorizontalGroup); + } + + protected override void AddPropertyChild(VisualElement child, TriProperty property) + { + var index = _childIndex++; + + var wrapper = new VisualElement(); + wrapper.AddToClassList(TriStyles.HorizontalGroupColumn); + wrapper.AddToClassList(TriStyles.UnityInspectorElement); + wrapper.AddToClassList(TriStyles.UnityInspectorMainContainer); + wrapper.AddToClassList(TriStyles.TriInspectorElement); + + if (index < _sizes.Length && _sizes[index] > 0f) + { + wrapper.style.minWidth = _sizes[index]; + wrapper.style.width = _sizes[index]; + wrapper.style.flexGrow = 0; + wrapper.style.flexShrink = 0; + } + else + { + wrapper.style.flexGrow = 1; + wrapper.style.flexBasis = 0; + } + + if (index > 0) + { + wrapper.style.marginLeft = 2; + } + + wrapper.Add(child); + + Add(wrapper); + } + } +} diff --git a/Editor/VisualElements/Groups/TriHorizontalGroupVisualElement.cs.meta b/Editor/VisualElements/Groups/TriHorizontalGroupVisualElement.cs.meta new file mode 100644 index 00000000..af4b395e --- /dev/null +++ b/Editor/VisualElements/Groups/TriHorizontalGroupVisualElement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: fe6f7e44ed0017246ba6be025f8211a8 \ No newline at end of file diff --git a/Editor/VisualElements/Groups/TriTabGroupVisualElement.cs b/Editor/VisualElements/Groups/TriTabGroupVisualElement.cs new file mode 100644 index 00000000..15a6e798 --- /dev/null +++ b/Editor/VisualElements/Groups/TriTabGroupVisualElement.cs @@ -0,0 +1,168 @@ +using System.Collections.Generic; +using TriInspector.Resolvers; +using UnityEditor; +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements.Groups +{ + public class TriTabGroupVisualElement : TriPropertyCollectionVisualElement + { + private const string DefaultTabName = "Main"; + + private readonly VisualElement _tabBar; + private readonly VisualElement _content; + private readonly Dictionary _rows = new Dictionary(); + private readonly Dictionary _tabContents = new Dictionary(); + private readonly Dictionary _tabButtons = new Dictionary(); + private readonly List _tabs = new List(); + + private string _activeTab; + private string _activeTabKey; + + private struct TabInfo + { + public string name; + public TriProperty property; + public ValueResolver titleResolver; + } + + public TriTabGroupVisualElement() + { + AddToClassList(TriStyles.TabGroup); + + _tabBar = new VisualElement(); + + _content = new VisualElement(); + _content.AddToClassList(TriStyles.TabGroupContent); + + Add(_tabBar); + Add(_content); + + this.PeriodicRun(SyncTitles); + } + + protected override void AddPropertyChild(VisualElement child, TriProperty property) + { + var tabName = DefaultTabName; + var row = 0; + + if (property.TryGetAttribute(out TabAttribute tab)) + { + tabName = tab.TabName ?? tabName; + row = tab.Row; + } + + if (!_tabContents.TryGetValue(tabName, out var tabContent)) + { + tabContent = new VisualElement(); + _tabContents.Add(tabName, tabContent); + _content.Add(tabContent); + + var titleResolver = ValueResolver.ResolveString(property.Definition, tabName); + _tabs.Add(new TabInfo {name = tabName, property = property, titleResolver = titleResolver}); + + if (titleResolver.TryGetErrorString(out var error)) + { + tabContent.Add(new TriInfoBoxVisualElement(error, TriMessageType.Error)); + } + + var capturedName = tabName; + var button = new Button(() => SetActiveTab(capturedName)) + { + text = titleResolver.GetValue(property), + }; + button.AddToClassList(TriStyles.TabGroupButton); + _tabButtons.Add(tabName, button); + + var rowElement = GetRow(row); + rowElement.Add(button); + UpdateRowEdges(rowElement, row); + + if (_activeTabKey == null && property.TryGetAttribute(out GroupAttribute groupAttribute)) + { + _activeTabKey = + $"TriInspector.tab_group.{property.PropertyTree.TargetObjectType.Name}.{groupAttribute.Path}.active"; + _activeTab = SessionState.GetString(_activeTabKey, null); + } + + if (string.IsNullOrEmpty(_activeTab)) + { + _activeTab = tabName; + } + + SetActiveTab(_activeTab); + } + + tabContent.Add(child); + } + + private VisualElement GetRow(int row) + { + if (!_rows.TryGetValue(row, out var rowElement)) + { + rowElement = new VisualElement(); + rowElement.AddToClassList(TriStyles.TabGroupRow); + _rows.Add(row, rowElement); + + // Keep rows ordered by their declared row index? + var insertIndex = 0; + foreach (var key in _rows.Keys) + { + if (key < row) + { + insertIndex++; + } + } + + _tabBar.Insert(insertIndex, rowElement); + } + + return rowElement; + } + + // Round the outer top corners of the row: top-left on the first tab, top-right on the last. + private static void UpdateRowEdges(VisualElement rowElement, int row) + { + var count = rowElement.childCount; + + for (var i = 0; i < count; i++) + { + var button = rowElement.ElementAt(i); + button.EnableInClassList(TriStyles.TabGroupButtonFirst, i == 0); + button.EnableInClassList(TriStyles.TabGroupButtonLast, i == count - 1); + } + } + + private void SetActiveTab(string tabName) + { + _activeTab = tabName; + + if (_activeTabKey != null) + { + SessionState.SetString(_activeTabKey, tabName); + } + + foreach (var pair in _tabContents) + { + pair.Value.style.display = pair.Key == tabName ? DisplayStyle.Flex : DisplayStyle.None; + } + + foreach (var pair in _tabButtons) + { + pair.Value.EnableInClassList(TriStyles.TabGroupButtonActive, pair.Key == tabName); + pair.Value.EnableInClassList(TriStyles.TabGroupButtonNonActive, pair.Key != tabName); + } + } + + private void SyncTitles() + { + foreach (var tab in _tabs) + { + if (_tabButtons.TryGetValue(tab.name, out var button)) + { + button.text = tab.titleResolver.GetValue(tab.property); + } + } + } + } +} \ No newline at end of file diff --git a/Editor/VisualElements/Groups/TriTabGroupVisualElement.cs.meta b/Editor/VisualElements/Groups/TriTabGroupVisualElement.cs.meta new file mode 100644 index 00000000..7ebef069 --- /dev/null +++ b/Editor/VisualElements/Groups/TriTabGroupVisualElement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 85167c422a0c84f47927c2391a1f21b8 \ No newline at end of file diff --git a/Editor/VisualElements/Groups/TriToggleGroupVisualElement.cs b/Editor/VisualElements/Groups/TriToggleGroupVisualElement.cs new file mode 100644 index 00000000..a7b7bae7 --- /dev/null +++ b/Editor/VisualElements/Groups/TriToggleGroupVisualElement.cs @@ -0,0 +1,82 @@ +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements.Groups +{ + public class TriToggleGroupVisualElement : TriBoxGroupBaseVisualElement + { + private readonly bool _collapsible; + private readonly Toggle _toggle; + + private TriProperty _toggleProperty; + + public TriToggleGroupVisualElement(string title, bool collapsible, bool hideIfChildrenInvisible) + : base(title, hideIfChildrenInvisible) + { + _collapsible = collapsible; + + var header = new VisualElement(); + header.AddToClassList(TriStyles.BoxGroupHeader); + + _toggle = new Toggle(); + _toggle.RegisterValueChangedCallback(evt => + { + _toggleProperty?.SetValue(evt.newValue); + ApplyToggleState(evt.newValue); + }); + header.Add(_toggle); + + Add(header); + + var content = new VisualElement(); + Add(content); + UseContent(content); + } + + protected override bool TryConsumeProperty(TriProperty property) + { + if (_toggleProperty == null) + { + if (property.ValueType == typeof(bool)) + { + // The bool itself becomes the header toggle; it is not shown in the content. + _toggleProperty = property; + return true; + } + + if (property.ChildrenProperties != null && property.ChildrenProperties.Count > 0 && + property.ChildrenProperties[0].ValueType == typeof(bool)) + { + _toggleProperty = property.ChildrenProperties[0]; + } + } + + return false; + } + + protected override void OnSync(string title) + { + if (_toggleProperty?.Value is bool value) + { + _toggle.text = title; + _toggle.SetValueWithoutNotify(value); + ApplyToggleState(value); + } + else + { + _toggle.text = "The first property in the group must be of bool."; + } + } + + private void ApplyToggleState(bool on) + { + if (_collapsible) + { + Content.style.display = on ? DisplayStyle.Flex : DisplayStyle.None; + } + else + { + Content.SetEnabled(on); + } + } + } +} \ No newline at end of file diff --git a/Editor/VisualElements/Groups/TriToggleGroupVisualElement.cs.meta b/Editor/VisualElements/Groups/TriToggleGroupVisualElement.cs.meta new file mode 100644 index 00000000..a9fbe3a0 --- /dev/null +++ b/Editor/VisualElements/Groups/TriToggleGroupVisualElement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: af7b5eaf5b68b124abc0d514c57f265f \ No newline at end of file diff --git a/Editor/VisualElements/Groups/TriVerticalGroupVisualElement.cs b/Editor/VisualElements/Groups/TriVerticalGroupVisualElement.cs new file mode 100644 index 00000000..6789cb4c --- /dev/null +++ b/Editor/VisualElements/Groups/TriVerticalGroupVisualElement.cs @@ -0,0 +1,6 @@ +namespace TriInspector.VisualElements.Groups +{ + public class TriVerticalGroupVisualElement : TriPropertyCollectionVisualElement + { + } +} diff --git a/Editor/VisualElements/Groups/TriVerticalGroupVisualElement.cs.meta b/Editor/VisualElements/Groups/TriVerticalGroupVisualElement.cs.meta new file mode 100644 index 00000000..c480c996 --- /dev/null +++ b/Editor/VisualElements/Groups/TriVerticalGroupVisualElement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7665fd09edf51834d9b48685916a1e40 \ No newline at end of file diff --git a/Editor/VisualElements/TriAlignedLabelVisualElement.cs b/Editor/VisualElements/TriAlignedLabelVisualElement.cs new file mode 100644 index 00000000..b95d4d56 --- /dev/null +++ b/Editor/VisualElements/TriAlignedLabelVisualElement.cs @@ -0,0 +1,50 @@ +using UnityEngine; +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements +{ + public class TriAlignedLabelVisualElement : BaseField + { + public TriAlignedLabelVisualElement(TriProperty property, VisualElement content, + bool containsInlinedProperties = false) + : this(property.DisplayName, content) + { + this.AutoSyncLabelFromProperty(property); + + if (containsInlinedProperties) + { + AddToClassList(TriStyles.TriAlignedLabelContainsInlined); + } + } + + public TriAlignedLabelVisualElement(string label, VisualElement content) + : base(label, content) + { + AddToClassList(alignedFieldUssClassName); + AddToClassList(TriStyles.TriAlignedLabel); + content.AddToClassList(TriStyles.TriAlignedLabelContent); + + RegisterCallback(_ => + TriLabelWidthContextVisualElement.ApplyWidthFromAncestorToPrefixLabel(this)); + } + + /// + /// Overlays content onto a foldout's toggle: the content sits in the value column + /// while the foldout arrow + title stay in the label column. + /// The overlay ignores picking so the arrow underneath stays clickable. + /// + public static void InjectAlignedLabelFieldIntoFoldout(Foldout foldout, VisualElement content) + { + if (foldout.Q() is not { } toggle) + { + Debug.LogError("Failed to inject custom content into foldout"); + return; + } + + var overlay = new TriAlignedLabelVisualElement(" ", content); + overlay.AddToClassList(TriStyles.ReferenceTypeOverlay); + overlay.pickingMode = PickingMode.Ignore; + toggle.Add(overlay); + } + } +} \ No newline at end of file diff --git a/Editor/VisualElements/TriAlignedLabelVisualElement.cs.meta b/Editor/VisualElements/TriAlignedLabelVisualElement.cs.meta new file mode 100644 index 00000000..e89db886 --- /dev/null +++ b/Editor/VisualElements/TriAlignedLabelVisualElement.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 34f2cb6db28d45f4a1525db153372803 +timeCreated: 1785837737 \ No newline at end of file diff --git a/Editor/VisualElements/TriBuiltInPropertyVisualElement.cs b/Editor/VisualElements/TriBuiltInPropertyVisualElement.cs new file mode 100644 index 00000000..a30966a2 --- /dev/null +++ b/Editor/VisualElements/TriBuiltInPropertyVisualElement.cs @@ -0,0 +1,52 @@ +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements +{ + public class TriBuiltInPropertyVisualElement : PropertyField + { + private VisualElement _child; + private bool _labelWidthSet; + + public TriBuiltInPropertyVisualElement(TriProperty property, SerializedProperty serializedProperty) + : base(serializedProperty) + { + this.AutoSyncLabelFromProperty(property); + this.BindProperty(serializedProperty); + + RegisterCallback(_ => _labelWidthSet = false); + this.PeriodicRun(TrySetWidth); + } + + protected override void HandleEventBubbleUp(EventBase evt) + { + base.HandleEventBubbleUp(evt); + + var childChanged = childCount > 0 && _child != this[0]; + if (childChanged) + { + _child = this[0]; + TrySetWidth(); + } + } + + private void TrySetWidth() + { + if (_labelWidthSet) + { + return; + } + + if (childCount == 0) + { + return; + } + + if (TriLabelWidthContextVisualElement.ApplyWidthFromAncestorToPrefixLabel(this[0])) + { + _labelWidthSet = true; + } + } + } +} \ No newline at end of file diff --git a/Editor/VisualElements/TriBuiltInPropertyVisualElement.cs.meta b/Editor/VisualElements/TriBuiltInPropertyVisualElement.cs.meta new file mode 100644 index 00000000..cac75337 --- /dev/null +++ b/Editor/VisualElements/TriBuiltInPropertyVisualElement.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e89a1381f611451e8157ff99cf0e5dc1 +timeCreated: 1785846532 \ No newline at end of file diff --git a/Editor/VisualElements/TriBuiltinFieldFactory.cs b/Editor/VisualElements/TriBuiltinFieldFactory.cs new file mode 100644 index 00000000..a0794d8d --- /dev/null +++ b/Editor/VisualElements/TriBuiltinFieldFactory.cs @@ -0,0 +1,43 @@ +using System; +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements +{ + internal static class TriBuiltinFieldFactory + { + public static VisualElement Create(TriValue propertyValue, BaseField field) + { + return Create(propertyValue, field, v => v, v => v); + } + + public static VisualElement Create( + TriValue propertyValue, + BaseField field, + Func toField, + Func fromField) + { + var property = propertyValue.Property; + + field.RegisterValueChangedCallback(evt => propertyValue.SetValue(fromField(evt.newValue))); + field.AutoSyncValueFromProperty(property, () => toField(propertyValue.SmartValue)); + + return new TriAlignedLabelVisualElement(property, field); + } + + /// + /// Builds a two-way bound aligned field for an attribute drawer that only has a + /// (no ), with custom value conversion. + /// + public static VisualElement CreateForProperty( + TriProperty property, + BaseField field, + Func getValue, + Action setValue) + { + field.RegisterValueChangedCallback(evt => setValue(evt.newValue)); + field.AutoSyncValueFromProperty(property, getValue); + + return new TriAlignedLabelVisualElement(property, field); + } + } +} \ No newline at end of file diff --git a/Editor/VisualElements/TriBuiltinFieldFactory.cs.meta b/Editor/VisualElements/TriBuiltinFieldFactory.cs.meta new file mode 100644 index 00000000..af0b6041 --- /dev/null +++ b/Editor/VisualElements/TriBuiltinFieldFactory.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 108807f1fb637424a9c9683369f2537c \ No newline at end of file diff --git a/Editor/Elements/TriDropdownElement.cs b/Editor/VisualElements/TriDropdownVisualElement.cs similarity index 79% rename from Editor/Elements/TriDropdownElement.cs rename to Editor/VisualElements/TriDropdownVisualElement.cs index 49a08a48..80ccd6ab 100644 --- a/Editor/Elements/TriDropdownElement.cs +++ b/Editor/VisualElements/TriDropdownVisualElement.cs @@ -1,63 +1,58 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEngine; +using UnityEngine.UIElements; -namespace TriInspector.Elements +namespace TriInspector.VisualElements { - public class TriDropdownElement : TriElement + public class TriDropdownVisualElement : VisualElement { private readonly TriProperty _property; private readonly Func> _valuesGetter; private readonly bool _useAdvancedDropdown; private readonly AdvancedDropdownState _dropdownState; + private readonly IMGUIContainer _popup; private object _currentValue; private string _currentText; + private bool _hasCurrent; - private bool _hasNextValue; - private object _nextValue; - - public TriDropdownElement(TriProperty property, Func> valuesGetter, - bool useAdvancedDropdown = true) + public TriDropdownVisualElement(TriProperty property, + Func> valuesGetter, + bool useAdvancedDropdown) { _property = property; _valuesGetter = valuesGetter; _useAdvancedDropdown = useAdvancedDropdown; _dropdownState = new AdvancedDropdownState(); - } - public override float GetHeight(float width) - { - return EditorGUIUtility.singleLineHeight; + // The prefix label is native (so it aligns with sibling fields), but the popup button and the + // GenericMenu/AdvancedDropdown it opens have no native UI Toolkit equivalent, so they stay IMGUI. + _popup = new IMGUIContainer(OnPopupGUI); + _popup.style.flexGrow = 1; + + Add(new TriAlignedLabelVisualElement(_property, _popup)); } - public override void OnGUI(Rect position) + private void OnPopupGUI() { - if (_hasNextValue) - { - var nextValue = _nextValue; - _hasNextValue = false; - _nextValue = null; - - _property.SetValue(nextValue); - GUI.changed = true; - } + var position = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight); - if (!_property.Comparer.Equals(_currentValue, _property.Value)) + if (!_hasCurrent || !_property.Comparer.Equals(_currentValue, _property.Value)) { _currentValue = _property.Value; + _hasCurrent = true; _currentText = _valuesGetter.Invoke(_property) .FirstOrDefault(it => _property.Comparer.Equals(it.Value, _property.Value)) ?.Text ?? (_property.Value?.ToString() ?? string.Empty); } - var controlId = GUIUtility.GetControlID(FocusType.Passive); - position = EditorGUI.PrefixLabel(position, controlId, _property.DisplayNameContent); + var text = _property.IsValueMixed ? "—" : _currentText; - if (GUI.Button(position, _currentText, EditorStyles.popup)) + if (GUI.Button(position, text, EditorStyles.popup)) { if (_useAdvancedDropdown) { @@ -93,9 +88,9 @@ private void ShowAdvancedDropdown(Rect position) private void ChangeValue(object v) { - _nextValue = v; - _hasNextValue = true; - _property.PropertyTree.RequestRepaint(); + _property.SetValue(v); + _hasCurrent = false; + _popup.MarkDirtyRepaint(); } private class TriAdvancedDropdown : AdvancedDropdown @@ -181,4 +176,4 @@ public TriAdvancedDropdownItem(string name, object value, bool isOn) : base(name } } } -} \ No newline at end of file +} diff --git a/Editor/VisualElements/TriDropdownVisualElement.cs.meta b/Editor/VisualElements/TriDropdownVisualElement.cs.meta new file mode 100644 index 00000000..af136157 --- /dev/null +++ b/Editor/VisualElements/TriDropdownVisualElement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9a25f66fd8f149341bedfb1a2f7c790f \ No newline at end of file diff --git a/Editor/VisualElements/TriFoldoutVisualElement.cs b/Editor/VisualElements/TriFoldoutVisualElement.cs new file mode 100644 index 00000000..22645e2c --- /dev/null +++ b/Editor/VisualElements/TriFoldoutVisualElement.cs @@ -0,0 +1,57 @@ +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements +{ + public class TriFoldoutVisualElement : VisualElement + { + public TriFoldoutVisualElement(TriProperty property) + { + var foldout = new Foldout + { + value = property.IsExpanded, + }; + + foldout.SetAcceptClicksIfDisabled(true); + foldout.AutoSyncLabelFromProperty(property); + foldout.AddToClassList(TriStyles.Foldout); + + var built = false; + + void BuildContentIfNeeded() + { + if (built) + { + return; + } + + built = true; + + foldout.Add(new TriPropertyCollectionVisualElement(property.ValueType, property.ChildrenProperties)); + } + + if (property.IsExpanded) + { + BuildContentIfNeeded(); + } + + foldout.RegisterValueChangedCallback(evt => + { + if (evt.target != foldout) + { + return; + } + + property.IsExpanded = evt.newValue; + + if (evt.newValue) + { + BuildContentIfNeeded(); + } + }); + + VisualElement el = foldout; + el = new TriLabelWidthContextVisualElement(null, el); + Add(el); + } + } +} \ No newline at end of file diff --git a/Editor/VisualElements/TriFoldoutVisualElement.cs.meta b/Editor/VisualElements/TriFoldoutVisualElement.cs.meta new file mode 100644 index 00000000..c1a635f1 --- /dev/null +++ b/Editor/VisualElements/TriFoldoutVisualElement.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7161c9032562428fab3a41ececb0b650 +timeCreated: 1785853616 \ No newline at end of file diff --git a/Editor/VisualElements/TriHeaderBoxedVisualElement.cs b/Editor/VisualElements/TriHeaderBoxedVisualElement.cs new file mode 100644 index 00000000..d18d341c --- /dev/null +++ b/Editor/VisualElements/TriHeaderBoxedVisualElement.cs @@ -0,0 +1,63 @@ +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements +{ + public class TriHeaderBoxedVisualElement : VisualElement + { + private readonly VisualElement _content = new VisualElement(); + private bool _expanded; + + public TriHeaderBoxedVisualElement(TriProperty property, bool useFoldout, VisualElement headerControl = null) + { + _expanded = !useFoldout || property.IsExpanded; + + AddToClassList(TriStyles.BoxGroup); + + if (useFoldout) + { + var foldout = new Foldout + { + value = property.IsExpanded, + }; + + foldout.AutoSyncLabelFromProperty(property); + foldout.AddToClassList(TriStyles.Foldout); + foldout.SetAcceptClicksIfDisabled(true); + + if (headerControl != null) + { + TriAlignedLabelVisualElement.InjectAlignedLabelFieldIntoFoldout(foldout, headerControl); + } + + foldout.RegisterValueChangedCallback(evt => + { + // Foldout also bubbles ChangeEvent from child toggles; only react to its own. + if (evt.target != foldout) + { + return; + } + + _expanded = evt.newValue; + property.IsExpanded = evt.newValue; + OnExpandedChanged(evt.newValue); + }); + + Add(foldout); + } + else if (headerControl != null) + { + Add(new TriAlignedLabelVisualElement(property, headerControl)); + } + + Add(_content); + } + + public bool Expanded => _expanded; + + public VisualElement Content => _content; + + protected virtual void OnExpandedChanged(bool expanded) + { + } + } +} \ No newline at end of file diff --git a/Editor/VisualElements/TriHeaderBoxedVisualElement.cs.meta b/Editor/VisualElements/TriHeaderBoxedVisualElement.cs.meta new file mode 100644 index 00000000..dd9f59a4 --- /dev/null +++ b/Editor/VisualElements/TriHeaderBoxedVisualElement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e11d0bf07617cd44d9fbe3dcff622e05 \ No newline at end of file diff --git a/Editor/VisualElements/TriInfoBoxVisualElement.cs b/Editor/VisualElements/TriInfoBoxVisualElement.cs new file mode 100644 index 00000000..d508c068 --- /dev/null +++ b/Editor/VisualElements/TriInfoBoxVisualElement.cs @@ -0,0 +1,62 @@ +using System; +using TriInspectorUnityInternalBridge; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements +{ + public class TriInfoBoxVisualElement : VisualElement + { + public TriInfoBoxVisualElement(string message, TriMessageType type, Action fixAction = null, + string fixActionText = null) + { + AddToClassList(TriStyles.InfoBox); + AddToClassList(GetTypeClass(type)); + + var icon = EditorGUIUtilityProxy.GetHelpIcon(GetMessageType(type)); + if (icon != null) + { + var image = new Image + { + image = icon, + scaleMode = ScaleMode.ScaleToFit, + }; + image.AddToClassList(TriStyles.InfoBoxIcon); + Add(image); + } + + var label = new Label(message); + label.AddToClassList(TriStyles.InfoBoxLabel); + Add(label); + + if (fixAction != null) + { + var button = new Button(fixAction) {text = fixActionText}; + button.AddToClassList(TriStyles.InfoBoxAction); + Add(button); + } + } + + private static string GetTypeClass(TriMessageType type) + { + switch (type) + { + case TriMessageType.Error: return TriStyles.InfoBoxError; + case TriMessageType.Warning: return TriStyles.InfoBoxWarning; + default: return TriStyles.InfoBoxInfo; + } + } + + private static MessageType GetMessageType(TriMessageType type) + { + switch (type) + { + case TriMessageType.Info: return MessageType.Info; + case TriMessageType.Warning: return MessageType.Warning; + case TriMessageType.Error: return MessageType.Error; + default: return MessageType.None; + } + } + } +} \ No newline at end of file diff --git a/Editor/VisualElements/TriInfoBoxVisualElement.cs.meta b/Editor/VisualElements/TriInfoBoxVisualElement.cs.meta new file mode 100644 index 00000000..b2141e12 --- /dev/null +++ b/Editor/VisualElements/TriInfoBoxVisualElement.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fb7bf2d4c64a467d98571e3a729d01a9 +timeCreated: 1785852549 \ No newline at end of file diff --git a/Editor/VisualElements/TriInlineEditorVisualElement.cs b/Editor/VisualElements/TriInlineEditorVisualElement.cs new file mode 100644 index 00000000..abca69e6 --- /dev/null +++ b/Editor/VisualElements/TriInlineEditorVisualElement.cs @@ -0,0 +1,169 @@ +using System; +using TriInspectorUnityInternalBridge; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; +using Object = UnityEngine.Object; + +namespace TriInspector.VisualElements +{ + public class TriInlineEditorVisualElement : TriHeaderBoxedVisualElement + { + [Serializable] + public struct Props + { + public InlineEditorModes mode; + public float previewHeight; + + public bool DrawGUI => (mode & InlineEditorModes.GUIOnly) != 0; + public bool DrawHeader => (mode & InlineEditorModes.Header) != 0; + public bool DrawPreview => (mode & InlineEditorModes.Preview) != 0; + } + + private readonly TriProperty _property; + private readonly Props _props; + private readonly VisualElement _content; + + private Editor _editor; + private Object _editorTarget; + + public TriInlineEditorVisualElement(TriProperty property, Props props = default) + : base(property, useFoldout: true, BuildObjectField(property)) + { + _property = property; + _props = props; + + _content = Content; + _content.style.display = DisplayStyle.None; + + RegisterCallback(_ => + { + _property.ValueChanged += OnValueChanged; + SyncContent(); + }); + RegisterCallback(_ => + { + _property.ValueChanged -= OnValueChanged; + DestroyEditor(); + }); + + this.PeriodicRun(SyncContent); + } + + protected override void OnExpandedChanged(bool expanded) + { + SyncContent(); + } + + private static ObjectField BuildObjectField(TriProperty property) + { + var field = new ObjectField + { + objectType = property.FieldType, + allowSceneObjects = property.PropertyTree.TargetIsPersistent == false, + }; + field.RegisterValueChangedCallback(evt => property.SetValue(evt.newValue)); + field.AutoSyncValueFromProperty(property); + + return field; + } + + private void OnValueChanged(TriProperty changed) + { + SyncContent(); + } + + private void SyncContent() + { + var value = _property.Value as Object; + var shouldShow = _property.IsExpanded && !_property.IsValueMixed && value != null; + + if (!shouldShow) + { + if (_editor != null) + { + DestroyEditor(); + _content.Clear(); + } + + _content.style.display = DisplayStyle.None; + return; + } + + if (_editor == null || _editorTarget != value) + { + DestroyEditor(); + + _editor = Editor.CreateEditor(value); + _editorTarget = value; + + if (!InternalEditorUtilityProxy.GetIsInspectorExpanded(value)) + { + InternalEditorUtilityProxy.SetIsInspectorExpanded(value, true); + } + + RebuildContent(); + } + + _content.style.display = DisplayStyle.Flex; + } + + private void RebuildContent() + { + _content.Clear(); + + if (_props.DrawHeader) + { + _content.Add(new IMGUIContainer(() => + { + if (_editor != null) + { + _editor.DrawHeader(); + } + })); + } + + if (_props.DrawGUI) + { + _content.Add(new InspectorElement(_editor)); + } + + if (_props.DrawPreview) + { + var previewHeight = _props.previewHeight; + + // Preview GUIs have no UI Toolkit equivalent; keep them as an IMGUI + _content.Add(new IMGUIContainer(() => + { + if (_editor == null || !_editor.HasPreviewGUI()) + { + return; + } + + var rect = EditorGUILayout.GetControlRect(false, previewHeight); + rect.width = Mathf.Max(rect.width, 10); + rect.height = Mathf.Max(rect.height, 10); + + var guiEnabled = GUI.enabled; + GUI.enabled = true; + + _editor.DrawPreview(rect); + + GUI.enabled = guiEnabled; + })); + } + } + + private void DestroyEditor() + { + if (_editor != null) + { + Object.DestroyImmediate(_editor); + _editor = null; + } + + _editorTarget = null; + } + } +} \ No newline at end of file diff --git a/Editor/VisualElements/TriInlineEditorVisualElement.cs.meta b/Editor/VisualElements/TriInlineEditorVisualElement.cs.meta new file mode 100644 index 00000000..cf74fa3b --- /dev/null +++ b/Editor/VisualElements/TriInlineEditorVisualElement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 187313739d38bdb49bf8e7ad80ba8627 \ No newline at end of file diff --git a/Editor/VisualElements/TriInlineGenericVisualElement.cs b/Editor/VisualElements/TriInlineGenericVisualElement.cs new file mode 100644 index 00000000..1560f698 --- /dev/null +++ b/Editor/VisualElements/TriInlineGenericVisualElement.cs @@ -0,0 +1,34 @@ +using System; +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements +{ + public class TriInlineGenericVisualElement : VisualElement + { + [Serializable] + public struct Props + { + public bool drawPrefixLabel; + public float labelWidth; + } + + public TriInlineGenericVisualElement(TriProperty property, Props props = default) + { + VisualElement content = new TriPropertyCollectionVisualElement(property.ValueType, property.ChildrenProperties); + + content = new TriLabelWidthContextVisualElement(props.labelWidth, content); + + if (props.drawPrefixLabel) + { + content.AddToClassList(TriStyles.UnityInspectorElement); + content.AddToClassList(TriStyles.UnityInspectorMainContainer); + content.AddToClassList(TriStyles.TriInspectorElement); + + content = new TriAlignedLabelVisualElement(property, content, containsInlinedProperties: true); + + } + + Add(content); + } + } +} \ No newline at end of file diff --git a/Editor/VisualElements/TriInlineGenericVisualElement.cs.meta b/Editor/VisualElements/TriInlineGenericVisualElement.cs.meta new file mode 100644 index 00000000..24e017e9 --- /dev/null +++ b/Editor/VisualElements/TriInlineGenericVisualElement.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 52d18d7e26e9401ab3a8f01c42365a89 +timeCreated: 1785853314 \ No newline at end of file diff --git a/Editor/VisualElements/TriLabelWidthContextVisualElement.cs b/Editor/VisualElements/TriLabelWidthContextVisualElement.cs new file mode 100644 index 00000000..778b819e --- /dev/null +++ b/Editor/VisualElements/TriLabelWidthContextVisualElement.cs @@ -0,0 +1,49 @@ +using UnityEngine.UIElements; + +namespace TriInspector.VisualElements +{ + public class TriLabelWidthContextVisualElement : VisualElement + { + public float? LabelWidth { get; } + + public TriLabelWidthContextVisualElement(float? labelWidth, VisualElement child = null) + { + LabelWidth = labelWidth > 0 ? labelWidth : null; + + if (child != null) + { + Add(child); + } + } + + public static bool ApplyWidthFromAncestorToPrefixLabel(VisualElement el) + { + if (el.FindAncestor() is not { } labelContext) + { + return false; + } + + if (labelContext.LabelWidth is not { } customLabelWidth) + { + return true; + } + + if (el.Q