mirror of
https://github.com/ppy/osu.git
synced 2025-01-26 18:03:11 +08:00
Merge branch 'master' into taiko-drumroll-party
# Conflicts: # osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs
This commit is contained in:
commit
2a197db481
@ -41,8 +41,6 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
AccentColour = Color4.OrangeRed,
|
AccentColour = Color4.OrangeRed,
|
||||||
Clock = new FramedClock(new StopwatchClock()), // No scroll
|
Clock = new FramedClock(new StopwatchClock()), // No scroll
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("change direction", () => ((ScrollingTestContainer)HitObjectContainer).Flip());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Container CreateHitObjectContainer() => new ScrollingTestContainer(ScrollingDirection.Down) { RelativeSizeAxes = Axes.Both };
|
protected override Container CreateHitObjectContainer() => new ScrollingTestContainer(ScrollingDirection.Down) { RelativeSizeAxes = Axes.Both };
|
||||||
|
@ -1,17 +1,59 @@
|
|||||||
// 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.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Rulesets.Mania.Edit.Blueprints;
|
using osu.Game.Rulesets.Mania.Edit.Blueprints;
|
||||||
using osu.Game.Rulesets.Mania.Objects;
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Tests
|
namespace osu.Game.Rulesets.Mania.Tests
|
||||||
{
|
{
|
||||||
public class TestSceneNotePlacementBlueprint : ManiaPlacementBlueprintTestScene
|
public class TestSceneNotePlacementBlueprint : ManiaPlacementBlueprintTestScene
|
||||||
{
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup() => Schedule(() =>
|
||||||
|
{
|
||||||
|
this.ChildrenOfType<HitObjectContainer>().ForEach(c => c.Clear());
|
||||||
|
|
||||||
|
ResetPlacement();
|
||||||
|
|
||||||
|
((ScrollingTestContainer)HitObjectContainer).Direction = ScrollingDirection.Down;
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPlaceBeforeCurrentTimeDownwards()
|
||||||
|
{
|
||||||
|
AddStep("move mouse before current time", () => InputManager.MoveMouseTo(this.ChildrenOfType<Column>().Single().ScreenSpaceDrawQuad.BottomLeft - new Vector2(0, 10)));
|
||||||
|
|
||||||
|
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||||
|
|
||||||
|
AddAssert("note start time < 0", () => getNote().StartTime < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPlaceAfterCurrentTimeDownwards()
|
||||||
|
{
|
||||||
|
AddStep("move mouse after current time", () => InputManager.MoveMouseTo(this.ChildrenOfType<Column>().Single()));
|
||||||
|
|
||||||
|
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||||
|
|
||||||
|
AddAssert("note start time > 0", () => getNote().StartTime > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Note getNote() => this.ChildrenOfType<DrawableNote>().FirstOrDefault()?.HitObject;
|
||||||
|
|
||||||
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableNote((Note)hitObject);
|
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableNote((Note)hitObject);
|
||||||
protected override PlacementBlueprint CreateBlueprint() => new NotePlacementBlueprint();
|
protected override PlacementBlueprint CreateBlueprint() => new NotePlacementBlueprint();
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ using osu.Game.Rulesets.Mania.Beatmaps.Patterns;
|
|||||||
using osu.Game.Rulesets.Mania.MathUtils;
|
using osu.Game.Rulesets.Mania.MathUtils;
|
||||||
using osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy;
|
using osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osu.Game.Audio;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Beatmaps
|
namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||||
{
|
{
|
||||||
@ -67,7 +66,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CanConvert() => Beatmap.HitObjects.All(h => h is IHasXPosition || h is ManiaHitObject);
|
public override bool CanConvert() => Beatmap.HitObjects.All(h => h is IHasXPosition);
|
||||||
|
|
||||||
protected override Beatmap<ManiaHitObject> ConvertBeatmap(IBeatmap original)
|
protected override Beatmap<ManiaHitObject> ConvertBeatmap(IBeatmap original)
|
||||||
{
|
{
|
||||||
@ -239,8 +238,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
StartTime = HitObject.StartTime,
|
StartTime = HitObject.StartTime,
|
||||||
Duration = endTimeData.Duration,
|
Duration = endTimeData.Duration,
|
||||||
Column = column,
|
Column = column,
|
||||||
Head = { Samples = sampleInfoListAt(HitObject.StartTime) },
|
Samples = HitObject.Samples,
|
||||||
Tail = { Samples = sampleInfoListAt(endTimeData.EndTime) },
|
NodeSamples = (HitObject as IHasRepeats)?.NodeSamples
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (HitObject is IHasXPosition)
|
else if (HitObject is IHasXPosition)
|
||||||
@ -255,22 +254,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
|
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves the sample info list at a point in time.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="time">The time to retrieve the sample info list from.</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private IList<HitSampleInfo> sampleInfoListAt(double time)
|
|
||||||
{
|
|
||||||
if (!(HitObject is IHasCurve curveData))
|
|
||||||
return HitObject.Samples;
|
|
||||||
|
|
||||||
double segmentTime = (curveData.EndTime - HitObject.StartTime) / curveData.SpanCount();
|
|
||||||
|
|
||||||
int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime);
|
|
||||||
return curveData.NodeSamples[index];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -505,16 +505,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var holdNote = new HoldNote
|
newObject = new HoldNote
|
||||||
{
|
{
|
||||||
StartTime = startTime,
|
StartTime = startTime,
|
||||||
Column = column,
|
|
||||||
Duration = endTime - startTime,
|
Duration = endTime - startTime,
|
||||||
Head = { Samples = sampleInfoListAt(startTime) },
|
Column = column,
|
||||||
Tail = { Samples = sampleInfoListAt(endTime) }
|
Samples = HitObject.Samples,
|
||||||
|
NodeSamples = (HitObject as IHasRepeats)?.NodeSamples
|
||||||
};
|
};
|
||||||
|
|
||||||
newObject = holdNote;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern.Add(newObject);
|
pattern.Add(newObject);
|
||||||
|
@ -64,21 +64,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
|
|
||||||
if (holdNote)
|
if (holdNote)
|
||||||
{
|
{
|
||||||
var hold = new HoldNote
|
newObject = new HoldNote
|
||||||
{
|
{
|
||||||
StartTime = HitObject.StartTime,
|
StartTime = HitObject.StartTime,
|
||||||
|
Duration = endTime - HitObject.StartTime,
|
||||||
Column = column,
|
Column = column,
|
||||||
Duration = endTime - HitObject.StartTime
|
Samples = HitObject.Samples,
|
||||||
|
NodeSamples = (HitObject as IHasRepeats)?.NodeSamples
|
||||||
};
|
};
|
||||||
|
|
||||||
if (hold.Head.Samples == null)
|
|
||||||
hold.Head.Samples = new List<HitSampleInfo>();
|
|
||||||
|
|
||||||
hold.Head.Samples.Add(new HitSampleInfo { Name = HitSampleInfo.HIT_NORMAL });
|
|
||||||
|
|
||||||
hold.Tail.Samples = HitObject.Samples;
|
|
||||||
|
|
||||||
newObject = hold;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Rulesets.Mania.Edit.Blueprints.Components;
|
using osu.Game.Rulesets.Mania.Edit.Blueprints.Components;
|
||||||
using osu.Game.Rulesets.Mania.Objects;
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -46,6 +47,12 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
|||||||
bodyPiece.Height = (bottomPosition - topPosition).Y;
|
bodyPiece.Height = (bottomPosition - topPosition).Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseUp(MouseUpEvent e)
|
||||||
|
{
|
||||||
|
base.OnMouseUp(e);
|
||||||
|
EndPlacement(true);
|
||||||
|
}
|
||||||
|
|
||||||
private double originalStartTime;
|
private double originalStartTime;
|
||||||
|
|
||||||
public override void UpdatePosition(Vector2 screenSpacePosition)
|
public override void UpdatePosition(Vector2 screenSpacePosition)
|
||||||
|
@ -50,16 +50,10 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
|||||||
return base.OnMouseDown(e);
|
return base.OnMouseDown(e);
|
||||||
|
|
||||||
HitObject.Column = Column.Index;
|
HitObject.Column = Column.Index;
|
||||||
BeginPlacement(TimeAt(e.ScreenSpaceMousePosition));
|
BeginPlacement(TimeAt(e.ScreenSpaceMousePosition), true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnMouseUp(MouseUpEvent e)
|
|
||||||
{
|
|
||||||
EndPlacement(true);
|
|
||||||
base.OnMouseUp(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void UpdatePosition(Vector2 screenSpacePosition)
|
public override void UpdatePosition(Vector2 screenSpacePosition)
|
||||||
{
|
{
|
||||||
if (!PlacementActive)
|
if (!PlacementActive)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Rulesets.Mania.Edit.Blueprints.Components;
|
using osu.Game.Rulesets.Mania.Edit.Blueprints.Components;
|
||||||
using osu.Game.Rulesets.Mania.Objects;
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
|
|
||||||
@ -26,5 +27,15 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
|||||||
Width = SnappedWidth;
|
Width = SnappedWidth;
|
||||||
Position = SnappedMousePosition;
|
Position = SnappedMousePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool OnMouseDown(MouseDownEvent e)
|
||||||
|
{
|
||||||
|
base.OnMouseDown(e);
|
||||||
|
|
||||||
|
// Place the note immediately.
|
||||||
|
EndPlacement(true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
|
|
||||||
AddRangeInternal(new[]
|
AddRangeInternal(new[]
|
||||||
{
|
{
|
||||||
bodyPiece = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.HoldNoteBody, hitObject.Column), _ => new DefaultBodyPiece())
|
bodyPiece = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.HoldNoteBody, hitObject.Column), _ => new DefaultBodyPiece
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
})
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X
|
RelativeSizeAxes = Axes.X
|
||||||
},
|
},
|
||||||
@ -127,6 +130,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
bodyPiece.Anchor = bodyPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
|
bodyPiece.Anchor = bodyPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void PlaySamples()
|
||||||
|
{
|
||||||
|
// Samples are played by the head/tail notes.
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
@ -34,7 +34,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
public DefaultBodyPiece()
|
public DefaultBodyPiece()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both;
|
|
||||||
Blending = BlendingParameters.Additive;
|
Blending = BlendingParameters.Additive;
|
||||||
|
|
||||||
AddLayout(subtractionCache);
|
AddLayout(subtractionCache);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// 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.Collections.Generic;
|
||||||
|
using osu.Game.Audio;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
@ -28,6 +30,8 @@ namespace osu.Game.Rulesets.Mania.Objects
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
duration = value;
|
duration = value;
|
||||||
|
|
||||||
|
if (Tail != null)
|
||||||
Tail.StartTime = EndTime;
|
Tail.StartTime = EndTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,7 +42,11 @@ namespace osu.Game.Rulesets.Mania.Objects
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
base.StartTime = value;
|
base.StartTime = value;
|
||||||
|
|
||||||
|
if (Head != null)
|
||||||
Head.StartTime = value;
|
Head.StartTime = value;
|
||||||
|
|
||||||
|
if (Tail != null)
|
||||||
Tail.StartTime = EndTime;
|
Tail.StartTime = EndTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,20 +57,26 @@ namespace osu.Game.Rulesets.Mania.Objects
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
base.Column = value;
|
base.Column = value;
|
||||||
|
|
||||||
|
if (Head != null)
|
||||||
Head.Column = value;
|
Head.Column = value;
|
||||||
|
|
||||||
|
if (Tail != null)
|
||||||
Tail.Column = value;
|
Tail.Column = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<IList<HitSampleInfo>> NodeSamples { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The head note of the hold.
|
/// The head note of the hold.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly Note Head = new Note();
|
public Note Head { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The tail note of the hold.
|
/// The tail note of the hold.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly TailNote Tail = new TailNote();
|
public TailNote Tail { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The time between ticks of this hold.
|
/// The time between ticks of this hold.
|
||||||
@ -83,8 +97,19 @@ namespace osu.Game.Rulesets.Mania.Objects
|
|||||||
|
|
||||||
createTicks();
|
createTicks();
|
||||||
|
|
||||||
AddNested(Head);
|
AddNested(Head = new Note
|
||||||
AddNested(Tail);
|
{
|
||||||
|
StartTime = StartTime,
|
||||||
|
Column = Column,
|
||||||
|
Samples = getNodeSamples(0),
|
||||||
|
});
|
||||||
|
|
||||||
|
AddNested(Tail = new TailNote
|
||||||
|
{
|
||||||
|
StartTime = EndTime,
|
||||||
|
Column = Column,
|
||||||
|
Samples = getNodeSamples((NodeSamples?.Count - 1) ?? 1),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createTicks()
|
private void createTicks()
|
||||||
@ -105,5 +130,8 @@ namespace osu.Game.Rulesets.Mania.Objects
|
|||||||
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||||
|
|
||||||
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
||||||
|
|
||||||
|
private IList<HitSampleInfo> getNodeSamples(int nodeIndex) =>
|
||||||
|
nodeIndex < NodeSamples?.Count ? NodeSamples[nodeIndex] : Samples;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,12 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Game.Rulesets.Mania.Objects.Types;
|
using osu.Game.Rulesets.Mania.Objects.Types;
|
||||||
using osu.Game.Rulesets.Mania.Scoring;
|
using osu.Game.Rulesets.Mania.Scoring;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Objects
|
namespace osu.Game.Rulesets.Mania.Objects
|
||||||
{
|
{
|
||||||
public abstract class ManiaHitObject : HitObject, IHasColumn
|
public abstract class ManiaHitObject : HitObject, IHasColumn, IHasXPosition
|
||||||
{
|
{
|
||||||
public readonly Bindable<int> ColumnBindable = new Bindable<int>();
|
public readonly Bindable<int> ColumnBindable = new Bindable<int>();
|
||||||
|
|
||||||
@ -20,5 +21,11 @@ namespace osu.Game.Rulesets.Mania.Objects
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override HitWindows CreateHitWindows() => new ManiaHitWindows();
|
protected override HitWindows CreateHitWindows() => new ManiaHitWindows();
|
||||||
|
|
||||||
|
#region LegacyBeatmapEncoder
|
||||||
|
|
||||||
|
float IHasXPosition.X => Column;
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,6 +259,23 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
assertControlPointType(2, PathType.PerfectCurve);
|
assertControlPointType(2, PathType.PerfectCurve);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBeginPlacementWithoutReleasingMouse()
|
||||||
|
{
|
||||||
|
addMovementStep(new Vector2(200));
|
||||||
|
AddStep("press left button", () => InputManager.PressButton(MouseButton.Left));
|
||||||
|
|
||||||
|
addMovementStep(new Vector2(400, 200));
|
||||||
|
AddStep("release left button", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||||
|
|
||||||
|
addClickStep(MouseButton.Right);
|
||||||
|
|
||||||
|
assertPlaced(true);
|
||||||
|
assertLength(200);
|
||||||
|
assertControlPointCount(2);
|
||||||
|
assertControlPointType(0, PathType.Linear);
|
||||||
|
}
|
||||||
|
|
||||||
private void addMovementStep(Vector2 position) => AddStep($"move mouse to {position}", () => InputManager.MoveMouseTo(InputManager.ToScreenSpace(position)));
|
private void addMovementStep(Vector2 position) => AddStep($"move mouse to {position}", () => InputManager.MoveMouseTo(InputManager.ToScreenSpace(position)));
|
||||||
|
|
||||||
private void addClickStep(MouseButton button)
|
private void addClickStep(MouseButton button)
|
||||||
|
@ -6,6 +6,7 @@ using osu.Game.Rulesets.Edit;
|
|||||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
|
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
|
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
|
||||||
{
|
{
|
||||||
@ -28,16 +29,17 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
|
|||||||
circlePiece.UpdateFrom(HitObject);
|
circlePiece.UpdateFrom(HitObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnClick(ClickEvent e)
|
protected override bool OnMouseDown(MouseDownEvent e)
|
||||||
|
{
|
||||||
|
if (e.Button == MouseButton.Left)
|
||||||
{
|
{
|
||||||
EndPlacement(true);
|
EndPlacement(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdatePosition(Vector2 screenSpacePosition)
|
return base.OnMouseDown(e);
|
||||||
{
|
|
||||||
BeginPlacement();
|
|
||||||
HitObject.Position = ToLocalSpace(screenSpacePosition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void UpdatePosition(Vector2 screenSpacePosition) => HitObject.Position = ToLocalSpace(screenSpacePosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
public Action<PathControlPointPiece, MouseButtonEvent> RequestSelection;
|
public Action<PathControlPointPiece, MouseButtonEvent> RequestSelection;
|
||||||
|
|
||||||
public readonly BindableBool IsSelected = new BindableBool();
|
public readonly BindableBool IsSelected = new BindableBool();
|
||||||
|
|
||||||
public readonly PathControlPoint ControlPoint;
|
public readonly PathControlPoint ControlPoint;
|
||||||
|
|
||||||
private readonly Slider slider;
|
private readonly Slider slider;
|
||||||
@ -146,6 +145,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
|
|
||||||
protected override bool OnDragStart(DragStartEvent e)
|
protected override bool OnDragStart(DragStartEvent e)
|
||||||
{
|
{
|
||||||
|
if (RequestSelection == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (e.Button == MouseButton.Left)
|
if (e.Button == MouseButton.Left)
|
||||||
{
|
{
|
||||||
changeHandler?.BeginChange();
|
changeHandler?.BeginChange();
|
||||||
|
@ -82,8 +82,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnClick(ClickEvent e)
|
protected override bool OnMouseDown(MouseDownEvent e)
|
||||||
{
|
{
|
||||||
|
if (e.Button != MouseButton.Left)
|
||||||
|
return base.OnMouseDown(e);
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case PlacementState.Initial:
|
case PlacementState.Initial:
|
||||||
@ -91,9 +94,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PlacementState.Body:
|
case PlacementState.Body:
|
||||||
if (e.Button != MouseButton.Left)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (canPlaceNewControlPoint(out var lastPoint))
|
if (canPlaceNewControlPoint(out var lastPoint))
|
||||||
{
|
{
|
||||||
// Place a new point by detatching the current cursor.
|
// Place a new point by detatching the current cursor.
|
||||||
@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
|||||||
currentSegmentLength = 1;
|
currentSegmentLength = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 7.6 KiB |
@ -5,7 +5,9 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Taiko.Skinning;
|
using osu.Game.Rulesets.Taiko.Skinning;
|
||||||
using osu.Game.Rulesets.Taiko.UI;
|
using osu.Game.Rulesets.Taiko.UI;
|
||||||
@ -18,8 +20,9 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
|
|||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||||
{
|
{
|
||||||
typeof(HitTarget),
|
typeof(TaikoHitTarget),
|
||||||
typeof(LegacyHitTarget),
|
typeof(TaikoLegacyHitTarget),
|
||||||
|
typeof(PlayfieldBackgroundRight),
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
[Cached(typeof(IScrollingInfo))]
|
[Cached(typeof(IScrollingInfo))]
|
||||||
@ -33,10 +36,11 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
|
|||||||
{
|
{
|
||||||
AddStep("Load playfield", () => SetContents(() => new TaikoPlayfield(new ControlPointInfo())
|
AddStep("Load playfield", () => SetContents(() => new TaikoPlayfield(new ControlPointInfo())
|
||||||
{
|
{
|
||||||
Height = 0.4f,
|
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
AddRepeatStep("change height", () => this.ChildrenOfType<TaikoPlayfield>().ForEach(p => p.Height = Math.Max(0.2f, (p.Height + 0.2f) % 1f)), 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
/// osu! is generally slower than taiko, so a factor is added to increase
|
/// osu! is generally slower than taiko, so a factor is added to increase
|
||||||
/// speed. This must be used everywhere slider length or beat length is used.
|
/// speed. This must be used everywhere slider length or beat length is used.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const float legacy_velocity_multiplier = 1.4f;
|
public const float LEGACY_VELOCITY_MULTIPLIER = 1.4f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Because swells are easier in taiko than spinners are in osu!,
|
/// Because swells are easier in taiko than spinners are in osu!,
|
||||||
@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
// Rewrite the beatmap info to add the slider velocity multiplier
|
// Rewrite the beatmap info to add the slider velocity multiplier
|
||||||
original.BeatmapInfo = original.BeatmapInfo.Clone();
|
original.BeatmapInfo = original.BeatmapInfo.Clone();
|
||||||
original.BeatmapInfo.BaseDifficulty = original.BeatmapInfo.BaseDifficulty.Clone();
|
original.BeatmapInfo.BaseDifficulty = original.BeatmapInfo.BaseDifficulty.Clone();
|
||||||
original.BeatmapInfo.BaseDifficulty.SliderMultiplier *= legacy_velocity_multiplier;
|
original.BeatmapInfo.BaseDifficulty.SliderMultiplier *= LEGACY_VELOCITY_MULTIPLIER;
|
||||||
|
|
||||||
Beatmap<TaikoHitObject> converted = base.ConvertBeatmap(original);
|
Beatmap<TaikoHitObject> converted = base.ConvertBeatmap(original);
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
double speedAdjustedBeatLength = timingPoint.BeatLength / speedAdjustment;
|
double speedAdjustedBeatLength = timingPoint.BeatLength / speedAdjustment;
|
||||||
|
|
||||||
// The true distance, accounting for any repeats. This ends up being the drum roll distance later
|
// The true distance, accounting for any repeats. This ends up being the drum roll distance later
|
||||||
double distance = distanceData.Distance * spans * legacy_velocity_multiplier;
|
double distance = distanceData.Distance * spans * LEGACY_VELOCITY_MULTIPLIER;
|
||||||
|
|
||||||
// The velocity of the taiko hit object - calculated as the velocity of a drum roll
|
// The velocity of the taiko hit object - calculated as the velocity of a drum roll
|
||||||
double taikoVelocity = taiko_base_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / speedAdjustedBeatLength;
|
double taikoVelocity = taiko_base_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / speedAdjustedBeatLength;
|
||||||
|
@ -92,8 +92,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
// The input manager processes all input prior to us updating, so this is the perfect time
|
// The input manager processes all input prior to us updating, so this is the perfect time
|
||||||
// for us to remove the extra press blocking, before input is handled in the next frame
|
// for us to remove the extra press blocking, before input is handled in the next frame
|
||||||
pressHandledThisFrame = false;
|
pressHandledThisFrame = false;
|
||||||
|
|
||||||
Size = BaseSize * Parent.RelativeChildSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateStateTransforms(ArmedState state)
|
protected override void UpdateStateTransforms(ArmedState state)
|
||||||
|
@ -3,15 +3,20 @@
|
|||||||
|
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Game.Audio;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.Taiko.Beatmaps;
|
||||||
using osu.Game.Rulesets.Taiko.Judgements;
|
using osu.Game.Rulesets.Taiko.Judgements;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Objects
|
namespace osu.Game.Rulesets.Taiko.Objects
|
||||||
{
|
{
|
||||||
public class DrumRoll : TaikoHitObject, IHasEndTime
|
public class DrumRoll : TaikoHitObject, IHasCurve
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Drum roll distance that results in a duration of 1 speed-adjusted beat length.
|
/// Drum roll distance that results in a duration of 1 speed-adjusted beat length.
|
||||||
@ -26,6 +31,11 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
|||||||
|
|
||||||
public double Duration { get; set; }
|
public double Duration { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Velocity of this <see cref="DrumRoll"/>.
|
||||||
|
/// </summary>
|
||||||
|
public double Velocity { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Numer of ticks per beat length.
|
/// Numer of ticks per beat length.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -54,6 +64,10 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
|||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime);
|
TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime);
|
||||||
|
DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(StartTime);
|
||||||
|
|
||||||
|
double scoringDistance = base_distance * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier;
|
||||||
|
Velocity = scoringDistance / timingPoint.BeatLength;
|
||||||
|
|
||||||
tickSpacing = timingPoint.BeatLength / TickRate;
|
tickSpacing = timingPoint.BeatLength / TickRate;
|
||||||
overallDifficulty = difficulty.OverallDifficulty;
|
overallDifficulty = difficulty.OverallDifficulty;
|
||||||
@ -93,5 +107,18 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
|||||||
public override Judgement CreateJudgement() => new TaikoDrumRollJudgement();
|
public override Judgement CreateJudgement() => new TaikoDrumRollJudgement();
|
||||||
|
|
||||||
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
||||||
|
|
||||||
|
#region LegacyBeatmapEncoder
|
||||||
|
|
||||||
|
double IHasDistance.Distance => Duration * Velocity;
|
||||||
|
|
||||||
|
int IHasRepeats.RepeatCount { get => 0; set { } }
|
||||||
|
|
||||||
|
List<IList<HitSampleInfo>> IHasRepeats.NodeSamples => new List<IList<HitSampleInfo>>();
|
||||||
|
|
||||||
|
SliderPath IHasCurve.Path
|
||||||
|
=> new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(1) }, ((IHasDistance)this).Distance / TaikoBeatmapConverter.LEGACY_VELOCITY_MULTIPLIER);
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,41 +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 osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Game.Skinning;
|
|
||||||
using osuTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Skinning
|
|
||||||
{
|
|
||||||
public class LegacyHitTarget : CompositeDrawable
|
|
||||||
{
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(ISkinSource skin)
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
|
||||||
{
|
|
||||||
new Sprite
|
|
||||||
{
|
|
||||||
Texture = skin.GetTexture("approachcircle"),
|
|
||||||
Scale = new Vector2(0.73f),
|
|
||||||
Alpha = 0.7f,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
},
|
|
||||||
new Sprite
|
|
||||||
{
|
|
||||||
Texture = skin.GetTexture("taikobigcircle"),
|
|
||||||
Scale = new Vector2(0.7f),
|
|
||||||
Alpha = 0.5f,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,15 +20,19 @@ namespace osu.Game.Rulesets.Taiko.Skinning
|
|||||||
{
|
{
|
||||||
private LegacyHalfDrum left;
|
private LegacyHalfDrum left;
|
||||||
private LegacyHalfDrum right;
|
private LegacyHalfDrum right;
|
||||||
|
private Container content;
|
||||||
|
|
||||||
public LegacyInputDrum()
|
public LegacyInputDrum()
|
||||||
{
|
{
|
||||||
Size = new Vector2(180, 200);
|
RelativeSizeAxes = Axes.Both;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ISkinSource skin)
|
private void load(ISkinSource skin)
|
||||||
{
|
{
|
||||||
|
Child = content = new Container
|
||||||
|
{
|
||||||
|
Size = new Vector2(180, 200),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Sprite
|
new Sprite
|
||||||
@ -51,6 +55,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning
|
|||||||
RimAction = TaikoAction.RightRim,
|
RimAction = TaikoAction.RightRim,
|
||||||
CentreAction = TaikoAction.RightCentre
|
CentreAction = TaikoAction.RightCentre
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// this will be used in the future for stable skin alignment. keeping here for reference.
|
// this will be used in the future for stable skin alignment. keeping here for reference.
|
||||||
@ -60,7 +65,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning
|
|||||||
const float ratio = 1.6f;
|
const float ratio = 1.6f;
|
||||||
|
|
||||||
// because the right half is flipped, we need to position using width - position to get the true "topleft" origin position
|
// because the right half is flipped, we need to position using width - position to get the true "topleft" origin position
|
||||||
float negativeScaleAdjust = Width / ratio;
|
float negativeScaleAdjust = content.Width / ratio;
|
||||||
|
|
||||||
if (skin.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value >= 2.1m)
|
if (skin.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value >= 2.1m)
|
||||||
{
|
{
|
||||||
@ -78,6 +83,15 @@ namespace osu.Game.Rulesets.Taiko.Skinning
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
// Relying on RelativeSizeAxes.Both + FillMode.Fit doesn't work due to the precise pixel layout requirements.
|
||||||
|
// This is a bit ugly but makes the non-legacy implementations a lot cleaner to implement.
|
||||||
|
content.Scale = new Vector2(DrawHeight / content.Size.Y);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A half-drum. Contains one centre and one rim hit.
|
/// A half-drum. Contains one centre and one rim hit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
59
osu.Game.Rulesets.Taiko/Skinning/TaikoLegacyHitTarget.cs
Normal file
59
osu.Game.Rulesets.Taiko/Skinning/TaikoLegacyHitTarget.cs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// 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.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Rulesets.Taiko.UI;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Taiko.Skinning
|
||||||
|
{
|
||||||
|
public class TaikoLegacyHitTarget : CompositeDrawable
|
||||||
|
{
|
||||||
|
private Container content;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource skin)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
InternalChild = content = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Sprite
|
||||||
|
{
|
||||||
|
Texture = skin.GetTexture("approachcircle"),
|
||||||
|
Scale = new Vector2(0.73f),
|
||||||
|
Alpha = 0.7f,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
new Sprite
|
||||||
|
{
|
||||||
|
Texture = skin.GetTexture("taikobigcircle"),
|
||||||
|
Scale = new Vector2(0.7f),
|
||||||
|
Alpha = 0.5f,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
// Relying on RelativeSizeAxes.Both + FillMode.Fit doesn't work due to the precise pixel layout requirements.
|
||||||
|
// This is a bit ugly but makes the non-legacy implementations a lot cleaner to implement.
|
||||||
|
content.Scale = new Vector2(DrawHeight / TaikoPlayfield.DEFAULT_HEIGHT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Skinning
|
namespace osu.Game.Rulesets.Taiko.Skinning
|
||||||
{
|
{
|
||||||
@ -52,7 +53,26 @@ namespace osu.Game.Rulesets.Taiko.Skinning
|
|||||||
|
|
||||||
case TaikoSkinComponents.HitTarget:
|
case TaikoSkinComponents.HitTarget:
|
||||||
if (GetTexture("taikobigcircle") != null)
|
if (GetTexture("taikobigcircle") != null)
|
||||||
return new LegacyHitTarget();
|
return new TaikoLegacyHitTarget();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
case TaikoSkinComponents.PlayfieldBackgroundRight:
|
||||||
|
if (GetTexture("taiko-bar-right") != null)
|
||||||
|
{
|
||||||
|
return this.GetAnimation("taiko-bar-right", false, false).With(d =>
|
||||||
|
{
|
||||||
|
d.RelativeSizeAxes = Axes.Both;
|
||||||
|
d.Size = Vector2.One;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
case TaikoSkinComponents.PlayfieldBackgroundLeft:
|
||||||
|
// This is displayed inside LegacyInputDrum. It is required to be there for layout purposes (can be seen on legacy skins).
|
||||||
|
if (GetTexture("taiko-bar-right") != null)
|
||||||
|
return Drawable.Empty();
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@ namespace osu.Game.Rulesets.Taiko
|
|||||||
DrumRollBody,
|
DrumRollBody,
|
||||||
DrumRollTick,
|
DrumRollTick,
|
||||||
Swell,
|
Swell,
|
||||||
HitTarget
|
HitTarget,
|
||||||
|
PlayfieldBackgroundLeft,
|
||||||
|
PlayfieldBackgroundRight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
|
|
||||||
JudgedObject = judgedObject;
|
JudgedObject = judgedObject;
|
||||||
|
|
||||||
Anchor = Anchor.CentreLeft;
|
Anchor = Anchor.Centre;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
@ -31,7 +31,6 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
sampleMapping = new DrumSampleMapping(controlPoints);
|
sampleMapping = new DrumSampleMapping(controlPoints);
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
FillMode = FillMode.Fit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -40,6 +39,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
Child = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.InputDrum), _ => new Container
|
Child = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.InputDrum), _ => new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
FillMode = FillMode.Fit,
|
||||||
|
Scale = new Vector2(0.9f),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new TaikoHalfDrum(false)
|
new TaikoHalfDrum(false)
|
||||||
|
37
osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundLeft.cs
Normal file
37
osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundLeft.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// 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.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Taiko.UI
|
||||||
|
{
|
||||||
|
internal class PlayfieldBackgroundLeft : CompositeDrawable
|
||||||
|
{
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Colour = colours.Gray1,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Width = 10,
|
||||||
|
Colour = Framework.Graphics.Colour.ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.6f), Color4.Black.Opacity(0)),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundRight.cs
Normal file
61
osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundRight.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// 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.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Effects;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Taiko.UI
|
||||||
|
{
|
||||||
|
public class PlayfieldBackgroundRight : CompositeDrawable
|
||||||
|
{
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
Name = "Transparent playfield background";
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Masking = true;
|
||||||
|
BorderColour = colours.Gray1;
|
||||||
|
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Shadow,
|
||||||
|
Colour = Color4.Black.Opacity(0.2f),
|
||||||
|
Radius = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = colours.Gray0,
|
||||||
|
Alpha = 0.6f
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Name = "Border",
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
MaskingSmoothness = 0,
|
||||||
|
BorderThickness = 2,
|
||||||
|
AlwaysPresent = true,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,14 +13,14 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A component that is displayed at the hit position in the taiko playfield.
|
/// A component that is displayed at the hit position in the taiko playfield.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class HitTarget : Container
|
internal class TaikoHitTarget : Container
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Thickness of all drawn line pieces.
|
/// Thickness of all drawn line pieces.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const float border_thickness = 2.5f;
|
private const float border_thickness = 2.5f;
|
||||||
|
|
||||||
public HitTarget()
|
public TaikoHitTarget()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
@ -41,7 +41,6 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
FillMode = FillMode.Fit,
|
|
||||||
Scale = new Vector2(TaikoHitObject.DEFAULT_STRONG_SIZE),
|
Scale = new Vector2(TaikoHitObject.DEFAULT_STRONG_SIZE),
|
||||||
Masking = true,
|
Masking = true,
|
||||||
BorderColour = Color4.White,
|
BorderColour = Color4.White,
|
||||||
@ -63,7 +62,6 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
FillMode = FillMode.Fit,
|
|
||||||
Scale = new Vector2(TaikoHitObject.DEFAULT_SIZE),
|
Scale = new Vector2(TaikoHitObject.DEFAULT_SIZE),
|
||||||
Masking = true,
|
Masking = true,
|
||||||
BorderColour = Color4.White,
|
BorderColour = Color4.White,
|
@ -3,11 +3,8 @@
|
|||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
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.Shapes;
|
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
@ -20,108 +17,80 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables;
|
|||||||
using osu.Game.Rulesets.Taiko.Judgements;
|
using osu.Game.Rulesets.Taiko.Judgements;
|
||||||
using osu.Game.Rulesets.Taiko.Objects;
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.UI
|
namespace osu.Game.Rulesets.Taiko.UI
|
||||||
{
|
{
|
||||||
public class TaikoPlayfield : ScrollingPlayfield
|
public class TaikoPlayfield : ScrollingPlayfield
|
||||||
{
|
{
|
||||||
|
private readonly ControlPointInfo controlPoints;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default height of a <see cref="TaikoPlayfield"/> when inside a <see cref="DrawableTaikoRuleset"/>.
|
/// Default height of a <see cref="TaikoPlayfield"/> when inside a <see cref="DrawableTaikoRuleset"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const float DEFAULT_HEIGHT = 178;
|
public const float DEFAULT_HEIGHT = 178;
|
||||||
|
|
||||||
/// <summary>
|
private Container<HitExplosion> hitExplosionContainer;
|
||||||
/// The offset from <see cref="left_area_size"/> which the center of the hit target lies at.
|
private Container<KiaiHitExplosion> kiaiExplosionContainer;
|
||||||
/// </summary>
|
private JudgementContainer<DrawableTaikoJudgement> judgementContainer;
|
||||||
public const float HIT_TARGET_OFFSET = 100;
|
private ScrollingHitObjectContainer drumRollHitContainer;
|
||||||
|
internal Drawable HitTarget;
|
||||||
|
|
||||||
/// <summary>
|
private ProxyContainer topLevelHitContainer;
|
||||||
/// The size of the left area of the playfield. This area contains the input drum.
|
private ProxyContainer barlineContainer;
|
||||||
/// </summary>
|
private Container rightArea;
|
||||||
private const float left_area_size = 240;
|
private Container leftArea;
|
||||||
|
|
||||||
private readonly Container<HitExplosion> hitExplosionContainer;
|
private Container hitTargetOffsetContent;
|
||||||
private readonly Container<KiaiHitExplosion> kiaiExplosionContainer;
|
|
||||||
private readonly JudgementContainer<DrawableTaikoJudgement> judgementContainer;
|
|
||||||
private readonly ScrollingHitObjectContainer drumRollHitContainer;
|
|
||||||
internal readonly Drawable HitTarget;
|
|
||||||
|
|
||||||
private readonly ProxyContainer topLevelHitContainer;
|
|
||||||
private readonly ProxyContainer barlineContainer;
|
|
||||||
|
|
||||||
private readonly Container overlayBackgroundContainer;
|
|
||||||
private readonly Container backgroundContainer;
|
|
||||||
|
|
||||||
private readonly Box overlayBackground;
|
|
||||||
private readonly Box background;
|
|
||||||
|
|
||||||
public TaikoPlayfield(ControlPointInfo controlPoints)
|
public TaikoPlayfield(ControlPointInfo controlPoints)
|
||||||
{
|
{
|
||||||
InternalChildren = new[]
|
this.controlPoints = controlPoints;
|
||||||
{
|
|
||||||
backgroundContainer = new Container
|
|
||||||
{
|
|
||||||
Name = "Transparent playfield background",
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Masking = true,
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Shadow,
|
|
||||||
Colour = Color4.Black.Opacity(0.2f),
|
|
||||||
Radius = 5,
|
|
||||||
},
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
background = new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0.6f
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
new Container
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.PlayfieldBackgroundRight), _ => new PlayfieldBackgroundRight()),
|
||||||
|
rightArea = new Container
|
||||||
{
|
{
|
||||||
Name = "Right area",
|
Name = "Right area",
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Padding = new MarginPadding { Left = left_area_size },
|
RelativePositionAxes = Axes.Both,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
Name = "Masked elements before hit objects",
|
Name = "Masked elements before hit objects",
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Padding = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
FillMode = FillMode.Fit,
|
||||||
Masking = true,
|
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
hitExplosionContainer = new Container<HitExplosion>
|
hitExplosionContainer = new Container<HitExplosion>
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
FillMode = FillMode.Fit,
|
|
||||||
Blending = BlendingParameters.Additive,
|
Blending = BlendingParameters.Additive,
|
||||||
},
|
},
|
||||||
HitTarget = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.HitTarget), _ => new HitTarget())
|
HitTarget = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.HitTarget), _ => new TaikoHitTarget())
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
FillMode = FillMode.Fit
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
hitTargetOffsetContent = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
barlineContainer = new ProxyContainer
|
barlineContainer = new ProxyContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Padding = new MarginPadding { Left = HIT_TARGET_OFFSET }
|
|
||||||
},
|
},
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
Name = "Hit objects",
|
Name = "Hit objects",
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Padding = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
|
||||||
Masking = true,
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
HitObjectContainer,
|
HitObjectContainer,
|
||||||
@ -136,61 +105,32 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
Name = "Kiai hit explosions",
|
Name = "Kiai hit explosions",
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
FillMode = FillMode.Fit,
|
FillMode = FillMode.Fit,
|
||||||
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
|
||||||
Blending = BlendingParameters.Additive
|
Blending = BlendingParameters.Additive
|
||||||
},
|
},
|
||||||
judgementContainer = new JudgementContainer<DrawableTaikoJudgement>
|
judgementContainer = new JudgementContainer<DrawableTaikoJudgement>
|
||||||
{
|
{
|
||||||
Name = "Judgements",
|
Name = "Judgements",
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
|
||||||
Blending = BlendingParameters.Additive
|
Blending = BlendingParameters.Additive
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
overlayBackgroundContainer = new Container
|
}
|
||||||
|
},
|
||||||
|
leftArea = new Container
|
||||||
{
|
{
|
||||||
Name = "Left overlay",
|
Name = "Left overlay",
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Size = new Vector2(left_area_size, 1),
|
FillMode = FillMode.Fit,
|
||||||
|
BorderColour = colours.Gray0,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
overlayBackground = new Box
|
new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.PlayfieldBackgroundLeft), _ => new PlayfieldBackgroundLeft()),
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
},
|
|
||||||
new InputDrum(controlPoints)
|
new InputDrum(controlPoints)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreRight,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreRight,
|
Origin = Anchor.CentreLeft,
|
||||||
Scale = new Vector2(0.9f),
|
|
||||||
Margin = new MarginPadding { Right = 20 }
|
|
||||||
},
|
},
|
||||||
new Box
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Width = 10,
|
|
||||||
Colour = Framework.Graphics.Colour.ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.6f), Color4.Black.Opacity(0)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Container
|
|
||||||
{
|
|
||||||
Name = "Border",
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Masking = true,
|
|
||||||
MaskingSmoothness = 0,
|
|
||||||
BorderThickness = 2,
|
|
||||||
AlwaysPresent = true,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0,
|
|
||||||
AlwaysPresent = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
topLevelHitContainer = new ProxyContainer
|
topLevelHitContainer = new ProxyContainer
|
||||||
@ -202,14 +142,25 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
protected override void Update()
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
{
|
||||||
overlayBackgroundContainer.BorderColour = colours.Gray0;
|
base.Update();
|
||||||
overlayBackground.Colour = colours.Gray1;
|
|
||||||
|
|
||||||
backgroundContainer.BorderColour = colours.Gray1;
|
// Padding is required to be updated for elements which are based on "absolute" X sized elements.
|
||||||
background.Colour = colours.Gray0;
|
// This is basically allowing for correct alignment as relative pieces move around them.
|
||||||
|
rightArea.Padding = new MarginPadding { Left = leftArea.DrawWidth };
|
||||||
|
hitTargetOffsetContent.Padding = new MarginPadding { Left = HitTarget.DrawWidth / 2 };
|
||||||
|
|
||||||
|
// When rewinding, make sure to remove any auxilliary hit notes that were
|
||||||
|
// spawned and played during a drumroll.
|
||||||
|
if (Time.Elapsed < 0)
|
||||||
|
{
|
||||||
|
foreach (var o in drumRollHitContainer.Objects)
|
||||||
|
{
|
||||||
|
if (o.HitObject.StartTime >= Time.Current)
|
||||||
|
drumRollHitContainer.Remove(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Add(DrawableHitObject h)
|
public override void Add(DrawableHitObject h)
|
||||||
@ -286,22 +237,6 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
|
|
||||||
// When rewinding, make sure to remove any auxilliary hit notes that were
|
|
||||||
// spawned and played during a drumroll.
|
|
||||||
if (Time.Elapsed < 0)
|
|
||||||
{
|
|
||||||
foreach (var o in drumRollHitContainer.Objects)
|
|
||||||
{
|
|
||||||
if (o.HitObject.StartTime >= Time.Current)
|
|
||||||
drumRollHitContainer.Remove(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ProxyContainer : LifetimeManagementContainer
|
private class ProxyContainer : LifetimeManagementContainer
|
||||||
{
|
{
|
||||||
public new MarginPadding Padding
|
public new MarginPadding Padding
|
||||||
|
@ -5,7 +5,7 @@ using NUnit.Framework;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Editor
|
namespace osu.Game.Tests.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class EditorChangeHandlerTest
|
public class EditorChangeHandlerTest
|
@ -17,7 +17,7 @@ using osu.Game.Screens.Edit;
|
|||||||
using osuTK;
|
using osuTK;
|
||||||
using Decoder = osu.Game.Beatmaps.Formats.Decoder;
|
using Decoder = osu.Game.Beatmaps.Formats.Decoder;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Editor
|
namespace osu.Game.Tests.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class LegacyEditorBeatmapPatcherTest
|
public class LegacyEditorBeatmapPatcherTest
|
@ -14,7 +14,7 @@ using osu.Game.Rulesets.Osu.Edit;
|
|||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Editor
|
namespace osu.Game.Tests.Editing
|
||||||
{
|
{
|
||||||
[HeadlessTest]
|
[HeadlessTest]
|
||||||
public class TestSceneHitObjectComposerDistanceSnapping : EditorClockTestScene
|
public class TestSceneHitObjectComposerDistanceSnapping : EditorClockTestScene
|
30
osu.Game.Tests/Resources/sample-beatmap-catch.osu
Normal file
30
osu.Game.Tests/Resources/sample-beatmap-catch.osu
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[General]
|
||||||
|
SampleSet: Normal
|
||||||
|
StackLeniency: 0.7
|
||||||
|
Mode: 2
|
||||||
|
|
||||||
|
[Difficulty]
|
||||||
|
HPDrainRate:3
|
||||||
|
CircleSize:5
|
||||||
|
OverallDifficulty:8
|
||||||
|
ApproachRate:8
|
||||||
|
SliderMultiplier:3.59999990463257
|
||||||
|
SliderTickRate:2
|
||||||
|
|
||||||
|
[TimingPoints]
|
||||||
|
24,352.941176470588,4,1,1,100,1,0
|
||||||
|
6376,-50,4,1,1,100,0,0
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
32,183,24,5,0,0:0:0:0:
|
||||||
|
106,123,200,1,10,0:0:0:0:
|
||||||
|
199,108,376,1,2,0:0:0:0:
|
||||||
|
305,105,553,5,4,0:0:0:0:
|
||||||
|
386,112,729,1,14,0:0:0:0:
|
||||||
|
486,197,906,5,12,0:0:0:0:
|
||||||
|
14,199,1082,2,0,L|473:198,1,449.999988079071
|
||||||
|
14,199,1700,6,6,P|248:33|490:222,1,629.9999833107,0|8,0:0|0:0,0:0:0:0:
|
||||||
|
10,190,2494,2,8,B|252:29|254:335|468:167,1,449.999988079071,10|12,0:0|0:0,0:0:0:0:
|
||||||
|
256,192,3112,12,0,3906,0:0:0:0:
|
39
osu.Game.Tests/Resources/sample-beatmap-mania.osu
Normal file
39
osu.Game.Tests/Resources/sample-beatmap-mania.osu
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[General]
|
||||||
|
SampleSet: Normal
|
||||||
|
StackLeniency: 0.7
|
||||||
|
Mode: 3
|
||||||
|
|
||||||
|
[Difficulty]
|
||||||
|
HPDrainRate:3
|
||||||
|
CircleSize:5
|
||||||
|
OverallDifficulty:8
|
||||||
|
ApproachRate:8
|
||||||
|
SliderMultiplier:3.59999990463257
|
||||||
|
SliderTickRate:2
|
||||||
|
|
||||||
|
[TimingPoints]
|
||||||
|
24,352.941176470588,4,1,1,100,1,0
|
||||||
|
6376,-50,4,1,1,100,0,0
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
51,192,24,1,0,0:0:0:0:
|
||||||
|
153,192,200,1,0,0:0:0:0:
|
||||||
|
358,192,376,1,0,0:0:0:0:
|
||||||
|
460,192,553,1,0,0:0:0:0:
|
||||||
|
460,192,729,128,0,1435:0:0:0:0:
|
||||||
|
358,192,906,128,0,1612:0:0:0:0:
|
||||||
|
256,192,1082,128,0,1788:0:0:0:0:
|
||||||
|
153,192,1259,128,0,1965:0:0:0:0:
|
||||||
|
51,192,1435,128,0,2141:0:0:0:0:
|
||||||
|
51,192,2318,1,12,0:0:0:0:
|
||||||
|
153,192,2318,1,4,0:0:0:0:
|
||||||
|
256,192,2318,1,6,0:0:0:0:
|
||||||
|
358,192,2318,1,14,0:0:0:0:
|
||||||
|
460,192,2318,1,0,0:0:0:0:
|
||||||
|
51,192,2494,128,0,2582:0:0:0:0:
|
||||||
|
153,192,2494,128,14,2582:0:0:0:0:
|
||||||
|
256,192,2494,128,6,2582:0:0:0:0:
|
||||||
|
358,192,2494,128,4,2582:0:0:0:0:
|
||||||
|
460,192,2494,128,12,2582:0:0:0:0:
|
42
osu.Game.Tests/Resources/sample-beatmap-taiko.osu
Normal file
42
osu.Game.Tests/Resources/sample-beatmap-taiko.osu
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[General]
|
||||||
|
SampleSet: Normal
|
||||||
|
StackLeniency: 0.7
|
||||||
|
Mode: 1
|
||||||
|
|
||||||
|
[Difficulty]
|
||||||
|
HPDrainRate:3
|
||||||
|
CircleSize:5
|
||||||
|
OverallDifficulty:8
|
||||||
|
ApproachRate:8
|
||||||
|
SliderMultiplier:3.59999990463257
|
||||||
|
SliderTickRate:2
|
||||||
|
|
||||||
|
[TimingPoints]
|
||||||
|
24,352.941176470588,4,1,1,100,1,0
|
||||||
|
6376,-50,4,1,1,100,0,0
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
231,129,24,1,0,0:0:0:0:
|
||||||
|
231,129,200,1,0,0:0:0:0:
|
||||||
|
231,129,376,1,0,0:0:0:0:
|
||||||
|
231,129,553,1,0,0:0:0:0:
|
||||||
|
231,129,729,1,0,0:0:0:0:
|
||||||
|
373,132,906,1,4,0:0:0:0:
|
||||||
|
373,132,1082,1,4,0:0:0:0:
|
||||||
|
373,132,1259,1,4,0:0:0:0:
|
||||||
|
373,132,1435,1,4,0:0:0:0:
|
||||||
|
231,129,1788,1,8,0:0:0:0:
|
||||||
|
231,129,1964,1,8,0:0:0:0:
|
||||||
|
231,129,2140,1,8,0:0:0:0:
|
||||||
|
231,129,2317,1,8,0:0:0:0:
|
||||||
|
231,129,2493,1,8,0:0:0:0:
|
||||||
|
373,132,2670,1,12,0:0:0:0:
|
||||||
|
373,132,2846,1,12,0:0:0:0:
|
||||||
|
373,132,3023,1,12,0:0:0:0:
|
||||||
|
373,132,3199,1,12,0:0:0:0:
|
||||||
|
51,189,3553,2,0,L|150:188,1,89.9999976158143
|
||||||
|
52,191,3906,2,0,L|512:189,1,449.999988079071
|
||||||
|
26,196,4612,2,4,L|501:195,1,449.999988079071
|
||||||
|
17,242,5318,2,10,P|250:69|495:243,1,629.9999833107,0|8,0:0|0:0,0:0:0:0:
|
@ -14,7 +14,7 @@ using osu.Game.Screens.Edit.Compose.Components;
|
|||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
public class TestSceneBeatDivisorControl : OsuManualInputManagerTestScene
|
public class TestSceneBeatDivisorControl : OsuManualInputManagerTestScene
|
||||||
{
|
{
|
@ -9,7 +9,7 @@ using osu.Game.Rulesets.Osu.Beatmaps;
|
|||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Screens.Edit.Compose;
|
using osu.Game.Screens.Edit.Compose;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneComposeScreen : EditorClockTestScene
|
public class TestSceneComposeScreen : EditorClockTestScene
|
@ -13,7 +13,7 @@ using osu.Game.Screens.Edit.Compose.Components;
|
|||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
public class TestSceneDistanceSnapGrid : EditorClockTestScene
|
public class TestSceneDistanceSnapGrid : EditorClockTestScene
|
||||||
{
|
{
|
@ -4,33 +4,27 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Rulesets.Edit;
|
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
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.Compose.Components.Timeline;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
public class TestSceneEditorChangeStates : ScreenTestScene
|
public class TestSceneEditorChangeStates : EditorTestScene
|
||||||
{
|
{
|
||||||
|
public TestSceneEditorChangeStates()
|
||||||
|
: base(new OsuRuleset())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private EditorBeatmap editorBeatmap;
|
private EditorBeatmap editorBeatmap;
|
||||||
private TestEditor editor;
|
|
||||||
|
|
||||||
public override void SetUpSteps()
|
public override void SetUpSteps()
|
||||||
{
|
{
|
||||||
base.SetUpSteps();
|
base.SetUpSteps();
|
||||||
|
|
||||||
AddStep("load editor", () =>
|
AddStep("get beatmap", () => editorBeatmap = Editor.ChildrenOfType<EditorBeatmap>().Single());
|
||||||
{
|
|
||||||
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
|
||||||
LoadScreen(editor = new TestEditor());
|
|
||||||
});
|
|
||||||
|
|
||||||
AddUntilStep("wait for editor to load", () => editor.ChildrenOfType<HitObjectComposer>().FirstOrDefault()?.IsLoaded == true
|
|
||||||
&& editor.ChildrenOfType<TimelineArea>().FirstOrDefault()?.IsLoaded == true);
|
|
||||||
AddStep("get beatmap", () => editorBeatmap = editor.ChildrenOfType<EditorBeatmap>().Single());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -158,11 +152,13 @@ namespace osu.Game.Tests.Visual.Editor
|
|||||||
AddAssert("no hitobject added", () => addedObject == null);
|
AddAssert("no hitobject added", () => addedObject == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addUndoSteps() => AddStep("undo", () => editor.Undo());
|
private void addUndoSteps() => AddStep("undo", () => ((TestEditor)Editor).Undo());
|
||||||
|
|
||||||
private void addRedoSteps() => AddStep("redo", () => editor.Redo());
|
private void addRedoSteps() => AddStep("redo", () => ((TestEditor)Editor).Redo());
|
||||||
|
|
||||||
private class TestEditor : Screens.Edit.Editor
|
protected override Editor CreateEditor() => new TestEditor();
|
||||||
|
|
||||||
|
private class TestEditor : Editor
|
||||||
{
|
{
|
||||||
public new void Undo() => base.Undo();
|
public new void Undo() => base.Undo();
|
||||||
|
|
@ -7,7 +7,7 @@ using NUnit.Framework;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Screens.Edit.Components.RadioButtons;
|
using osu.Game.Screens.Edit.Components.RadioButtons;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneEditorComposeRadioButtons : OsuTestScene
|
public class TestSceneEditorComposeRadioButtons : OsuTestScene
|
@ -10,7 +10,7 @@ using osu.Framework.Graphics.UserInterface;
|
|||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Screens.Edit.Components.Menus;
|
using osu.Game.Screens.Edit.Components.Menus;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneEditorMenuBar : OsuTestScene
|
public class TestSceneEditorMenuBar : OsuTestScene
|
@ -13,7 +13,7 @@ using osu.Game.Rulesets.Osu.Objects;
|
|||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneEditorSeekSnapping : EditorClockTestScene
|
public class TestSceneEditorSeekSnapping : EditorClockTestScene
|
@ -10,7 +10,7 @@ using osu.Game.Rulesets.Osu;
|
|||||||
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneEditorSummaryTimeline : EditorClockTestScene
|
public class TestSceneEditorSummaryTimeline : EditorClockTestScene
|
@ -20,7 +20,7 @@ using osu.Game.Screens.Edit;
|
|||||||
using osu.Game.Screens.Edit.Compose.Components;
|
using osu.Game.Screens.Edit.Compose.Components;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneHitObjectComposer : EditorClockTestScene
|
public class TestSceneHitObjectComposer : EditorClockTestScene
|
@ -9,7 +9,7 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Screens.Edit.Components;
|
using osu.Game.Screens.Edit.Components;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestScenePlaybackControl : OsuTestScene
|
public class TestScenePlaybackControl : OsuTestScene
|
@ -7,7 +7,7 @@ using NUnit.Framework;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneTimelineBlueprintContainer : TimelineTestScene
|
public class TestSceneTimelineBlueprintContainer : TimelineTestScene
|
@ -8,7 +8,7 @@ using osu.Game.Screens.Edit.Compose.Components;
|
|||||||
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneTimelineTickDisplay : TimelineTestScene
|
public class TestSceneTimelineTickDisplay : TimelineTestScene
|
@ -9,7 +9,7 @@ using osu.Game.Rulesets.Osu.Beatmaps;
|
|||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Screens.Edit.Timing;
|
using osu.Game.Screens.Edit.Timing;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneTimingScreen : EditorClockTestScene
|
public class TestSceneTimingScreen : EditorClockTestScene
|
@ -14,7 +14,7 @@ using osu.Game.Graphics.Sprites;
|
|||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneWaveform : OsuTestScene
|
public class TestSceneWaveform : OsuTestScene
|
@ -15,7 +15,7 @@ using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
|||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
public class TestSceneZoomableScrollContainer : OsuManualInputManagerTestScene
|
public class TestSceneZoomableScrollContainer : OsuManualInputManagerTestScene
|
||||||
{
|
{
|
@ -18,7 +18,7 @@ using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
|||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editor
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
public abstract class TimelineTestScene : EditorClockTestScene
|
public abstract class TimelineTestScene : EditorClockTestScene
|
||||||
{
|
{
|
@ -13,6 +13,7 @@ using osu.Game.Beatmaps.Legacy;
|
|||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Legacy;
|
using osu.Game.Rulesets.Objects.Legacy;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps.Formats
|
namespace osu.Game.Beatmaps.Formats
|
||||||
{
|
{
|
||||||
@ -124,7 +125,12 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
writer.WriteLine(FormattableString.Invariant($"CircleSize: {beatmap.BeatmapInfo.BaseDifficulty.CircleSize}"));
|
writer.WriteLine(FormattableString.Invariant($"CircleSize: {beatmap.BeatmapInfo.BaseDifficulty.CircleSize}"));
|
||||||
writer.WriteLine(FormattableString.Invariant($"OverallDifficulty: {beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty}"));
|
writer.WriteLine(FormattableString.Invariant($"OverallDifficulty: {beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty}"));
|
||||||
writer.WriteLine(FormattableString.Invariant($"ApproachRate: {beatmap.BeatmapInfo.BaseDifficulty.ApproachRate}"));
|
writer.WriteLine(FormattableString.Invariant($"ApproachRate: {beatmap.BeatmapInfo.BaseDifficulty.ApproachRate}"));
|
||||||
writer.WriteLine(FormattableString.Invariant($"SliderMultiplier: {beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier}"));
|
|
||||||
|
// Taiko adjusts the slider multiplier (see: TaikoBeatmapConverter.LEGACY_VELOCITY_MULTIPLIER)
|
||||||
|
writer.WriteLine(beatmap.BeatmapInfo.RulesetID == 1
|
||||||
|
? FormattableString.Invariant($"SliderMultiplier: {beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / 1.4f}")
|
||||||
|
: FormattableString.Invariant($"SliderMultiplier: {beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier}"));
|
||||||
|
|
||||||
writer.WriteLine(FormattableString.Invariant($"SliderTickRate: {beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate}"));
|
writer.WriteLine(FormattableString.Invariant($"SliderTickRate: {beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,51 +203,63 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
|
|
||||||
writer.WriteLine("[HitObjects]");
|
writer.WriteLine("[HitObjects]");
|
||||||
|
|
||||||
// TODO: implement other legacy rulesets
|
foreach (var h in beatmap.HitObjects)
|
||||||
|
handleHitObject(writer, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleHitObject(TextWriter writer, HitObject hitObject)
|
||||||
|
{
|
||||||
|
Vector2 position = new Vector2(256, 192);
|
||||||
|
|
||||||
switch (beatmap.BeatmapInfo.RulesetID)
|
switch (beatmap.BeatmapInfo.RulesetID)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
foreach (var h in beatmap.HitObjects)
|
position = ((IHasPosition)hitObject).Position;
|
||||||
handleOsuHitObject(writer, h);
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
position.X = ((IHasXPosition)hitObject).X * 512;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
int totalColumns = (int)Math.Max(1, beatmap.BeatmapInfo.BaseDifficulty.CircleSize);
|
||||||
|
position.X = (int)Math.Ceiling(((IHasXPosition)hitObject).X * (512f / totalColumns));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void handleOsuHitObject(TextWriter writer, HitObject hitObject)
|
writer.Write(FormattableString.Invariant($"{position.X},"));
|
||||||
{
|
writer.Write(FormattableString.Invariant($"{position.Y},"));
|
||||||
var positionData = (IHasPosition)hitObject;
|
|
||||||
|
|
||||||
writer.Write(FormattableString.Invariant($"{positionData.X},"));
|
|
||||||
writer.Write(FormattableString.Invariant($"{positionData.Y},"));
|
|
||||||
writer.Write(FormattableString.Invariant($"{hitObject.StartTime},"));
|
writer.Write(FormattableString.Invariant($"{hitObject.StartTime},"));
|
||||||
writer.Write(FormattableString.Invariant($"{(int)getObjectType(hitObject)},"));
|
writer.Write(FormattableString.Invariant($"{(int)getObjectType(hitObject)},"));
|
||||||
|
writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(hitObject.Samples)},"));
|
||||||
writer.Write(hitObject is IHasCurve
|
|
||||||
? FormattableString.Invariant($"0,")
|
|
||||||
: FormattableString.Invariant($"{(int)toLegacyHitSoundType(hitObject.Samples)},"));
|
|
||||||
|
|
||||||
if (hitObject is IHasCurve curveData)
|
if (hitObject is IHasCurve curveData)
|
||||||
{
|
{
|
||||||
addCurveData(writer, curveData, positionData);
|
addCurveData(writer, curveData, position);
|
||||||
writer.Write(getSampleBank(hitObject.Samples, zeroBanks: true));
|
writer.Write(getSampleBank(hitObject.Samples, zeroBanks: true));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (hitObject is IHasEndTime endTimeData)
|
if (hitObject is IHasEndTime _)
|
||||||
writer.Write(FormattableString.Invariant($"{endTimeData.EndTime},"));
|
addEndTimeData(writer, hitObject);
|
||||||
|
|
||||||
writer.Write(getSampleBank(hitObject.Samples));
|
writer.Write(getSampleBank(hitObject.Samples));
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteLine();
|
writer.WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LegacyHitObjectType getObjectType(HitObject hitObject)
|
private LegacyHitObjectType getObjectType(HitObject hitObject)
|
||||||
{
|
{
|
||||||
var comboData = (IHasCombo)hitObject;
|
LegacyHitObjectType type = 0;
|
||||||
|
|
||||||
var type = (LegacyHitObjectType)(comboData.ComboOffset << 4);
|
if (hitObject is IHasCombo combo)
|
||||||
|
{
|
||||||
|
type = (LegacyHitObjectType)(combo.ComboOffset << 4);
|
||||||
|
|
||||||
if (comboData.NewCombo) type |= LegacyHitObjectType.NewCombo;
|
if (combo.NewCombo)
|
||||||
|
type |= LegacyHitObjectType.NewCombo;
|
||||||
|
}
|
||||||
|
|
||||||
switch (hitObject)
|
switch (hitObject)
|
||||||
{
|
{
|
||||||
@ -250,6 +268,9 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IHasEndTime _:
|
case IHasEndTime _:
|
||||||
|
if (beatmap.BeatmapInfo.RulesetID == 3)
|
||||||
|
type |= LegacyHitObjectType.Hold;
|
||||||
|
else
|
||||||
type |= LegacyHitObjectType.Spinner;
|
type |= LegacyHitObjectType.Spinner;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -261,7 +282,7 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCurveData(TextWriter writer, IHasCurve curveData, IHasPosition positionData)
|
private void addCurveData(TextWriter writer, IHasCurve curveData, Vector2 position)
|
||||||
{
|
{
|
||||||
PathType? lastType = null;
|
PathType? lastType = null;
|
||||||
|
|
||||||
@ -297,13 +318,13 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// New segment with the same type - duplicate the control point
|
// New segment with the same type - duplicate the control point
|
||||||
writer.Write(FormattableString.Invariant($"{positionData.X + point.Position.Value.X}:{positionData.Y + point.Position.Value.Y}|"));
|
writer.Write(FormattableString.Invariant($"{position.X + point.Position.Value.X}:{position.Y + point.Position.Value.Y}|"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
{
|
{
|
||||||
writer.Write(FormattableString.Invariant($"{positionData.X + point.Position.Value.X}:{positionData.Y + point.Position.Value.Y}"));
|
writer.Write(FormattableString.Invariant($"{position.X + point.Position.Value.X}:{position.Y + point.Position.Value.Y}"));
|
||||||
writer.Write(i != curveData.Path.ControlPoints.Count - 1 ? "|" : ",");
|
writer.Write(i != curveData.Path.ControlPoints.Count - 1 ? "|" : ",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,6 +345,20 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addEndTimeData(TextWriter writer, HitObject hitObject)
|
||||||
|
{
|
||||||
|
var endTimeData = (IHasEndTime)hitObject;
|
||||||
|
var type = getObjectType(hitObject);
|
||||||
|
|
||||||
|
char suffix = ',';
|
||||||
|
|
||||||
|
// Holds write the end time as if it's part of sample data.
|
||||||
|
if (type == LegacyHitObjectType.Hold)
|
||||||
|
suffix = ':';
|
||||||
|
|
||||||
|
writer.Write(FormattableString.Invariant($"{endTimeData.EndTime}{suffix}"));
|
||||||
|
}
|
||||||
|
|
||||||
private string getSampleBank(IList<HitSampleInfo> samples, bool banksOnly = false, bool zeroBanks = false)
|
private string getSampleBank(IList<HitSampleInfo> samples, bool banksOnly = false, bool zeroBanks = false)
|
||||||
{
|
{
|
||||||
LegacySampleBank normalBank = toLegacySampleBank(samples.SingleOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL)?.Bank);
|
LegacySampleBank normalBank = toLegacySampleBank(samples.SingleOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL)?.Bank);
|
||||||
|
@ -153,7 +153,7 @@ namespace osu.Game.Overlays.Comments
|
|||||||
request?.Cancel();
|
request?.Cancel();
|
||||||
loadCancellation?.Cancel();
|
loadCancellation?.Cancel();
|
||||||
request = new GetCommentsRequest(id.Value, type.Value, Sort.Value, currentPage++, 0);
|
request = new GetCommentsRequest(id.Value, type.Value, Sort.Value, currentPage++, 0);
|
||||||
request.Success += onSuccess;
|
request.Success += res => Schedule(() => onSuccess(res));
|
||||||
api.PerformAsync(request);
|
api.PerformAsync(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,15 @@ namespace osu.Game.Rulesets.UI
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void Clear(bool disposeChildren = true)
|
||||||
|
{
|
||||||
|
ClearInternal(disposeChildren);
|
||||||
|
|
||||||
|
foreach (var kvp in startTimeMap)
|
||||||
|
kvp.Value.bindable.UnbindAll();
|
||||||
|
startTimeMap.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
public int IndexOf(DrawableHitObject hitObject) => IndexOfInternal(hitObject);
|
public int IndexOf(DrawableHitObject hitObject) => IndexOfInternal(hitObject);
|
||||||
|
|
||||||
private void onStartTimeChanged(DrawableHitObject hitObject)
|
private void onStartTimeChanged(DrawableHitObject hitObject)
|
||||||
|
@ -58,6 +58,14 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Clear(bool disposeChildren = true)
|
||||||
|
{
|
||||||
|
base.Clear(disposeChildren);
|
||||||
|
|
||||||
|
initialStateCache.Invalidate();
|
||||||
|
hitObjectInitialStateCache.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
private float scrollLength;
|
private float scrollLength;
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
|
@ -60,9 +60,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
waveform.Waveform = b.NewValue.Waveform;
|
waveform.Waveform = b.NewValue.Waveform;
|
||||||
track = b.NewValue.Track;
|
track = b.NewValue.Track;
|
||||||
|
|
||||||
|
if (track.Length > 0)
|
||||||
|
{
|
||||||
MaxZoom = getZoomLevelForVisibleMilliseconds(500);
|
MaxZoom = getZoomLevelForVisibleMilliseconds(500);
|
||||||
MinZoom = getZoomLevelForVisibleMilliseconds(10000);
|
MinZoom = getZoomLevelForVisibleMilliseconds(10000);
|
||||||
Zoom = getZoomLevelForVisibleMilliseconds(2000);
|
Zoom = getZoomLevelForVisibleMilliseconds(2000);
|
||||||
|
}
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +138,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
|
|
||||||
private void scrollToTrackTime()
|
private void scrollToTrackTime()
|
||||||
{
|
{
|
||||||
if (!track.IsLoaded)
|
if (!track.IsLoaded || track.Length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ScrollTo((float)(adjustableClock.CurrentTime / track.Length) * Content.DrawWidth, false);
|
ScrollTo((float)(adjustableClock.CurrentTime / track.Length) * Content.DrawWidth, false);
|
||||||
|
@ -23,6 +23,7 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
HitObjects = baseBeatmap.HitObjects;
|
HitObjects = baseBeatmap.HitObjects;
|
||||||
|
|
||||||
BeatmapInfo.Ruleset = ruleset;
|
BeatmapInfo.Ruleset = ruleset;
|
||||||
|
BeatmapInfo.RulesetID = ruleset.ID ?? 0;
|
||||||
BeatmapInfo.BeatmapSet.Metadata = BeatmapInfo.Metadata;
|
BeatmapInfo.BeatmapSet.Metadata = BeatmapInfo.Metadata;
|
||||||
BeatmapInfo.BeatmapSet.Beatmaps = new List<BeatmapInfo> { BeatmapInfo };
|
BeatmapInfo.BeatmapSet.Beatmaps = new List<BeatmapInfo> { BeatmapInfo };
|
||||||
BeatmapInfo.BeatmapSet.OnlineInfo = new BeatmapSetOnlineInfo
|
BeatmapInfo.BeatmapSet.OnlineInfo = new BeatmapSetOnlineInfo
|
||||||
|
@ -3,9 +3,13 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
|
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
{
|
{
|
||||||
@ -13,6 +17,8 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(Editor), typeof(EditorScreen) };
|
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(Editor), typeof(EditorScreen) };
|
||||||
|
|
||||||
|
protected Editor Editor { get; private set; }
|
||||||
|
|
||||||
private readonly Ruleset ruleset;
|
private readonly Ruleset ruleset;
|
||||||
|
|
||||||
protected EditorTestScene(Ruleset ruleset)
|
protected EditorTestScene(Ruleset ruleset)
|
||||||
@ -30,7 +36,11 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
base.SetUpSteps();
|
base.SetUpSteps();
|
||||||
|
|
||||||
AddStep("Load editor", () => LoadScreen(new Editor()));
|
AddStep("load editor", () => LoadScreen(Editor = CreateEditor()));
|
||||||
|
AddUntilStep("wait for editor to load", () => Editor.ChildrenOfType<HitObjectComposer>().FirstOrDefault()?.IsLoaded == true
|
||||||
|
&& Editor.ChildrenOfType<TimelineArea>().FirstOrDefault()?.IsLoaded == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual Editor CreateEditor() => new Editor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,11 @@ namespace osu.Game.Tests.Visual
|
|||||||
set => scrollingInfo.TimeRange.Value = value;
|
set => scrollingInfo.TimeRange.Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ScrollingDirection Direction
|
||||||
|
{
|
||||||
|
set => scrollingInfo.Direction.Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
public IScrollingInfo ScrollingInfo => scrollingInfo;
|
public IScrollingInfo ScrollingInfo => scrollingInfo;
|
||||||
|
|
||||||
[Cached(Type = typeof(IScrollingInfo))]
|
[Cached(Type = typeof(IScrollingInfo))]
|
||||||
|
Loading…
Reference in New Issue
Block a user