Skip to content

Allow more granular control over permissible operations on skinnables - #39128

Open
bdach wants to merge 11 commits into
ppy:masterfrom
bdach:more-granular-skinnable-constraints
Open

bdach wants to merge 11 commits into
ppy:masterfrom
bdach:more-granular-skinnable-constraints

Conversation

@bdach

@bdach bdach commented Nov 3, 2026

Copy link
Copy Markdown
Collaborator

RFC.

Currently, ISerialisableDrawable has

/// <summary>
/// Whether this component should be editable by an end user.
/// </summary>
bool IsEditable => true;

The issue with it (other than that nothing actually ever used it) is that it allows for a very crude degree of control over the relevant component. You can do either everything or nothing to it. This diff allows controlling which specific operations apply to which component, as well as controlling whether a component can be placed alongside others.

That last possibility allows to implement singleton components (e.g. components which there should be never more than one of), or mutually exclusive components (if component A is present, then B cannot be). All of this is relevant for results screen work (#24996).

Aside from enforcement in skin editor via hiding all relevant controls, this also adds enforcement at skin deserialization / load time by ignoring impermissible changes made externally in .json files.

If wishing to test this outside of the provided test scenes, one can use

diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorSceneLibrary.cs b/osu.Game/Overlays/SkinEditor/SkinEditorSceneLibrary.cs
index 52dcadd977..505bf7586c 100644
--- a/osu.Game/Overlays/SkinEditor/SkinEditorSceneLibrary.cs
+++ b/osu.Game/Overlays/SkinEditor/SkinEditorSceneLibrary.cs
@@ -2,16 +2,20 @@
 // See the LICENCE file in the repository root for full licence text.
 
 using osu.Framework.Allocation;
+using osu.Framework.Bindables;
 using osu.Framework.Graphics;
 using osu.Framework.Graphics.Containers;
 using osu.Framework.Graphics.Shapes;
 using osu.Framework.Screens;
+using osu.Game.Beatmaps;
 using osu.Game.Graphics;
 using osu.Game.Graphics.Containers;
 using osu.Game.Graphics.Sprites;
 using osu.Game.Graphics.UserInterface;
 using osu.Game.Localisation;
+using osu.Game.Scoring;
 using osu.Game.Screens;
+using osu.Game.Screens.RankingV2;
 using osu.Game.Screens.Select;
 using osuTK;
 
@@ -31,6 +35,15 @@ public partial class SkinEditorSceneLibrary : CompositeDrawable
         [Resolved]
         private SkinEditorOverlay? skinEditorOverlay { get; set; }
 
+        [Resolved]
+        private ScoreManager? scoreManager { get; set; } = null!;
+
+        [Resolved]
+        private BeatmapManager? beatmapManager { get; set; } = null!;
+
+        [Resolved]
+        private Bindable<WorkingBeatmap> beatmap { get; set; } = null!;
+
         public SkinEditorSceneLibrary()
         {
             Height = HEIGHT;
@@ -88,6 +101,21 @@ private void load(OverlayColourProvider overlayColourProvider)
                                     Origin = Anchor.CentreLeft,
                                     Action = () => skinEditorOverlay?.PresentGameplay(),
                                 },
+                                new SceneButton
+                                {
+                                    Text = "Results",
+                                    Anchor = Anchor.CentreLeft,
+                                    Origin = Anchor.CentreLeft,
+                                    Action = () => performer?.PerformFromScreen(screen =>
+                                    {
+                                        var score = scoreManager?.Query(_ => true);
+                                        if (score == null || beatmapManager == null)
+                                            return;
+
+                                        beatmap.Value = beatmapManager.GetWorkingBeatmap(score.BeatmapInfo);
+                                        screen.Push(new SoloResultsScreenV2(score));
+                                    }),
+                                },
                             }
                         },
                     }

and then use the scene library in the skin editor to navigate to the current draft of new results to test.

@bdach bdach self-assigned this Nov 3, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants