1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-22 05:23:05 +08:00

Merge branch 'master' into add-overlay-link-colours

This commit is contained in:
Bartłomiej Dach 2021-05-17 20:11:27 +02:00 committed by GitHub
commit 2bf62b86ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 258 additions and 211 deletions

View File

@ -166,7 +166,7 @@ namespace osu.Game.Rulesets.Osu.Statistics
var point = new HitPoint(pointType, this) var point = new HitPoint(pointType, this)
{ {
Colour = pointType == HitPointType.Hit ? new Color4(102, 255, 204, 255) : new Color4(255, 102, 102, 255) BaseColour = pointType == HitPointType.Hit ? new Color4(102, 255, 204, 255) : new Color4(255, 102, 102, 255)
}; };
points[r][c] = point; points[r][c] = point;
@ -234,6 +234,11 @@ namespace osu.Game.Rulesets.Osu.Statistics
private class HitPoint : Circle private class HitPoint : Circle
{ {
/// <summary>
/// The base colour which will be lightened/darkened depending on the value of this <see cref="HitPoint"/>.
/// </summary>
public Color4 BaseColour;
private readonly HitPointType pointType; private readonly HitPointType pointType;
private readonly AccuracyHeatmap heatmap; private readonly AccuracyHeatmap heatmap;
@ -284,7 +289,7 @@ namespace osu.Game.Rulesets.Osu.Statistics
Alpha = Math.Min(amount / lighten_cutoff, 1); Alpha = Math.Min(amount / lighten_cutoff, 1);
if (pointType == HitPointType.Hit) if (pointType == HitPointType.Hit)
Colour = ((Color4)Colour).Lighten(Math.Max(0, amount - lighten_cutoff)); Colour = BaseColour.Lighten(Math.Max(0, amount - lighten_cutoff));
} }
} }

View File

@ -63,7 +63,7 @@ namespace osu.Game.Tests.Visual.Gameplay
private void seekToBreak(int breakIndex) private void seekToBreak(int breakIndex)
{ {
AddStep($"seek to break {breakIndex}", () => Player.GameplayClockContainer.Seek(destBreak().StartTime)); AddStep($"seek to break {breakIndex}", () => Player.GameplayClockContainer.Seek(destBreak().StartTime));
AddUntilStep("wait for seek to complete", () => Player.HUDOverlay.Progress.ReferenceClock.CurrentTime >= destBreak().StartTime); AddUntilStep("wait for seek to complete", () => Player.DrawableRuleset.FrameStableClock.CurrentTime >= destBreak().StartTime);
BreakPeriod destBreak() => Beatmap.Value.Beatmap.Breaks.ElementAt(breakIndex); BreakPeriod destBreak() => Beatmap.Value.Beatmap.Breaks.ElementAt(breakIndex);
} }

View File

@ -0,0 +1,128 @@
// 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;
using System.IO;
using osu.Framework.Allocation;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Screens;
using osuTK;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Localisation;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Framework.Screens;
namespace osu.Game.Overlays.Settings.Sections.Maintenance
{
public abstract class DirectorySelectScreen : OsuScreen
{
private TriangleButton selectionButton;
private DirectorySelector directorySelector;
/// <summary>
/// Text to display in the header to inform the user of what they are selecting.
/// </summary>
public abstract LocalisableString HeaderText { get; }
/// <summary>
/// Called upon selection of a directory by the user.
/// </summary>
/// <param name="directory">The selected directory</param>
protected abstract void OnSelection(DirectoryInfo directory);
/// <summary>
/// Whether the current directory is considered to be valid and can be selected.
/// </summary>
/// <param name="info">The current directory.</param>
/// <returns>Whether the selected directory is considered valid.</returns>
protected virtual bool IsValidDirectory(DirectoryInfo info) => true;
/// <summary>
/// The path at which to start selection from.
/// </summary>
protected virtual DirectoryInfo InitialPath => null;
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
InternalChild = new Container
{
Masking = true,
CornerRadius = 10,
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(0.5f, 0.8f),
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colours.GreySeafoamDark
},
new GridContainer
{
RelativeSizeAxes = Axes.Both,
RowDimensions = new[]
{
new Dimension(),
new Dimension(GridSizeMode.Relative, 0.8f),
new Dimension(),
},
Content = new[]
{
new Drawable[]
{
new OsuSpriteText
{
Text = HeaderText,
Font = OsuFont.Default.With(size: 40),
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
}
},
new Drawable[]
{
directorySelector = new DirectorySelector
{
RelativeSizeAxes = Axes.Both,
}
},
new Drawable[]
{
selectionButton = new TriangleButton
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Width = 300,
Text = "Select directory",
Action = () => OnSelection(directorySelector.CurrentPath.Value)
},
}
}
}
}
};
}
protected override void LoadComplete()
{
if (InitialPath != null)
directorySelector.CurrentPath.Value = InitialPath;
directorySelector.CurrentPath.BindValueChanged(e => selectionButton.Enabled.Value = e.NewValue != null && IsValidDirectory(e.NewValue), true);
base.LoadComplete();
}
public override void OnSuspending(IScreen next)
{
base.OnSuspending(next);
this.FadeOut(250);
}
}
}

View File

@ -4,24 +4,19 @@
using System; using System;
using System.IO; using System.IO;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Localisation;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Screens;
using osuTK;
namespace osu.Game.Overlays.Settings.Sections.Maintenance namespace osu.Game.Overlays.Settings.Sections.Maintenance
{ {
public class MigrationSelectScreen : OsuScreen public class MigrationSelectScreen : DirectorySelectScreen
{ {
private DirectorySelector directorySelector; [Resolved]
private Storage storage { get; set; }
protected override DirectoryInfo InitialPath => new DirectoryInfo(storage.GetFullPath(string.Empty)).Parent;
public override bool AllowExternalScreenChange => false; public override bool AllowExternalScreenChange => false;
@ -29,84 +24,11 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
public override bool HideOverlaysOnEnter => true; public override bool HideOverlaysOnEnter => true;
[BackgroundDependencyLoader(true)] public override LocalisableString HeaderText => "Please select a new location";
private void load(OsuGame game, Storage storage, OsuColour colours)
{
game?.Toolbar.Hide();
// begin selection in the parent directory of the current storage location protected override void OnSelection(DirectoryInfo directory)
var initialPath = new DirectoryInfo(storage.GetFullPath(string.Empty)).Parent?.FullName;
InternalChild = new Container
{ {
Masking = true, var target = directory;
CornerRadius = 10,
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(0.5f, 0.8f),
Children = new Drawable[]
{
new Box
{
Colour = colours.GreySeafoamDark,
RelativeSizeAxes = Axes.Both,
},
new GridContainer
{
RelativeSizeAxes = Axes.Both,
RowDimensions = new[]
{
new Dimension(),
new Dimension(GridSizeMode.Relative, 0.8f),
new Dimension(),
},
Content = new[]
{
new Drawable[]
{
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = "Please select a new location",
Font = OsuFont.Default.With(size: 40)
},
},
new Drawable[]
{
directorySelector = new DirectorySelector(initialPath)
{
RelativeSizeAxes = Axes.Both,
}
},
new Drawable[]
{
new TriangleButton
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Width = 300,
Text = "Begin folder migration",
Action = start
},
}
}
}
}
};
}
public override void OnSuspending(IScreen next)
{
base.OnSuspending(next);
this.FadeOut(250);
}
private void start()
{
var target = directorySelector.CurrentPath.Value;
try try
{ {

View File

@ -35,8 +35,12 @@ namespace osu.Game.Screens.Play
/// </summary> /// </summary>
public float TopScoringElementsHeight { get; private set; } public float TopScoringElementsHeight { get; private set; }
/// <summary>
/// The total height of all the bottom of screen scoring elements.
/// </summary>
public float BottomScoringElementsHeight { get; private set; }
public readonly KeyCounterDisplay KeyCounter; public readonly KeyCounterDisplay KeyCounter;
public readonly SongProgress Progress;
public readonly ModDisplay ModDisplay; public readonly ModDisplay ModDisplay;
public readonly HoldForMenuButton HoldToQuit; public readonly HoldForMenuButton HoldToQuit;
public readonly PlayerSettingsOverlay PlayerSettingsOverlay; public readonly PlayerSettingsOverlay PlayerSettingsOverlay;
@ -59,8 +63,6 @@ namespace osu.Game.Screens.Play
private static bool hasShownNotificationOnce; private static bool hasShownNotificationOnce;
public Action<double> RequestSeek;
private readonly FillFlowContainer bottomRightElements; private readonly FillFlowContainer bottomRightElements;
private readonly FillFlowContainer topRightElements; private readonly FillFlowContainer topRightElements;
@ -83,16 +85,6 @@ namespace osu.Game.Screens.Play
{ {
CreateFailingLayer(), CreateFailingLayer(),
visibilityContainer = new Container visibilityContainer = new Container
{
RelativeSizeAxes = Axes.Both,
Child = new GridContainer
{
RelativeSizeAxes = Axes.Both,
Content = new[]
{
new Drawable[]
{
new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Children = new Drawable[] Children = new Drawable[]
@ -112,19 +104,6 @@ namespace osu.Game.Screens.Play
}, },
} }
}, },
},
new Drawable[]
{
Progress = CreateProgress(),
}
},
RowDimensions = new[]
{
new Dimension(),
new Dimension(GridSizeMode.AutoSize)
}
},
},
topRightElements = new FillFlowContainer topRightElements = new FillFlowContainer
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
@ -164,10 +143,6 @@ namespace osu.Game.Screens.Play
if (drawableRuleset != null) if (drawableRuleset != null)
{ {
BindDrawableRuleset(drawableRuleset); BindDrawableRuleset(drawableRuleset);
Progress.Objects = drawableRuleset.Objects;
Progress.RequestSeek = time => RequestSeek(time);
Progress.ReferenceClock = drawableRuleset.FrameStableClock;
} }
ModDisplay.Current.Value = mods; ModDisplay.Current.Value = mods;
@ -206,26 +181,43 @@ namespace osu.Game.Screens.Play
{ {
base.Update(); base.Update();
Vector2 lowestScreenSpace = Vector2.Zero; Vector2? lowestTopScreenSpace = null;
Vector2? highestBottomScreenSpace = null;
// LINQ cast can be removed when IDrawable interface includes Anchor / RelativeSizeAxes. // LINQ cast can be removed when IDrawable interface includes Anchor / RelativeSizeAxes.
foreach (var element in mainComponents.Components.Cast<Drawable>()) foreach (var element in mainComponents.Components.Cast<Drawable>())
{ {
// for now align top-right components with the bottom-edge of the lowest top-anchored hud element. // 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)) if (!element.RelativeSizeAxes.HasFlagFast(Axes.X))
continue; continue;
if (element.Anchor.HasFlagFast(Anchor.TopRight))
{
// health bars are excluded for the sake of hacky legacy skins which extend the health bar to take up the full screen area. // 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) if (element is LegacyHealthDisplay)
continue; continue;
var bottomRight = element.ScreenSpaceDrawQuad.BottomRight; var bottomRight = element.ScreenSpaceDrawQuad.BottomRight;
if (bottomRight.Y > lowestScreenSpace.Y) if (lowestTopScreenSpace == null || bottomRight.Y > lowestTopScreenSpace.Value.Y)
lowestScreenSpace = bottomRight; lowestTopScreenSpace = bottomRight;
}
else if (element.Anchor.HasFlagFast(Anchor.y2))
{
var topLeft = element.ScreenSpaceDrawQuad.TopLeft;
if (highestBottomScreenSpace == null || topLeft.Y < highestBottomScreenSpace.Value.Y)
highestBottomScreenSpace = topLeft;
}
} }
topRightElements.Y = TopScoringElementsHeight = ToLocalSpace(lowestScreenSpace).Y; if (lowestTopScreenSpace.HasValue)
bottomRightElements.Y = -Progress.Height; topRightElements.Y = TopScoringElementsHeight = ToLocalSpace(lowestTopScreenSpace.Value).Y;
else
topRightElements.Y = 0;
if (highestBottomScreenSpace.HasValue)
bottomRightElements.Y = BottomScoringElementsHeight = -(DrawHeight - ToLocalSpace(highestBottomScreenSpace.Value).Y);
else
bottomRightElements.Y = 0;
} }
private void updateVisibility() private void updateVisibility()
@ -281,8 +273,6 @@ namespace osu.Game.Screens.Play
(drawableRuleset as ICanAttachKeyCounter)?.Attach(KeyCounter); (drawableRuleset as ICanAttachKeyCounter)?.Attach(KeyCounter);
replayLoaded.BindTo(drawableRuleset.HasReplayLoaded); replayLoaded.BindTo(drawableRuleset.HasReplayLoaded);
Progress.BindDrawableRuleset(drawableRuleset);
} }
protected FailingLayer CreateFailingLayer() => new FailingLayer protected FailingLayer CreateFailingLayer() => new FailingLayer
@ -296,13 +286,6 @@ namespace osu.Game.Screens.Play
Origin = Anchor.BottomRight, Origin = Anchor.BottomRight,
}; };
protected SongProgress CreateProgress() => new SongProgress
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.X,
};
protected HoldForMenuButton CreateHoldForMenuButton() => new HoldForMenuButton protected HoldForMenuButton CreateHoldForMenuButton() => new HoldForMenuButton
{ {
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,

View File

@ -154,6 +154,9 @@ namespace osu.Game.Screens.Play
{ {
base.LoadComplete(); base.LoadComplete();
if (!LoadedBeatmapSuccessfully)
return;
// replays should never be recorded or played back when autoplay is enabled // replays should never be recorded or played back when autoplay is enabled
if (!Mods.Value.Any(m => m is ModAutoplay)) if (!Mods.Value.Any(m => m is ModAutoplay))
PrepareReplay(); PrepareReplay();
@ -198,6 +201,7 @@ namespace osu.Game.Screens.Play
LocalUserPlaying.BindTo(osuGame.LocalUserPlaying); LocalUserPlaying.BindTo(osuGame.LocalUserPlaying);
DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value); DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value);
dependencies.CacheAs(DrawableRuleset);
ScoreProcessor = ruleset.CreateScoreProcessor(); ScoreProcessor = ruleset.CreateScoreProcessor();
ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.ApplyBeatmap(playableBeatmap);
@ -357,11 +361,6 @@ namespace osu.Game.Screens.Play
AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded }, AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded },
IsCounting = false IsCounting = false
}, },
RequestSeek = time =>
{
GameplayClockContainer.Seek(time);
GameplayClockContainer.Start();
},
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre Origin = Anchor.Centre
}, },
@ -566,6 +565,12 @@ namespace osu.Game.Screens.Play
updateSampleDisabledState(); updateSampleDisabledState();
} }
/// <summary>
/// Seek to a specific time in gameplay.
/// </summary>
/// <param name="time">The destination time to seek to.</param>
public void Seek(double time) => GameplayClockContainer.Seek(time);
/// <summary> /// <summary>
/// Restart gameplay via a parent <see cref="PlayerLoader"/>. /// Restart gameplay via a parent <see cref="PlayerLoader"/>.
/// <remarks>This can be called from a child screen in order to trigger the restart process.</remarks> /// <remarks>This can be called from a child screen in order to trigger the restart process.</remarks>

View File

@ -14,10 +14,11 @@ using osu.Framework.Timing;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Skinning;
namespace osu.Game.Screens.Play namespace osu.Game.Screens.Play
{ {
public class SongProgress : OverlayContainer public class SongProgress : OverlayContainer, ISkinnableDrawable
{ {
private const int info_height = 20; private const int info_height = 20;
private const int bottom_bar_height = 5; private const int bottom_bar_height = 5;
@ -39,9 +40,6 @@ namespace osu.Game.Screens.Play
public readonly Bindable<bool> ShowGraph = new Bindable<bool>(); public readonly Bindable<bool> ShowGraph = new Bindable<bool>();
//TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list).
private double lastHitTime => objects.Last().GetEndTime() + 1;
public override bool HandleNonPositionalInput => AllowSeeking.Value; public override bool HandleNonPositionalInput => AllowSeeking.Value;
public override bool HandlePositionalInput => AllowSeeking.Value; public override bool HandlePositionalInput => AllowSeeking.Value;
@ -49,6 +47,9 @@ namespace osu.Game.Screens.Play
private double firstHitTime => objects.First().StartTime; private double firstHitTime => objects.First().StartTime;
//TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list).
private double lastHitTime => objects.Last().GetEndTime() + 1;
private IEnumerable<HitObject> objects; private IEnumerable<HitObject> objects;
public IEnumerable<HitObject> Objects public IEnumerable<HitObject> Objects
@ -65,16 +66,20 @@ namespace osu.Game.Screens.Play
} }
} }
public IClock ReferenceClock; [Resolved(canBeNull: true)]
private Player player { get; set; }
private IClock gameplayClock; [Resolved(canBeNull: true)]
private GameplayClock gameplayClock { get; set; }
private IClock referenceClock;
public SongProgress() public SongProgress()
{ {
Children = new Drawable[] RelativeSizeAxes = Axes.X;
{ Anchor = Anchor.BottomRight;
new SongProgressDisplay Origin = Anchor.BottomRight;
{
Children = new Drawable[] Children = new Drawable[]
{ {
info = new SongProgressInfo info = new SongProgressInfo
@ -96,20 +101,23 @@ namespace osu.Game.Screens.Play
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
OnSeek = time => RequestSeek?.Invoke(time), OnSeek = time => player?.Seek(time),
},
}
}, },
}; };
} }
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(OsuColour colours, GameplayClock clock, OsuConfigManager config) private void load(OsuColour colours, OsuConfigManager config, DrawableRuleset drawableRuleset)
{ {
base.LoadComplete(); base.LoadComplete();
if (clock != null) if (drawableRuleset != null)
gameplayClock = clock; {
AllowSeeking.BindTo(drawableRuleset.HasReplayLoaded);
referenceClock = drawableRuleset.FrameStableClock;
Objects = drawableRuleset.Objects;
}
config.BindWith(OsuSetting.ShowProgressGraph, ShowGraph); config.BindWith(OsuSetting.ShowProgressGraph, ShowGraph);
@ -124,11 +132,6 @@ namespace osu.Game.Screens.Play
ShowGraph.BindValueChanged(_ => updateGraphVisibility(), true); ShowGraph.BindValueChanged(_ => updateGraphVisibility(), true);
} }
public void BindDrawableRuleset(DrawableRuleset drawableRuleset)
{
AllowSeeking.BindTo(drawableRuleset.HasReplayLoaded);
}
protected override void PopIn() protected override void PopIn()
{ {
this.FadeIn(500, Easing.OutQuint); this.FadeIn(500, Easing.OutQuint);
@ -147,7 +150,7 @@ namespace osu.Game.Screens.Play
return; return;
double gameplayTime = gameplayClock?.CurrentTime ?? Time.Current; double gameplayTime = gameplayClock?.CurrentTime ?? Time.Current;
double frameStableTime = ReferenceClock?.CurrentTime ?? gameplayTime; double frameStableTime = referenceClock?.CurrentTime ?? gameplayTime;
double progress = Math.Min(1, (frameStableTime - firstHitTime) / (lastHitTime - firstHitTime)); double progress = Math.Min(1, (frameStableTime - firstHitTime) / (lastHitTime - firstHitTime));
@ -179,19 +182,5 @@ namespace osu.Game.Screens.Play
float finalMargin = bottom_bar_height + (AllowSeeking.Value ? handle_size.Y : 0) + (ShowGraph.Value ? graph_height : 0); float finalMargin = bottom_bar_height + (AllowSeeking.Value ? handle_size.Y : 0) + (ShowGraph.Value ? graph_height : 0);
info.TransformTo(nameof(info.Margin), new MarginPadding { Bottom = finalMargin }, transition_duration, Easing.In); info.TransformTo(nameof(info.Margin), new MarginPadding { Bottom = finalMargin }, transition_duration, Easing.In);
} }
public class SongProgressDisplay : Container
{
public SongProgressDisplay()
{
// TODO: move actual implementation into this.
// exists for skin customisation purposes (interface should be added to this container).
Masking = true;
RelativeSizeAxes = Axes.Both;
Anchor = Anchor.BottomCentre;
Origin = Anchor.BottomCentre;
}
}
} }
} }

View File

@ -12,6 +12,7 @@ using osu.Framework.Graphics.Textures;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Extensions; using osu.Game.Extensions;
using osu.Game.IO; using osu.Game.IO;
using osu.Game.Screens.Play;
using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
@ -86,6 +87,7 @@ namespace osu.Game.Skinning
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.ScoreCounter)), GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.ScoreCounter)),
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter)), GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter)),
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.HealthDisplay)), GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.HealthDisplay)),
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.SongProgress)),
} }
}; };
@ -109,6 +111,9 @@ namespace osu.Game.Skinning
case HUDSkinComponents.HealthDisplay: case HUDSkinComponents.HealthDisplay:
return new DefaultHealthDisplay(); return new DefaultHealthDisplay();
case HUDSkinComponents.SongProgress:
return new SongProgress();
} }
break; break;

View File

@ -57,7 +57,10 @@ namespace osu.Game.Skinning.Editor
Spacing = new Vector2(20) Spacing = new Vector2(20)
}; };
var skinnableTypes = typeof(OsuGame).Assembly.GetTypes().Where(t => typeof(ISkinnableDrawable).IsAssignableFrom(t)).ToArray(); var skinnableTypes = typeof(OsuGame).Assembly.GetTypes()
.Where(t => !t.IsInterface)
.Where(t => typeof(ISkinnableDrawable).IsAssignableFrom(t))
.ToArray();
foreach (var type in skinnableTypes) foreach (var type in skinnableTypes)
{ {
@ -92,6 +95,10 @@ namespace osu.Game.Skinning.Editor
private class ToolboxComponentButton : OsuButton private class ToolboxComponentButton : OsuButton
{ {
protected override bool ShouldBeConsideredForInput(Drawable child) => false;
public override bool PropagateNonPositionalInputSubTree => false;
private readonly Drawable component; private readonly Drawable component;
public Action<Type> RequestPlacement; public Action<Type> RequestPlacement;

View File

@ -9,5 +9,6 @@ namespace osu.Game.Skinning
ScoreCounter, ScoreCounter,
AccuracyCounter, AccuracyCounter,
HealthDisplay, HealthDisplay,
SongProgress,
} }
} }

View File

@ -17,6 +17,7 @@ using osu.Game.Audio;
using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Formats;
using osu.Game.IO; using osu.Game.IO;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play;
using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD;
using osuTK.Graphics; using osuTK.Graphics;
@ -350,6 +351,7 @@ namespace osu.Game.Skinning
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.ScoreCounter)) ?? new DefaultScoreCounter(), GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.ScoreCounter)) ?? new DefaultScoreCounter(),
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter)) ?? new DefaultAccuracyCounter(), GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter)) ?? new DefaultAccuracyCounter(),
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.HealthDisplay)) ?? new DefaultHealthDisplay(), GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.HealthDisplay)) ?? new DefaultHealthDisplay(),
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.SongProgress)) ?? new SongProgress(),
} }
}; };