using AV.Inspector.Runtime; using AV.UITK; using UnityEditor; using UnityEditor.UIElements; using UnityEngine; using UnityEngine.UIElements; namespace AV.Inspector { internal class InspectorPrefsUI : VisualElement { StyleSheet styleSheet = FluentUITK.FindStyleSheet(guid: "6932d1ef107ed0d49a54fb25d3699c9c"); StyleSheet stylesLight = FluentUITK.FindStyleSheet(guid: "3ebaa7bab52db3c40b0457ab4ab089a8"); InspectorPrefs prefs; SerializedObject serialized; bool wasJustCreated; FluentElement ui; FluentUITK.Tab enablePlugin; FluentElement optionsPanel; FluentElement patchesPanel; public InspectorPrefsUI(InspectorPrefs prefs) { this.prefs = prefs; this.serialized = new SerializedObject(prefs); styleSheets.Add(styleSheet); if (!FluentUITK.isProSkin) styleSheets.Add(stylesLight); ui = this.Fluent(); ui.OnChange(OnChange); optionsPanel = CreateOptionsPanel(); patchesPanel = new InspectorPatchesUI(); var scrollView = new ScrollView().Fluent().Shrink(-100).Add( optionsPanel, patchesPanel ); ui.Add( CreateTopPanel(), scrollView ); ui.Bind(serialized); } void SaveAndRebuildInspectors() { prefs.SaveToUserData(); PropertyEditorRef.RebuildAllInspectors(); } VisualElement CreateTabsBar() { var me = ui.NewTabsBar(Styles.Button); me.x.AddNewTab(optionsPanel, "Options").Out(out var optionsTab); me.x.AddNewTab(patchesPanel, "Patches"); me.OnAttach(optionsTab.x.Show); return me; } VisualElement CreateTopPanel() { var me = ui.NewGroup().Name("Top Panel"); var topBar = me.NewRow().AddClass("top-bar").Add( me.NewHyperlink("Github", PackageInfo.RepoURL), me.NewBullet(), me.NewHyperlink("Patreon", PackageInfo.PatreonURL), me.NewBullet(), me.NewHyperlink("Discord", PackageInfo.OpenLabsDiscordURL), me.NewFlexibleSpace(), PresetsButton() ); var topGroup = me.NewRow().Margin(left: 6, right: 4).AddClass("top-group").Add( CreateTabsBar(), enablePlugin = me.NewTab(style: Styles.ButtonBlue) .Grow(1) .Bind(x => x.enablePlugin) ); SetEnablePluginState(prefs.enabled); me.Add(topBar); me.Add(topGroup); return me; } VisualElement CreateOptionsPanel() { wasJustCreated = true; EditorApplication.delayCall += () => wasJustCreated = false; var me = ui.NewGroup().Name("Options"); me.OnLayoutUpdate((_, c) => { if (c.totalCalls > 1) c.Unregister(); OnFirstLayoutUpdates(); }); var toolbar = me.NewHeader("Toolbar").Add( me.NewField(x => x.toolbar.showTabsBar, "Components Toolbar") ); var headers = me.NewHeader("Titlebars").Add( me.NewField(x => x.headers.showHelp), me.NewField(x => x.headers.showPresets), me.NewField(x => x.headers.showMenu).Enabled(false) ); var components = me.NewHeader("Components").Add( me.NewField(x => x.components.showScript, "Show (Script)"), me.NewField(x => x.components.showScriptField) ); var enhancements = me.NewHeader("Enhancements").Add( #if UNITY_2020_1_OR_NEWER me.NewField(x => x.enhancements.imguiCulling, "IMGUI Culling"), #endif me.NewField(x => x.enhancements.compactUnityEvents).Enabled(false), me.NewField(x => x.enhancements.compactPrefabInspector), me.NewField(x => x.enhancements.compactScrollbar), me.NewField(x => x.enhancements.smoothScrolling), me.NewField(x => x.enhancements.smartComponentDragging, "Improved Component Dragging") ); var additionalButtons = me.NewHeader("Additional Buttons").Add( me.NewField(x => x.additionalButtons.addressable), me.NewField(x => x.additionalButtons.convertToEntity), me.NewField(x => x.additionalButtons.assetLabels), me.NewField(x => x.additionalButtons.assetBundle) ); me.Add(toolbar); me.Add(headers); me.Add(components); me.Add(enhancements); me.Add(additionalButtons); me.Add(me.NewSpace(height: 20)); me.x.Query().ForEach(x => x.Fluent().Style(Styles.Separator)); return me; } void OnChange(ChangeEvent evt) { if (wasJustCreated) return; var e = evt.target as VisualElement; var boolEvt = evt as ChangeEvent; if (e == enablePlugin) { var patch = boolEvt.newValue; prefs.enablePlugin = patch; SetEnablePluginState(true, patch ? "Patching..." : "Unpatching..."); enablePlugin.MarkDirtyRepaint(); EditorApplication.delayCall += () => { SetEnablePluginState(patch); PatchOrUnpatchAll(patch); }; } else { SaveAndRebuildInspectors(); } } void PatchOrUnpatchAll(bool patch) { if (patch) { Patcher.ApplyPatches(); SaveAndRebuildInspectors(); } else { SaveAndRebuildInspectors(); Patcher.UnpatchAll(); } } void SetEnablePluginState(bool enabled, string text = null) { enablePlugin.text = text ?? (enabled ? "Disable Plugin" : "Enable Plugin"); this.Query().ForEach(x => x.container.SetEnabled(enabled)); } Button PresetsButton() { var icon = FluentUITK.GetEditorIcon("Preset.Context"); return ui.NewButton(icon: icon).Style(Styles.Tab).OnClick(_ => EditorUtils.Presets.ShowMenu(prefs)); } void OnFirstLayoutUpdates() { this.Query().ForEach(TurnFoldoutIntoHeader); ui.x.Query().ForEach(e => e.Fluent().Style(Styles.ToggleLeft)); } void TurnFoldoutIntoHeader(Foldout x) { x.value = true; x.RemoveFromClassList("unity-foldout"); x.Query().First().pickingMode = PickingMode.Ignore; x.Query().Children().ForEach(e => e.pickingMode = PickingMode.Ignore); } } }