Use ISkinnableComponent wherever possible (and expose as BindableList)

This commit is contained in:
Dean Herbert 2021-05-11 17:48:08 +09:00
parent 61ea3f2e64
commit a88a8b7d8d
4 changed files with 42 additions and 28 deletions

View File

@ -1,8 +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.
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Extensions;
using osu.Game.Skinning;
@ -15,30 +17,46 @@ namespace osu.Game.Screens.Play.HUD
public SkinnableTarget Target { get; }
public IBindableList<ISkinnableComponent> Components => components;
private readonly BindableList<ISkinnableComponent> components = new BindableList<ISkinnableComponent>();
public SkinnableElementTargetContainer(SkinnableTarget target)
{
Target = target;
}
public IReadOnlyList<Drawable> Children => content?.Children;
public void Reload()
{
ClearInternal();
components.Clear();
content = CurrentSkin.GetDrawableComponent(new SkinnableTargetComponent(Target)) as SkinnableTargetWrapper;
ClearInternal();
if (content != null)
LoadComponentAsync(content, AddInternal);
{
LoadComponentAsync(content, wrapper =>
{
AddInternal(wrapper);
components.AddRange(wrapper.Children.OfType<ISkinnableComponent>());
});
}
}
public void Add(Drawable drawable)
public void Add(ISkinnableComponent component)
{
if (content == null)
throw new NotSupportedException("Attempting to add a new component to a target container which is not supported by the current skin.");
if (!(component is Drawable drawable))
throw new ArgumentException("Provided argument must be of type {nameof(ISkinnableComponent)}.", nameof(drawable));
content.Add(drawable);
components.Add(component);
}
public IEnumerable<SkinnableInfo> CreateSerialisedChildren() =>
content.Select(d => d.CreateSerialisedInformation());
components.Select(d => ((Drawable)d).CreateSerialisedInformation());
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.EnumExtensions;
@ -207,27 +208,24 @@ namespace osu.Game.Screens.Play
Vector2 lowestScreenSpace = Vector2.Zero;
// TODO: may be null during skin switching. not sure if there's a better way of exposing these children.
if (mainComponents.Children != null)
// LINQ cast can be removed when IDrawable interface includes Anchor / RelativeSizeAxes.
foreach (var element in mainComponents.Components.Cast<Drawable>())
{
foreach (var element in mainComponents.Children)
{
// for now align top-right components with the bottom-edge of the lowest top-anchored hud element.
if (!element.Anchor.HasFlagFast(Anchor.TopRight) && !element.RelativeSizeAxes.HasFlagFast(Axes.X))
continue;
// for now align top-right components with the bottom-edge of the lowest top-anchored hud element.
if (!element.Anchor.HasFlagFast(Anchor.TopRight) && !element.RelativeSizeAxes.HasFlagFast(Axes.X))
continue;
// health bars are excluded for the sake of hacky legacy skins which extend the health bar to take up the full screen area.
if (element is LegacyHealthDisplay)
continue;
// health bars are excluded for the sake of hacky legacy skins which extend the health bar to take up the full screen area.
if (element is LegacyHealthDisplay)
continue;
var bottomRight = element.ScreenSpaceDrawQuad.BottomRight;
if (bottomRight.Y > lowestScreenSpace.Y)
lowestScreenSpace = bottomRight;
}
topRightElements.Y = TopScoringElementsHeight = ToLocalSpace(lowestScreenSpace).Y;
bottomRightElements.Y = -Progress.Height;
var bottomRight = element.ScreenSpaceDrawQuad.BottomRight;
if (bottomRight.Y > lowestScreenSpace.Y)
lowestScreenSpace = bottomRight;
}
topRightElements.Y = TopScoringElementsHeight = ToLocalSpace(lowestScreenSpace).Y;
bottomRightElements.Y = -Progress.Height;
}
private void updateVisibility()

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 osu.Framework.Graphics;
namespace osu.Game.Skinning
{
/// <summary>
@ -20,6 +18,6 @@ namespace osu.Game.Skinning
/// <summary>
/// Add the provided item to this target.
/// </summary>
public void Add(Drawable drawable);
public void Add(ISkinnableComponent drawable);
}
}

View File

@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers;
namespace osu.Game.Skinning
{
/// <summary>
/// A container which is serialised and can encapsulate multiple skinnable elements into a single return type.
/// A container which is serialised and can encapsulate multiple skinnable elements into a single return type (for consumption via <see cref="ISkin.GetDrawableComponent"/>.
/// Will also optionally apply default cross-element layout dependencies when initialised from a non-deserialised source.
/// </summary>
public class SkinnableTargetWrapper : Container, ISkinSerialisable