mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 07:42:57 +08:00
Merge branch 'master' into BPM_counter_fix
This commit is contained in:
commit
ef900bccdf
@ -187,28 +187,19 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
if (b.IsSelected)
|
||||
continue;
|
||||
|
||||
var hitObject = (OsuHitObject)b.Item;
|
||||
var snapPositions = b.ScreenSpaceSnapPoints;
|
||||
|
||||
Vector2? snap = checkSnap(hitObject.Position);
|
||||
if (snap == null && hitObject.Position != hitObject.EndPosition)
|
||||
snap = checkSnap(hitObject.EndPosition);
|
||||
if (!snapPositions.Any())
|
||||
continue;
|
||||
|
||||
if (snap != null)
|
||||
var closestSnapPosition = snapPositions.MinBy(p => Vector2.Distance(p, screenSpacePosition));
|
||||
|
||||
if (Vector2.Distance(closestSnapPosition, screenSpacePosition) < snapRadius)
|
||||
{
|
||||
// only return distance portion, since time is not really valid
|
||||
snapResult = new SnapResult(snap.Value, null, playfield);
|
||||
snapResult = new SnapResult(closestSnapPosition, null, playfield);
|
||||
return true;
|
||||
}
|
||||
|
||||
Vector2? checkSnap(Vector2 checkPos)
|
||||
{
|
||||
Vector2 checkScreenPos = playfield.GamefieldToScreenSpace(checkPos);
|
||||
|
||||
if (Vector2.Distance(checkScreenPos, screenSpacePosition) < snapRadius)
|
||||
return checkScreenPos;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
snapResult = null;
|
||||
|
@ -2,8 +2,11 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Rulesets.Taiko.Configuration;
|
||||
using osu.Game.Rulesets.Taiko.UI;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
@ -14,36 +17,48 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
private DrumTouchInputArea drumTouchInputArea = null!;
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
private readonly Bindable<TaikoTouchControlScheme> controlScheme = new Bindable<TaikoTouchControlScheme>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddStep("create drum", () =>
|
||||
var config = (TaikoRulesetConfigManager)RulesetConfigs.GetConfigFor(Ruleset.Value.CreateInstance()).AsNonNull();
|
||||
config.BindWith(TaikoRulesetSetting.TouchControlScheme, controlScheme);
|
||||
}
|
||||
|
||||
private void createDrum()
|
||||
{
|
||||
Child = new TaikoInputManager(new TaikoRuleset().RulesetInfo)
|
||||
{
|
||||
Child = new TaikoInputManager(new TaikoRuleset().RulesetInfo)
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
new InputDrum
|
||||
{
|
||||
new InputDrum
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Height = 0.2f,
|
||||
},
|
||||
drumTouchInputArea = new DrumTouchInputArea
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
},
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Height = 0.2f,
|
||||
},
|
||||
};
|
||||
});
|
||||
drumTouchInputArea = new DrumTouchInputArea
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDrum()
|
||||
{
|
||||
AddStep("create drum", createDrum);
|
||||
AddStep("show drum", () => drumTouchInputArea.Show());
|
||||
|
||||
AddStep("change scheme (kddk)", () => controlScheme.Value = TaikoTouchControlScheme.KDDK);
|
||||
AddStep("change scheme (kkdd)", () => controlScheme.Value = TaikoTouchControlScheme.KKDD);
|
||||
AddStep("change scheme (ddkk)", () => controlScheme.Value = TaikoTouchControlScheme.DDKK);
|
||||
}
|
||||
|
||||
protected override Ruleset CreateRuleset() => new TaikoRuleset();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
// 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.Game.Configuration;
|
||||
using osu.Game.Rulesets.Configuration;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Configuration
|
||||
{
|
||||
public class TaikoRulesetConfigManager : RulesetConfigManager<TaikoRulesetSetting>
|
||||
{
|
||||
public TaikoRulesetConfigManager(SettingsStore? settings, RulesetInfo ruleset, int? variant = null)
|
||||
: base(settings, ruleset, variant)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void InitialiseDefaults()
|
||||
{
|
||||
base.InitialiseDefaults();
|
||||
|
||||
SetDefault(TaikoRulesetSetting.TouchControlScheme, TaikoTouchControlScheme.KDDK);
|
||||
}
|
||||
}
|
||||
|
||||
public enum TaikoRulesetSetting
|
||||
{
|
||||
TouchControlScheme
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
// 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.
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Configuration
|
||||
{
|
||||
public enum TaikoTouchControlScheme
|
||||
{
|
||||
KDDK,
|
||||
DDKK,
|
||||
KKDD
|
||||
}
|
||||
}
|
@ -28,9 +28,13 @@ using osu.Game.Rulesets.Taiko.Skinning.Argon;
|
||||
using osu.Game.Rulesets.Taiko.Skinning.Legacy;
|
||||
using osu.Game.Rulesets.Taiko.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Ranking.Statistics;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Rulesets.Configuration;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets.Taiko.Configuration;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko
|
||||
{
|
||||
@ -194,6 +198,10 @@ namespace osu.Game.Rulesets.Taiko
|
||||
|
||||
public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new TaikoReplayFrame();
|
||||
|
||||
public override IRulesetConfigManager CreateConfig(SettingsStore? settings) => new TaikoRulesetConfigManager(settings, RulesetInfo);
|
||||
|
||||
public override RulesetSettingsSubsection CreateSettings() => new TaikoSettingsSubsection(this);
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
|
36
osu.Game.Rulesets.Taiko/TaikoSettingsSubsection.cs
Normal file
36
osu.Game.Rulesets.Taiko/TaikoSettingsSubsection.cs
Normal file
@ -0,0 +1,36 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Taiko.Configuration;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko
|
||||
{
|
||||
public partial class TaikoSettingsSubsection : RulesetSettingsSubsection
|
||||
{
|
||||
protected override LocalisableString Header => "osu!taiko";
|
||||
|
||||
public TaikoSettingsSubsection(TaikoRuleset ruleset)
|
||||
: base(ruleset)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var config = (TaikoRulesetConfigManager)Config;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsEnumDropdown<TaikoTouchControlScheme>
|
||||
{
|
||||
LabelText = "Touch control scheme",
|
||||
Current = config.GetBindable<TaikoTouchControlScheme>(TaikoRulesetSetting.TouchControlScheme)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -11,6 +13,7 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Taiko.Configuration;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -31,15 +34,18 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
private Container mainContent = null!;
|
||||
|
||||
private QuarterCircle leftCentre = null!;
|
||||
private QuarterCircle rightCentre = null!;
|
||||
private QuarterCircle leftRim = null!;
|
||||
private QuarterCircle rightRim = null!;
|
||||
private DrumSegment leftCentre = null!;
|
||||
private DrumSegment rightCentre = null!;
|
||||
private DrumSegment leftRim = null!;
|
||||
private DrumSegment rightRim = null!;
|
||||
|
||||
private readonly Bindable<TaikoTouchControlScheme> configTouchControlScheme = new Bindable<TaikoTouchControlScheme>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TaikoInputManager taikoInputManager, OsuColour colours)
|
||||
private void load(TaikoInputManager taikoInputManager, TaikoRulesetConfigManager config)
|
||||
{
|
||||
Debug.Assert(taikoInputManager.KeyBindingContainer != null);
|
||||
|
||||
keyBindingContainer = taikoInputManager.KeyBindingContainer;
|
||||
|
||||
// Container should handle input everywhere.
|
||||
@ -65,27 +71,27 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
leftRim = new QuarterCircle(TaikoAction.LeftRim, colours.Blue)
|
||||
leftRim = new DrumSegment
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomRight,
|
||||
X = -2,
|
||||
},
|
||||
rightRim = new QuarterCircle(TaikoAction.RightRim, colours.Blue)
|
||||
rightRim = new DrumSegment
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomRight,
|
||||
X = 2,
|
||||
Rotation = 90,
|
||||
},
|
||||
leftCentre = new QuarterCircle(TaikoAction.LeftCentre, colours.Pink)
|
||||
leftCentre = new DrumSegment
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomRight,
|
||||
X = -2,
|
||||
Scale = new Vector2(centre_region),
|
||||
},
|
||||
rightCentre = new QuarterCircle(TaikoAction.RightCentre, colours.Pink)
|
||||
rightCentre = new DrumSegment
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomRight,
|
||||
@ -98,6 +104,17 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
config.BindWith(TaikoRulesetSetting.TouchControlScheme, configTouchControlScheme);
|
||||
configTouchControlScheme.BindValueChanged(scheme =>
|
||||
{
|
||||
var actions = getOrderedActionsForScheme(scheme.NewValue);
|
||||
|
||||
leftRim.Action = actions[0];
|
||||
leftCentre.Action = actions[1];
|
||||
rightCentre.Action = actions[2];
|
||||
rightRim.Action = actions[3];
|
||||
}, true);
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
@ -119,11 +136,47 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
base.OnTouchUp(e);
|
||||
}
|
||||
|
||||
private static TaikoAction[] getOrderedActionsForScheme(TaikoTouchControlScheme scheme)
|
||||
{
|
||||
switch (scheme)
|
||||
{
|
||||
case TaikoTouchControlScheme.KDDK:
|
||||
return new[]
|
||||
{
|
||||
TaikoAction.LeftRim,
|
||||
TaikoAction.LeftCentre,
|
||||
TaikoAction.RightCentre,
|
||||
TaikoAction.RightRim
|
||||
};
|
||||
|
||||
case TaikoTouchControlScheme.DDKK:
|
||||
return new[]
|
||||
{
|
||||
TaikoAction.LeftCentre,
|
||||
TaikoAction.RightCentre,
|
||||
TaikoAction.LeftRim,
|
||||
TaikoAction.RightRim
|
||||
};
|
||||
|
||||
case TaikoTouchControlScheme.KKDD:
|
||||
return new[]
|
||||
{
|
||||
TaikoAction.LeftRim,
|
||||
TaikoAction.RightRim,
|
||||
TaikoAction.LeftCentre,
|
||||
TaikoAction.RightCentre
|
||||
};
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(scheme), scheme, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDown(object source, Vector2 position)
|
||||
{
|
||||
Show();
|
||||
|
||||
TaikoAction taikoAction = getTaikoActionFromInput(position);
|
||||
TaikoAction taikoAction = getTaikoActionFromPosition(position);
|
||||
|
||||
// Not too sure how this can happen, but let's avoid throwing.
|
||||
if (trackedActions.ContainsKey(source))
|
||||
@ -139,18 +192,15 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
trackedActions.Remove(source);
|
||||
}
|
||||
|
||||
private bool validMouse(MouseButtonEvent e) =>
|
||||
leftRim.Contains(e.ScreenSpaceMouseDownPosition) || rightRim.Contains(e.ScreenSpaceMouseDownPosition);
|
||||
|
||||
private TaikoAction getTaikoActionFromInput(Vector2 inputPosition)
|
||||
private TaikoAction getTaikoActionFromPosition(Vector2 inputPosition)
|
||||
{
|
||||
bool centreHit = leftCentre.Contains(inputPosition) || rightCentre.Contains(inputPosition);
|
||||
bool leftSide = ToLocalSpace(inputPosition).X < DrawWidth / 2;
|
||||
|
||||
if (leftSide)
|
||||
return centreHit ? TaikoAction.LeftCentre : TaikoAction.LeftRim;
|
||||
return centreHit ? leftCentre.Action : leftRim.Action;
|
||||
|
||||
return centreHit ? TaikoAction.RightCentre : TaikoAction.RightRim;
|
||||
return centreHit ? rightCentre.Action : rightRim.Action;
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
@ -163,23 +213,42 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
mainContent.FadeOut(300);
|
||||
}
|
||||
|
||||
private partial class QuarterCircle : CompositeDrawable, IKeyBindingHandler<TaikoAction>
|
||||
private partial class DrumSegment : CompositeDrawable, IKeyBindingHandler<TaikoAction>
|
||||
{
|
||||
private readonly Circle overlay;
|
||||
private TaikoAction action;
|
||||
|
||||
private readonly TaikoAction handledAction;
|
||||
public TaikoAction Action
|
||||
{
|
||||
get => action;
|
||||
set
|
||||
{
|
||||
if (action == value)
|
||||
return;
|
||||
|
||||
private readonly Circle circle;
|
||||
action = value;
|
||||
updateColoursFromAction();
|
||||
}
|
||||
}
|
||||
|
||||
private Circle overlay = null!;
|
||||
|
||||
private Circle circle = null!;
|
||||
|
||||
[Resolved]
|
||||
private OsuColour colours { get; set; } = null!;
|
||||
|
||||
public override bool Contains(Vector2 screenSpacePos) => circle.Contains(screenSpacePos);
|
||||
|
||||
public QuarterCircle(TaikoAction handledAction, Color4 colour)
|
||||
public DrumSegment()
|
||||
{
|
||||
this.handledAction = handledAction;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
FillMode = FillMode.Fit;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
@ -191,7 +260,6 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
circle = new Circle
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colour.Multiply(1.4f).Darken(2.8f),
|
||||
Alpha = 0.8f,
|
||||
Scale = new Vector2(2),
|
||||
},
|
||||
@ -200,7 +268,6 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
Alpha = 0,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Blending = BlendingParameters.Additive,
|
||||
Colour = colour,
|
||||
Scale = new Vector2(2),
|
||||
}
|
||||
}
|
||||
@ -208,18 +275,52 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
updateColoursFromAction();
|
||||
}
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<TaikoAction> e)
|
||||
{
|
||||
if (e.Action == handledAction)
|
||||
if (e.Action == Action)
|
||||
overlay.FadeTo(1f, 80, Easing.OutQuint);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(KeyBindingReleaseEvent<TaikoAction> e)
|
||||
{
|
||||
if (e.Action == handledAction)
|
||||
if (e.Action == Action)
|
||||
overlay.FadeOut(1000, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void updateColoursFromAction()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
var colour = getColourFromTaikoAction(Action);
|
||||
|
||||
circle.Colour = colour.Multiply(1.4f).Darken(2.8f);
|
||||
overlay.Colour = colour;
|
||||
}
|
||||
|
||||
private Color4 getColourFromTaikoAction(TaikoAction handledAction)
|
||||
{
|
||||
switch (handledAction)
|
||||
{
|
||||
case TaikoAction.LeftRim:
|
||||
case TaikoAction.RightRim:
|
||||
return colours.Blue;
|
||||
|
||||
case TaikoAction.LeftCentre:
|
||||
case TaikoAction.RightCentre:
|
||||
return colours.Pink;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,21 +36,24 @@ namespace osu.Game.Overlays.Profile
|
||||
AutoSizeAxes = Axes.Y;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = 10;
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Offset = new Vector2(0, 1),
|
||||
Radius = 3,
|
||||
Colour = Colour4.Black.Opacity(0.25f)
|
||||
};
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
background = new Box
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
CornerRadius = 10,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Offset = new Vector2(0, 1),
|
||||
Radius = 3,
|
||||
Colour = Colour4.Black.Opacity(0.25f)
|
||||
},
|
||||
Child = background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
|
@ -40,7 +40,7 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(2)
|
||||
Spacing = new Vector2(EditorSidebar.PADDING)
|
||||
};
|
||||
|
||||
reloadComponents();
|
||||
|
@ -18,6 +18,8 @@ namespace osu.Game.Screens.Edit.Components
|
||||
{
|
||||
public const float WIDTH = 250;
|
||||
|
||||
public const float PADDING = 3;
|
||||
|
||||
private readonly Box background;
|
||||
|
||||
protected override Container<EditorSidebarSection> Content { get; }
|
||||
@ -35,13 +37,13 @@ namespace osu.Game.Screens.Edit.Components
|
||||
},
|
||||
new OsuScrollContainer
|
||||
{
|
||||
Padding = new MarginPadding { Left = 20 },
|
||||
ScrollbarOverlapsContent = false,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = Content = new FillFlowContainer<EditorSidebarSection>
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding(PADDING),
|
||||
Direction = FillDirection.Vertical,
|
||||
},
|
||||
}
|
||||
|
@ -91,6 +91,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
blueprint.DrawableObject = drawableObject;
|
||||
}
|
||||
|
||||
private bool nudgeMovementActive;
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
{
|
||||
if (e.ControlPressed)
|
||||
@ -98,19 +100,19 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Left:
|
||||
moveSelection(new Vector2(-1, 0));
|
||||
nudgeSelection(new Vector2(-1, 0));
|
||||
return true;
|
||||
|
||||
case Key.Right:
|
||||
moveSelection(new Vector2(1, 0));
|
||||
nudgeSelection(new Vector2(1, 0));
|
||||
return true;
|
||||
|
||||
case Key.Up:
|
||||
moveSelection(new Vector2(0, -1));
|
||||
nudgeSelection(new Vector2(0, -1));
|
||||
return true;
|
||||
|
||||
case Key.Down:
|
||||
moveSelection(new Vector2(0, 1));
|
||||
nudgeSelection(new Vector2(0, 1));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -118,12 +120,29 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void OnKeyUp(KeyUpEvent e)
|
||||
{
|
||||
base.OnKeyUp(e);
|
||||
|
||||
if (nudgeMovementActive && !e.ControlPressed)
|
||||
{
|
||||
Beatmap.EndChange();
|
||||
nudgeMovementActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move the current selection spatially by the specified delta, in gamefield coordinates (ie. the same coordinates as the blueprints).
|
||||
/// </summary>
|
||||
/// <param name="delta"></param>
|
||||
private void moveSelection(Vector2 delta)
|
||||
private void nudgeSelection(Vector2 delta)
|
||||
{
|
||||
if (!nudgeMovementActive)
|
||||
{
|
||||
nudgeMovementActive = true;
|
||||
Beatmap.BeginChange();
|
||||
}
|
||||
|
||||
var firstBlueprint = SelectionHandler.SelectedBlueprints.FirstOrDefault();
|
||||
|
||||
if (firstBlueprint == null)
|
||||
|
@ -47,8 +47,9 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
|
||||
private Sprite background = null!;
|
||||
|
||||
private Action<BeatmapInfo>? startRequested;
|
||||
private Action<BeatmapInfo>? editRequested;
|
||||
private MenuItem[]? mainMenuItems;
|
||||
|
||||
private Action<BeatmapInfo>? selectRequested;
|
||||
private Action<BeatmapInfo>? hideRequested;
|
||||
|
||||
private Triangles triangles = null!;
|
||||
@ -84,9 +85,8 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
|
||||
if (songSelect != null)
|
||||
{
|
||||
startRequested = b => songSelect.FinaliseSelection(b);
|
||||
if (songSelect.AllowEditing)
|
||||
editRequested = songSelect.Edit;
|
||||
mainMenuItems = songSelect.CreateForwardNavigationMenuItemsForBeatmap(beatmapInfo);
|
||||
selectRequested = b => songSelect.FinaliseSelection(b);
|
||||
}
|
||||
|
||||
if (manager != null)
|
||||
@ -193,7 +193,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
if (Item?.State.Value == CarouselItemState.Selected)
|
||||
startRequested?.Invoke(beatmapInfo);
|
||||
selectRequested?.Invoke(beatmapInfo);
|
||||
|
||||
return base.OnClick(e);
|
||||
}
|
||||
@ -227,11 +227,8 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
{
|
||||
List<MenuItem> items = new List<MenuItem>();
|
||||
|
||||
if (startRequested != null)
|
||||
items.Add(new OsuMenuItem("Play", MenuItemType.Highlighted, () => startRequested(beatmapInfo)));
|
||||
|
||||
if (editRequested != null)
|
||||
items.Add(new OsuMenuItem(CommonStrings.ButtonsEdit, MenuItemType.Standard, () => editRequested(beatmapInfo)));
|
||||
if (mainMenuItems != null)
|
||||
items.AddRange(mainMenuItems);
|
||||
|
||||
if (beatmapInfo.OnlineID > 0 && beatmapOverlay != null)
|
||||
items.Add(new OsuMenuItem("Details...", MenuItemType.Standard, () => beatmapOverlay.FetchAndShowBeatmap(beatmapInfo.OnlineID)));
|
||||
|
@ -4,10 +4,14 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.LocalisationExtensions;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
@ -30,6 +34,12 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
public override bool AllowExternalScreenChange => true;
|
||||
|
||||
public override MenuItem[] CreateForwardNavigationMenuItemsForBeatmap(BeatmapInfo beatmap) => new MenuItem[]
|
||||
{
|
||||
new OsuMenuItem(ButtonSystemStrings.Play.ToSentence(), MenuItemType.Highlighted, () => FinaliseSelection(beatmap)),
|
||||
new OsuMenuItem(ButtonSystemStrings.Edit.ToSentence(), MenuItemType.Standard, () => Edit(beatmap))
|
||||
};
|
||||
|
||||
protected override UserActivity InitialActivity => new UserActivity.ChoosingBeatmap();
|
||||
|
||||
private PlayBeatmapDetailArea playBeatmapDetailArea = null!;
|
||||
@ -37,7 +47,7 @@ namespace osu.Game.Screens.Select
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
BeatmapOptions.AddButton(@"Edit", @"beatmap", FontAwesome.Solid.PencilAlt, colours.Yellow, () => Edit());
|
||||
BeatmapOptions.AddButton(ButtonSystemStrings.Edit.ToSentence(), @"beatmap", FontAwesome.Solid.PencilAlt, colours.Yellow, () => Edit());
|
||||
}
|
||||
|
||||
protected void PresentScore(ScoreInfo score) =>
|
||||
|
@ -1,19 +1,31 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Collections;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods;
|
||||
@ -21,23 +33,12 @@ using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Select.Options;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Collections;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Screens.Select
|
||||
{
|
||||
@ -83,6 +84,17 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
public bool BeatmapSetsLoaded => IsLoaded && Carousel.BeatmapSetsLoaded;
|
||||
|
||||
/// <summary>
|
||||
/// Creates any "action" menu items for the provided beatmap (ie. "Select", "Play", "Edit").
|
||||
/// These will always be placed at the top of the context menu, with common items added below them.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The beatmap to create items for.</param>
|
||||
/// <returns>The menu items.</returns>
|
||||
public virtual MenuItem[] CreateForwardNavigationMenuItemsForBeatmap(BeatmapInfo beatmap) => new MenuItem[]
|
||||
{
|
||||
new OsuMenuItem(@"Select", MenuItemType.Highlighted, () => FinaliseSelection(beatmap))
|
||||
};
|
||||
|
||||
[Resolved]
|
||||
private Bindable<IReadOnlyList<Mod>> selectedMods { get; set; } = null!;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user