Community Made Tools

Have you made any useful utilities with Odin?

Login and submit your creations here

Page Slider Attribute

Authored by Bjarke
Shared 22-05-2019

An attribute that makes big editors with a lot of data more easy to navigate.

The root/first PageSlider property will act as the slide container, and all PageSliders inside of that will be drawn as a buttons which will slide to that object when pressed.

Usage

[PageSlider] public SomeTestClass test; // Or place it above the class to enable it globally. [PageSlider] public class SomeOtherTestClass { }

SomeScriptableObject.cs Some random data for you to try it out with.

// // Test data - you can delete this part or name the file SomeScriptableObject.cs and try it out // [CreateAssetMenu] public class SomeScriptableObject : SerializedScriptableObject { [ShowInInspector] [LabelText("$testName")] public static SomeData test = new SomeData(); public string testName() { return test.Name; } } [PageSlider, HideReferenceObjectPicker] public class SomeData { public string Name; public int b, c, d; public SomeData b1, c1, d2; [ListDrawerSettings(Expanded = true)] public SomeData[] a = new SomeData[3]; [ListDrawerSettings(Expanded = true), InlineEditor(ObjectFieldMode = InlineEditorObjectFieldModes.Foldout, Expanded = true)] [PageSlider] public Material[] e = new Material[0]; public int f, g, h; public override string ToString() { return this.Name ?? "Some Data"; } }

PageSliderAttribute.cs

public class PageSliderAttribute : System.Attribute { }

PageSliderAttributeDrawer.cs

[DrawerPriority(0, 200, 0)] public class PageSliderAttributeDrawer : OdinAttributeDrawer<PageSliderAttribute> { private static GUIStyle titleStyle; private static SlidePageNavigationHelper<InspectorProperty> currentSlider; private static InspectorProperty currentDrawingPageProperty; private SlidePageNavigationHelper<InspectorProperty> slider; private SlidePageNavigationHelper<InspectorProperty>.Page page; private GUIContent pageLabel; protected override bool CanDrawAttributeProperty(InspectorProperty property) { return !(property.ChildResolver is ICollectionResolver); } protected override void Initialize() { titleStyle = titleStyle ?? new GUIStyle("ShurikenModuleTitle"); } protected override void DrawPropertyLayout(GUIContent label) { if (this.Property.ValueEntry.WeakSmartValue == null) { this.CallNextDrawer(label); return; } this.UpdateBreadcrumbLabel(label); if (currentSlider == null) { this.DrawPageSlider(label); } else if (currentDrawingPageProperty == this.Property) { this.CallNextDrawer(null); } else { if (GUILayout.Button(new GUIContent(this.GetLabelText(label)), titleStyle)) { currentSlider.PushPage(this.Property, Guid.NewGuid().ToString()); currentSlider.EnumeratePages.Last(); this.page = currentSlider.EnumeratePages.Last(); this.page.Name = this.GetLabelText(label); this.pageLabel = label; } } } private void UpdateBreadcrumbLabel(GUIContent label) { if (Event.current.type != EventType.Layout) return; if (this.page == null) return; if (this.pageLabel != null && this.pageLabel != this.Property.Label) return; var newLabel = this.GetLabelText(label ?? this.pageLabel); if (newLabel != this.page.Name) { this.page.Name = newLabel; this.page.GetType().GetField("TitleWidth", Flags.AllMembers).SetValue(this.page, null); } } private void DrawPageSlider(GUIContent label) { try { if (this.slider == null) { this.slider = new SlidePageNavigationHelper<InspectorProperty>(); this.slider.PushPage(this.Property, Guid.NewGuid().ToString()); this.page = this.slider.EnumeratePages.Last(); this.page.Name = this.GetLabelText(label); } currentSlider = this.slider; SirenixEditorGUI.BeginBox(); SirenixEditorGUI.BeginToolbarBoxHeader(); { var rect = GUILayoutUtility.GetRect(0, 20); rect.x -= 5; this.slider.DrawPageNavigation(rect); } SirenixEditorGUI.EndToolbarBoxHeader(); { this.slider.BeginGroup(); foreach (var p in this.slider.EnumeratePages) { if (p.BeginPage()) { if (p.Value == this.Property) { this.CallNextDrawer(null); } else { currentDrawingPageProperty = p.Value; if (p.Value.Tree != this.Property.Tree) { InspectorUtilities.BeginDrawPropertyTree(p.Value.Tree, true); } p.Value.Draw(null); if (p.Value.Tree != this.Property.Tree) { InspectorUtilities.EndDrawPropertyTree(p.Value.Tree); } currentDrawingPageProperty = null; } } p.EndPage(); } this.slider.EndGroup(); } SirenixEditorGUI.EndBox(); } finally { currentSlider = null; } } private string GetLabelText(GUIContent label) { if (label != null) { return label.text; } var val = this.Property.ValueEntry.WeakSmartValue; if (val == null) { return "Null"; } var uObj = val as UnityEngine.Object; if (uObj) { if (string.IsNullOrEmpty(uObj.name)) { return uObj.ToString(); } else { return uObj.name; } } return val.ToString(); } }