From 00fcee0c5a98565122a8ac48fafaf7145bf76dd7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Feb 2023 15:50:48 +0900 Subject: [PATCH] Add per-ruleset component toolbox and placement support --- .../SkinEditor/SkinComponentToolbox.cs | 9 ++-- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 49 ++++++++++++++----- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs b/osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs index cd9f7cc935..de2bb46611 100644 --- a/osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs +++ b/osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -21,12 +22,12 @@ namespace osu.Game.Overlays.SkinEditor { public Action? RequestPlacement; - private readonly CompositeDrawable? target; + private readonly SkinComponentsContainer? target; private FillFlowContainer fill = null!; - public SkinComponentToolbox(CompositeDrawable? target = null) - : base(SkinEditorStrings.Components) + public SkinComponentToolbox(SkinComponentsContainer? target = null) + : base(target?.Lookup.Ruleset == null ? SkinEditorStrings.Components : LocalisableString.Interpolate($"{SkinEditorStrings.Components} ({target.Lookup.Ruleset.Name})")) { this.target = target; } @@ -49,7 +50,7 @@ namespace osu.Game.Overlays.SkinEditor { fill.Clear(); - var skinnableTypes = SerialisedDrawableInfo.GetAllAvailableDrawables(); + var skinnableTypes = SerialisedDrawableInfo.GetAllAvailableDrawables(target?.Lookup.Ruleset); foreach (var type in skinnableTypes) attemptAddComponent(type); } diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index fccddac84f..b3813b4d2c 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -221,6 +221,8 @@ namespace osu.Game.Overlays.SkinEditor }, true); SelectedComponents.BindCollectionChanged((_, _) => Scheduler.AddOnce(populateSettings), true); + + selectedTarget.BindValueChanged(targetChanged, true); } public bool OnPressed(KeyBindingPressEvent e) @@ -274,10 +276,6 @@ namespace osu.Game.Overlays.SkinEditor content.Child = new SkinBlueprintContainer(targetScreen); - selectedTarget.Default = getFirstTarget()?.Lookup; - if (!availableTargets.Any(t => t.Lookup.Equals(selectedTarget.Value))) - selectedTarget.Value = getFirstTarget()?.Lookup; - componentsSidebar.Children = new[] { new EditorSidebarSection("Current working layer") @@ -291,14 +289,41 @@ namespace osu.Game.Overlays.SkinEditor } } }, - new SkinComponentToolbox(getFirstTarget()) - { - RequestPlacement = placeComponent - } }; + + selectedTarget.Default = getFirstTarget()?.Lookup; + + if (!availableTargets.Any(t => t.Lookup.Equals(selectedTarget.Value))) + selectedTarget.Value = getFirstTarget()?.Lookup; + else + selectedTarget.TriggerChange(); } } + private void targetChanged(ValueChangedEvent target) + { + foreach (var toolbox in componentsSidebar.OfType()) + toolbox.Expire(); + + if (target.NewValue == null) + return; + + // If the new target has a ruleset, let's show ruleset-specific items at the top, and the rest below. + if (target.NewValue.Ruleset != null) + { + componentsSidebar.Add(new SkinComponentToolbox(getTarget(target.NewValue)) + { + RequestPlacement = placeComponent + }); + } + + // Remove the ruleset from the lookup to get base components. + componentsSidebar.Add(new SkinComponentToolbox(getTarget(new SkinComponentsContainerLookup(target.NewValue.Target))) + { + RequestPlacement = placeComponent + }); + } + private void skinChanged() { headerText.Clear(); @@ -331,7 +356,7 @@ namespace osu.Game.Overlays.SkinEditor private void placeComponent(ISerialisableDrawable component, bool applyDefaults = true) { - var targetContainer = getFirstTarget(); + var targetContainer = getTarget(selectedTarget.Value); if (targetContainer == null) return; @@ -364,9 +389,9 @@ namespace osu.Game.Overlays.SkinEditor private SkinComponentsContainer? getFirstTarget() => availableTargets.FirstOrDefault(); - private SkinComponentsContainer? getTarget(SkinComponentsContainerLookup.TargetArea target) + private SkinComponentsContainer? getTarget(SkinComponentsContainerLookup? target) { - return availableTargets.FirstOrDefault(c => c.Lookup.Target == target); + return availableTargets.FirstOrDefault(c => c.Lookup.Equals(target)); } private void revert() @@ -378,7 +403,7 @@ namespace osu.Game.Overlays.SkinEditor currentSkin.Value.ResetDrawableTarget(t); // add back default components - getTarget(t.Lookup.Target)?.Reload(); + getTarget(t.Lookup)?.Reload(); } }