1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-13 13:32:54 +08:00

Add the concept of skinnable target containers and mark a basic one for HUD elements

This commit is contained in:
Dean Herbert 2021-05-07 19:13:38 +09:00
parent 67ea4a7e97
commit 95a8f21ab2
11 changed files with 154 additions and 36 deletions

View File

@ -45,6 +45,15 @@ namespace osu.Game.Extensions
public static Vector2 ScreenSpaceDeltaToParentSpace(this Drawable drawable, Vector2 delta) => public static Vector2 ScreenSpaceDeltaToParentSpace(this Drawable drawable, Vector2 delta) =>
drawable.Parent.ToLocalSpace(drawable.Parent.ToScreenSpace(Vector2.Zero) + delta); drawable.Parent.ToLocalSpace(drawable.Parent.ToScreenSpace(Vector2.Zero) + delta);
public static StoredSkinnableInfo CreateSerialisedInformation(this Drawable component) => new StoredSkinnableInfo(component); public static SkinnableInfo CreateSerialisedInformation(this Drawable component) => new SkinnableInfo(component);
public static void ApplySerialisedInformation(this Drawable component, ISkinnableInfo info)
{
// todo: can probably make this better via deserialisation directly using a common interface.
component.Position = info.Position;
component.Rotation = info.Rotation;
component.Scale = info.Scale;
component.Anchor = info.Anchor;
}
} }
} }

View File

@ -13,13 +13,12 @@ using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Screens.Play.HUD.HitErrorMeters namespace osu.Game.Screens.Play.HUD.HitErrorMeters
{ {
public class BarHitErrorMeter : HitErrorMeter, ISkinnableComponent public class BarHitErrorMeter : HitErrorMeter
{ {
private readonly Anchor alignment; private readonly Anchor alignment;

View File

@ -4,6 +4,7 @@
using System; using System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.IO.Serialization; using osu.Game.IO.Serialization;
using osu.Game.Skinning;
using osuTK; using osuTK;
namespace osu.Game.Screens.Play.HUD namespace osu.Game.Screens.Play.HUD
@ -12,7 +13,7 @@ namespace osu.Game.Screens.Play.HUD
{ {
public Type Type { get; set; } public Type Type { get; set; }
public Type Target { get; set; } public SkinnableTarget? Target { get; set; }
public Vector2 Position { get; set; } public Vector2 Position { get; set; }
@ -22,11 +23,4 @@ namespace osu.Game.Screens.Play.HUD
public Anchor Anchor { get; set; } public Anchor Anchor { get; set; }
} }
/// <summary>
/// A container which supports skinnable components being added to it.
/// </summary>
public interface ISkinnableTarget
{
}
} }

View File

@ -0,0 +1,15 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Skinning;
namespace osu.Game.Screens.Play.HUD
{
/// <summary>
/// A container which supports skinnable components being added to it.
/// </summary>
public interface ISkinnableTarget
{
public SkinnableTarget Target { get; }
}
}

View File

@ -1,24 +1,28 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Framework.Graphics;
using osu.Game.Skinning; using osu.Game.Skinning;
namespace osu.Game.Screens.Play.HUD namespace osu.Game.Screens.Play.HUD
{ {
public class SkinnableElementTargetContainer : SkinReloadableDrawable, ISkinnableTarget public class SkinnableElementTargetContainer : SkinReloadableDrawable, ISkinnableTarget
{ {
public SkinnableTarget Target { get; }
public SkinnableElementTargetContainer(SkinnableTarget target)
{
Target = target;
}
protected override void SkinChanged(ISkinSource skin, bool allowFallback) protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{ {
base.SkinChanged(skin, allowFallback); base.SkinChanged(skin, allowFallback);
var loadable = skin.GetConfig<Type, IEnumerable<Drawable>>(this.GetType()); var loadable = skin.GetDrawableComponent(new SkinnableTargetComponent(Target));
ClearInternal(); ClearInternal();
if (loadable != null) if (loadable != null)
LoadComponentsAsync(loadable.Value, AddRangeInternal); LoadComponentAsync(loadable, AddInternal);
} }
} }
} }

View File

@ -2,7 +2,11 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Extensions;
using osu.Game.Skinning;
using osuTK; using osuTK;
namespace osu.Game.Screens.Play.HUD namespace osu.Game.Screens.Play.HUD
@ -10,17 +14,20 @@ namespace osu.Game.Screens.Play.HUD
/// <summary> /// <summary>
/// Serialised information governing custom changes to an <see cref="ISkinnableComponent"/>. /// Serialised information governing custom changes to an <see cref="ISkinnableComponent"/>.
/// </summary> /// </summary>
public class StoredSkinnableInfo : ISkinnableInfo [Serializable]
public class SkinnableInfo : ISkinnableInfo
{ {
public StoredSkinnableInfo(Drawable component) public SkinnableInfo()
{
}
public SkinnableInfo(Drawable component)
{ {
Type = component.GetType(); Type = component.GetType();
var target = component.Parent as ISkinnableTarget ISkinnableTarget 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(); Target = target?.Target;
Position = component.Position; Position = component.Position;
Rotation = component.Rotation; Rotation = component.Rotation;
@ -30,7 +37,8 @@ namespace osu.Game.Screens.Play.HUD
public Type Type { get; set; } public Type Type { get; set; }
public Type Target { get; set; } [JsonConverter(typeof(StringEnumConverter))]
public SkinnableTarget? Target { get; set; }
public Vector2 Position { get; set; } public Vector2 Position { get; set; }
@ -40,4 +48,14 @@ namespace osu.Game.Screens.Play.HUD
public Anchor Anchor { get; set; } public Anchor Anchor { get; set; }
} }
public static class SkinnableInfoExtensions
{
public static Drawable CreateInstance(this ISkinnableInfo info)
{
Drawable d = (Drawable)Activator.CreateInstance(info.Type);
d.ApplySerialisedInformation(info);
return d;
}
}
} }

View File

@ -91,16 +91,37 @@ namespace osu.Game.Screens.Play
{ {
new Drawable[] new Drawable[]
{ {
new MainHUDElements new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Children = new Drawable[] Children = new Drawable[]
{ {
HealthDisplay = new SkinnableHealthDisplay(), new SkinnableElementTargetContainer(SkinnableTarget.MainHUDComponents)
AccuracyCounter = new SkinnableAccuracyCounter(), {
ScoreCounter = new SkinnableScoreCounter(), RelativeSizeAxes = Axes.Both,
new SkinnableComboCounter(), },
new HitErrorDisplay(this.drawableRuleset?.FirstAvailableHitWindows), new Container
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
Children = new Drawable[]
{
// remaining cross-dependencies need tidying.
// kept to ensure non-null, but hidden for testing.
HealthDisplay = new SkinnableHealthDisplay(),
AccuracyCounter = new SkinnableAccuracyCounter(),
ScoreCounter = new SkinnableScoreCounter(),
}
},
new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
// still need to be migrated; a bit more involved.
new HitErrorDisplay(this.drawableRuleset?.FirstAvailableHitWindows),
}
},
} }
}, },
}, },
@ -337,9 +358,5 @@ namespace osu.Game.Screens.Play
break; break;
} }
} }
public class MainHUDElements : SkinnableElementTargetContainer
{
}
} }
} }

View File

@ -2,12 +2,17 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.OpenGL.Textures;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Screens.Play.HUD;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Skinning namespace osu.Game.Skinning
@ -20,7 +25,29 @@ namespace osu.Game.Skinning
Configuration = new DefaultSkinConfiguration(); Configuration = new DefaultSkinConfiguration();
} }
public override Drawable GetDrawableComponent(ISkinComponent component) => null; public override Drawable GetDrawableComponent(ISkinComponent component)
{
switch (component)
{
case SkinnableTargetComponent target:
switch (target.Target)
{
case SkinnableTarget.MainHUDComponents:
var infos = JsonConvert.DeserializeObject<IEnumerable<SkinnableInfo>>(File.ReadAllText("/Users/Dean/json-out.json")).Where(i => i.Target == SkinnableTarget.MainHUDComponents);
var container = new SkinnableTargetWrapper(target.Target)
{
ChildrenEnumerable = infos.Select(i => i.CreateInstance())
};
return container;
}
break;
}
return null;
}
public override Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => null; public override Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => null;
@ -45,4 +72,14 @@ namespace osu.Game.Skinning
return null; return null;
} }
} }
public class SkinnableTargetWrapper : Container, ISkinnableTarget
{
public SkinnableTarget Target { get; }
public SkinnableTargetWrapper(SkinnableTarget target)
{
Target = target;
}
}
} }

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using JetBrains.Annotations; using JetBrains.Annotations;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
using osu.Framework.Bindables; using osu.Framework.Bindables;

View File

@ -0,0 +1,10 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Skinning
{
public enum SkinnableTarget
{
MainHUDComponents
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Skinning
{
public class SkinnableTargetComponent : ISkinComponent
{
public readonly SkinnableTarget Target;
public string LookupName => Target.ToString();
public SkinnableTargetComponent(SkinnableTarget target)
{
Target = target;
}
}
}