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

Disable toolbox composition buttons when beatmap is not timed

This commit is contained in:
Dean Herbert 2021-07-17 02:30:13 +09:00
parent 3ae5f6707a
commit eac9b1ec7e
3 changed files with 103 additions and 32 deletions

View File

@ -2,17 +2,24 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Timing; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Edit;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.Edit; using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Components.RadioButtons;
using osu.Game.Screens.Edit.Compose.Components;
using osuTK; using osuTK;
namespace osu.Game.Tests.Visual.Editing namespace osu.Game.Tests.Visual.Editing
@ -20,37 +27,89 @@ namespace osu.Game.Tests.Visual.Editing
[TestFixture] [TestFixture]
public class TestSceneHitObjectComposer : EditorClockTestScene public class TestSceneHitObjectComposer : EditorClockTestScene
{ {
[BackgroundDependencyLoader] private OsuHitObjectComposer hitObjectComposer;
private void load() private EditorBeatmapContainer editorBeatmapContainer;
private EditorBeatmap editorBeatmap => editorBeatmapContainer.EditorBeatmap;
[SetUpSteps]
public void SetUpSteps()
{ {
Beatmap.Value = CreateWorkingBeatmap(new Beatmap AddStep("create beatmap", () =>
{ {
HitObjects = new List<HitObject> Beatmap.Value = CreateWorkingBeatmap(new Beatmap
{ {
new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f }, HitObjects = new List<HitObject>
new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f },
new Slider
{ {
Position = new Vector2(128, 256), new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f },
Path = new SliderPath(PathType.Linear, new[] new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f },
new Slider
{ {
Vector2.Zero, Position = new Vector2(128, 256),
new Vector2(216, 0), Path = new SliderPath(PathType.Linear, new[]
}), {
Scale = 0.5f, Vector2.Zero,
} new Vector2(216, 0),
}, }),
Scale = 0.5f,
}
},
});
}); });
var editorBeatmap = new EditorBeatmap(Beatmap.Value.GetPlayableBeatmap(new OsuRuleset().RulesetInfo)); AddStep("Create composer", () =>
{
Child = editorBeatmapContainer = new EditorBeatmapContainer(Beatmap.Value)
{
Child = hitObjectComposer = new OsuHitObjectComposer(new OsuRuleset())
};
});
}
var clock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; [Test]
Dependencies.CacheAs<IAdjustableClock>(clock); public void TestPlacementOnlyWorksWithTiming()
Dependencies.CacheAs<IFrameBasedClock>(clock); {
Dependencies.CacheAs(editorBeatmap); AddStep("clear all control points", () => editorBeatmap.ControlPointInfo.Clear());
Dependencies.CacheAs<IBeatSnapProvider>(editorBeatmap);
Child = new OsuHitObjectComposer(new OsuRuleset()); AddAssert("Tool is selection", () => hitObjectComposer.ChildrenOfType<ComposeBlueprintContainer>().First().CurrentTool is SelectTool);
AddAssert("Hitcircle button not clickable", () => !hitObjectComposer.ChildrenOfType<DrawableRadioButton>().First(d => d.Button.Item == "HitCircle").Enabled.Value);
AddStep("Add timing point", () => editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint()));
AddAssert("Hitcircle button is clickable", () => hitObjectComposer.ChildrenOfType<DrawableRadioButton>().First(d => d.Button.Item == "HitCircle").Enabled.Value);
AddStep("Change to hitcircle", () => hitObjectComposer.ChildrenOfType<DrawableRadioButton>().First(d => d.Button.Item == "HitCircle").Click());
AddAssert("Tool changed", () => hitObjectComposer.ChildrenOfType<ComposeBlueprintContainer>().First().CurrentTool is HitCircleCompositionTool);
}
public class EditorBeatmapContainer : Container
{
private readonly WorkingBeatmap working;
public EditorBeatmap EditorBeatmap { get; private set; }
public EditorBeatmapContainer(WorkingBeatmap working)
{
this.working = working;
RelativeSizeAxes = Axes.Both;
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
EditorBeatmap = new EditorBeatmap(working.GetPlayableBeatmap(new OsuRuleset().RulesetInfo));
dependencies.CacheAs(EditorBeatmap);
dependencies.CacheAs<IBeatSnapProvider>(EditorBeatmap);
return dependencies;
}
protected override void LoadComplete()
{
base.LoadComplete();
Add(EditorBeatmap);
}
} }
} }
} }

View File

@ -219,7 +219,8 @@ namespace osu.Game.Rulesets.Edit
if (item != null) if (item != null)
{ {
item.Select(); if (!item.Selected.Disabled)
item.Select();
return true; return true;
} }
} }

View File

@ -5,9 +5,11 @@ using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
@ -16,24 +18,28 @@ using osuTK.Graphics;
namespace osu.Game.Screens.Edit.Components.RadioButtons namespace osu.Game.Screens.Edit.Components.RadioButtons
{ {
public class DrawableRadioButton : OsuButton public class DrawableRadioButton : OsuButton, IHasTooltip
{ {
/// <summary> /// <summary>
/// Invoked when this <see cref="DrawableRadioButton"/> has been selected. /// Invoked when this <see cref="DrawableRadioButton"/> has been selected.
/// </summary> /// </summary>
public Action<RadioButton> Selected; public Action<RadioButton> Selected;
public readonly RadioButton Button;
private Color4 defaultBackgroundColour; private Color4 defaultBackgroundColour;
private Color4 defaultBubbleColour; private Color4 defaultBubbleColour;
private Color4 selectedBackgroundColour; private Color4 selectedBackgroundColour;
private Color4 selectedBubbleColour; private Color4 selectedBubbleColour;
private Drawable icon; private Drawable icon;
private readonly RadioButton button;
[Resolved(canBeNull: true)]
private EditorBeatmap editorBeatmap { get; set; }
public DrawableRadioButton(RadioButton button) public DrawableRadioButton(RadioButton button)
{ {
this.button = button; this.Button = button;
Text = button.Item.ToString(); Text = button.Item.ToString();
Action = button.Select; Action = button.Select;
@ -57,7 +63,7 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons
Colour = Color4.Black.Opacity(0.5f) Colour = Color4.Black.Opacity(0.5f)
}; };
Add(icon = (button.CreateIcon?.Invoke() ?? new Circle()).With(b => Add(icon = (Button.CreateIcon?.Invoke() ?? new Circle()).With(b =>
{ {
b.Blending = BlendingParameters.Additive; b.Blending = BlendingParameters.Additive;
b.Anchor = Anchor.CentreLeft; b.Anchor = Anchor.CentreLeft;
@ -71,13 +77,16 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons
{ {
base.LoadComplete(); base.LoadComplete();
button.Selected.ValueChanged += selected => Button.Selected.ValueChanged += selected =>
{ {
updateSelectionState(); updateSelectionState();
if (selected.NewValue) if (selected.NewValue)
Selected?.Invoke(button); Selected?.Invoke(Button);
}; };
editorBeatmap?.HasTiming.BindValueChanged(hasTiming => Button.Selected.Disabled = !hasTiming.NewValue, true);
Button.Selected.BindDisabledChanged(disabled => Enabled.Value = !disabled, true);
updateSelectionState(); updateSelectionState();
} }
@ -86,8 +95,8 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons
if (!IsLoaded) if (!IsLoaded)
return; return;
BackgroundColour = button.Selected.Value ? selectedBackgroundColour : defaultBackgroundColour; BackgroundColour = Button.Selected.Value ? selectedBackgroundColour : defaultBackgroundColour;
icon.Colour = button.Selected.Value ? selectedBubbleColour : defaultBubbleColour; icon.Colour = Button.Selected.Value ? selectedBubbleColour : defaultBubbleColour;
} }
protected override SpriteText CreateText() => new OsuSpriteText protected override SpriteText CreateText() => new OsuSpriteText
@ -97,5 +106,7 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
X = 40f X = 40f
}; };
public LocalisableString TooltipText => Enabled.Value ? string.Empty : "Add at least one timing point first!";
} }
} }