diff --git a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs
index 88c855d768..cb769c31b8 100644
--- a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs
+++ b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs
@@ -166,7 +166,7 @@ namespace osu.Game.Rulesets.Osu.Statistics
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;
@@ -234,6 +234,11 @@ namespace osu.Game.Rulesets.Osu.Statistics
private class HitPoint : Circle
{
+ ///
+ /// The base colour which will be lightened/darkened depending on the value of this .
+ ///
+ public Color4 BaseColour;
+
private readonly HitPointType pointType;
private readonly AccuracyHeatmap heatmap;
@@ -284,7 +289,7 @@ namespace osu.Game.Rulesets.Osu.Statistics
Alpha = Math.Min(amount / lighten_cutoff, 1);
if (pointType == HitPointType.Hit)
- Colour = ((Color4)Colour).Lighten(Math.Max(0, amount - lighten_cutoff));
+ Colour = BaseColour.Lighten(Math.Max(0, amount - lighten_cutoff));
}
}
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs
index e198a8504b..e47c782bca 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs
@@ -63,7 +63,7 @@ namespace osu.Game.Tests.Visual.Gameplay
private void seekToBreak(int breakIndex)
{
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);
}
diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs
new file mode 100644
index 0000000000..e7c69e89fe
--- /dev/null
+++ b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs
@@ -0,0 +1,128 @@
+// Copyright (c) ppy Pty Ltd . 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;
+
+ ///
+ /// Text to display in the header to inform the user of what they are selecting.
+ ///
+ public abstract LocalisableString HeaderText { get; }
+
+ ///
+ /// Called upon selection of a directory by the user.
+ ///
+ /// The selected directory
+ protected abstract void OnSelection(DirectoryInfo directory);
+
+ ///
+ /// Whether the current directory is considered to be valid and can be selected.
+ ///
+ /// The current directory.
+ /// Whether the selected directory is considered valid.
+ protected virtual bool IsValidDirectory(DirectoryInfo info) => true;
+
+ ///
+ /// The path at which to start selection from.
+ ///
+ 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);
+ }
+ }
+}
diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationSelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationSelectScreen.cs
index ad540e3691..1a60ab0638 100644
--- a/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationSelectScreen.cs
+++ b/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationSelectScreen.cs
@@ -4,24 +4,19 @@
using System;
using System.IO;
using osu.Framework.Allocation;
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Containers;
-using osu.Framework.Graphics.Shapes;
+using osu.Framework.Localisation;
using osu.Framework.Logging;
using osu.Framework.Platform;
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
{
- 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;
@@ -29,84 +24,11 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
public override bool HideOverlaysOnEnter => true;
- [BackgroundDependencyLoader(true)]
- private void load(OsuGame game, Storage storage, OsuColour colours)
+ public override LocalisableString HeaderText => "Please select a new location";
+
+ protected override void OnSelection(DirectoryInfo directory)
{
- game?.Toolbar.Hide();
-
- // begin selection in the parent directory of the current storage location
- var initialPath = new DirectoryInfo(storage.GetFullPath(string.Empty)).Parent?.FullName;
-
- 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
- {
- 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;
+ var target = directory;
try
{
diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs
index a10e91dae8..dcee64ff0d 100644
--- a/osu.Game/Screens/Play/HUDOverlay.cs
+++ b/osu.Game/Screens/Play/HUDOverlay.cs
@@ -35,8 +35,12 @@ namespace osu.Game.Screens.Play
///
public float TopScoringElementsHeight { get; private set; }
+ ///
+ /// The total height of all the bottom of screen scoring elements.
+ ///
+ public float BottomScoringElementsHeight { get; private set; }
+
public readonly KeyCounterDisplay KeyCounter;
- public readonly SongProgress Progress;
public readonly ModDisplay ModDisplay;
public readonly HoldForMenuButton HoldToQuit;
public readonly PlayerSettingsOverlay PlayerSettingsOverlay;
@@ -59,8 +63,6 @@ namespace osu.Game.Screens.Play
private static bool hasShownNotificationOnce;
- public Action RequestSeek;
-
private readonly FillFlowContainer bottomRightElements;
private readonly FillFlowContainer topRightElements;
@@ -85,45 +87,22 @@ namespace osu.Game.Screens.Play
visibilityContainer = new Container
{
RelativeSizeAxes = Axes.Both,
- Child = new GridContainer
+ Children = new Drawable[]
{
- RelativeSizeAxes = Axes.Both,
- Content = new[]
+ mainComponents = new SkinnableTargetContainer(SkinnableTarget.MainHUDComponents)
{
- new Drawable[]
+ RelativeSizeAxes = Axes.Both,
+ },
+ new Container
+ {
+ RelativeSizeAxes = Axes.Both,
+ Children = new Drawable[]
{
- new Container
- {
- RelativeSizeAxes = Axes.Both,
- Children = new Drawable[]
- {
- mainComponents = new SkinnableTargetContainer(SkinnableTarget.MainHUDComponents)
- {
- RelativeSizeAxes = Axes.Both,
- },
- new Container
- {
- RelativeSizeAxes = Axes.Both,
- Children = new Drawable[]
- {
- // still need to be migrated; a bit more involved.
- new HitErrorDisplay(this.drawableRuleset?.FirstAvailableHitWindows),
- }
- },
- }
- },
- },
- new Drawable[]
- {
- Progress = CreateProgress(),
+ // still need to be migrated; a bit more involved.
+ new HitErrorDisplay(this.drawableRuleset?.FirstAvailableHitWindows),
}
},
- RowDimensions = new[]
- {
- new Dimension(),
- new Dimension(GridSizeMode.AutoSize)
- }
- },
+ }
},
topRightElements = new FillFlowContainer
{
@@ -164,10 +143,6 @@ namespace osu.Game.Screens.Play
if (drawableRuleset != null)
{
BindDrawableRuleset(drawableRuleset);
-
- Progress.Objects = drawableRuleset.Objects;
- Progress.RequestSeek = time => RequestSeek(time);
- Progress.ReferenceClock = drawableRuleset.FrameStableClock;
}
ModDisplay.Current.Value = mods;
@@ -206,26 +181,43 @@ namespace osu.Game.Screens.Play
{
base.Update();
- Vector2 lowestScreenSpace = Vector2.Zero;
+ Vector2? lowestTopScreenSpace = null;
+ Vector2? highestBottomScreenSpace = null;
// LINQ cast can be removed when IDrawable interface includes Anchor / RelativeSizeAxes.
foreach (var element in mainComponents.Components.Cast())
{
// 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;
- // 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;
+ 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.
+ if (element is LegacyHealthDisplay)
+ continue;
- var bottomRight = element.ScreenSpaceDrawQuad.BottomRight;
- if (bottomRight.Y > lowestScreenSpace.Y)
- lowestScreenSpace = bottomRight;
+ var bottomRight = element.ScreenSpaceDrawQuad.BottomRight;
+ if (lowestTopScreenSpace == null || bottomRight.Y > lowestTopScreenSpace.Value.Y)
+ 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;
- bottomRightElements.Y = -Progress.Height;
+ if (lowestTopScreenSpace.HasValue)
+ 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()
@@ -281,8 +273,6 @@ namespace osu.Game.Screens.Play
(drawableRuleset as ICanAttachKeyCounter)?.Attach(KeyCounter);
replayLoaded.BindTo(drawableRuleset.HasReplayLoaded);
-
- Progress.BindDrawableRuleset(drawableRuleset);
}
protected FailingLayer CreateFailingLayer() => new FailingLayer
@@ -296,13 +286,6 @@ namespace osu.Game.Screens.Play
Origin = Anchor.BottomRight,
};
- protected SongProgress CreateProgress() => new SongProgress
- {
- Anchor = Anchor.BottomLeft,
- Origin = Anchor.BottomLeft,
- RelativeSizeAxes = Axes.X,
- };
-
protected HoldForMenuButton CreateHoldForMenuButton() => new HoldForMenuButton
{
Anchor = Anchor.BottomRight,
diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs
index ac0c921ccf..890883f0d2 100644
--- a/osu.Game/Screens/Play/Player.cs
+++ b/osu.Game/Screens/Play/Player.cs
@@ -154,6 +154,9 @@ namespace osu.Game.Screens.Play
{
base.LoadComplete();
+ if (!LoadedBeatmapSuccessfully)
+ return;
+
// replays should never be recorded or played back when autoplay is enabled
if (!Mods.Value.Any(m => m is ModAutoplay))
PrepareReplay();
@@ -198,6 +201,7 @@ namespace osu.Game.Screens.Play
LocalUserPlaying.BindTo(osuGame.LocalUserPlaying);
DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value);
+ dependencies.CacheAs(DrawableRuleset);
ScoreProcessor = ruleset.CreateScoreProcessor();
ScoreProcessor.ApplyBeatmap(playableBeatmap);
@@ -357,11 +361,6 @@ namespace osu.Game.Screens.Play
AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded },
IsCounting = false
},
- RequestSeek = time =>
- {
- GameplayClockContainer.Seek(time);
- GameplayClockContainer.Start();
- },
Anchor = Anchor.Centre,
Origin = Anchor.Centre
},
@@ -566,6 +565,12 @@ namespace osu.Game.Screens.Play
updateSampleDisabledState();
}
+ ///
+ /// Seek to a specific time in gameplay.
+ ///
+ /// The destination time to seek to.
+ public void Seek(double time) => GameplayClockContainer.Seek(time);
+
///
/// Restart gameplay via a parent .
/// This can be called from a child screen in order to trigger the restart process.
diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs
index 4a0787bfae..b7939b5e75 100644
--- a/osu.Game/Screens/Play/SongProgress.cs
+++ b/osu.Game/Screens/Play/SongProgress.cs
@@ -14,10 +14,11 @@ using osu.Framework.Timing;
using osu.Game.Configuration;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI;
+using osu.Game.Skinning;
namespace osu.Game.Screens.Play
{
- public class SongProgress : OverlayContainer
+ public class SongProgress : OverlayContainer, ISkinnableDrawable
{
private const int info_height = 20;
private const int bottom_bar_height = 5;
@@ -39,9 +40,6 @@ namespace osu.Game.Screens.Play
public readonly Bindable ShowGraph = new Bindable();
- //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 HandlePositionalInput => AllowSeeking.Value;
@@ -49,6 +47,9 @@ namespace osu.Game.Screens.Play
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 objects;
public IEnumerable Objects
@@ -65,51 +66,58 @@ 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()
{
+ RelativeSizeAxes = Axes.X;
+ Anchor = Anchor.BottomRight;
+ Origin = Anchor.BottomRight;
+
Children = new Drawable[]
{
- new SongProgressDisplay
+ info = new SongProgressInfo
{
- Children = new Drawable[]
- {
- info = new SongProgressInfo
- {
- Origin = Anchor.BottomLeft,
- Anchor = Anchor.BottomLeft,
- RelativeSizeAxes = Axes.X,
- Height = info_height,
- },
- graph = new SongProgressGraph
- {
- RelativeSizeAxes = Axes.X,
- Origin = Anchor.BottomLeft,
- Anchor = Anchor.BottomLeft,
- Height = graph_height,
- Margin = new MarginPadding { Bottom = bottom_bar_height },
- },
- bar = new SongProgressBar(bottom_bar_height, graph_height, handle_size)
- {
- Anchor = Anchor.BottomLeft,
- Origin = Anchor.BottomLeft,
- OnSeek = time => RequestSeek?.Invoke(time),
- },
- }
+ Origin = Anchor.BottomLeft,
+ Anchor = Anchor.BottomLeft,
+ RelativeSizeAxes = Axes.X,
+ Height = info_height,
+ },
+ graph = new SongProgressGraph
+ {
+ RelativeSizeAxes = Axes.X,
+ Origin = Anchor.BottomLeft,
+ Anchor = Anchor.BottomLeft,
+ Height = graph_height,
+ Margin = new MarginPadding { Bottom = bottom_bar_height },
+ },
+ bar = new SongProgressBar(bottom_bar_height, graph_height, handle_size)
+ {
+ Anchor = Anchor.BottomLeft,
+ Origin = Anchor.BottomLeft,
+ OnSeek = time => player?.Seek(time),
},
};
}
[BackgroundDependencyLoader(true)]
- private void load(OsuColour colours, GameplayClock clock, OsuConfigManager config)
+ private void load(OsuColour colours, OsuConfigManager config, DrawableRuleset drawableRuleset)
{
base.LoadComplete();
- if (clock != null)
- gameplayClock = clock;
+ if (drawableRuleset != null)
+ {
+ AllowSeeking.BindTo(drawableRuleset.HasReplayLoaded);
+
+ referenceClock = drawableRuleset.FrameStableClock;
+ Objects = drawableRuleset.Objects;
+ }
config.BindWith(OsuSetting.ShowProgressGraph, ShowGraph);
@@ -124,11 +132,6 @@ namespace osu.Game.Screens.Play
ShowGraph.BindValueChanged(_ => updateGraphVisibility(), true);
}
- public void BindDrawableRuleset(DrawableRuleset drawableRuleset)
- {
- AllowSeeking.BindTo(drawableRuleset.HasReplayLoaded);
- }
-
protected override void PopIn()
{
this.FadeIn(500, Easing.OutQuint);
@@ -147,7 +150,7 @@ namespace osu.Game.Screens.Play
return;
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));
@@ -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);
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;
- }
- }
}
}
diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs
index 9b4e32531a..d13ddcf22b 100644
--- a/osu.Game/Skinning/DefaultSkin.cs
+++ b/osu.Game/Skinning/DefaultSkin.cs
@@ -12,6 +12,7 @@ using osu.Framework.Graphics.Textures;
using osu.Game.Audio;
using osu.Game.Extensions;
using osu.Game.IO;
+using osu.Game.Screens.Play;
using osu.Game.Screens.Play.HUD;
using osuTK;
using osuTK.Graphics;
@@ -86,6 +87,7 @@ namespace osu.Game.Skinning
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.ScoreCounter)),
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter)),
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.HealthDisplay)),
+ GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.SongProgress)),
}
};
@@ -109,6 +111,9 @@ namespace osu.Game.Skinning
case HUDSkinComponents.HealthDisplay:
return new DefaultHealthDisplay();
+
+ case HUDSkinComponents.SongProgress:
+ return new SongProgress();
}
break;
diff --git a/osu.Game/Skinning/Editor/SkinComponentToolbox.cs b/osu.Game/Skinning/Editor/SkinComponentToolbox.cs
index 59420bfc87..935d2756fb 100644
--- a/osu.Game/Skinning/Editor/SkinComponentToolbox.cs
+++ b/osu.Game/Skinning/Editor/SkinComponentToolbox.cs
@@ -57,7 +57,10 @@ namespace osu.Game.Skinning.Editor
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)
{
@@ -92,6 +95,10 @@ namespace osu.Game.Skinning.Editor
private class ToolboxComponentButton : OsuButton
{
+ protected override bool ShouldBeConsideredForInput(Drawable child) => false;
+
+ public override bool PropagateNonPositionalInputSubTree => false;
+
private readonly Drawable component;
public Action RequestPlacement;
diff --git a/osu.Game/Skinning/HUDSkinComponents.cs b/osu.Game/Skinning/HUDSkinComponents.cs
index a345e060e5..2e6c3a9937 100644
--- a/osu.Game/Skinning/HUDSkinComponents.cs
+++ b/osu.Game/Skinning/HUDSkinComponents.cs
@@ -9,5 +9,6 @@ namespace osu.Game.Skinning
ScoreCounter,
AccuracyCounter,
HealthDisplay,
+ SongProgress,
}
}
diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs
index a6f8f45c0f..6c8d6ee45a 100644
--- a/osu.Game/Skinning/LegacySkin.cs
+++ b/osu.Game/Skinning/LegacySkin.cs
@@ -17,6 +17,7 @@ using osu.Game.Audio;
using osu.Game.Beatmaps.Formats;
using osu.Game.IO;
using osu.Game.Rulesets.Scoring;
+using osu.Game.Screens.Play;
using osu.Game.Screens.Play.HUD;
using osuTK.Graphics;
@@ -350,6 +351,7 @@ namespace osu.Game.Skinning
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.ScoreCounter)) ?? new DefaultScoreCounter(),
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter)) ?? new DefaultAccuracyCounter(),
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.HealthDisplay)) ?? new DefaultHealthDisplay(),
+ GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.SongProgress)) ?? new SongProgress(),
}
};