mirror of
https://github.com/ppy/osu.git
synced 2025-02-21 03:02:54 +08:00
Merge branch 'master' into add-overlay-link-colours
This commit is contained in:
commit
2bf62b86ea
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
|
||||||
|
protected override void OnSelection(DirectoryInfo directory)
|
||||||
{
|
{
|
||||||
game?.Toolbar.Hide();
|
var target = directory;
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -85,45 +87,22 @@ namespace osu.Game.Screens.Play
|
|||||||
visibilityContainer = new Container
|
visibilityContainer = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Child = new GridContainer
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
mainComponents = new SkinnableTargetContainer(SkinnableTarget.MainHUDComponents)
|
||||||
Content = new[]
|
|
||||||
{
|
{
|
||||||
new Drawable[]
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Container
|
// still need to be migrated; a bit more involved.
|
||||||
{
|
new HitErrorDisplay(this.drawableRuleset?.FirstAvailableHitWindows),
|
||||||
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(),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
RowDimensions = new[]
|
}
|
||||||
{
|
|
||||||
new Dimension(),
|
|
||||||
new Dimension(GridSizeMode.AutoSize)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
topRightElements = new FillFlowContainer
|
topRightElements = new FillFlowContainer
|
||||||
{
|
{
|
||||||
@ -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;
|
||||||
|
|
||||||
// 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.Anchor.HasFlagFast(Anchor.TopRight))
|
||||||
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;
|
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,
|
||||||
|
@ -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>
|
||||||
|
@ -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,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()
|
public SongProgress()
|
||||||
{
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
Anchor = Anchor.BottomRight;
|
||||||
|
Origin = Anchor.BottomRight;
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new SongProgressDisplay
|
info = new SongProgressInfo
|
||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Origin = Anchor.BottomLeft,
|
||||||
{
|
Anchor = Anchor.BottomLeft,
|
||||||
info = new SongProgressInfo
|
RelativeSizeAxes = Axes.X,
|
||||||
{
|
Height = info_height,
|
||||||
Origin = Anchor.BottomLeft,
|
},
|
||||||
Anchor = Anchor.BottomLeft,
|
graph = new SongProgressGraph
|
||||||
RelativeSizeAxes = Axes.X,
|
{
|
||||||
Height = info_height,
|
RelativeSizeAxes = Axes.X,
|
||||||
},
|
Origin = Anchor.BottomLeft,
|
||||||
graph = new SongProgressGraph
|
Anchor = Anchor.BottomLeft,
|
||||||
{
|
Height = graph_height,
|
||||||
RelativeSizeAxes = Axes.X,
|
Margin = new MarginPadding { Bottom = bottom_bar_height },
|
||||||
Origin = Anchor.BottomLeft,
|
},
|
||||||
Anchor = Anchor.BottomLeft,
|
bar = new SongProgressBar(bottom_bar_height, graph_height, handle_size)
|
||||||
Height = graph_height,
|
{
|
||||||
Margin = new MarginPadding { Bottom = bottom_bar_height },
|
Anchor = Anchor.BottomLeft,
|
||||||
},
|
Origin = Anchor.BottomLeft,
|
||||||
bar = new SongProgressBar(bottom_bar_height, graph_height, handle_size)
|
OnSeek = time => player?.Seek(time),
|
||||||
{
|
|
||||||
Anchor = Anchor.BottomLeft,
|
|
||||||
Origin = Anchor.BottomLeft,
|
|
||||||
OnSeek = time => RequestSeek?.Invoke(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -9,5 +9,6 @@ namespace osu.Game.Skinning
|
|||||||
ScoreCounter,
|
ScoreCounter,
|
||||||
AccuracyCounter,
|
AccuracyCounter,
|
||||||
HealthDisplay,
|
HealthDisplay,
|
||||||
|
SongProgress,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user