1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-30 01:32:55 +08:00

Merge branch 'master' into update-osu-stable-from-registry

This commit is contained in:
Susko3 2025-01-11 04:23:23 +00:00 committed by GitHub
commit fef81781e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 295 additions and 186 deletions

View File

@ -88,10 +88,9 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
switch (PlacementActive)
{
case PlacementState.Waiting:
if (!(result.Time is double snappedTime)) return;
HitObject.OriginalX = ToLocalSpace(result.ScreenSpacePosition).X;
HitObject.StartTime = snappedTime;
if (result.Time is double snappedTime)
HitObject.StartTime = snappedTime;
break;
case PlacementState.Active:
@ -107,21 +106,13 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
Vector2 startPosition = CatchHitObjectUtils.GetStartPosition(HitObjectContainer, HitObject);
editablePath.Position = nestedOutlineContainer.Position = scrollingPath.Position = startPosition;
updateHitObjectFromPath();
}
if (lastEditablePathId != editablePath.PathId)
editablePath.UpdateHitObjectFromPath(HitObject);
lastEditablePathId = editablePath.PathId;
private void updateHitObjectFromPath()
{
if (lastEditablePathId == editablePath.PathId)
return;
editablePath.UpdateHitObjectFromPath(HitObject);
ApplyDefaultsToHitObject();
scrollingPath.UpdatePathFrom(HitObjectContainer, HitObject);
nestedOutlineContainer.UpdateNestedObjectsFrom(HitObjectContainer, HitObject);
lastEditablePathId = editablePath.PathId;
}
private double positionToTime(float relativeYPosition)

View File

@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Catch.Edit
protected override Drawable CreateHitObjectInspector() => new CatchHitObjectInspector(DistanceSnapProvider);
protected override IEnumerable<TernaryButton> CreateTernaryButtons()
protected override IEnumerable<DrawableTernaryButton> CreateTernaryButtons()
=> base.CreateTernaryButtons()
.Concat(DistanceSnapProvider.CreateTernaryButtons());

View File

@ -53,9 +53,14 @@ namespace osu.Game.Rulesets.Osu.Edit
protected override Drawable CreateHitObjectInspector() => new OsuHitObjectInspector();
protected override IEnumerable<TernaryButton> CreateTernaryButtons()
protected override IEnumerable<DrawableTernaryButton> CreateTernaryButtons()
=> base.CreateTernaryButtons()
.Append(new TernaryButton(rectangularGridSnapToggle, "Grid Snap", () => new SpriteIcon { Icon = OsuIcon.EditorGridSnap }))
.Append(new DrawableTernaryButton
{
Current = rectangularGridSnapToggle,
Description = "Grid Snap",
CreateIcon = () => new SpriteIcon { Icon = OsuIcon.EditorGridSnap },
})
.Concat(DistanceSnapProvider.CreateTernaryButtons());
private BindableList<HitObject> selectedHitObjects;

View File

@ -7,16 +7,15 @@ using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.UI;
using osu.Game.Screens;
using osu.Game.Screens.Backgrounds;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Components;
@ -43,14 +42,6 @@ namespace osu.Game.Tests.Visual.Editing
private BeatmapSetInfo importedBeatmapSet;
private Bindable<float> editorDim;
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
editorDim = config.GetBindable<float>(OsuSetting.EditorDim);
}
public override void SetUpSteps()
{
AddStep("import test beatmap", () => importedBeatmapSet = BeatmapImportHelper.LoadOszIntoOsu(game).GetResultSafely());
@ -81,15 +72,7 @@ namespace osu.Game.Tests.Visual.Editing
AddUntilStep("player pushed", () => (editorPlayer = Stack.CurrentScreen as EditorPlayer) != null);
AddStep("exit player", () => editorPlayer.Exit());
AddUntilStep("current screen is editor", () => Stack.CurrentScreen is Editor);
AddUntilStep("background has correct params", () =>
{
// the test gameplay player's beatmap may be the "same" beatmap as the one being edited, *but* the `BeatmapInfo` references may differ
// due to the beatmap refetch logic ran on editor suspend.
// this test cares about checking the background belonging to the editor specifically, so check that using reference equality
// (as `.Equals()` cannot discern between the two, as they technically share the same database GUID).
var background = this.ChildrenOfType<BackgroundScreenBeatmap>().Single(b => ReferenceEquals(b.Beatmap.BeatmapInfo, EditorBeatmap.BeatmapInfo));
return background.DimWhenUserSettingsIgnored.Value == editorDim.Value && background.BlurAmount.Value == 0;
});
AddUntilStep("background is correct", () => this.ChildrenOfType<BackgroundScreenStack>().Single().CurrentScreen is EditorBackgroundScreen);
AddAssert("no mods selected", () => SelectedMods.Value.Count == 0);
}
@ -114,15 +97,7 @@ namespace osu.Game.Tests.Visual.Editing
AddStep("exit player", () => editorPlayer.Exit());
AddUntilStep("current screen is editor", () => Stack.CurrentScreen is Editor);
AddUntilStep("background has correct params", () =>
{
// the test gameplay player's beatmap may be the "same" beatmap as the one being edited, *but* the `BeatmapInfo` references may differ
// due to the beatmap refetch logic ran on editor suspend.
// this test cares about checking the background belonging to the editor specifically, so check that using reference equality
// (as `.Equals()` cannot discern between the two, as they technically share the same database GUID).
var background = this.ChildrenOfType<BackgroundScreenBeatmap>().Single(b => ReferenceEquals(b.Beatmap.BeatmapInfo, EditorBeatmap.BeatmapInfo));
return background.DimWhenUserSettingsIgnored.Value == editorDim.Value && background.BlurAmount.Value == 0;
});
AddUntilStep("background is correct", () => this.ChildrenOfType<BackgroundScreenStack>().Single().CurrentScreen is EditorBackgroundScreen);
AddStep("start track", () => EditorClock.Start());
AddAssert("sample playback re-enabled", () => !Editor.SamplePlaybackDisabled.Value);

View File

@ -220,6 +220,7 @@ namespace osu.Game.Configuration
SetDefault(OsuSetting.AlwaysShowHoldForMenuButton, false);
SetDefault(OsuSetting.AlwaysRequireHoldingForPause, false);
SetDefault(OsuSetting.EditorShowStoryboard, true);
}
protected override bool CheckLookupContainsPrivateInformation(OsuSetting lookup)
@ -455,5 +456,6 @@ namespace osu.Game.Configuration
MultiplayerShowInProgressFilter,
BeatmapListingFeaturedArtistFilter,
ShowMobileDisclaimer,
EditorShowStoryboard,
}
}

View File

@ -191,9 +191,14 @@ namespace osu.Game.Rulesets.Edit
}
}
public IEnumerable<TernaryButton> CreateTernaryButtons() => new[]
public IEnumerable<DrawableTernaryButton> CreateTernaryButtons() => new[]
{
new TernaryButton(DistanceSnapToggle, "Distance Snap", () => new SpriteIcon { Icon = OsuIcon.EditorDistanceSnap })
new DrawableTernaryButton
{
Current = DistanceSnapToggle,
Description = "Distance Snap",
CreateIcon = () => new SpriteIcon { Icon = OsuIcon.EditorDistanceSnap },
}
};
public void HandleToggleViaKey(KeyboardEvent key)

View File

@ -269,10 +269,9 @@ namespace osu.Game.Rulesets.Edit
};
}
TernaryStates = CreateTernaryButtons().ToArray();
togglesCollection.AddRange(TernaryStates.Select(b => new DrawableTernaryButton(b)));
togglesCollection.AddRange(CreateTernaryButtons().ToArray());
sampleBankTogglesCollection.AddRange(BlueprintContainer.SampleBankTernaryStates.Zip(BlueprintContainer.SampleAdditionBankTernaryStates).Select(b => new SampleBankTernaryButton(b.First, b.Second)));
sampleBankTogglesCollection.AddRange(BlueprintContainer.SampleBankTernaryStates);
SetSelectTool();
@ -368,15 +367,10 @@ namespace osu.Game.Rulesets.Edit
/// </remarks>
protected abstract IReadOnlyList<CompositionTool> CompositionTools { get; }
/// <summary>
/// A collection of states which will be displayed to the user in the toolbox.
/// </summary>
public TernaryButton[] TernaryStates { get; private set; }
/// <summary>
/// Create all ternary states required to be displayed to the user.
/// </summary>
protected virtual IEnumerable<TernaryButton> CreateTernaryButtons() => BlueprintContainer.MainTernaryStates;
protected virtual IEnumerable<DrawableTernaryButton> CreateTernaryButtons() => BlueprintContainer.MainTernaryStates;
/// <summary>
/// Construct a relevant blueprint container. This will manage hitobject selection/placement input handling and display logic.
@ -437,7 +431,7 @@ namespace osu.Game.Rulesets.Edit
{
if (togglesCollection.ElementAtOrDefault(rightIndex) is DrawableTernaryButton button)
{
button.Button.Toggle();
button.Toggle();
return true;
}
}

View File

@ -56,7 +56,12 @@ namespace osu.Game.Rulesets.Edit
Spacing = new Vector2(0, 5),
Children = new[]
{
new DrawableTernaryButton(new TernaryButton(showSpeedChanges, "Show speed changes", () => new SpriteIcon { Icon = FontAwesome.Solid.TachometerAlt }))
new DrawableTernaryButton
{
Current = showSpeedChanges,
Description = "Show speed changes",
CreateIcon = () => new SpriteIcon { Icon = FontAwesome.Solid.TachometerAlt },
}
}
},
});

View File

@ -101,18 +101,6 @@ namespace osu.Game.Screens.Backgrounds
}
}
/// <summary>
/// Reloads beatmap's background.
/// </summary>
public void RefreshBackground()
{
Schedule(() =>
{
cancellationSource?.Cancel();
LoadComponentAsync(new BeatmapBackground(beatmap), switchBackground, (cancellationSource = new CancellationTokenSource()).Token);
});
}
private void switchBackground(BeatmapBackground b)
{
float newDepth = 0;

View File

@ -0,0 +1,117 @@
// 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 System.Collections.Generic;
using System.Linq;
using System.Threading;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds;
using osu.Game.Storyboards.Drawables;
namespace osu.Game.Screens.Backgrounds
{
public partial class EditorBackgroundScreen : BackgroundScreen
{
private readonly WorkingBeatmap beatmap;
private readonly Container dimContainer;
private CancellationTokenSource? cancellationTokenSource;
private Bindable<float> dimLevel = null!;
private Bindable<bool> showStoryboard = null!;
private BeatmapBackground background = null!;
private Container storyboardContainer = null!;
private IFrameBasedClock? clockSource;
public EditorBackgroundScreen(WorkingBeatmap beatmap)
{
this.beatmap = beatmap;
InternalChild = dimContainer = new Container
{
RelativeSizeAxes = Axes.Both,
};
}
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
dimContainer.AddRange(createContent());
background = dimContainer.OfType<BeatmapBackground>().Single();
storyboardContainer = dimContainer.OfType<Container>().Single();
dimLevel = config.GetBindable<float>(OsuSetting.EditorDim);
showStoryboard = config.GetBindable<bool>(OsuSetting.EditorShowStoryboard);
}
private IEnumerable<Drawable> createContent() =>
[
new BeatmapBackground(beatmap) { RelativeSizeAxes = Axes.Both, },
// this kooky container nesting is here because the storyboard needs a custom clock
// but also needs it on an isolated-enough level that doesn't break screen stack expiry logic (which happens if the clock was put on `this`),
// or doesn't make it literally impossible to fade the storyboard in/out in real time (which happens if the fade transforms were to be applied directly to the storyboard).
new Container
{
RelativeSizeAxes = Axes.Both,
Child = new DrawableStoryboard(beatmap.Storyboard)
{
Clock = clockSource ?? Clock,
}
}
];
protected override void LoadComplete()
{
base.LoadComplete();
dimLevel.BindValueChanged(_ => dimContainer.FadeColour(OsuColour.Gray(1 - dimLevel.Value), 500, Easing.OutQuint), true);
showStoryboard.BindValueChanged(_ => updateState());
updateState(0);
}
private void updateState(double duration = 500)
{
storyboardContainer.FadeTo(showStoryboard.Value ? 1 : 0, duration, Easing.OutQuint);
// yes, this causes overdraw, but is also a (crude) fix for bad-looking transitions on screen entry
// caused by the previous background on the background stack poking out from under this one and then instantly fading out
background.FadeColour(beatmap.Storyboard.ReplacesBackground && showStoryboard.Value ? Colour4.Black : Colour4.White, duration, Easing.OutQuint);
}
public void ChangeClockSource(IFrameBasedClock frameBasedClock)
{
clockSource = frameBasedClock;
if (IsLoaded)
storyboardContainer.Child.Clock = frameBasedClock;
}
public void RefreshBackground()
{
cancellationTokenSource?.Cancel();
LoadComponentsAsync(createContent(), loaded =>
{
dimContainer.Clear();
dimContainer.AddRange(loaded);
background = dimContainer.OfType<BeatmapBackground>().Single();
storyboardContainer = dimContainer.OfType<Container>().Single();
updateState(0);
}, (cancellationTokenSource ??= new CancellationTokenSource()).Token);
}
public override bool Equals(BackgroundScreen? other)
{
if (other is not EditorBackgroundScreen otherBeatmapBackground)
return false;
return base.Equals(other) && beatmap == otherBeatmapBackground.beatmap;
}
}
}

View File

@ -1,12 +1,15 @@
// 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 System;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Localisation;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
@ -16,8 +19,29 @@ using osuTK.Graphics;
namespace osu.Game.Screens.Edit.Components.TernaryButtons
{
public partial class DrawableTernaryButton : OsuButton, IHasTooltip
public partial class DrawableTernaryButton : OsuButton, IHasTooltip, IHasCurrentValue<TernaryState>
{
public Bindable<TernaryState> Current
{
get => current.Current;
set => current.Current = value;
}
private readonly BindableWithCurrent<TernaryState> current = new BindableWithCurrent<TernaryState>();
public required LocalisableString Description
{
get => Text;
set => Text = value;
}
public LocalisableString TooltipText { get; set; }
/// <summary>
/// A function which creates a drawable icon to represent this item. If null, a sane default should be used.
/// </summary>
public Func<Drawable>? CreateIcon { get; init; }
private Color4 defaultBackgroundColour;
private Color4 defaultIconColour;
private Color4 selectedBackgroundColour;
@ -25,14 +49,8 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
protected Drawable Icon { get; private set; } = null!;
public readonly TernaryButton Button;
public DrawableTernaryButton(TernaryButton button)
public DrawableTernaryButton()
{
Button = button;
Text = button.Description;
RelativeSizeAxes = Axes.X;
}
@ -45,7 +63,7 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
defaultIconColour = defaultBackgroundColour.Darken(0.5f);
selectedIconColour = selectedBackgroundColour.Lighten(0.5f);
Add(Icon = (Button.CreateIcon?.Invoke() ?? new Circle()).With(b =>
Add(Icon = (CreateIcon?.Invoke() ?? new Circle()).With(b =>
{
b.Blending = BlendingParameters.Additive;
b.Anchor = Anchor.CentreLeft;
@ -59,18 +77,32 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
{
base.LoadComplete();
Button.Bindable.BindValueChanged(_ => updateSelectionState(), true);
Button.Enabled.BindTo(Enabled);
current.BindValueChanged(_ => updateSelectionState(), true);
Action = onAction;
}
private void onAction()
{
if (!Button.Enabled.Value)
if (!Enabled.Value)
return;
Button.Toggle();
Toggle();
}
public void Toggle()
{
switch (Current.Value)
{
case TernaryState.False:
case TernaryState.Indeterminate:
Current.Value = TernaryState.True;
break;
case TernaryState.True:
Current.Value = TernaryState.False;
break;
}
}
private void updateSelectionState()
@ -78,7 +110,7 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
if (!IsLoaded)
return;
switch (Button.Bindable.Value)
switch (Current.Value)
{
case TernaryState.Indeterminate:
Icon.Colour = selectedIconColour.Darken(0.5f);
@ -104,7 +136,5 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
Anchor = Anchor.CentreLeft,
X = 40f
};
public LocalisableString TooltipText => Button.Tooltip;
}
}

View File

@ -1,23 +1,32 @@
// 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 System;
using Humanizer;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Edit;
namespace osu.Game.Screens.Edit.Components.TernaryButtons
{
public partial class SampleBankTernaryButton : CompositeDrawable
{
public readonly TernaryButton NormalButton;
public readonly TernaryButton AdditionsButton;
public string BankName { get; }
public Func<Drawable>? CreateIcon { get; init; }
public SampleBankTernaryButton(TernaryButton normalButton, TernaryButton additionsButton)
public readonly BindableWithCurrent<TernaryState> NormalState = new BindableWithCurrent<TernaryState>();
public readonly BindableWithCurrent<TernaryState> AdditionsState = new BindableWithCurrent<TernaryState>();
public DrawableTernaryButton NormalButton { get; private set; } = null!;
public DrawableTernaryButton AdditionsButton { get; private set; } = null!;
public SampleBankTernaryButton(string bankName)
{
NormalButton = normalButton;
AdditionsButton = additionsButton;
BankName = bankName;
}
[BackgroundDependencyLoader]
@ -36,7 +45,12 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
AutoSizeAxes = Axes.Y,
Width = 0.5f,
Padding = new MarginPadding { Right = 1 },
Child = new InlineDrawableTernaryButton(NormalButton),
Child = NormalButton = new InlineDrawableTernaryButton
{
Current = NormalState,
Description = BankName.Titleize(),
CreateIcon = CreateIcon,
},
},
new Container
{
@ -46,18 +60,18 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
AutoSizeAxes = Axes.Y,
Width = 0.5f,
Padding = new MarginPadding { Left = 1 },
Child = new InlineDrawableTernaryButton(AdditionsButton),
Child = AdditionsButton = new InlineDrawableTernaryButton
{
Current = AdditionsState,
Description = BankName.Titleize(),
CreateIcon = CreateIcon,
},
},
};
}
private partial class InlineDrawableTernaryButton : DrawableTernaryButton
{
public InlineDrawableTernaryButton(TernaryButton button)
: base(button)
{
}
[BackgroundDependencyLoader]
private void load()
{

View File

@ -1,48 +0,0 @@
// 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 System;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Graphics.UserInterface;
namespace osu.Game.Screens.Edit.Components.TernaryButtons
{
public class TernaryButton
{
public readonly Bindable<TernaryState> Bindable;
public readonly Bindable<bool> Enabled = new Bindable<bool>(true);
public readonly string Description;
/// <summary>
/// A function which creates a drawable icon to represent this item. If null, a sane default should be used.
/// </summary>
public readonly Func<Drawable>? CreateIcon;
public string Tooltip { get; set; } = string.Empty;
public TernaryButton(Bindable<TernaryState> bindable, string description, Func<Drawable>? createIcon = null)
{
Bindable = bindable;
Description = description;
CreateIcon = createIcon;
}
public void Toggle()
{
switch (Bindable.Value)
{
case TernaryState.False:
case TernaryState.Indeterminate:
Bindable.Value = TernaryState.True;
break;
case TernaryState.True:
Bindable.Value = TernaryState.False;
break;
}
}
}
}

View File

@ -65,11 +65,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
private void load()
{
MainTernaryStates = CreateTernaryButtons().ToArray();
SampleBankTernaryStates = createSampleBankTernaryButtons(SelectionHandler.SelectionBankStates).ToArray();
SampleAdditionBankTernaryStates = createSampleBankTernaryButtons(SelectionHandler.SelectionAdditionBankStates).ToArray();
SelectionHandler.AutoSelectionBankEnabled.BindValueChanged(_ => updateAutoBankTernaryButtonTooltip(), true);
SelectionHandler.SelectionAdditionBanksEnabled.BindValueChanged(_ => updateAdditionBankTernaryButtonTooltips(), true);
SampleBankTernaryStates = createSampleBankTernaryButtons().ToArray();
AddInternal(new DrawableRulesetDependenciesProvidingContainer(Composer.Ruleset)
{
@ -98,6 +94,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
foreach (var kvp in SelectionHandler.SelectionAdditionBankStates)
kvp.Value.BindValueChanged(_ => updatePlacementSamples());
SelectionHandler.AutoSelectionBankEnabled.BindValueChanged(_ => updateAutoBankTernaryButtonTooltip(), true);
SelectionHandler.SelectionAdditionBanksEnabled.BindValueChanged(_ => updateAdditionBankTernaryButtonTooltips(), true);
}
protected override void TransferBlueprintFor(HitObject hitObject, DrawableHitObject drawableObject)
@ -238,28 +237,45 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// <summary>
/// A collection of states which will be displayed to the user in the toolbox.
/// </summary>
public TernaryButton[] MainTernaryStates { get; private set; }
public DrawableTernaryButton[] MainTernaryStates { get; private set; }
public TernaryButton[] SampleBankTernaryStates { get; private set; }
public TernaryButton[] SampleAdditionBankTernaryStates { get; private set; }
public SampleBankTernaryButton[] SampleBankTernaryStates { get; private set; }
/// <summary>
/// Create all ternary states required to be displayed to the user.
/// </summary>
protected virtual IEnumerable<TernaryButton> CreateTernaryButtons()
protected virtual IEnumerable<DrawableTernaryButton> CreateTernaryButtons()
{
//TODO: this should only be enabled (visible?) for rulesets that provide combo-supporting HitObjects.
yield return new TernaryButton(NewCombo, "New combo", () => new SpriteIcon { Icon = OsuIcon.EditorNewComboA });
yield return new DrawableTernaryButton
{
Current = NewCombo,
Description = "New combo",
CreateIcon = () => new SpriteIcon { Icon = OsuIcon.EditorNewComboA },
};
foreach (var kvp in SelectionHandler.SelectionSampleStates)
yield return new TernaryButton(kvp.Value, kvp.Key.Replace("hit", string.Empty).Titleize(), () => GetIconForSample(kvp.Key));
{
yield return new DrawableTernaryButton
{
Current = kvp.Value,
Description = kvp.Key.Replace(@"hit", string.Empty).Titleize(),
CreateIcon = () => GetIconForSample(kvp.Key),
};
}
}
private IEnumerable<TernaryButton> createSampleBankTernaryButtons(Dictionary<string, Bindable<TernaryState>> sampleBankStates)
private IEnumerable<SampleBankTernaryButton> createSampleBankTernaryButtons()
{
foreach (var kvp in sampleBankStates)
yield return new TernaryButton(kvp.Value, kvp.Key.Titleize(), () => getIconForBank(kvp.Key));
foreach (string bankName in HitSampleInfo.ALL_BANKS.Prepend(EditorSelectionHandler.HIT_BANK_AUTO))
{
yield return new SampleBankTernaryButton(bankName)
{
NormalState = { Current = SelectionHandler.SelectionBankStates[bankName], },
AdditionsState = { Current = SelectionHandler.SelectionAdditionBankStates[bankName], },
CreateIcon = () => getIconForBank(bankName)
};
}
}
private Drawable getIconForBank(string sampleName)
@ -295,19 +311,19 @@ namespace osu.Game.Screens.Edit.Compose.Components
{
bool enabled = SelectionHandler.AutoSelectionBankEnabled.Value;
var autoBankButton = SampleBankTernaryStates.Single(t => t.Bindable == SelectionHandler.SelectionBankStates[EditorSelectionHandler.HIT_BANK_AUTO]);
autoBankButton.Enabled.Value = enabled;
autoBankButton.Tooltip = !enabled ? "Auto normal bank can only be used during hit object placement" : string.Empty;
var autoBankButton = SampleBankTernaryStates.Single(t => t.BankName == EditorSelectionHandler.HIT_BANK_AUTO);
autoBankButton.NormalButton.Enabled.Value = enabled;
autoBankButton.NormalButton.TooltipText = !enabled ? "Auto normal bank can only be used during hit object placement" : string.Empty;
}
private void updateAdditionBankTernaryButtonTooltips()
{
bool enabled = SelectionHandler.SelectionAdditionBanksEnabled.Value;
foreach (var ternaryButton in SampleAdditionBankTernaryStates)
foreach (var ternaryButton in SampleBankTernaryStates)
{
ternaryButton.Enabled.Value = enabled;
ternaryButton.Tooltip = !enabled ? "Add an addition sample first to be able to set a bank" : string.Empty;
ternaryButton.AdditionsButton.Enabled.Value = enabled;
ternaryButton.AdditionsButton.TooltipText = !enabled ? "Add an addition sample first to be able to set a bank" : string.Empty;
}
}

View File

@ -300,7 +300,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
createStateBindables();
updateTernaryStates();
togglesCollection.AddRange(createTernaryButtons().Select(b => new DrawableTernaryButton(b) { RelativeSizeAxes = Axes.None, Size = new Vector2(40, 40) }));
togglesCollection.AddRange(createTernaryButtons());
}
private string? getCommonBank() => allRelevantSamples.Select(h => GetBankValue(h.samples)).Distinct().Count() == 1
@ -444,10 +444,19 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
}
}
private IEnumerable<TernaryButton> createTernaryButtons()
private IEnumerable<DrawableTernaryButton> createTernaryButtons()
{
foreach ((string sampleName, var bindable) in selectionSampleStates)
yield return new TernaryButton(bindable, string.Empty, () => ComposeBlueprintContainer.GetIconForSample(sampleName));
{
yield return new DrawableTernaryButton
{
Current = bindable,
Description = string.Empty,
CreateIcon = () => ComposeBlueprintContainer.GetIconForSample(sampleName),
RelativeSizeAxes = Axes.None,
Size = new Vector2(40, 40),
};
}
}
private void addHitSample(string sampleName)
@ -516,7 +525,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
if (item is not DrawableTernaryButton button) return base.OnKeyDown(e);
button.Button.Toggle();
button.Toggle();
}
return true;

View File

@ -45,6 +45,7 @@ using osu.Game.Rulesets;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Screens.Backgrounds;
using osu.Game.Screens.Edit.Components.Menus;
using osu.Game.Screens.Edit.Compose;
using osu.Game.Screens.Edit.Compose.Components.Timeline;
@ -54,7 +55,6 @@ using osu.Game.Screens.Edit.Setup;
using osu.Game.Screens.Edit.Timing;
using osu.Game.Screens.Edit.Verify;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Screens.Play;
using osu.Game.Users;
using osuTK.Input;
using WebCommonStrings = osu.Game.Resources.Localisation.Web.CommonStrings;
@ -63,7 +63,7 @@ namespace osu.Game.Screens.Edit
{
[Cached(typeof(IBeatSnapProvider))]
[Cached]
public partial class Editor : ScreenWithBeatmapBackground, IKeyBindingHandler<GlobalAction>, IKeyBindingHandler<PlatformAction>, IBeatSnapProvider, ISamplePlaybackDisabler, IBeatSyncProvider
public partial class Editor : OsuScreen, IKeyBindingHandler<GlobalAction>, IKeyBindingHandler<PlatformAction>, IBeatSnapProvider, ISamplePlaybackDisabler, IBeatSyncProvider
{
/// <summary>
/// An offset applied to waveform visuals to align them with expectations.
@ -210,6 +210,7 @@ namespace osu.Game.Screens.Edit
private OnScreenDisplay onScreenDisplay { get; set; }
private Bindable<float> editorBackgroundDim;
private Bindable<bool> editorShowStoryboard;
private Bindable<bool> editorHitMarkers;
private Bindable<bool> editorAutoSeekOnPlacement;
private Bindable<bool> editorLimitedDistanceSnap;
@ -320,6 +321,7 @@ namespace osu.Game.Screens.Edit
OsuMenuItem redoMenuItem;
editorBackgroundDim = config.GetBindable<float>(OsuSetting.EditorDim);
editorShowStoryboard = config.GetBindable<bool>(OsuSetting.EditorShowStoryboard);
editorHitMarkers = config.GetBindable<bool>(OsuSetting.EditorShowHitMarkers);
editorAutoSeekOnPlacement = config.GetBindable<bool>(OsuSetting.EditorAutoSeekOnPlacement);
editorLimitedDistanceSnap = config.GetBindable<bool>(OsuSetting.EditorLimitedDistanceSnap);
@ -398,7 +400,13 @@ namespace osu.Game.Screens.Edit
},
]
},
new OsuMenuItemSpacer(),
new BackgroundDimMenuItem(editorBackgroundDim),
new ToggleMenuItem("Show storyboard")
{
State = { BindTarget = editorShowStoryboard },
},
new OsuMenuItemSpacer(),
new ToggleMenuItem(EditorStrings.ShowHitMarkers)
{
State = { BindTarget = editorHitMarkers },
@ -466,12 +474,14 @@ namespace osu.Game.Screens.Edit
changeHandler?.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true);
changeHandler?.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true);
editorBackgroundDim.BindValueChanged(_ => dimBackground());
editorBackgroundDim.BindValueChanged(_ => setUpBackground());
}
[Resolved]
private MusicController musicController { get; set; }
protected override BackgroundScreen CreateBackground() => new EditorBackgroundScreen(Beatmap.Value);
protected override void LoadComplete()
{
base.LoadComplete();
@ -853,24 +863,23 @@ namespace osu.Game.Screens.Edit
public override void OnEntering(ScreenTransitionEvent e)
{
base.OnEntering(e);
dimBackground();
setUpBackground();
resetTrack(true);
}
public override void OnResuming(ScreenTransitionEvent e)
{
base.OnResuming(e);
dimBackground();
setUpBackground();
clock.BindAdjustments();
}
private void dimBackground()
private void setUpBackground()
{
ApplyToBackground(b =>
{
b.IgnoreUserSettings.Value = true;
b.DimWhenUserSettingsIgnored.Value = editorBackgroundDim.Value;
b.BlurAmount.Value = 0;
var editorBackground = (EditorBackgroundScreen)b;
editorBackground.ChangeClockSource(clock);
});
}
@ -909,11 +918,6 @@ namespace osu.Game.Screens.Edit
beatmap.EditorTimestamp = clock.CurrentTime;
});
ApplyToBackground(b =>
{
b.DimWhenUserSettingsIgnored.Value = 0;
});
resetTrack();
refetchBeatmap();

View File

@ -12,6 +12,7 @@ using osu.Game.Beatmaps;
using osu.Game.Overlays;
using osu.Game.Localisation;
using osu.Game.Models;
using osu.Game.Screens.Backgrounds;
using osu.Game.Utils;
namespace osu.Game.Screens.Edit.Setup
@ -87,7 +88,7 @@ namespace osu.Game.Screens.Edit.Setup
(metadata, name) => metadata.BackgroundFile = name);
headerBackground.UpdateBackground();
editor?.ApplyToBackground(bg => bg.RefreshBackground());
editor?.ApplyToBackground(bg => ((EditorBackgroundScreen)bg).RefreshBackground());
return true;
}

View File

@ -840,6 +840,7 @@ See the LICENCE file in the repository root for full licence text.&#xD;
<s:Boolean x:Key="/Default/Environment/AutoImport2/=CSHARP/BlackLists/=Microsoft_002EToolkit_002EHighPerformance_002EBox_002A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/AutoImport2/=CSHARP/BlackLists/=OpenTabletDriver_002EPlugin_002EDependencyInjection_002E_002A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/AutoImport2/=CSHARP/BlackLists/=Realms_002ELogging_002ELogger/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/AutoImport2/=CSHARP/BlackLists/=Realms_002EThreadSafe_002A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/AutoImport2/=CSHARP/BlackLists/=System_002EComponentModel_002EComponent/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/AutoImport2/=CSHARP/BlackLists/=System_002EComponentModel_002EContainer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/AutoImport2/=CSHARP/BlackLists/=System_002ENumerics_002E_002A/@EntryIndexedValue">True</s:Boolean>