1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 05:02:55 +08:00

Merge branch 'master' into multi-spectator-better-start-time

This commit is contained in:
Bartłomiej Dach 2023-08-03 22:07:47 +02:00 committed by GitHub
commit 785d2ed9b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 108 additions and 41 deletions

View File

@ -9,6 +9,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics.Primitives;
using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Objects;
@ -25,6 +26,22 @@ namespace osu.Game.Rulesets.Mania.UI
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 ManiaPlayfield(List<StageDefinition> stageDefinitions)

View File

@ -125,13 +125,13 @@ namespace osu.Game.Tests.Visual.Background
createFakeStoryboard();
AddStep("Enable Storyboard", () =>
{
player.ReplacesBackground.Value = true;
player.StoryboardReplacesBackground.Value = true;
player.StoryboardEnabled.Value = true;
});
AddUntilStep("Background is invisible, storyboard is visible", () => songSelect.IsBackgroundInvisible() && player.IsStoryboardVisible);
AddUntilStep("Background is black, storyboard is visible", () => songSelect.IsBackgroundVisible() && songSelect.IsBackgroundBlack() && player.IsStoryboardVisible);
AddStep("Disable Storyboard", () =>
{
player.ReplacesBackground.Value = false;
player.StoryboardReplacesBackground.Value = false;
player.StoryboardEnabled.Value = false;
});
AddUntilStep("Background is visible, storyboard is invisible", () => songSelect.IsBackgroundVisible() && !player.IsStoryboardVisible);
@ -173,7 +173,7 @@ namespace osu.Game.Tests.Visual.Background
createFakeStoryboard();
AddStep("Enable Storyboard", () =>
{
player.ReplacesBackground.Value = true;
player.StoryboardReplacesBackground.Value = true;
player.StoryboardEnabled.Value = true;
});
AddStep("Enable user dim", () => player.DimmableStoryboard.IgnoreUserSettings.Value = false);
@ -188,7 +188,7 @@ namespace osu.Game.Tests.Visual.Background
{
performFullSetup();
createFakeStoryboard();
AddStep("Enable replacing background", () => player.ReplacesBackground.Value = true);
AddStep("Enable replacing background", () => player.StoryboardReplacesBackground.Value = true);
AddUntilStep("Storyboard is invisible", () => !player.IsStoryboardVisible);
AddUntilStep("Background is visible", () => songSelect.IsBackgroundVisible());
@ -199,11 +199,11 @@ namespace osu.Game.Tests.Visual.Background
player.DimmableStoryboard.IgnoreUserSettings.Value = true;
});
AddUntilStep("Storyboard is visible", () => player.IsStoryboardVisible);
AddUntilStep("Background is invisible", () => songSelect.IsBackgroundInvisible());
AddUntilStep("Background is dimmed", () => songSelect.IsBackgroundVisible() && songSelect.IsBackgroundBlack());
AddStep("Disable background replacement", () => player.ReplacesBackground.Value = false);
AddStep("Disable background replacement", () => player.StoryboardReplacesBackground.Value = false);
AddUntilStep("Storyboard is visible", () => player.IsStoryboardVisible);
AddUntilStep("Background is visible", () => songSelect.IsBackgroundVisible());
AddUntilStep("Background is visible", () => songSelect.IsBackgroundVisible() && !songSelect.IsBackgroundBlack());
}
/// <summary>
@ -257,7 +257,7 @@ namespace osu.Game.Tests.Visual.Background
private void createFakeStoryboard() => AddStep("Create storyboard", () =>
{
player.StoryboardEnabled.Value = false;
player.ReplacesBackground.Value = false;
player.StoryboardReplacesBackground.Value = false;
player.DimmableStoryboard.Add(new OsuSpriteText
{
Size = new Vector2(500, 50),
@ -323,6 +323,8 @@ namespace osu.Game.Tests.Visual.Background
config.BindWith(OsuSetting.BlurLevel, BlurLevel);
}
public bool IsBackgroundBlack() => background.CurrentColour == OsuColour.Gray(0);
public bool IsBackgroundDimmed() => background.CurrentColour == OsuColour.Gray(1f - background.CurrentDim);
public bool IsBackgroundUndimmed() => background.CurrentColour == Color4.White;
@ -331,8 +333,6 @@ namespace osu.Game.Tests.Visual.Background
public bool IsUserBlurDisabled() => background.CurrentBlur == new Vector2(0);
public bool IsBackgroundInvisible() => background.CurrentAlpha == 0;
public bool IsBackgroundVisible() => background.CurrentAlpha == 1;
public bool IsBackgroundBlur() => Precision.AlmostEquals(background.CurrentBlur, new Vector2(BACKGROUND_BLUR), 0.1f);
@ -367,7 +367,7 @@ namespace osu.Game.Tests.Visual.Background
{
base.OnEntering(e);
ApplyToBackground(b => ReplacesBackground.BindTo(b.StoryboardReplacesBackground));
ApplyToBackground(b => StoryboardReplacesBackground.BindTo(b.StoryboardReplacesBackground));
}
public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard;
@ -376,7 +376,7 @@ namespace osu.Game.Tests.Visual.Background
public bool BlockLoad;
public Bindable<bool> StoryboardEnabled;
public readonly Bindable<bool> ReplacesBackground = new Bindable<bool>();
public readonly Bindable<bool> StoryboardReplacesBackground = new Bindable<bool>();
public readonly Bindable<bool> IsPaused = new Bindable<bool>();
public LoadBlockingTestPlayer(bool allowPause = true)

View File

@ -8,6 +8,7 @@ using osu.Game.Overlays;
using osu.Game.Overlays.SkinEditor;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Skinning;
namespace osu.Game.Tests.Visual.Gameplay
{
@ -19,7 +20,9 @@ namespace osu.Game.Tests.Visual.Gameplay
[Test]
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,
Origin = Anchor.TopRight,

View File

@ -124,7 +124,7 @@ namespace osu.Game.Beatmaps
{
base.Update();
if (Source != null && Source is not IAdjustableClock && Source.CurrentTime < decoupledClock.CurrentTime)
if (Source != null && Source is not IAdjustableClock && Source.CurrentTime < decoupledClock.CurrentTime - 100)
{
// InterpolatingFramedClock won't interpolate backwards unless its source has an ElapsedFrameTime.
// See https://github.com/ppy/osu-framework/blob/ba1385330cc501f34937e08257e586c84e35d772/osu.Framework/Timing/InterpolatingFramedClock.cs#L91-L93

View File

@ -24,15 +24,13 @@ namespace osu.Game.Graphics.Containers
public const double BACKGROUND_FADE_DURATION = 800;
/// <summary>
/// Whether or not user-configured settings relating to brightness of elements should be ignored
/// Whether or not user-configured settings relating to brightness of elements should be ignored.
/// </summary>
/// <remarks>
/// For best or worst, this also bypasses storyboard disable. Not sure this is correct but leaving it as to not break anything.
/// </remarks>
public readonly Bindable<bool> IgnoreUserSettings = new Bindable<bool>();
/// <summary>
/// Whether or not the storyboard loaded should completely hide the background behind it.
/// </summary>
public readonly Bindable<bool> StoryboardReplacesBackground = new Bindable<bool>();
/// <summary>
/// Whether player is in break time.
/// Must be bound to <see cref="BreakTracker.IsBreakTime"/> to allow for dim adjustments in gameplay.
@ -57,7 +55,7 @@ namespace osu.Game.Graphics.Containers
private float breakLightening => LightenDuringBreaks.Value && IsBreakTime.Value ? BREAK_LIGHTEN_AMOUNT : 0;
protected float DimLevel => Math.Max(!IgnoreUserSettings.Value ? (float)UserDimLevel.Value - breakLightening : DimWhenUserSettingsIgnored.Value, 0);
protected virtual float DimLevel => Math.Max(!IgnoreUserSettings.Value ? (float)UserDimLevel.Value - breakLightening : DimWhenUserSettingsIgnored.Value, 0);
protected override Container<Drawable> Content => dimContent;
@ -83,7 +81,6 @@ namespace osu.Game.Graphics.Containers
LightenDuringBreaks.ValueChanged += _ => UpdateVisuals();
IsBreakTime.ValueChanged += _ => UpdateVisuals();
ShowStoryboard.ValueChanged += _ => UpdateVisuals();
StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals();
IgnoreUserSettings.ValueChanged += _ => UpdateVisuals();
}

View File

@ -31,7 +31,7 @@ namespace osu.Game.IO.Archives
{
ZipArchiveEntry entry = archive.Entries.SingleOrDefault(e => e.Key == name);
if (entry == null)
throw new FileNotFoundException();
return null;
var owner = MemoryAllocator.Default.Allocate<byte>((int)entry.Size);

View File

@ -13,6 +13,7 @@ using osu.Framework.Threading;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
using osu.Game.Rulesets;
using osu.Game.Screens.Edit.Components;
using osu.Game.Skinning;
using osuTK;
@ -23,14 +24,22 @@ namespace osu.Game.Overlays.SkinEditor
{
public Action<Type>? RequestPlacement;
private readonly SkinComponentsContainer? target;
private readonly SkinComponentsContainer target;
private readonly RulesetInfo? ruleset;
private FillFlowContainer fill = null!;
public SkinComponentToolbox(SkinComponentsContainer? target = null)
: base(target?.Lookup.Ruleset == null ? SkinEditorStrings.Components : LocalisableString.Interpolate($"{SkinEditorStrings.Components} ({target.Lookup.Ruleset.Name})"))
/// <summary>
/// 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.ruleset = ruleset;
}
[BackgroundDependencyLoader]
@ -51,7 +60,7 @@ namespace osu.Game.Overlays.SkinEditor
{
fill.Clear();
var skinnableTypes = SerialisedDrawableInfo.GetAllAvailableDrawables(target?.Lookup.Ruleset);
var skinnableTypes = SerialisedDrawableInfo.GetAllAvailableDrawables(ruleset);
foreach (var type in skinnableTypes)
attemptAddComponent(type);
}

View File

@ -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 (target.NewValue.Ruleset != null)
{
componentsSidebar.Add(new SkinComponentToolbox(skinComponentsContainer)
componentsSidebar.Add(new SkinComponentToolbox(skinComponentsContainer, target.NewValue.Ruleset)
{
RequestPlacement = requestPlacement
});
}
// 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
});

View File

@ -23,6 +23,7 @@ using osu.Game.Skinning;
using osuTK;
using osu.Game.Rulesets.Objects.Pooling;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics.Primitives;
namespace osu.Game.Rulesets.UI
{
@ -94,6 +95,16 @@ namespace osu.Game.Rulesets.UI
/// </summary>
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)]
[CanBeNull]
protected IReadOnlyList<Mod> Mods { get; private set; }

View File

@ -36,6 +36,9 @@ namespace osu.Game.Screens.Backgrounds
/// </remarks>
public readonly Bindable<bool> IgnoreUserSettings = new Bindable<bool>(true);
/// <summary>
/// Whether or not the storyboard loaded should completely hide the background behind it.
/// </summary>
public readonly Bindable<bool> StoryboardReplacesBackground = new Bindable<bool>();
/// <summary>
@ -60,12 +63,11 @@ namespace osu.Game.Screens.Backgrounds
InternalChild = dimmable = CreateFadeContainer();
dimmable.StoryboardReplacesBackground.BindTo(StoryboardReplacesBackground);
dimmable.IgnoreUserSettings.BindTo(IgnoreUserSettings);
dimmable.IsBreakTime.BindTo(IsBreakTime);
dimmable.BlurAmount.BindTo(BlurAmount);
dimmable.DimWhenUserSettingsIgnored.BindTo(DimWhenUserSettingsIgnored);
StoryboardReplacesBackground.BindTo(dimmable.StoryboardReplacesBackground);
}
[BackgroundDependencyLoader]
@ -144,6 +146,8 @@ namespace osu.Game.Screens.Backgrounds
/// </remarks>
public readonly Bindable<float> BlurAmount = new BindableFloat();
public readonly Bindable<bool> StoryboardReplacesBackground = new Bindable<bool>();
public Background Background
{
get => background;
@ -187,11 +191,19 @@ namespace osu.Game.Screens.Backgrounds
userBlurLevel.ValueChanged += _ => UpdateVisuals();
BlurAmount.ValueChanged += _ => UpdateVisuals();
StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals();
}
protected override bool ShowDimContent
// The background needs to be hidden in the case of it being replaced by the storyboard
=> (!ShowStoryboard.Value && !IgnoreUserSettings.Value) || !StoryboardReplacesBackground.Value;
protected override float DimLevel
{
get
{
if ((IgnoreUserSettings.Value || ShowStoryboard.Value) && StoryboardReplacesBackground.Value)
return 1;
return base.DimLevel;
}
}
protected override void UpdateVisuals()
{

View File

@ -12,6 +12,7 @@ using osu.Framework.Bindables;
using osu.Framework.Extensions.EnumExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Configuration;
@ -69,7 +70,9 @@ namespace osu.Game.Screens.Play
public Bindable<bool> ShowHealthBar = new Bindable<bool>(true);
[CanBeNull]
private readonly DrawableRuleset drawableRuleset;
private readonly IReadOnlyList<Mod> mods;
/// <summary>
@ -103,10 +106,11 @@ namespace osu.Game.Screens.Play
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;
this.drawableRuleset = drawableRuleset;
this.mods = mods;
@ -123,6 +127,9 @@ namespace osu.Game.Screens.Play
rulesetComponents = drawableRuleset != null
? new HUDComponentsContainer(drawableRuleset.Ruleset.RulesetInfo) { AlwaysPresent = true, }
: Empty(),
playfieldComponents = drawableRuleset != null
? new SkinComponentsContainer(new SkinComponentsContainerLookup(SkinComponentsContainerLookup.TargetArea.Playfield, drawableRuleset.Ruleset.RulesetInfo)) { AlwaysPresent = true, }
: Empty(),
topRightElements = new FillFlowContainer
{
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)
hideTargets.Add(LeaderboardFlow);
@ -230,6 +237,16 @@ namespace osu.Game.Screens.Play
{
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? lowestTopScreenSpaceRight = null;

View File

@ -1049,8 +1049,6 @@ namespace osu.Game.Screens.Play
DimmableStoryboard.IsBreakTime.BindTo(breakTracker.IsBreakTime);
DimmableStoryboard.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground);
storyboardReplacesBackground.Value = Beatmap.Value.Storyboard.ReplacesBackground && Beatmap.Value.Storyboard.HasDrawable;
foreach (var mod in GameplayState.Mods.OfType<IApplicableToPlayer>())

View File

@ -68,7 +68,10 @@ namespace osu.Game.Skinning
MainHUDComponents,
[Description("Song select")]
SongSelect
SongSelect,
[Description("Playfield")]
Playfield
}
}
}