mirror of
https://github.com/ppy/osu.git
synced 2024-12-15 00:33:21 +08:00
Merge pull request #24387 from peppy/playfield-skin-layer
Add new skin layer to allow components anchored to the playfield
This commit is contained in:
commit
bd8b9c8e63
@ -9,6 +9,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics.Primitives;
|
||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mania.Objects;
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
@ -25,6 +26,22 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
private readonly List<Stage> stages = new List<Stage>();
|
private readonly List<Stage> stages = new List<Stage>();
|
||||||
|
|
||||||
|
public override Quad SkinnableComponentScreenSpaceDrawQuad
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Stages.Count == 1)
|
||||||
|
return Stages.First().ScreenSpaceDrawQuad;
|
||||||
|
|
||||||
|
RectangleF area = RectangleF.Empty;
|
||||||
|
|
||||||
|
foreach (var stage in Stages)
|
||||||
|
area = RectangleF.Union(area, stage.ScreenSpaceDrawQuad.AABBFloat);
|
||||||
|
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => stages.Any(s => s.ReceivePositionalInputAt(screenSpacePos));
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => stages.Any(s => s.ReceivePositionalInputAt(screenSpacePos));
|
||||||
|
|
||||||
public ManiaPlayfield(List<StageDefinition> stageDefinitions)
|
public ManiaPlayfield(List<StageDefinition> stageDefinitions)
|
||||||
|
@ -8,6 +8,7 @@ using osu.Game.Overlays;
|
|||||||
using osu.Game.Overlays.SkinEditor;
|
using osu.Game.Overlays.SkinEditor;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Gameplay
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
{
|
{
|
||||||
@ -19,7 +20,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestToggleEditor()
|
public void TestToggleEditor()
|
||||||
{
|
{
|
||||||
AddStep("show available components", () => SetContents(_ => new SkinComponentToolbox
|
var skinComponentsContainer = new SkinComponentsContainer(new SkinComponentsContainerLookup(SkinComponentsContainerLookup.TargetArea.SongSelect));
|
||||||
|
|
||||||
|
AddStep("show available components", () => SetContents(_ => new SkinComponentToolbox(skinComponentsContainer, null)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
Origin = Anchor.TopRight,
|
Origin = Anchor.TopRight,
|
||||||
|
@ -31,7 +31,7 @@ namespace osu.Game.IO.Archives
|
|||||||
{
|
{
|
||||||
ZipArchiveEntry entry = archive.Entries.SingleOrDefault(e => e.Key == name);
|
ZipArchiveEntry entry = archive.Entries.SingleOrDefault(e => e.Key == name);
|
||||||
if (entry == null)
|
if (entry == null)
|
||||||
throw new FileNotFoundException();
|
return null;
|
||||||
|
|
||||||
var owner = MemoryAllocator.Default.Allocate<byte>((int)entry.Size);
|
var owner = MemoryAllocator.Default.Allocate<byte>((int)entry.Size);
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ using osu.Framework.Threading;
|
|||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Localisation;
|
using osu.Game.Localisation;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Screens.Edit.Components;
|
using osu.Game.Screens.Edit.Components;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -23,14 +24,22 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
{
|
{
|
||||||
public Action<Type>? RequestPlacement;
|
public Action<Type>? RequestPlacement;
|
||||||
|
|
||||||
private readonly SkinComponentsContainer? target;
|
private readonly SkinComponentsContainer target;
|
||||||
|
|
||||||
|
private readonly RulesetInfo? ruleset;
|
||||||
|
|
||||||
private FillFlowContainer fill = null!;
|
private FillFlowContainer fill = null!;
|
||||||
|
|
||||||
public SkinComponentToolbox(SkinComponentsContainer? target = null)
|
/// <summary>
|
||||||
: base(target?.Lookup.Ruleset == null ? SkinEditorStrings.Components : LocalisableString.Interpolate($"{SkinEditorStrings.Components} ({target.Lookup.Ruleset.Name})"))
|
/// Create a new component toolbox for the specified taget.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">The target. This is mainly used as a dependency source to find candidate components.</param>
|
||||||
|
/// <param name="ruleset">A ruleset to filter components by. If null, only components which are not ruleset-specific will be included.</param>
|
||||||
|
public SkinComponentToolbox(SkinComponentsContainer target, RulesetInfo? ruleset)
|
||||||
|
: base(ruleset == null ? SkinEditorStrings.Components : LocalisableString.Interpolate($"{SkinEditorStrings.Components} ({ruleset.Name})"))
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
this.ruleset = ruleset;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -51,7 +60,7 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
{
|
{
|
||||||
fill.Clear();
|
fill.Clear();
|
||||||
|
|
||||||
var skinnableTypes = SerialisedDrawableInfo.GetAllAvailableDrawables(target?.Lookup.Ruleset);
|
var skinnableTypes = SerialisedDrawableInfo.GetAllAvailableDrawables(ruleset);
|
||||||
foreach (var type in skinnableTypes)
|
foreach (var type in skinnableTypes)
|
||||||
attemptAddComponent(type);
|
attemptAddComponent(type);
|
||||||
}
|
}
|
||||||
|
@ -366,14 +366,14 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
// If the new target has a ruleset, let's show ruleset-specific items at the top, and the rest below.
|
// If the new target has a ruleset, let's show ruleset-specific items at the top, and the rest below.
|
||||||
if (target.NewValue.Ruleset != null)
|
if (target.NewValue.Ruleset != null)
|
||||||
{
|
{
|
||||||
componentsSidebar.Add(new SkinComponentToolbox(skinComponentsContainer)
|
componentsSidebar.Add(new SkinComponentToolbox(skinComponentsContainer, target.NewValue.Ruleset)
|
||||||
{
|
{
|
||||||
RequestPlacement = requestPlacement
|
RequestPlacement = requestPlacement
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the ruleset from the lookup to get base components.
|
// Remove the ruleset from the lookup to get base components.
|
||||||
componentsSidebar.Add(new SkinComponentToolbox(getTarget(new SkinComponentsContainerLookup(target.NewValue.Target)))
|
componentsSidebar.Add(new SkinComponentToolbox(skinComponentsContainer, null)
|
||||||
{
|
{
|
||||||
RequestPlacement = requestPlacement
|
RequestPlacement = requestPlacement
|
||||||
});
|
});
|
||||||
|
@ -23,6 +23,7 @@ using osu.Game.Skinning;
|
|||||||
using osuTK;
|
using osuTK;
|
||||||
using osu.Game.Rulesets.Objects.Pooling;
|
using osu.Game.Rulesets.Objects.Pooling;
|
||||||
using osu.Framework.Extensions.ObjectExtensions;
|
using osu.Framework.Extensions.ObjectExtensions;
|
||||||
|
using osu.Framework.Graphics.Primitives;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.UI
|
namespace osu.Game.Rulesets.UI
|
||||||
{
|
{
|
||||||
@ -94,6 +95,16 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly BindableBool DisplayJudgements = new BindableBool(true);
|
public readonly BindableBool DisplayJudgements = new BindableBool(true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A screen space draw quad which resembles the edges of the playfield for skinning purposes.
|
||||||
|
/// This will allow users / components to snap objects to the "edge" of the playfield.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Rulesets which reduce the visible area further than the full relative playfield space itself
|
||||||
|
/// should retarget this to the ScreenSpaceDrawQuad of the appropriate container.
|
||||||
|
/// </remarks>
|
||||||
|
public virtual Quad SkinnableComponentScreenSpaceDrawQuad => ScreenSpaceDrawQuad;
|
||||||
|
|
||||||
[Resolved(CanBeNull = true)]
|
[Resolved(CanBeNull = true)]
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
protected IReadOnlyList<Mod> Mods { get; private set; }
|
protected IReadOnlyList<Mod> Mods { get; private set; }
|
||||||
|
@ -12,6 +12,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Extensions.EnumExtensions;
|
using osu.Framework.Extensions.EnumExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Primitives;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
@ -69,7 +70,9 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
public Bindable<bool> ShowHealthBar = new Bindable<bool>(true);
|
public Bindable<bool> ShowHealthBar = new Bindable<bool>(true);
|
||||||
|
|
||||||
|
[CanBeNull]
|
||||||
private readonly DrawableRuleset drawableRuleset;
|
private readonly DrawableRuleset drawableRuleset;
|
||||||
|
|
||||||
private readonly IReadOnlyList<Mod> mods;
|
private readonly IReadOnlyList<Mod> mods;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -103,10 +106,11 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
private readonly List<Drawable> hideTargets;
|
private readonly List<Drawable> hideTargets;
|
||||||
|
|
||||||
public HUDOverlay(DrawableRuleset drawableRuleset, IReadOnlyList<Mod> mods, bool alwaysShowLeaderboard = true)
|
private readonly Drawable playfieldComponents;
|
||||||
|
|
||||||
|
public HUDOverlay([CanBeNull] DrawableRuleset drawableRuleset, IReadOnlyList<Mod> mods, bool alwaysShowLeaderboard = true)
|
||||||
{
|
{
|
||||||
Drawable rulesetComponents;
|
Drawable rulesetComponents;
|
||||||
|
|
||||||
this.drawableRuleset = drawableRuleset;
|
this.drawableRuleset = drawableRuleset;
|
||||||
this.mods = mods;
|
this.mods = mods;
|
||||||
|
|
||||||
@ -123,6 +127,9 @@ namespace osu.Game.Screens.Play
|
|||||||
rulesetComponents = drawableRuleset != null
|
rulesetComponents = drawableRuleset != null
|
||||||
? new HUDComponentsContainer(drawableRuleset.Ruleset.RulesetInfo) { AlwaysPresent = true, }
|
? new HUDComponentsContainer(drawableRuleset.Ruleset.RulesetInfo) { AlwaysPresent = true, }
|
||||||
: Empty(),
|
: Empty(),
|
||||||
|
playfieldComponents = drawableRuleset != null
|
||||||
|
? new SkinComponentsContainer(new SkinComponentsContainerLookup(SkinComponentsContainerLookup.TargetArea.Playfield, drawableRuleset.Ruleset.RulesetInfo)) { AlwaysPresent = true, }
|
||||||
|
: Empty(),
|
||||||
topRightElements = new FillFlowContainer
|
topRightElements = new FillFlowContainer
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
@ -162,7 +169,7 @@ namespace osu.Game.Screens.Play
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
hideTargets = new List<Drawable> { mainComponents, rulesetComponents, topRightElements };
|
hideTargets = new List<Drawable> { mainComponents, rulesetComponents, playfieldComponents, topRightElements };
|
||||||
|
|
||||||
if (!alwaysShowLeaderboard)
|
if (!alwaysShowLeaderboard)
|
||||||
hideTargets.Add(LeaderboardFlow);
|
hideTargets.Add(LeaderboardFlow);
|
||||||
@ -230,6 +237,16 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
|
if (drawableRuleset != null)
|
||||||
|
{
|
||||||
|
Quad playfieldScreenSpaceDrawQuad = drawableRuleset.Playfield.SkinnableComponentScreenSpaceDrawQuad;
|
||||||
|
|
||||||
|
playfieldComponents.Position = ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft);
|
||||||
|
playfieldComponents.Width = (ToLocalSpace(playfieldScreenSpaceDrawQuad.TopRight) - ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft)).Length;
|
||||||
|
playfieldComponents.Height = (ToLocalSpace(playfieldScreenSpaceDrawQuad.BottomLeft) - ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft)).Length;
|
||||||
|
playfieldComponents.Rotation = drawableRuleset.Playfield.Rotation;
|
||||||
|
}
|
||||||
|
|
||||||
float? lowestTopScreenSpaceLeft = null;
|
float? lowestTopScreenSpaceLeft = null;
|
||||||
float? lowestTopScreenSpaceRight = null;
|
float? lowestTopScreenSpaceRight = null;
|
||||||
|
|
||||||
|
@ -68,7 +68,10 @@ namespace osu.Game.Skinning
|
|||||||
MainHUDComponents,
|
MainHUDComponents,
|
||||||
|
|
||||||
[Description("Song select")]
|
[Description("Song select")]
|
||||||
SongSelect
|
SongSelect,
|
||||||
|
|
||||||
|
[Description("Playfield")]
|
||||||
|
Playfield
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user