From b9ab9342faeee26c54903beb326109698c8525b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 May 2021 15:16:16 +0900 Subject: [PATCH] Setup basics to allow extracting serializable content from skinnable `Drawable`s --- osu.Game/Extensions/DrawableExtensions.cs | 3 ++ osu.Game/Screens/Play/HUD/ISkinnableInfo.cs | 32 ++++++++++++++ .../HUD/SkinnableElementTargetContainer.cs | 11 +++++ .../Screens/Play/HUD/StoredSkinnableInfo.cs | 43 +++++++++++++++++++ osu.Game/Screens/Play/HUDOverlay.cs | 38 +++++++--------- .../Skinning/Editor/SkinBlueprintContainer.cs | 13 +++++- osu.Game/Skinning/ISkin.cs | 2 + 7 files changed, 119 insertions(+), 23 deletions(-) create mode 100644 osu.Game/Screens/Play/HUD/ISkinnableInfo.cs create mode 100644 osu.Game/Screens/Play/HUD/SkinnableElementTargetContainer.cs create mode 100644 osu.Game/Screens/Play/HUD/StoredSkinnableInfo.cs diff --git a/osu.Game/Extensions/DrawableExtensions.cs b/osu.Game/Extensions/DrawableExtensions.cs index a8de3f6407..3d2ffe0ea1 100644 --- a/osu.Game/Extensions/DrawableExtensions.cs +++ b/osu.Game/Extensions/DrawableExtensions.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Framework.Threading; +using osu.Game.Screens.Play.HUD; using osuTK; namespace osu.Game.Extensions @@ -43,5 +44,7 @@ namespace osu.Game.Extensions /// The delta vector in Parent's coordinates. public static Vector2 ScreenSpaceDeltaToParentSpace(this Drawable drawable, Vector2 delta) => drawable.Parent.ToLocalSpace(drawable.Parent.ToScreenSpace(Vector2.Zero) + delta); + + public static StoredSkinnableInfo CreateSerialisedInformation(this Drawable component) => new StoredSkinnableInfo(component); } } diff --git a/osu.Game/Screens/Play/HUD/ISkinnableInfo.cs b/osu.Game/Screens/Play/HUD/ISkinnableInfo.cs new file mode 100644 index 0000000000..0e571b5cb4 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/ISkinnableInfo.cs @@ -0,0 +1,32 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Graphics; +using osu.Game.IO.Serialization; +using osuTK; + +namespace osu.Game.Screens.Play.HUD +{ + public interface ISkinnableInfo : IJsonSerializable + { + public Type Type { get; set; } + + public Type Target { get; set; } + + public Vector2 Position { get; set; } + + public float Rotation { get; set; } + + public Vector2 Scale { get; set; } + + public Anchor Anchor { get; set; } + } + + /// + /// A container which supports skinnable components being added to it. + /// + public interface ISkinnableTarget + { + } +} diff --git a/osu.Game/Screens/Play/HUD/SkinnableElementTargetContainer.cs b/osu.Game/Screens/Play/HUD/SkinnableElementTargetContainer.cs new file mode 100644 index 0000000000..7ba32e2d46 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/SkinnableElementTargetContainer.cs @@ -0,0 +1,11 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Screens.Play.HUD +{ + public class SkinnableElementTargetContainer : Container, ISkinnableTarget + { + } +} diff --git a/osu.Game/Screens/Play/HUD/StoredSkinnableInfo.cs b/osu.Game/Screens/Play/HUD/StoredSkinnableInfo.cs new file mode 100644 index 0000000000..e4ec035e68 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/StoredSkinnableInfo.cs @@ -0,0 +1,43 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Graphics; +using osuTK; + +namespace osu.Game.Screens.Play.HUD +{ + /// + /// Serialised information governing custom changes to an . + /// + public class StoredSkinnableInfo : ISkinnableInfo + { + public StoredSkinnableInfo(Drawable component) + { + Type = component.GetType(); + + var target = component.Parent as ISkinnableTarget + // todo: this is temporary until we serialise the default layouts out of SkinnableDrawables. + ?? component.Parent?.Parent as ISkinnableTarget; + + Target = target?.GetType(); + + Position = component.Position; + Rotation = component.Rotation; + Scale = component.Scale; + Anchor = component.Anchor; + } + + public Type Type { get; set; } + + public Type Target { get; set; } + + public Vector2 Position { get; set; } + + public float Rotation { get; set; } + + public Vector2 Scale { get; set; } + + public Anchor Anchor { get; set; } + } +} diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 6ddaa338cc..13449e3a2b 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -91,16 +91,16 @@ namespace osu.Game.Screens.Play { new Drawable[] { - new Container + new MainHUDElements { RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - HealthDisplay = CreateHealthDisplay(), - AccuracyCounter = CreateAccuracyCounter(), - ScoreCounter = CreateScoreCounter(), - CreateComboCounter(), - CreateHitErrorDisplayOverlay(), + HealthDisplay = new SkinnableHealthDisplay(), + AccuracyCounter = new SkinnableAccuracyCounter(), + ScoreCounter = new SkinnableScoreCounter(), + new SkinnableComboCounter(), + new HitErrorDisplay(this.drawableRuleset?.FirstAvailableHitWindows), } }, }, @@ -263,48 +263,38 @@ namespace osu.Game.Screens.Play Progress.BindDrawableRuleset(drawableRuleset); } - protected SkinnableAccuracyCounter CreateAccuracyCounter() => new SkinnableAccuracyCounter(); - - protected SkinnableScoreCounter CreateScoreCounter() => new SkinnableScoreCounter(); - - protected SkinnableComboCounter CreateComboCounter() => new SkinnableComboCounter(); - - protected SkinnableHealthDisplay CreateHealthDisplay() => new SkinnableHealthDisplay(); - - protected virtual FailingLayer CreateFailingLayer() => new FailingLayer + protected FailingLayer CreateFailingLayer() => new FailingLayer { ShowHealth = { BindTarget = ShowHealthbar } }; - protected virtual KeyCounterDisplay CreateKeyCounter() => new KeyCounterDisplay + protected KeyCounterDisplay CreateKeyCounter() => new KeyCounterDisplay { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, }; - protected virtual SongProgress CreateProgress() => new SongProgress + protected SongProgress CreateProgress() => new SongProgress { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, }; - protected virtual HoldForMenuButton CreateHoldForMenuButton() => new HoldForMenuButton + protected HoldForMenuButton CreateHoldForMenuButton() => new HoldForMenuButton { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, }; - protected virtual ModDisplay CreateModsContainer() => new ModDisplay + protected ModDisplay CreateModsContainer() => new ModDisplay { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, AutoSizeAxes = Axes.Both, }; - protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(drawableRuleset?.FirstAvailableHitWindows); - - protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); + protected PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); public bool OnPressed(GlobalAction action) { @@ -347,5 +337,9 @@ namespace osu.Game.Screens.Play break; } } + + public class MainHUDElements : SkinnableElementTargetContainer + { + } } } diff --git a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs index 35e93d9aff..a6f60afd90 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs @@ -1,9 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.IO; using System.Linq; +using Newtonsoft.Json; using osu.Framework.Graphics; using osu.Framework.Testing; +using osu.Game.Extensions; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Compose.Components; @@ -27,7 +30,15 @@ namespace osu.Game.Skinning.Editor private void checkForComponents() { - foreach (var c in target.ChildrenOfType().ToArray()) AddBlueprintFor(c); + ISkinnableComponent[] skinnableComponents = target.ChildrenOfType().ToArray(); + + // todo: the OfType() call can be removed with better IDrawable support. + string json = JsonConvert.SerializeObject(skinnableComponents.OfType().Select(d => d.CreateSerialisedInformation()), new JsonSerializerSettings { Formatting = Formatting.Indented }); + + File.WriteAllText("/Users/Dean/json-out.json", json); + + foreach (var c in skinnableComponents) + AddBlueprintFor(c); // We'd hope to eventually be running this in a more sensible way, but this handles situations where new drawables become present (ie. during ongoing gameplay) // or when drawables in the target are loaded asynchronously and may not be immediately available when this BlueprintContainer is loaded. diff --git a/osu.Game/Skinning/ISkin.cs b/osu.Game/Skinning/ISkin.cs index 73f7cf6d39..9fa781fa5d 100644 --- a/osu.Game/Skinning/ISkin.cs +++ b/osu.Game/Skinning/ISkin.cs @@ -57,5 +57,7 @@ namespace osu.Game.Skinning /// A matching value boxed in an , or null if unavailable. [CanBeNull] IBindable GetConfig(TLookup lookup); + + // IEnumerable ComponentInfo { get; } } }