1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-13 07:22: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) =>
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.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Screens.Play.HUD.HitErrorMeters
{
public class BarHitErrorMeter : HitErrorMeter, ISkinnableComponent
public class BarHitErrorMeter : HitErrorMeter
{
private readonly Anchor alignment;

View File

@ -4,6 +4,7 @@
using System;
using osu.Framework.Graphics;
using osu.Game.IO.Serialization;
using osu.Game.Skinning;
using osuTK;
namespace osu.Game.Screens.Play.HUD
@ -12,7 +13,7 @@ namespace osu.Game.Screens.Play.HUD
{
public Type Type { get; set; }
public Type Target { get; set; }
public SkinnableTarget? Target { get; set; }
public Vector2 Position { get; set; }
@ -22,11 +23,4 @@ namespace osu.Game.Screens.Play.HUD
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.
// 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;
namespace osu.Game.Screens.Play.HUD
{
public class SkinnableElementTargetContainer : SkinReloadableDrawable, ISkinnableTarget
{
public SkinnableTarget Target { get; }
public SkinnableElementTargetContainer(SkinnableTarget target)
{
Target = target;
}
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
var loadable = skin.GetConfig<Type, IEnumerable<Drawable>>(this.GetType());
var loadable = skin.GetDrawableComponent(new SkinnableTargetComponent(Target));
ClearInternal();
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.
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using osu.Framework.Graphics;
using osu.Game.Extensions;
using osu.Game.Skinning;
using osuTK;
namespace osu.Game.Screens.Play.HUD
@ -10,17 +14,20 @@ namespace osu.Game.Screens.Play.HUD
/// <summary>
/// Serialised information governing custom changes to an <see cref="ISkinnableComponent"/>.
/// </summary>
public class StoredSkinnableInfo : ISkinnableInfo
[Serializable]
public class SkinnableInfo : ISkinnableInfo
{
public StoredSkinnableInfo(Drawable component)
public SkinnableInfo()
{
}
public SkinnableInfo(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;
ISkinnableTarget target = component.Parent as ISkinnableTarget;
Target = target?.GetType();
Target = target?.Target;
Position = component.Position;
Rotation = component.Rotation;
@ -30,7 +37,8 @@ namespace osu.Game.Screens.Play.HUD
public Type Type { get; set; }
public Type Target { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public SkinnableTarget? Target { get; set; }
public Vector2 Position { get; set; }
@ -40,4 +48,14 @@ namespace osu.Game.Screens.Play.HUD
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 MainHUDElements
new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
HealthDisplay = new SkinnableHealthDisplay(),
AccuracyCounter = new SkinnableAccuracyCounter(),
ScoreCounter = new SkinnableScoreCounter(),
new SkinnableComboCounter(),
new HitErrorDisplay(this.drawableRuleset?.FirstAvailableHitWindows),
new SkinnableElementTargetContainer(SkinnableTarget.MainHUDComponents)
{
RelativeSizeAxes = Axes.Both,
},
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;
}
}
public class MainHUDElements : SkinnableElementTargetContainer
{
}
}
}

View File

@ -2,12 +2,17 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using osu.Framework.Audio.Sample;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.OpenGL.Textures;
using osu.Framework.Graphics.Textures;
using osu.Game.Audio;
using osu.Game.Screens.Play.HUD;
using osuTK.Graphics;
namespace osu.Game.Skinning
@ -20,7 +25,29 @@ namespace osu.Game.Skinning
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;
@ -45,4 +72,14 @@ namespace osu.Game.Skinning
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.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using osu.Framework.Audio.Sample;
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;
}
}
}