mirror of
https://github.com/osukey/osukey.git
synced 2025-05-23 06:27:24 +09:00
Merge remote-tracking branch 'upstream/master' into beatsnap-grid-integration
This commit is contained in:
commit
b157aaead1
@ -16,6 +16,11 @@ namespace osu.Android
|
|||||||
|
|
||||||
protected override void OnCreate(Bundle savedInstanceState)
|
protected override void OnCreate(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
|
// The default current directory on android is '/'.
|
||||||
|
// On some devices '/' maps to the app data directory. On others it maps to the root of the internal storage.
|
||||||
|
// In order to have a consistent current directory on all devices the full path of the app data directory is set as the current directory.
|
||||||
|
System.Environment.CurrentDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
|
||||||
|
|
||||||
base.OnCreate(savedInstanceState);
|
base.OnCreate(savedInstanceState);
|
||||||
|
|
||||||
Window.AddFlags(WindowManagerFlags.Fullscreen);
|
Window.AddFlags(WindowManagerFlags.Fullscreen);
|
||||||
|
@ -65,24 +65,27 @@ namespace osu.Game.Rulesets.Mania.Edit
|
|||||||
|
|
||||||
private void performDragMovement(MoveSelectionEvent moveEvent)
|
private void performDragMovement(MoveSelectionEvent moveEvent)
|
||||||
{
|
{
|
||||||
|
float delta = moveEvent.InstantDelta.Y;
|
||||||
|
|
||||||
|
// When scrolling downwards the anchor position is at the bottom of the screen, however the movement event assumes the anchor is at the top of the screen.
|
||||||
|
// This causes the delta to assume a positive hitobject position, and which can be corrected for by subtracting the parent height.
|
||||||
|
if (scrollingInfo.Direction.Value == ScrollingDirection.Down)
|
||||||
|
delta -= moveEvent.Blueprint.HitObject.Parent.DrawHeight;
|
||||||
|
|
||||||
foreach (var b in SelectedBlueprints)
|
foreach (var b in SelectedBlueprints)
|
||||||
{
|
{
|
||||||
var hitObject = b.HitObject;
|
var hitObject = b.HitObject;
|
||||||
|
|
||||||
var objectParent = (HitObjectContainer)hitObject.Parent;
|
var objectParent = (HitObjectContainer)hitObject.Parent;
|
||||||
|
|
||||||
// Using the hitobject position is required since AdjustPosition can be invoked multiple times per frame
|
// StartTime could be used to adjust the position if only one movement event was received per frame.
|
||||||
// without the position having been updated by the parenting ScrollingHitObjectContainer
|
// However this is not the case and ScrollingHitObjectContainer performs movement in UpdateAfterChildren() so the position must also be updated to be valid for further movement events
|
||||||
hitObject.Y += moveEvent.InstantDelta.Y;
|
hitObject.Y += delta;
|
||||||
|
|
||||||
float targetPosition;
|
float targetPosition = hitObject.Position.Y;
|
||||||
|
|
||||||
// If we're scrolling downwards, a position of 0 is actually further away from the hit target
|
// The scrolling algorithm always assumes an anchor at the top of the screen, so the position must be flipped when scrolling downwards to reflect a top anchor
|
||||||
// so we need to flip the vertical coordinate in the hitobject container's space
|
|
||||||
if (scrollingInfo.Direction.Value == ScrollingDirection.Down)
|
if (scrollingInfo.Direction.Value == ScrollingDirection.Down)
|
||||||
targetPosition = -hitObject.Position.Y;
|
targetPosition = -targetPosition;
|
||||||
else
|
|
||||||
targetPosition = hitObject.Position.Y;
|
|
||||||
|
|
||||||
objectParent.Remove(hitObject);
|
objectParent.Remove(hitObject);
|
||||||
|
|
||||||
|
@ -52,6 +52,13 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.Position);
|
AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestStackedHitObject()
|
||||||
|
{
|
||||||
|
AddStep("set stacking", () => hitCircle.StackHeight = 5);
|
||||||
|
AddAssert("blueprint positioned over hitobject", () => blueprint.CirclePiece.Position == hitCircle.StackedPosition);
|
||||||
|
}
|
||||||
|
|
||||||
private class TestBlueprint : HitCircleSelectionBlueprint
|
private class TestBlueprint : HitCircleSelectionBlueprint
|
||||||
{
|
{
|
||||||
public new HitCirclePiece CirclePiece => base.CirclePiece;
|
public new HitCirclePiece CirclePiece => base.CirclePiece;
|
||||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
|
|||||||
/// <param name="hitObject">The <see cref="OsuHitObject"/> to reference properties from.</param>
|
/// <param name="hitObject">The <see cref="OsuHitObject"/> to reference properties from.</param>
|
||||||
public virtual void UpdateFrom(T hitObject)
|
public virtual void UpdateFrom(T hitObject)
|
||||||
{
|
{
|
||||||
Position = hitObject.Position;
|
Position = hitObject.StackedPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,11 @@
|
|||||||
// 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 osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Effects;
|
using osu.Framework.Graphics.Effects;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Configuration;
|
|
||||||
using osu.Game.Rulesets.Osu.Skinning;
|
using osu.Game.Rulesets.Osu.Skinning;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -23,12 +20,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
|
|
||||||
private bool cursorExpand;
|
private bool cursorExpand;
|
||||||
|
|
||||||
private Bindable<float> cursorScale;
|
|
||||||
private Bindable<bool> autoCursorScale;
|
|
||||||
private readonly IBindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
|
||||||
|
|
||||||
private Container expandTarget;
|
private Container expandTarget;
|
||||||
private Drawable scaleTarget;
|
|
||||||
|
|
||||||
public OsuCursor()
|
public OsuCursor()
|
||||||
{
|
{
|
||||||
@ -43,43 +35,19 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuConfigManager config, IBindable<WorkingBeatmap> beatmap)
|
private void load()
|
||||||
{
|
{
|
||||||
InternalChild = expandTarget = new Container
|
InternalChild = expandTarget = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Child = scaleTarget = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.Cursor), _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling)
|
Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.Cursor), _ => new DefaultCursor(), confineMode: ConfineMode.NoScaling)
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.beatmap.BindTo(beatmap);
|
|
||||||
this.beatmap.ValueChanged += _ => calculateScale();
|
|
||||||
|
|
||||||
cursorScale = config.GetBindable<float>(OsuSetting.GameplayCursorSize);
|
|
||||||
cursorScale.ValueChanged += _ => calculateScale();
|
|
||||||
|
|
||||||
autoCursorScale = config.GetBindable<bool>(OsuSetting.AutoCursorSize);
|
|
||||||
autoCursorScale.ValueChanged += _ => calculateScale();
|
|
||||||
|
|
||||||
calculateScale();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateScale()
|
|
||||||
{
|
|
||||||
float scale = cursorScale.Value;
|
|
||||||
|
|
||||||
if (autoCursorScale.Value && beatmap.Value != null)
|
|
||||||
{
|
|
||||||
// if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier.
|
|
||||||
scale *= 1f - 0.7f * (1f + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
scaleTarget.Scale = new Vector2(scale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private const float pressed_scale = 1.2f;
|
private const float pressed_scale = 1.2f;
|
||||||
|
@ -8,6 +8,8 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Rulesets.Osu.Configuration;
|
using osu.Game.Rulesets.Osu.Configuration;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
@ -27,6 +29,11 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
|
|
||||||
private readonly Drawable cursorTrail;
|
private readonly Drawable cursorTrail;
|
||||||
|
|
||||||
|
public Bindable<float> CursorScale;
|
||||||
|
private Bindable<float> userCursorScale;
|
||||||
|
private Bindable<bool> autoCursorScale;
|
||||||
|
private readonly IBindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
public OsuCursorContainer()
|
public OsuCursorContainer()
|
||||||
{
|
{
|
||||||
InternalChild = fadeContainer = new Container
|
InternalChild = fadeContainer = new Container
|
||||||
@ -37,9 +44,36 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(OsuRulesetConfigManager config)
|
private void load(OsuConfigManager config, OsuRulesetConfigManager rulesetConfig, IBindable<WorkingBeatmap> beatmap)
|
||||||
{
|
{
|
||||||
config?.BindWith(OsuRulesetSetting.ShowCursorTrail, showTrail);
|
rulesetConfig?.BindWith(OsuRulesetSetting.ShowCursorTrail, showTrail);
|
||||||
|
|
||||||
|
this.beatmap.BindTo(beatmap);
|
||||||
|
this.beatmap.ValueChanged += _ => calculateScale();
|
||||||
|
|
||||||
|
userCursorScale = config.GetBindable<float>(OsuSetting.GameplayCursorSize);
|
||||||
|
userCursorScale.ValueChanged += _ => calculateScale();
|
||||||
|
|
||||||
|
autoCursorScale = config.GetBindable<bool>(OsuSetting.AutoCursorSize);
|
||||||
|
autoCursorScale.ValueChanged += _ => calculateScale();
|
||||||
|
|
||||||
|
CursorScale = new Bindable<float>();
|
||||||
|
CursorScale.ValueChanged += e => ActiveCursor.Scale = cursorTrail.Scale = new Vector2(e.NewValue);
|
||||||
|
|
||||||
|
calculateScale();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calculateScale()
|
||||||
|
{
|
||||||
|
float scale = userCursorScale.Value;
|
||||||
|
|
||||||
|
if (autoCursorScale.Value && beatmap.Value != null)
|
||||||
|
{
|
||||||
|
// if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier.
|
||||||
|
scale *= 1f - 0.7f * (1f + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
CursorScale.Value = scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
@ -95,13 +129,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
protected override void PopIn()
|
protected override void PopIn()
|
||||||
{
|
{
|
||||||
fadeContainer.FadeTo(1, 300, Easing.OutQuint);
|
fadeContainer.FadeTo(1, 300, Easing.OutQuint);
|
||||||
ActiveCursor.ScaleTo(1, 400, Easing.OutQuint);
|
ActiveCursor.ScaleTo(CursorScale.Value, 400, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopOut()
|
protected override void PopOut()
|
||||||
{
|
{
|
||||||
fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint);
|
fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint);
|
||||||
ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint);
|
ActiveCursor.ScaleTo(CursorScale.Value * 0.8f, 450, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DefaultCursorTrail : CursorTrail
|
private class DefaultCursorTrail : CursorTrail
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Cursor;
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Rulesets.Osu.UI.Cursor;
|
using osu.Game.Rulesets.Osu.UI.Cursor;
|
||||||
using osu.Game.Rulesets.UI;
|
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
@ -18,9 +18,11 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
{
|
{
|
||||||
public class OsuResumeOverlay : ResumeOverlay
|
public class OsuResumeOverlay : ResumeOverlay
|
||||||
{
|
{
|
||||||
|
private Container cursorScaleContainer;
|
||||||
private OsuClickToResumeCursor clickToResumeCursor;
|
private OsuClickToResumeCursor clickToResumeCursor;
|
||||||
|
|
||||||
private GameplayCursorContainer localCursorContainer;
|
private OsuCursorContainer localCursorContainer;
|
||||||
|
private Bindable<float> localCursorScale;
|
||||||
|
|
||||||
public override CursorContainer LocalCursor => State.Value == Visibility.Visible ? localCursorContainer : null;
|
public override CursorContainer LocalCursor => State.Value == Visibility.Visible ? localCursorContainer : null;
|
||||||
|
|
||||||
@ -29,22 +31,35 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
Add(clickToResumeCursor = new OsuClickToResumeCursor { ResumeRequested = Resume });
|
Add(cursorScaleContainer = new Container
|
||||||
|
{
|
||||||
|
RelativePositionAxes = Axes.Both,
|
||||||
|
Child = clickToResumeCursor = new OsuClickToResumeCursor { ResumeRequested = Resume }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Show()
|
public override void Show()
|
||||||
{
|
{
|
||||||
base.Show();
|
base.Show();
|
||||||
clickToResumeCursor.ShowAt(GameplayCursor.ActiveCursor.Position);
|
GameplayCursor.ActiveCursor.Hide();
|
||||||
|
cursorScaleContainer.MoveTo(GameplayCursor.ActiveCursor.Position);
|
||||||
|
clickToResumeCursor.Appear();
|
||||||
|
|
||||||
if (localCursorContainer == null)
|
if (localCursorContainer == null)
|
||||||
|
{
|
||||||
Add(localCursorContainer = new OsuCursorContainer());
|
Add(localCursorContainer = new OsuCursorContainer());
|
||||||
|
|
||||||
|
localCursorScale = new Bindable<float>();
|
||||||
|
localCursorScale.BindTo(localCursorContainer.CursorScale);
|
||||||
|
localCursorScale.BindValueChanged(scale => cursorScaleContainer.Scale = new Vector2(scale.NewValue), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Hide()
|
public override void Hide()
|
||||||
{
|
{
|
||||||
localCursorContainer?.Expire();
|
localCursorContainer?.Expire();
|
||||||
localCursorContainer = null;
|
localCursorContainer = null;
|
||||||
|
GameplayCursor.ActiveCursor.Show();
|
||||||
|
|
||||||
base.Hide();
|
base.Hide();
|
||||||
}
|
}
|
||||||
@ -82,7 +97,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
case OsuAction.RightButton:
|
case OsuAction.RightButton:
|
||||||
if (!IsHovered) return false;
|
if (!IsHovered) return false;
|
||||||
|
|
||||||
this.ScaleTo(new Vector2(2), TRANSITION_TIME, Easing.OutQuint);
|
this.ScaleTo(2, TRANSITION_TIME, Easing.OutQuint);
|
||||||
|
|
||||||
ResumeRequested?.Invoke();
|
ResumeRequested?.Invoke();
|
||||||
return true;
|
return true;
|
||||||
@ -93,11 +108,10 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
|
|
||||||
public bool OnReleased(OsuAction action) => false;
|
public bool OnReleased(OsuAction action) => false;
|
||||||
|
|
||||||
public void ShowAt(Vector2 activeCursorPosition) => Schedule(() =>
|
public void Appear() => Schedule(() =>
|
||||||
{
|
{
|
||||||
updateColour();
|
updateColour();
|
||||||
this.MoveTo(activeCursorPosition);
|
this.ScaleTo(4).Then().ScaleTo(1, 1000, Easing.OutQuint);
|
||||||
this.ScaleTo(new Vector2(4)).Then().ScaleTo(Vector2.One, 1000, Easing.OutQuint);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
private void updateColour()
|
private void updateColour()
|
||||||
|
143
osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs
Normal file
143
osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
// 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 NUnit.Framework;
|
||||||
|
using osu.Framework.Audio.Sample;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Gameplay
|
||||||
|
{
|
||||||
|
[HeadlessTest]
|
||||||
|
public class TestSceneHitObjectAccentColour : OsuTestScene
|
||||||
|
{
|
||||||
|
private Container skinContainer;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup() => Schedule(() => Child = skinContainer = new SkinProvidingContainer(new TestSkin()));
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestChangeComboIndexBeforeLoad()
|
||||||
|
{
|
||||||
|
TestDrawableHitObject hitObject = null;
|
||||||
|
|
||||||
|
AddStep("set combo and add hitobject", () =>
|
||||||
|
{
|
||||||
|
hitObject = new TestDrawableHitObject();
|
||||||
|
hitObject.HitObject.ComboIndex = 1;
|
||||||
|
|
||||||
|
skinContainer.Add(hitObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("combo colour is green", () => hitObject.AccentColour.Value == Color4.Green);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestChangeComboIndexDuringLoad()
|
||||||
|
{
|
||||||
|
TestDrawableHitObject hitObject = null;
|
||||||
|
|
||||||
|
AddStep("add hitobject and set combo", () =>
|
||||||
|
{
|
||||||
|
skinContainer.Add(hitObject = new TestDrawableHitObject());
|
||||||
|
hitObject.HitObject.ComboIndex = 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("combo colour is green", () => hitObject.AccentColour.Value == Color4.Green);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestChangeComboIndexAfterLoad()
|
||||||
|
{
|
||||||
|
TestDrawableHitObject hitObject = null;
|
||||||
|
|
||||||
|
AddStep("add hitobject", () => skinContainer.Add(hitObject = new TestDrawableHitObject()));
|
||||||
|
AddAssert("combo colour is red", () => hitObject.AccentColour.Value == Color4.Red);
|
||||||
|
|
||||||
|
AddStep("change combo", () => hitObject.HitObject.ComboIndex = 1);
|
||||||
|
AddAssert("combo colour is green", () => hitObject.AccentColour.Value == Color4.Green);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestDrawableHitObject : DrawableHitObject<TestHitObjectWithCombo>
|
||||||
|
{
|
||||||
|
public TestDrawableHitObject()
|
||||||
|
: base(new TestHitObjectWithCombo())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestHitObjectWithCombo : HitObject, IHasComboInformation
|
||||||
|
{
|
||||||
|
public bool NewCombo { get; } = false;
|
||||||
|
public int ComboOffset { get; } = 0;
|
||||||
|
|
||||||
|
public Bindable<int> IndexInCurrentComboBindable { get; } = new Bindable<int>();
|
||||||
|
|
||||||
|
public int IndexInCurrentCombo
|
||||||
|
{
|
||||||
|
get => IndexInCurrentComboBindable.Value;
|
||||||
|
set => IndexInCurrentComboBindable.Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bindable<int> ComboIndexBindable { get; } = new Bindable<int>();
|
||||||
|
|
||||||
|
public int ComboIndex
|
||||||
|
{
|
||||||
|
get => ComboIndexBindable.Value;
|
||||||
|
set => ComboIndexBindable.Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bindable<bool> LastInComboBindable { get; } = new Bindable<bool>();
|
||||||
|
|
||||||
|
public bool LastInCombo
|
||||||
|
{
|
||||||
|
get => LastInComboBindable.Value;
|
||||||
|
set => LastInComboBindable.Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestSkin : ISkin
|
||||||
|
{
|
||||||
|
public readonly List<Color4> ComboColours = new List<Color4>
|
||||||
|
{
|
||||||
|
Color4.Red,
|
||||||
|
Color4.Green
|
||||||
|
};
|
||||||
|
|
||||||
|
public Drawable GetDrawableComponent(ISkinComponent component) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public Texture GetTexture(string componentName) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
|
{
|
||||||
|
switch (lookup)
|
||||||
|
{
|
||||||
|
case GlobalSkinConfiguration global:
|
||||||
|
switch (global)
|
||||||
|
{
|
||||||
|
case GlobalSkinConfiguration.ComboColours:
|
||||||
|
return SkinUtils.As<TValue>(new Bindable<List<Color4>>(ComboColours));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs
Normal file
48
osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// 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 NUnit.Framework;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.NonVisual
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class BeatmapSetInfoEqualityTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestOnlineWithOnline()
|
||||||
|
{
|
||||||
|
var ourInfo = new BeatmapSetInfo { OnlineBeatmapSetID = 123 };
|
||||||
|
var otherInfo = new BeatmapSetInfo { OnlineBeatmapSetID = 123 };
|
||||||
|
|
||||||
|
Assert.AreEqual(ourInfo, otherInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDatabasedWithDatabased()
|
||||||
|
{
|
||||||
|
var ourInfo = new BeatmapSetInfo { ID = 123 };
|
||||||
|
var otherInfo = new BeatmapSetInfo { ID = 123 };
|
||||||
|
|
||||||
|
Assert.AreEqual(ourInfo, otherInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDatabasedWithOnline()
|
||||||
|
{
|
||||||
|
var ourInfo = new BeatmapSetInfo { ID = 123, OnlineBeatmapSetID = 12 };
|
||||||
|
var otherInfo = new BeatmapSetInfo { OnlineBeatmapSetID = 12 };
|
||||||
|
|
||||||
|
Assert.AreEqual(ourInfo, otherInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCheckNullID()
|
||||||
|
{
|
||||||
|
var ourInfo = new BeatmapSetInfo { Status = BeatmapSetOnlineStatus.Loved };
|
||||||
|
var otherInfo = new BeatmapSetInfo { Status = BeatmapSetOnlineStatus.Approved };
|
||||||
|
|
||||||
|
Assert.AreNotEqual(ourInfo, otherInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -63,6 +63,21 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public bool Protected { get; set; }
|
public bool Protected { get; set; }
|
||||||
|
|
||||||
public bool Equals(BeatmapSetInfo other) => OnlineBeatmapSetID == other?.OnlineBeatmapSetID;
|
public bool Equals(BeatmapSetInfo other)
|
||||||
|
{
|
||||||
|
if (other == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ID != 0 && other.ID != 0)
|
||||||
|
return ID == other.ID;
|
||||||
|
|
||||||
|
if (OnlineBeatmapSetID.HasValue && other.OnlineBeatmapSetID.HasValue)
|
||||||
|
return OnlineBeatmapSetID == other.OnlineBeatmapSetID;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Hash) && !string.IsNullOrEmpty(other.Hash))
|
||||||
|
return Hash == other.Hash;
|
||||||
|
|
||||||
|
return ReferenceEquals(this, other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ namespace osu.Game.Overlays.AccountCreation
|
|||||||
multiAccountExplanationText.AddText("? osu! has a policy of ");
|
multiAccountExplanationText.AddText("? osu! has a policy of ");
|
||||||
multiAccountExplanationText.AddText("one account per person!", cp => cp.Colour = colours.Yellow);
|
multiAccountExplanationText.AddText("one account per person!", cp => cp.Colour = colours.Yellow);
|
||||||
multiAccountExplanationText.AddText(" Please be aware that creating more than one account per person may result in ");
|
multiAccountExplanationText.AddText(" Please be aware that creating more than one account per person may result in ");
|
||||||
multiAccountExplanationText.AddText("permanent deactivation of accounts", cp => cp.Colour = colours.Yellow);
|
multiAccountExplanationText.AddText("permanent deactivation of accounts", cp => cp.Colour = colours.Yellow);
|
||||||
multiAccountExplanationText.AddText(".");
|
multiAccountExplanationText.AddText(".");
|
||||||
|
|
||||||
furtherAssistance.AddText("Need further assistance? Contact us via our ");
|
furtherAssistance.AddText("Need further assistance? Contact us via our ");
|
||||||
|
@ -64,7 +64,8 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
{
|
{
|
||||||
drawableRulesetWrapper = new DrawableEditRulesetWrapper<TObject>(CreateDrawableRuleset(Ruleset, workingBeatmap, Array.Empty<Mod>()))
|
drawableRulesetWrapper = new DrawableEditRulesetWrapper<TObject>(CreateDrawableRuleset(Ruleset, workingBeatmap, Array.Empty<Mod>()))
|
||||||
{
|
{
|
||||||
Clock = framedClock
|
Clock = framedClock,
|
||||||
|
ProcessCustomClock = false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -135,7 +135,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
if (HitObject is IHasComboInformation combo)
|
if (HitObject is IHasComboInformation combo)
|
||||||
{
|
{
|
||||||
comboIndexBindable = combo.ComboIndexBindable.GetBoundCopy();
|
comboIndexBindable = combo.ComboIndexBindable.GetBoundCopy();
|
||||||
comboIndexBindable.BindValueChanged(_ => updateAccentColour());
|
comboIndexBindable.BindValueChanged(_ => updateAccentColour(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateState(ArmedState.Idle, true);
|
updateState(ArmedState.Idle, true);
|
||||||
@ -161,11 +161,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
{
|
{
|
||||||
var drawableNested = CreateNestedHitObject(h) ?? throw new InvalidOperationException($"{nameof(CreateNestedHitObject)} returned null for {h.GetType().ReadableName()}.");
|
var drawableNested = CreateNestedHitObject(h) ?? throw new InvalidOperationException($"{nameof(CreateNestedHitObject)} returned null for {h.GetType().ReadableName()}.");
|
||||||
|
|
||||||
drawableNested.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r);
|
addNested(drawableNested);
|
||||||
drawableNested.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r);
|
|
||||||
drawableNested.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j);
|
|
||||||
|
|
||||||
nestedHitObjects.Value.Add(drawableNested);
|
|
||||||
AddNestedHitObject(drawableNested);
|
AddNestedHitObject(drawableNested);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,14 +179,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="h"></param>
|
/// <param name="h"></param>
|
||||||
[Obsolete("Use AddNestedHitObject() / ClearNestedHitObjects() / CreateNestedHitObject() instead.")] // can be removed 20200417
|
[Obsolete("Use AddNestedHitObject() / ClearNestedHitObjects() / CreateNestedHitObject() instead.")] // can be removed 20200417
|
||||||
protected virtual void AddNested(DrawableHitObject h)
|
protected virtual void AddNested(DrawableHitObject h) => addNested(h);
|
||||||
{
|
|
||||||
h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r);
|
|
||||||
h.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r);
|
|
||||||
h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j);
|
|
||||||
|
|
||||||
nestedHitObjects.Value.Add(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked by the base <see cref="DrawableHitObject"/> to remove all previously-added nested <see cref="DrawableHitObject"/>s.
|
/// Invoked by the base <see cref="DrawableHitObject"/> to remove all previously-added nested <see cref="DrawableHitObject"/>s.
|
||||||
@ -206,6 +195,17 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
/// <returns>The drawable representation for <paramref name="hitObject"/>.</returns>
|
/// <returns>The drawable representation for <paramref name="hitObject"/>.</returns>
|
||||||
protected virtual DrawableHitObject CreateNestedHitObject(HitObject hitObject) => null;
|
protected virtual DrawableHitObject CreateNestedHitObject(HitObject hitObject) => null;
|
||||||
|
|
||||||
|
private void addNested(DrawableHitObject hitObject)
|
||||||
|
{
|
||||||
|
// Todo: Exists for legacy purposes, can be removed 20200417
|
||||||
|
|
||||||
|
hitObject.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r);
|
||||||
|
hitObject.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r);
|
||||||
|
hitObject.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j);
|
||||||
|
|
||||||
|
nestedHitObjects.Value.Add(hitObject);
|
||||||
|
}
|
||||||
|
|
||||||
#region State / Transform Management
|
#region State / Transform Management
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -124,20 +124,12 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
if (blueprint == null)
|
if (blueprint == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (hitObject.IsLoaded)
|
blueprint.Selected += onBlueprintSelected;
|
||||||
addBlueprint();
|
blueprint.Deselected += onBlueprintDeselected;
|
||||||
else
|
blueprint.SelectionRequested += onSelectionRequested;
|
||||||
hitObject.OnLoadComplete += _ => addBlueprint();
|
blueprint.DragRequested += onDragRequested;
|
||||||
|
|
||||||
void addBlueprint()
|
selectionBlueprints.Add(blueprint);
|
||||||
{
|
|
||||||
blueprint.Selected += onBlueprintSelected;
|
|
||||||
blueprint.Deselected += onBlueprintDeselected;
|
|
||||||
blueprint.SelectionRequested += onSelectionRequested;
|
|
||||||
blueprint.DragRequested += onDragRequested;
|
|
||||||
|
|
||||||
selectionBlueprints.Add(blueprint);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeBlueprintFor(DrawableHitObject hitObject) => removeBlueprintFor(hitObject.HitObject);
|
private void removeBlueprintFor(DrawableHitObject hitObject) => removeBlueprintFor(hitObject.HitObject);
|
||||||
|
@ -173,6 +173,12 @@ namespace osu.Game.Screens.Edit
|
|||||||
bottomBackground.Colour = colours.Gray2;
|
bottomBackground.Colour = colours.Gray2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
clock.ProcessFrame();
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool OnKeyDown(KeyDownEvent e)
|
protected override bool OnKeyDown(KeyDownEvent e)
|
||||||
{
|
{
|
||||||
switch (e.Key)
|
switch (e.Key)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user