diff --git a/.github/ISSUE_TEMPLATE/bug-issues.md b/.github/ISSUE_TEMPLATE/bug-issues.md
new file mode 100644
index 0000000000..8d85c92fec
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug-issues.md
@@ -0,0 +1,14 @@
+---
+name: Bug Report
+about: For issues regarding encountered game bugs
+---
+
+
+
+**Describe your problem:**
+
+**Screenshots or videos showing encountered issue:**
+
+**osu!lazer version:**
+
+**Logs:**
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/crash-issues.md b/.github/ISSUE_TEMPLATE/crash-issues.md
new file mode 100644
index 0000000000..849f042c1f
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/crash-issues.md
@@ -0,0 +1,16 @@
+---
+name: Crash Report
+about: For issues regarding game crashes or permanent freezes
+---
+
+
+
+**Describe your problem:**
+
+**Screenshots or videos showing encountered issue:**
+
+**osu!lazer version:**
+
+**Logs:**
+
+**Computer Specifications:**
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/feature-request-issues.md b/.github/ISSUE_TEMPLATE/feature-request-issues.md
new file mode 100644
index 0000000000..73c4f37a3e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature-request-issues.md
@@ -0,0 +1,10 @@
+---
+name: Feature Request
+about: Let us know what you would like to see in the game!
+---
+
+
+
+**Describe the feature:**
+
+**Proposal designs of the feature:**
diff --git a/.github/ISSUE_TEMPLATE/missing-for-live-issues.md b/.github/ISSUE_TEMPLATE/missing-for-live-issues.md
new file mode 100644
index 0000000000..ae3cf20a8c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/missing-for-live-issues.md
@@ -0,0 +1,10 @@
+---
+name: Missing for Live
+about: Let us know the features you need which are available in osu-stable but not lazer
+---
+
+
+
+**Describe the feature:**
+
+**Designs:**
diff --git a/.gitignore b/.gitignore
index 8f011deabe..f95a04e517 100644
--- a/.gitignore
+++ b/.gitignore
@@ -252,7 +252,11 @@ paket-files/
.fake/
# JetBrains Rider
-.idea/
+.idea/.idea.osu/.idea/*.xml
+.idea/.idea.osu/.idea/codeStyles/*.xml
+.idea/.idea.osu/.idea/dataSources/*.xml
+.idea/.idea.osu/.idea/dictionaries/*.xml
+.idea/.idea.osu/*.iml
*.sln.iml
# CodeRush
diff --git a/build.sh b/build.sh
old mode 100644
new mode 100755
diff --git a/osu-resources b/osu-resources
index c3848d8b1c..651e598b01 160000
--- a/osu-resources
+++ b/osu-resources
@@ -1 +1 @@
-Subproject commit c3848d8b1c84966abe851d915bcca878415614b4
+Subproject commit 651e598b016b43e31ab1c1b29d5b30c92361b8d9
diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs
index cac1356c81..bea64302c3 100644
--- a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs
+++ b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs
@@ -5,6 +5,7 @@ using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.UI;
+using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Screens.Play;
using osu.Game.Tests.Visual;
@@ -37,13 +38,11 @@ namespace osu.Game.Rulesets.Catch.Tests
beatmap.HitObjects.Add(new JuiceStream
{
X = 0.5f - width / 2,
- ControlPoints = new[]
+ Path = new SliderPath(PathType.Linear, new[]
{
Vector2.Zero,
new Vector2(width * CatchPlayfield.BASE_WIDTH, 0)
- },
- PathType = PathType.Linear,
- Distance = width * CatchPlayfield.BASE_WIDTH,
+ }),
StartTime = i * 2000,
NewCombo = i % 8 == 0
});
diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj
index 326791f506..b76f591239 100644
--- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj
+++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj
@@ -4,7 +4,7 @@
-
+
diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs
index a178748bd5..c3dc9499c2 100644
--- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs
+++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs
@@ -34,10 +34,8 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
{
StartTime = obj.StartTime,
Samples = obj.Samples,
- ControlPoints = curveData.ControlPoints,
- PathType = curveData.PathType,
- Distance = curveData.Distance,
- RepeatSamples = curveData.RepeatSamples,
+ Path = curveData.Path,
+ NodeSamples = curveData.NodeSamples,
RepeatCount = curveData.RepeatCount,
X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH,
NewCombo = comboData?.NewCombo ?? false,
diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
index da581d9619..d8bd3e0edc 100644
--- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
+++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
@@ -10,7 +10,6 @@ using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
-using OpenTK;
namespace osu.Game.Rulesets.Catch.Objects
{
@@ -138,27 +137,17 @@ namespace osu.Game.Rulesets.Catch.Objects
public double Duration => EndTime - StartTime;
- public double Distance
+ private SliderPath path;
+
+ public SliderPath Path
{
- get { return Path.Distance; }
- set { Path.Distance = value; }
+ get => path;
+ set => path = value;
}
- public SliderPath Path { get; } = new SliderPath();
+ public double Distance => Path.Distance;
- public Vector2[] ControlPoints
- {
- get { return Path.ControlPoints; }
- set { Path.ControlPoints = value; }
- }
-
- public List> RepeatSamples { get; set; } = new List>();
-
- public PathType PathType
- {
- get { return Path.PathType; }
- set { Path.PathType = value; }
- }
+ public List> NodeSamples { get; set; } = new List>();
public double? LegacyLastTickOffset { get; set; }
}
diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
index bf75ebbff8..98ad086c66 100644
--- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
+++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
@@ -4,7 +4,7 @@
-
+
diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs
index 5d8480d969..d86ebc9a09 100644
--- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs
+++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs
@@ -247,7 +247,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
double segmentTime = (curveData.EndTime - HitObject.StartTime) / curveData.SpanCount();
int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime);
- return curveData.RepeatSamples[index];
+ return curveData.NodeSamples[index];
}
}
}
diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs
index 37a8062d75..635004d2f6 100644
--- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs
+++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs
@@ -470,7 +470,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
double segmentTime = (EndTime - HitObject.StartTime) / spanCount;
int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime);
- return curveData.RepeatSamples[index];
+ return curveData.NodeSamples[index];
}
///
diff --git a/osu.Game.Rulesets.Mania/Edit/Masks/HoldNoteSelectionMask.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs
similarity index 84%
rename from osu.Game.Rulesets.Mania/Edit/Masks/HoldNoteSelectionMask.cs
rename to osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs
index a2c01d7a0e..3da2538497 100644
--- a/osu.Game.Rulesets.Mania/Edit/Masks/HoldNoteSelectionMask.cs
+++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs
@@ -5,7 +5,6 @@ using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Game.Graphics;
-using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
using osu.Game.Rulesets.Mania.UI;
@@ -13,9 +12,9 @@ using osu.Game.Rulesets.UI.Scrolling;
using OpenTK;
using OpenTK.Graphics;
-namespace osu.Game.Rulesets.Mania.Edit.Masks
+namespace osu.Game.Rulesets.Mania.Edit.Blueprints
{
- public class HoldNoteSelectionMask : SelectionMask
+ public class HoldNoteSelectionBlueprint : ManiaSelectionBlueprint
{
public new DrawableHoldNote HitObject => (DrawableHoldNote)base.HitObject;
@@ -23,13 +22,13 @@ namespace osu.Game.Rulesets.Mania.Edit.Masks
private readonly BodyPiece body;
- public HoldNoteSelectionMask(DrawableHoldNote hold)
+ public HoldNoteSelectionBlueprint(DrawableHoldNote hold)
: base(hold)
{
InternalChildren = new Drawable[]
{
- new HoldNoteNoteSelectionMask(hold.Head),
- new HoldNoteNoteSelectionMask(hold.Tail),
+ new HoldNoteNoteSelectionBlueprint(hold.Head),
+ new HoldNoteNoteSelectionBlueprint(hold.Tail),
body = new BodyPiece
{
AccentColour = Color4.Transparent
@@ -59,9 +58,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Masks
Y -= HitObject.Tail.DrawHeight;
}
- private class HoldNoteNoteSelectionMask : NoteSelectionMask
+ private class HoldNoteNoteSelectionBlueprint : NoteSelectionBlueprint
{
- public HoldNoteNoteSelectionMask(DrawableNote note)
+ public HoldNoteNoteSelectionBlueprint(DrawableNote note)
: base(note)
{
Select();
diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs
new file mode 100644
index 0000000000..474b8c662e
--- /dev/null
+++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs
@@ -0,0 +1,21 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using osu.Framework.Input.Events;
+using osu.Game.Rulesets.Edit;
+using osu.Game.Rulesets.Objects.Drawables;
+
+namespace osu.Game.Rulesets.Mania.Edit.Blueprints
+{
+ public class ManiaSelectionBlueprint : SelectionBlueprint
+ {
+ public ManiaSelectionBlueprint(DrawableHitObject hitObject)
+ : base(hitObject)
+ {
+ }
+
+ public override void AdjustPosition(DragEvent dragEvent)
+ {
+ }
+ }
+}
diff --git a/osu.Game.Rulesets.Mania/Edit/Masks/NoteSelectionMask.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs
similarity index 82%
rename from osu.Game.Rulesets.Mania/Edit/Masks/NoteSelectionMask.cs
rename to osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs
index 18f042a483..7c0337dc4e 100644
--- a/osu.Game.Rulesets.Mania/Edit/Masks/NoteSelectionMask.cs
+++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs
@@ -3,15 +3,14 @@
using osu.Framework.Allocation;
using osu.Game.Graphics;
-using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
-namespace osu.Game.Rulesets.Mania.Edit.Masks
+namespace osu.Game.Rulesets.Mania.Edit.Blueprints
{
- public class NoteSelectionMask : SelectionMask
+ public class NoteSelectionBlueprint : ManiaSelectionBlueprint
{
- public NoteSelectionMask(DrawableNote note)
+ public NoteSelectionBlueprint(DrawableNote note)
: base(note)
{
Scale = note.Scale;
diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs
index fcacde769b..06d67821a9 100644
--- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs
+++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs
@@ -11,7 +11,7 @@ using osu.Game.Rulesets.Objects.Drawables;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Game.Rulesets.Mania.Configuration;
-using osu.Game.Rulesets.Mania.Edit.Masks;
+using osu.Game.Rulesets.Mania.Edit.Blueprints;
using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.UI;
@@ -38,17 +38,17 @@ namespace osu.Game.Rulesets.Mania.Edit
protected override IReadOnlyList CompositionTools => Array.Empty();
- public override SelectionMask CreateMaskFor(DrawableHitObject hitObject)
+ public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject)
{
switch (hitObject)
{
case DrawableNote note:
- return new NoteSelectionMask(note);
+ return new NoteSelectionBlueprint(note);
case DrawableHoldNote holdNote:
- return new HoldNoteSelectionMask(holdNote);
+ return new HoldNoteSelectionBlueprint(holdNote);
}
- return base.CreateMaskFor(hitObject);
+ return base.CreateBlueprintFor(hitObject);
}
}
}
diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementMask.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementBlueprint.cs
similarity index 69%
rename from osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementMask.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementBlueprint.cs
index be0b94c4c8..313438a337 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementMask.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementBlueprint.cs
@@ -4,16 +4,16 @@
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
-using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests
{
- public class TestCaseHitCirclePlacementMask : HitObjectPlacementMaskTestCase
+ public class TestCaseHitCirclePlacementBlueprint : PlacementBlueprintTestCase
{
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHitCircle((HitCircle)hitObject);
- protected override PlacementMask CreateMask() => new HitCirclePlacementMask();
+ protected override PlacementBlueprint CreateBlueprint() => new HitCirclePlacementBlueprint();
}
}
diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionMask.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionBlueprint.cs
similarity index 71%
rename from osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionMask.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionBlueprint.cs
index e3d61623bf..9662e0018f 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionMask.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionBlueprint.cs
@@ -4,7 +4,7 @@
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit;
-using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Tests.Visual;
@@ -12,11 +12,11 @@ using OpenTK;
namespace osu.Game.Rulesets.Osu.Tests
{
- public class TestCaseHitCircleSelectionMask : HitObjectSelectionMaskTestCase
+ public class TestCaseHitCircleSelectionBlueprint : SelectionBlueprintTestCase
{
private readonly DrawableHitCircle drawableObject;
- public TestCaseHitCircleSelectionMask()
+ public TestCaseHitCircleSelectionBlueprint()
{
var hitCircle = new HitCircle { Position = new Vector2(256, 192) };
hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 });
@@ -24,6 +24,6 @@ namespace osu.Game.Rulesets.Osu.Tests
Add(drawableObject = new DrawableHitCircle(hitCircle));
}
- protected override SelectionMask CreateMask() => new HitCircleSelectionMask(drawableObject);
+ protected override SelectionBlueprint CreateBlueprint() => new HitCircleSelectionBlueprint(drawableObject);
}
}
diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs
index 4c0385deda..5b638782fb 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs
@@ -18,6 +18,7 @@ using System.Linq;
using NUnit.Framework;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Judgements;
+using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
@@ -108,15 +109,14 @@ namespace osu.Game.Rulesets.Osu.Tests
{
StartTime = Time.Current + 1000,
Position = new Vector2(239, 176),
- ControlPoints = new[]
+ Path = new SliderPath(PathType.PerfectCurve, new[]
{
Vector2.Zero,
new Vector2(154, 28),
new Vector2(52, -34)
- },
- Distance = 700,
+ }, 700),
RepeatCount = repeats,
- RepeatSamples = createEmptySamples(repeats),
+ NodeSamples = createEmptySamples(repeats),
StackHeight = 10
};
@@ -141,14 +141,13 @@ namespace osu.Game.Rulesets.Osu.Tests
{
StartTime = Time.Current + 1000,
Position = new Vector2(-(distance / 2), 0),
- ControlPoints = new[]
+ Path = new SliderPath(PathType.PerfectCurve, new[]
{
Vector2.Zero,
new Vector2(distance, 0),
- },
- Distance = distance,
+ }, distance),
RepeatCount = repeats,
- RepeatSamples = createEmptySamples(repeats),
+ NodeSamples = createEmptySamples(repeats),
StackHeight = stackHeight
};
@@ -161,15 +160,14 @@ namespace osu.Game.Rulesets.Osu.Tests
{
StartTime = Time.Current + 1000,
Position = new Vector2(-200, 0),
- ControlPoints = new[]
+ Path = new SliderPath(PathType.PerfectCurve, new[]
{
Vector2.Zero,
new Vector2(200, 200),
new Vector2(400, 0)
- },
- Distance = 600,
+ }, 600),
RepeatCount = repeats,
- RepeatSamples = createEmptySamples(repeats)
+ NodeSamples = createEmptySamples(repeats)
};
addSlider(slider, 2, 3);
@@ -181,10 +179,9 @@ namespace osu.Game.Rulesets.Osu.Tests
{
var slider = new Slider
{
- PathType = PathType.Linear,
StartTime = Time.Current + 1000,
Position = new Vector2(-200, 0),
- ControlPoints = new[]
+ Path = new SliderPath(PathType.Linear, new[]
{
Vector2.Zero,
new Vector2(150, 75),
@@ -192,10 +189,9 @@ namespace osu.Game.Rulesets.Osu.Tests
new Vector2(300, -200),
new Vector2(400, 0),
new Vector2(430, 0)
- },
- Distance = 793.4417,
+ }),
RepeatCount = repeats,
- RepeatSamples = createEmptySamples(repeats)
+ NodeSamples = createEmptySamples(repeats)
};
addSlider(slider, 2, 3);
@@ -207,20 +203,18 @@ namespace osu.Game.Rulesets.Osu.Tests
{
var slider = new Slider
{
- PathType = PathType.Bezier,
StartTime = Time.Current + 1000,
Position = new Vector2(-200, 0),
- ControlPoints = new[]
+ Path = new SliderPath(PathType.Bezier, new[]
{
Vector2.Zero,
new Vector2(150, 75),
new Vector2(200, 100),
new Vector2(300, -200),
new Vector2(430, 0)
- },
- Distance = 480,
+ }),
RepeatCount = repeats,
- RepeatSamples = createEmptySamples(repeats)
+ NodeSamples = createEmptySamples(repeats)
};
addSlider(slider, 2, 3);
@@ -232,10 +226,9 @@ namespace osu.Game.Rulesets.Osu.Tests
{
var slider = new Slider
{
- PathType = PathType.Linear,
StartTime = Time.Current + 1000,
Position = new Vector2(0, 0),
- ControlPoints = new[]
+ Path = new SliderPath(PathType.Linear, new[]
{
Vector2.Zero,
new Vector2(-200, 0),
@@ -243,10 +236,9 @@ namespace osu.Game.Rulesets.Osu.Tests
new Vector2(0, -200),
new Vector2(-200, -200),
new Vector2(0, -200)
- },
- Distance = 1000,
+ }),
RepeatCount = repeats,
- RepeatSamples = createEmptySamples(repeats)
+ NodeSamples = createEmptySamples(repeats)
};
addSlider(slider, 2, 3);
@@ -264,17 +256,15 @@ namespace osu.Game.Rulesets.Osu.Tests
{
StartTime = Time.Current + 1000,
Position = new Vector2(-100, 0),
- PathType = PathType.Catmull,
- ControlPoints = new[]
+ Path = new SliderPath(PathType.Catmull, new[]
{
Vector2.Zero,
new Vector2(50, -50),
new Vector2(150, 50),
new Vector2(200, 0)
- },
- Distance = 300,
+ }),
RepeatCount = repeats,
- RepeatSamples = repeatSamples
+ NodeSamples = repeatSamples
};
addSlider(slider, 3, 1);
diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementMask.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementBlueprint.cs
similarity index 70%
rename from osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementMask.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementBlueprint.cs
index 889ea0c311..1f693ad9f4 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementMask.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementBlueprint.cs
@@ -4,16 +4,16 @@
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
-using osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests
{
- public class TestCaseSliderPlacementMask : HitObjectPlacementMaskTestCase
+ public class TestCaseSliderPlacementBlueprint : PlacementBlueprintTestCase
{
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableSlider((Slider)hitObject);
- protected override PlacementMask CreateMask() => new SliderPlacementMask();
+ protected override PlacementBlueprint CreateBlueprint() => new SliderPlacementBlueprint();
}
}
diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionMask.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionBlueprint.cs
similarity index 68%
rename from osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionMask.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionBlueprint.cs
index 87e0e1a7ec..cacbcb2cd6 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionMask.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionBlueprint.cs
@@ -6,9 +6,10 @@ using System.Collections.Generic;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit;
+using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
-using osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks;
-using osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Tests.Visual;
@@ -16,12 +17,12 @@ using OpenTK;
namespace osu.Game.Rulesets.Osu.Tests
{
- public class TestCaseSliderSelectionMask : HitObjectSelectionMaskTestCase
+ public class TestCaseSliderSelectionBlueprint : SelectionBlueprintTestCase
{
public override IReadOnlyList RequiredTypes => new[]
{
- typeof(SliderSelectionMask),
- typeof(SliderCircleSelectionMask),
+ typeof(SliderSelectionBlueprint),
+ typeof(SliderCircleSelectionBlueprint),
typeof(SliderBodyPiece),
typeof(SliderCircle),
typeof(PathControlPointVisualiser),
@@ -30,19 +31,17 @@ namespace osu.Game.Rulesets.Osu.Tests
private readonly DrawableSlider drawableObject;
- public TestCaseSliderSelectionMask()
+ public TestCaseSliderSelectionBlueprint()
{
var slider = new Slider
{
Position = new Vector2(256, 192),
- ControlPoints = new[]
+ Path = new SliderPath(PathType.Bezier, new[]
{
Vector2.Zero,
new Vector2(150, 150),
new Vector2(300, 0)
- },
- PathType = PathType.Bezier,
- Distance = 350
+ })
};
slider.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 });
@@ -50,6 +49,6 @@ namespace osu.Game.Rulesets.Osu.Tests
Add(drawableObject = new DrawableSlider(slider));
}
- protected override SelectionMask CreateMask() => new SliderSelectionMask(drawableObject);
+ protected override SelectionBlueprint CreateBlueprint() => new SliderSelectionBlueprint(drawableObject);
}
}
diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementMask.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementBlueprint.cs
similarity index 70%
rename from osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementMask.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementBlueprint.cs
index c2c7942c57..9a90be2582 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementMask.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementBlueprint.cs
@@ -4,17 +4,17 @@
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
-using osu.Game.Rulesets.Osu.Edit.Masks.SpinnerMasks;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests
{
- public class TestCaseSpinnerPlacementMask : HitObjectPlacementMaskTestCase
+ public class TestCaseSpinnerPlacementBlueprint : PlacementBlueprintTestCase
{
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableSpinner((Spinner)hitObject);
- protected override PlacementMask CreateMask() => new SpinnerPlacementMask();
+ protected override PlacementBlueprint CreateBlueprint() => new SpinnerPlacementBlueprint();
}
}
diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionMask.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionBlueprint.cs
similarity index 74%
rename from osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionMask.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionBlueprint.cs
index b436ff0e9f..a0cfd4487e 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionMask.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionBlueprint.cs
@@ -8,8 +8,8 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit;
-using osu.Game.Rulesets.Osu.Edit.Masks.SpinnerMasks;
-using osu.Game.Rulesets.Osu.Edit.Masks.SpinnerMasks.Components;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Tests.Visual;
@@ -17,17 +17,17 @@ using OpenTK;
namespace osu.Game.Rulesets.Osu.Tests
{
- public class TestCaseSpinnerSelectionMask : HitObjectSelectionMaskTestCase
+ public class TestCaseSpinnerSelectionBlueprint : SelectionBlueprintTestCase
{
public override IReadOnlyList RequiredTypes => new[]
{
- typeof(SpinnerSelectionMask),
+ typeof(SpinnerSelectionBlueprint),
typeof(SpinnerPiece)
};
private readonly DrawableSpinner drawableSpinner;
- public TestCaseSpinnerSelectionMask()
+ public TestCaseSpinnerSelectionBlueprint()
{
var spinner = new Spinner
{
@@ -45,6 +45,6 @@ namespace osu.Game.Rulesets.Osu.Tests
});
}
- protected override SelectionMask CreateMask() => new SpinnerSelectionMask(drawableSpinner) { Size = new Vector2(0.5f) };
+ protected override SelectionBlueprint CreateBlueprint() => new SpinnerSelectionBlueprint(drawableSpinner) { Size = new Vector2(0.5f) };
}
}
diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj
index 23c6150b6a..6117812f45 100644
--- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj
+++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj
@@ -4,7 +4,7 @@
-
+
diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs
index 9f432fc31a..4fc4f3edc3 100644
--- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs
+++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs
@@ -35,10 +35,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
{
StartTime = original.StartTime,
Samples = original.Samples,
- ControlPoints = curveData.ControlPoints,
- PathType = curveData.PathType,
- Distance = curveData.Distance,
- RepeatSamples = curveData.RepeatSamples,
+ Path = curveData.Path,
+ NodeSamples = curveData.NodeSamples,
RepeatCount = curveData.RepeatCount,
Position = positionData?.Position ?? Vector2.Zero,
NewCombo = comboData?.NewCombo ?? false,
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/HitCircleMasks/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs
similarity index 94%
rename from osu.Game.Rulesets.Osu/Edit/Masks/HitCircleMasks/Components/HitCirclePiece.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs
index c11ae096a7..9c33435285 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/HitCircleMasks/Components/HitCirclePiece.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs
@@ -9,7 +9,7 @@ using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
using OpenTK;
-namespace osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks.Components
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components
{
public class HitCirclePiece : CompositeDrawable
{
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/HitCircleMasks/HitCirclePlacementMask.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs
similarity index 82%
rename from osu.Game.Rulesets.Osu/Edit/Masks/HitCircleMasks/HitCirclePlacementMask.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs
index 0d0acbed7d..eddd399a4a 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/HitCircleMasks/HitCirclePlacementMask.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs
@@ -3,16 +3,16 @@
using osu.Framework.Input.Events;
using osu.Game.Rulesets.Edit;
-using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks.Components;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
-namespace osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
{
- public class HitCirclePlacementMask : PlacementMask
+ public class HitCirclePlacementBlueprint : PlacementBlueprint
{
public new HitCircle HitObject => (HitCircle)base.HitObject;
- public HitCirclePlacementMask()
+ public HitCirclePlacementBlueprint()
: base(new HitCircle())
{
InternalChild = new HitCirclePiece(HitObject);
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/HitCircleMasks/HitCircleSelectionMask.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs
similarity index 58%
rename from osu.Game.Rulesets.Osu/Edit/Masks/HitCircleMasks/HitCircleSelectionMask.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs
index da46da92a5..a59dac1834 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/HitCircleMasks/HitCircleSelectionMask.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs
@@ -1,16 +1,15 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using osu.Game.Rulesets.Edit;
-using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks.Components;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
-namespace osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
{
- public class HitCircleSelectionMask : SelectionMask
+ public class HitCircleSelectionBlueprint : OsuSelectionBlueprint
{
- public HitCircleSelectionMask(DrawableHitCircle hitCircle)
+ public HitCircleSelectionBlueprint(DrawableHitCircle hitCircle)
: base(hitCircle)
{
InternalChild = new HitCirclePiece((HitCircle)hitCircle.HitObject);
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs
new file mode 100644
index 0000000000..8431d5d5d0
--- /dev/null
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs
@@ -0,0 +1,22 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using osu.Framework.Input.Events;
+using osu.Game.Rulesets.Edit;
+using osu.Game.Rulesets.Objects.Drawables;
+using osu.Game.Rulesets.Osu.Objects;
+
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints
+{
+ public class OsuSelectionBlueprint : SelectionBlueprint
+ {
+ protected OsuHitObject OsuObject => (OsuHitObject)HitObject.HitObject;
+
+ public OsuSelectionBlueprint(DrawableHitObject hitObject)
+ : base(hitObject)
+ {
+ }
+
+ public override void AdjustPosition(DragEvent dragEvent) => OsuObject.Position += dragEvent.Delta;
+ }
+}
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs
similarity index 82%
rename from osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/Components/PathControlPointPiece.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs
index 70156578b4..7100d9443e 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/Components/PathControlPointPiece.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@@ -9,10 +8,11 @@ using osu.Framework.Graphics.Lines;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
+using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects;
using OpenTK;
-namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{
public class PathControlPointPiece : CompositeDrawable
{
@@ -55,16 +55,16 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
{
base.Update();
- Position = slider.StackedPosition + slider.ControlPoints[index];
+ Position = slider.StackedPosition + slider.Path.ControlPoints[index];
marker.Colour = isSegmentSeparator ? colours.Red : colours.Yellow;
path.ClearVertices();
- if (index != slider.ControlPoints.Length - 1)
+ if (index != slider.Path.ControlPoints.Length - 1)
{
path.AddVertex(Vector2.Zero);
- path.AddVertex(slider.ControlPoints[index + 1] - slider.ControlPoints[index]);
+ path.AddVertex(slider.Path.ControlPoints[index + 1] - slider.Path.ControlPoints[index]);
}
path.OriginPosition = path.PositionInBoundingBox(Vector2.Zero);
@@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
protected override bool OnDrag(DragEvent e)
{
- var newControlPoints = slider.ControlPoints.ToArray();
+ var newControlPoints = slider.Path.ControlPoints.ToArray();
if (index == 0)
{
@@ -96,8 +96,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
if (isSegmentSeparatorWithPrevious)
newControlPoints[index - 1] = newControlPoints[index];
- slider.ControlPoints = newControlPoints;
- slider.Path.Calculate(true);
+ slider.Path = new SliderPath(slider.Path.Type, newControlPoints);
return true;
}
@@ -106,8 +105,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
private bool isSegmentSeparator => isSegmentSeparatorWithNext || isSegmentSeparatorWithPrevious;
- private bool isSegmentSeparatorWithNext => index < slider.ControlPoints.Length - 1 && slider.ControlPoints[index + 1] == slider.ControlPoints[index];
+ private bool isSegmentSeparatorWithNext => index < slider.Path.ControlPoints.Length - 1 && slider.Path.ControlPoints[index + 1] == slider.Path.ControlPoints[index];
- private bool isSegmentSeparatorWithPrevious => index > 0 && slider.ControlPoints[index - 1] == slider.ControlPoints[index];
+ private bool isSegmentSeparatorWithPrevious => index > 0 && slider.Path.ControlPoints[index - 1] == slider.Path.ControlPoints[index];
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs
similarity index 77%
rename from osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/Components/PathControlPointVisualiser.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs
index 1d25f8cd39..ab9d81574a 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/Components/PathControlPointVisualiser.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs
@@ -5,7 +5,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Osu.Objects;
-namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{
public class PathControlPointVisualiser : CompositeDrawable
{
@@ -19,15 +19,15 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
InternalChild = pieces = new Container { RelativeSizeAxes = Axes.Both };
- slider.ControlPointsChanged += _ => updatePathControlPoints();
+ slider.PathChanged += _ => updatePathControlPoints();
updatePathControlPoints();
}
private void updatePathControlPoints()
{
- while (slider.ControlPoints.Length > pieces.Count)
+ while (slider.Path.ControlPoints.Length > pieces.Count)
pieces.Add(new PathControlPointPiece(slider, pieces.Count));
- while (slider.ControlPoints.Length < pieces.Count)
+ while (slider.Path.ControlPoints.Length < pieces.Count)
pieces.Remove(pieces[pieces.Count - 1]);
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs
similarity index 93%
rename from osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/Components/SliderBodyPiece.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs
index 006c256d53..06bc265258 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/Components/SliderBodyPiece.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs
@@ -10,7 +10,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
using OpenTK;
using OpenTK.Graphics;
-namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{
public class SliderBodyPiece : CompositeDrawable
{
@@ -45,8 +45,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
{
base.Update();
- slider.Path.Calculate();
-
var vertices = new List();
slider.Path.GetPathToProgress(vertices, 0, 1);
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/Components/SliderCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs
similarity index 83%
rename from osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/Components/SliderCirclePiece.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs
index 7864429d93..1ee765f5e0 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/Components/SliderCirclePiece.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs
@@ -1,10 +1,10 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks.Components;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
-namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{
public class SliderCirclePiece : HitCirclePiece
{
@@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
this.slider = slider;
this.position = position;
- slider.ControlPointsChanged += _ => UpdatePosition();
+ slider.PathChanged += _ => UpdatePosition();
}
protected override void UpdatePosition()
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/SliderCircleSelectionMask.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs
similarity index 53%
rename from osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/SliderCircleSelectionMask.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs
index a1b3fd545c..4bac9d3556 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/SliderCircleSelectionMask.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs
@@ -1,18 +1,22 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using osu.Game.Rulesets.Edit;
-using osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components;
+using osu.Framework.Input.Events;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
-namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{
- public class SliderCircleSelectionMask : SelectionMask
+ public class SliderCircleSelectionBlueprint : OsuSelectionBlueprint
{
- public SliderCircleSelectionMask(DrawableOsuHitObject hitObject, Slider slider, SliderPosition position)
+ private readonly Slider slider;
+
+ public SliderCircleSelectionBlueprint(DrawableOsuHitObject hitObject, Slider slider, SliderPosition position)
: base(hitObject)
{
+ this.slider = slider;
+
InternalChild = new SliderCirclePiece(slider, position);
Select();
@@ -20,5 +24,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks
// Todo: This is temporary, since the slider circle masks don't do anything special yet. In the future they will handle input.
public override bool HandlePositionalInput => false;
+
+ public override void AdjustPosition(DragEvent dragEvent) => slider.Position += dragEvent.Delta;
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/SliderPlacementMask.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs
similarity index 67%
rename from osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/SliderPlacementMask.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs
index 12e768d58e..d59cd35f19 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/SliderPlacementMask.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs
@@ -1,24 +1,23 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Input.Events;
-using osu.Framework.MathUtils;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
+using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
-using osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
using OpenTK;
using OpenTK.Input;
-namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{
- public class SliderPlacementMask : PlacementMask
+ public class SliderPlacementBlueprint : PlacementBlueprint
{
public new Objects.Slider HitObject => (Objects.Slider)base.HitObject;
@@ -27,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks
private PlacementState state;
- public SliderPlacementMask()
+ public SliderPlacementBlueprint()
: base(new Objects.Slider())
{
RelativeSizeAxes = Axes.Both;
@@ -119,12 +118,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks
private void updateSlider()
{
- for (int i = 0; i < segments.Count; i++)
- segments[i].Calculate(i == segments.Count - 1 ? (Vector2?)cursor : null);
-
- HitObject.ControlPoints = segments.SelectMany(s => s.ControlPoints).Concat(cursor.Yield()).ToArray();
- HitObject.PathType = HitObject.ControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear;
- HitObject.Distance = segments.Sum(s => s.Distance);
+ var newControlPoints = segments.SelectMany(s => s.ControlPoints).Concat(cursor.Yield()).ToArray();
+ HitObject.Path = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints);
}
private void setState(PlacementState newState)
@@ -140,41 +135,12 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks
private class Segment
{
- public float Distance { get; private set; }
-
public readonly List ControlPoints = new List();
public Segment(Vector2 offset)
{
ControlPoints.Add(offset);
}
-
- public void Calculate(Vector2? cursor = null)
- {
- Span allControlPoints = stackalloc Vector2[ControlPoints.Count + (cursor.HasValue ? 1 : 0)];
-
- for (int i = 0; i < ControlPoints.Count; i++)
- allControlPoints[i] = ControlPoints[i];
- if (cursor.HasValue)
- allControlPoints[allControlPoints.Length - 1] = cursor.Value;
-
- List result;
-
- switch (allControlPoints.Length)
- {
- case 1:
- case 2:
- result = PathApproximator.ApproximateLinear(allControlPoints);
- break;
- default:
- result = PathApproximator.ApproximateBezier(allControlPoints);
- break;
- }
-
- Distance = 0;
- for (int i = 0; i < result.Count - 1; i++)
- Distance += Vector2.Distance(result[i], result[i + 1]);
- }
}
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/SliderPosition.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs
similarity index 80%
rename from osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/SliderPosition.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs
index 01c1871131..a117a7056e 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/SliderPosition.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs
@@ -1,7 +1,7 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{
public enum SliderPosition
{
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs
new file mode 100644
index 0000000000..4810d76bf8
--- /dev/null
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs
@@ -0,0 +1,32 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using osu.Framework.Graphics;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
+using osu.Game.Rulesets.Osu.Objects;
+using osu.Game.Rulesets.Osu.Objects.Drawables;
+using OpenTK;
+
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
+{
+ public class SliderSelectionBlueprint : OsuSelectionBlueprint
+ {
+ private readonly SliderCircleSelectionBlueprint headBlueprint;
+
+ public SliderSelectionBlueprint(DrawableSlider slider)
+ : base(slider)
+ {
+ var sliderObject = (Slider)slider.HitObject;
+
+ InternalChildren = new Drawable[]
+ {
+ new SliderBodyPiece(sliderObject),
+ headBlueprint = new SliderCircleSelectionBlueprint(slider.HeadCircle, sliderObject, SliderPosition.Start),
+ new SliderCircleSelectionBlueprint(slider.TailCircle, sliderObject, SliderPosition.End),
+ new PathControlPointVisualiser(sliderObject),
+ };
+ }
+
+ public override Vector2 SelectionPoint => headBlueprint.SelectionPoint;
+ }
+}
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/SpinnerMasks/Components/SpinnerPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs
similarity index 96%
rename from osu.Game.Rulesets.Osu/Edit/Masks/SpinnerMasks/Components/SpinnerPiece.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs
index 0d9609facf..bd63a3e607 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/SpinnerMasks/Components/SpinnerPiece.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs
@@ -10,7 +10,7 @@ using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
using OpenTK;
-namespace osu.Game.Rulesets.Osu.Edit.Masks.SpinnerMasks.Components
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components
{
public class SpinnerPiece : CompositeDrawable
{
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/SpinnerMasks/SpinnerPlacementMask.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs
similarity index 82%
rename from osu.Game.Rulesets.Osu/Edit/Masks/SpinnerMasks/SpinnerPlacementMask.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs
index cd5d6cff04..c97adde427 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/SpinnerMasks/SpinnerPlacementMask.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs
@@ -4,13 +4,13 @@
using osu.Framework.Graphics;
using osu.Framework.Input.Events;
using osu.Game.Rulesets.Edit;
-using osu.Game.Rulesets.Osu.Edit.Masks.SpinnerMasks.Components;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.UI;
-namespace osu.Game.Rulesets.Osu.Edit.Masks.SpinnerMasks
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners
{
- public class SpinnerPlacementMask : PlacementMask
+ public class SpinnerPlacementBlueprint : PlacementBlueprint
{
public new Spinner HitObject => (Spinner)base.HitObject;
@@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SpinnerMasks
private bool isPlacingEnd;
- public SpinnerPlacementMask()
+ public SpinnerPlacementBlueprint()
: base(new Spinner { Position = OsuPlayfield.BASE_SIZE / 2 })
{
InternalChild = piece = new SpinnerPiece(HitObject) { Alpha = 0.5f };
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/SpinnerMasks/SpinnerSelectionMask.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs
similarity index 56%
rename from osu.Game.Rulesets.Osu/Edit/Masks/SpinnerMasks/SpinnerSelectionMask.cs
rename to osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs
index 0e47bd2a8b..9e9cc87c5e 100644
--- a/osu.Game.Rulesets.Osu/Edit/Masks/SpinnerMasks/SpinnerSelectionMask.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs
@@ -1,24 +1,29 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using osu.Game.Rulesets.Edit;
-using osu.Game.Rulesets.Osu.Edit.Masks.SpinnerMasks.Components;
+using osu.Framework.Input.Events;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using OpenTK;
-namespace osu.Game.Rulesets.Osu.Edit.Masks.SpinnerMasks
+namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners
{
- public class SpinnerSelectionMask : SelectionMask
+ public class SpinnerSelectionBlueprint : OsuSelectionBlueprint
{
private readonly SpinnerPiece piece;
- public SpinnerSelectionMask(DrawableSpinner spinner)
+ public SpinnerSelectionBlueprint(DrawableSpinner spinner)
: base(spinner)
{
InternalChild = piece = new SpinnerPiece((Spinner)spinner.HitObject);
}
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => piece.ReceivePositionalInputAt(screenSpacePos);
+
+ public override void AdjustPosition(DragEvent dragEvent)
+ {
+ // Spinners don't support position adjustments
+ }
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs
index 767c7db5da..ddab70d53a 100644
--- a/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs
+++ b/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs
@@ -3,7 +3,7 @@
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools;
-using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Edit
@@ -15,6 +15,6 @@ namespace osu.Game.Rulesets.Osu.Edit
{
}
- public override PlacementMask CreatePlacementMask() => new HitCirclePlacementMask();
+ public override PlacementBlueprint CreatePlacementBlueprint() => new HitCirclePlacementBlueprint();
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/SliderSelectionMask.cs b/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/SliderSelectionMask.cs
deleted file mode 100644
index b79b0ba1fb..0000000000
--- a/osu.Game.Rulesets.Osu/Edit/Masks/SliderMasks/SliderSelectionMask.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2007-2018 ppy Pty Ltd .
-// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-
-using osu.Framework.Graphics;
-using osu.Game.Rulesets.Edit;
-using osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components;
-using osu.Game.Rulesets.Osu.Objects;
-using osu.Game.Rulesets.Osu.Objects.Drawables;
-using OpenTK;
-
-namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks
-{
- public class SliderSelectionMask : SelectionMask
- {
- private readonly SliderCircleSelectionMask headMask;
-
- public SliderSelectionMask(DrawableSlider slider)
- : base(slider)
- {
- var sliderObject = (Slider)slider.HitObject;
-
- InternalChildren = new Drawable[]
- {
- new SliderBodyPiece(sliderObject),
- headMask = new SliderCircleSelectionMask(slider.HeadCircle, sliderObject, SliderPosition.Start),
- new SliderCircleSelectionMask(slider.TailCircle, sliderObject, SliderPosition.End),
- new PathControlPointVisualiser(sliderObject),
- };
- }
-
- public override Vector2 SelectionPoint => headMask.SelectionPoint;
- }
-}
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
index 005ccec151..a706e1d4be 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs
@@ -8,9 +8,9 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Objects.Drawables;
-using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks;
-using osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks;
-using osu.Game.Rulesets.Osu.Edit.Masks.SpinnerMasks;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Osu.UI;
@@ -37,19 +37,19 @@ namespace osu.Game.Rulesets.Osu.Edit
protected override Container CreateLayerContainer() => new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both };
- public override SelectionMask CreateMaskFor(DrawableHitObject hitObject)
+ public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject)
{
switch (hitObject)
{
case DrawableHitCircle circle:
- return new HitCircleSelectionMask(circle);
+ return new HitCircleSelectionBlueprint(circle);
case DrawableSlider slider:
- return new SliderSelectionMask(slider);
+ return new SliderSelectionBlueprint(slider);
case DrawableSpinner spinner:
- return new SpinnerSelectionMask(spinner);
+ return new SpinnerSelectionBlueprint(spinner);
}
- return base.CreateMaskFor(hitObject);
+ return base.CreateBlueprintFor(hitObject);
}
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs
index fd0430ce4c..6d4f67c597 100644
--- a/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs
+++ b/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs
@@ -3,7 +3,7 @@
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools;
-using osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Edit
@@ -15,6 +15,6 @@ namespace osu.Game.Rulesets.Osu.Edit
{
}
- public override PlacementMask CreatePlacementMask() => new SliderPlacementMask();
+ public override PlacementBlueprint CreatePlacementBlueprint() => new SliderPlacementBlueprint();
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs
index a1419fe281..5c19a1bac0 100644
--- a/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs
+++ b/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs
@@ -3,7 +3,7 @@
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools;
-using osu.Game.Rulesets.Osu.Edit.Masks.SpinnerMasks;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners;
using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Edit
@@ -15,6 +15,6 @@ namespace osu.Game.Rulesets.Osu.Edit
{
}
- public override PlacementMask CreatePlacementMask() => new SpinnerPlacementMask();
+ public override PlacementBlueprint CreatePlacementBlueprint() => new SpinnerPlacementBlueprint();
}
}
diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs
index e01d71e1f8..223e4df844 100644
--- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs
+++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs
@@ -32,12 +32,11 @@ namespace osu.Game.Rulesets.Osu.Mods
slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y));
slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y));
- var newControlPoints = new Vector2[slider.ControlPoints.Length];
- for (int i = 0; i < slider.ControlPoints.Length; i++)
- newControlPoints[i] = new Vector2(slider.ControlPoints[i].X, -slider.ControlPoints[i].Y);
+ var newControlPoints = new Vector2[slider.Path.ControlPoints.Length];
+ for (int i = 0; i < slider.Path.ControlPoints.Length; i++)
+ newControlPoints[i] = new Vector2(slider.Path.ControlPoints[i].X, -slider.Path.ControlPoints[i].Y);
- slider.ControlPoints = newControlPoints;
- slider.Path?.Calculate(); // Recalculate the slider curve
+ slider.Path = new SliderPath(slider.Path.Type, newControlPoints, slider.Path.ExpectedDistance);
}
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
index 514ae09064..a90182cecb 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
@@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Ball.Scale = new Vector2(HitObject.Scale);
};
- slider.ControlPointsChanged += _ => Body.Refresh();
+ slider.PathChanged += _ => Body.Refresh();
}
public override Color4 AccentColour
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs
index 6a836679a2..b933364887 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs
@@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
this.slider = slider;
h.PositionChanged += _ => updatePosition();
- slider.ControlPointsChanged += _ => updatePosition();
+ slider.PathChanged += _ => updatePosition();
updatePosition();
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs
index cc88a6718b..6946a55d8e 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs
@@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
AlwaysPresent = true;
hitCircle.PositionChanged += _ => updatePosition();
- slider.ControlPointsChanged += _ => updatePosition();
+ slider.PathChanged += _ => updatePosition();
updatePosition();
}
diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
index 67396c7ae4..61d199a7dc 100644
--- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
@@ -7,11 +7,10 @@ using osu.Game.Rulesets.Objects;
using OpenTK;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Beatmaps.ControlPoints;
-using osu.Game.Rulesets.Edit.Types;
namespace osu.Game.Rulesets.Osu.Objects
{
- public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasEditablePosition
+ public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasPosition
{
public const double OBJECT_RADIUS = 64;
@@ -100,8 +99,6 @@ namespace osu.Game.Rulesets.Osu.Objects
Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
}
- public virtual void OffsetPosition(Vector2 offset) => Position += offset;
-
protected override HitWindows CreateHitWindows() => new OsuHitWindows();
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs
index b7240991d4..cf57f24b83 100644
--- a/osu.Game.Rulesets.Osu/Objects/Slider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs
@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Objects
///
private const float base_scoring_distance = 100;
- public event Action ControlPointsChanged;
+ public event Action PathChanged;
public double EndTime => StartTime + this.SpanCount() * Path.Distance / Velocity;
public double Duration => EndTime - StartTime;
@@ -52,35 +52,23 @@ namespace osu.Game.Rulesets.Osu.Objects
}
}
- public SliderPath Path { get; } = new SliderPath();
+ private SliderPath path;
- public Vector2[] ControlPoints
+ public SliderPath Path
{
- get => Path.ControlPoints;
+ get => path;
set
{
- if (Path.ControlPoints == value)
- return;
- Path.ControlPoints = value;
+ path = value;
- ControlPointsChanged?.Invoke(value);
+ PathChanged?.Invoke(value);
if (TailCircle != null)
TailCircle.Position = EndPosition;
}
}
- public PathType PathType
- {
- get { return Path.PathType; }
- set { Path.PathType = value; }
- }
-
- public double Distance
- {
- get { return Path.Distance; }
- set { Path.Distance = value; }
- }
+ public double Distance => Path.Distance;
public override Vector2 Position
{
@@ -111,7 +99,8 @@ namespace osu.Game.Rulesets.Osu.Objects
///
internal float LazyTravelDistance;
- public List> RepeatSamples { get; set; } = new List>();
+ public List> NodeSamples { get; set; } = new List>();
+
public int RepeatCount { get; set; }
///
@@ -165,17 +154,17 @@ namespace osu.Game.Rulesets.Osu.Objects
private void createSliderEnds()
{
- HeadCircle = new SliderCircle(this)
+ HeadCircle = new SliderCircle
{
StartTime = StartTime,
Position = Position,
- Samples = Samples,
+ Samples = getNodeSamples(0),
SampleControlPoint = SampleControlPoint,
IndexInCurrentCombo = IndexInCurrentCombo,
ComboIndex = ComboIndex,
};
- TailCircle = new SliderTailCircle(this)
+ TailCircle = new SliderTailCircle
{
StartTime = EndTime,
Position = EndPosition,
@@ -249,11 +238,18 @@ namespace osu.Game.Rulesets.Osu.Objects
Position = Position + Path.PositionAt(repeat % 2),
StackHeight = StackHeight,
Scale = Scale,
- Samples = new List(RepeatSamples[repeatIndex])
+ Samples = getNodeSamples(1 + repeatIndex)
});
}
}
+ private List getNodeSamples(int nodeIndex)
+ {
+ if (nodeIndex < NodeSamples.Count)
+ return NodeSamples[nodeIndex];
+ return Samples;
+ }
+
public override Judgement CreateJudgement() => new OsuJudgement();
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/SliderCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderCircle.cs
index 1bdd16c9df..deda951378 100644
--- a/osu.Game.Rulesets.Osu/Objects/SliderCircle.cs
+++ b/osu.Game.Rulesets.Osu/Objects/SliderCircle.cs
@@ -1,19 +1,9 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using OpenTK;
-
namespace osu.Game.Rulesets.Osu.Objects
{
public class SliderCircle : HitCircle
{
- private readonly Slider slider;
-
- public SliderCircle(Slider slider)
- {
- this.slider = slider;
- }
-
- public override void OffsetPosition(Vector2 offset) => slider.OffsetPosition(offset);
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs
index 23616ea005..b567bd8423 100644
--- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs
+++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs
@@ -8,11 +8,6 @@ namespace osu.Game.Rulesets.Osu.Objects
{
public class SliderTailCircle : SliderCircle
{
- public SliderTailCircle(Slider slider)
- : base(slider)
- {
- }
-
public override Judgement CreateJudgement() => new OsuSliderTailJudgement();
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs
index 1270685ab5..1c60fd4831 100644
--- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs
@@ -7,7 +7,6 @@ using osu.Game.Rulesets.Objects.Types;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Osu.Judgements;
-using OpenTK;
namespace osu.Game.Rulesets.Osu.Objects
{
@@ -32,10 +31,5 @@ namespace osu.Game.Rulesets.Osu.Objects
}
public override Judgement CreateJudgement() => new OsuJudgement();
-
- public override void OffsetPosition(Vector2 offset)
- {
- // for now we don't want to allow spinners to be moved around.
- }
}
}
diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj
index 6ae9a018c5..3ba64398f3 100644
--- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj
+++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj
@@ -4,7 +4,7 @@
-
+
diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs
index c2cde332e8..c4a84f416e 100644
--- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs
+++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs
@@ -117,7 +117,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength)
{
- List> allSamples = curveData != null ? curveData.RepeatSamples : new List>(new[] { samples });
+ List> allSamples = curveData != null ? curveData.NodeSamples : new List>(new[] { samples });
int i = 0;
for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing)
diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs
index f1ae366ee1..464cfbf5e9 100644
--- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs
+++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs
@@ -14,6 +14,7 @@ using osu.Game.Beatmaps.Formats;
using osu.Game.Beatmaps.Timing;
using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Objects;
+using osu.Game.Rulesets.Objects.Legacy;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Skinning;
@@ -333,5 +334,61 @@ namespace osu.Game.Tests.Beatmaps.Formats
SampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]);
}
+
+ [Test]
+ public void TestDecodeSliderSamples()
+ {
+ var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false };
+ using (var resStream = Resource.OpenResource("slider-samples.osu"))
+ using (var stream = new StreamReader(resStream))
+ {
+ var hitObjects = decoder.Decode(stream).HitObjects;
+
+ var slider1 = (ConvertSlider)hitObjects[0];
+
+ Assert.AreEqual(1, slider1.NodeSamples[0].Count);
+ Assert.AreEqual(SampleInfo.HIT_NORMAL, slider1.NodeSamples[0][0].Name);
+ Assert.AreEqual(1, slider1.NodeSamples[1].Count);
+ Assert.AreEqual(SampleInfo.HIT_NORMAL, slider1.NodeSamples[1][0].Name);
+ Assert.AreEqual(1, slider1.NodeSamples[2].Count);
+ Assert.AreEqual(SampleInfo.HIT_NORMAL, slider1.NodeSamples[2][0].Name);
+
+ var slider2 = (ConvertSlider)hitObjects[1];
+
+ Assert.AreEqual(2, slider2.NodeSamples[0].Count);
+ Assert.AreEqual(SampleInfo.HIT_NORMAL, slider2.NodeSamples[0][0].Name);
+ Assert.AreEqual(SampleInfo.HIT_CLAP, slider2.NodeSamples[0][1].Name);
+ Assert.AreEqual(2, slider2.NodeSamples[1].Count);
+ Assert.AreEqual(SampleInfo.HIT_NORMAL, slider2.NodeSamples[1][0].Name);
+ Assert.AreEqual(SampleInfo.HIT_CLAP, slider2.NodeSamples[1][1].Name);
+ Assert.AreEqual(2, slider2.NodeSamples[2].Count);
+ Assert.AreEqual(SampleInfo.HIT_NORMAL, slider2.NodeSamples[2][0].Name);
+ Assert.AreEqual(SampleInfo.HIT_CLAP, slider2.NodeSamples[2][1].Name);
+
+ var slider3 = (ConvertSlider)hitObjects[2];
+
+ Assert.AreEqual(2, slider3.NodeSamples[0].Count);
+ Assert.AreEqual(SampleInfo.HIT_NORMAL, slider3.NodeSamples[0][0].Name);
+ Assert.AreEqual(SampleInfo.HIT_WHISTLE, slider3.NodeSamples[0][1].Name);
+ Assert.AreEqual(1, slider3.NodeSamples[1].Count);
+ Assert.AreEqual(SampleInfo.HIT_NORMAL, slider3.NodeSamples[1][0].Name);
+ Assert.AreEqual(2, slider3.NodeSamples[2].Count);
+ Assert.AreEqual(SampleInfo.HIT_NORMAL, slider3.NodeSamples[2][0].Name);
+ Assert.AreEqual(SampleInfo.HIT_CLAP, slider3.NodeSamples[2][1].Name);
+ }
+ }
+
+ [Test]
+ public void TestDecodeHitObjectNullAdditionBank()
+ {
+ var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false };
+ using (var resStream = Resource.OpenResource("hitobject-no-addition-bank.osu"))
+ using (var stream = new StreamReader(resStream))
+ {
+ var hitObjects = decoder.Decode(stream).HitObjects;
+
+ Assert.AreEqual(hitObjects[0].Samples[0].Bank, hitObjects[0].Samples[1].Bank);
+ }
+ }
}
}
diff --git a/osu.Game.Tests/Resources/hitobject-no-addition-bank.osu b/osu.Game.Tests/Resources/hitobject-no-addition-bank.osu
new file mode 100644
index 0000000000..43d0b8cc16
--- /dev/null
+++ b/osu.Game.Tests/Resources/hitobject-no-addition-bank.osu
@@ -0,0 +1,4 @@
+osu file format v14
+
+[HitObjects]
+444,320,1000,5,2,3:0:1:0:
\ No newline at end of file
diff --git a/osu.Game.Tests/Resources/slider-samples.osu b/osu.Game.Tests/Resources/slider-samples.osu
new file mode 100644
index 0000000000..7759a2e35f
--- /dev/null
+++ b/osu.Game.Tests/Resources/slider-samples.osu
@@ -0,0 +1,23 @@
+osu file format v14
+
+[General]
+SampleSet: Normal
+
+[Difficulty]
+
+SliderMultiplier:1.6
+SliderTickRate:2
+
+[TimingPoints]
+24735,389.61038961039,4,1,1,25,1,0
+
+[HitObjects]
+// Unified: Normal, Normal, Normal
+168,256,30579,6,0,B|248:320|320:248,2,160
+
+// Unified: Normal+Clap, Normal+Clap, Normal+Clap
+168,256,32137,6,8,B|248:320|320:248,2,160
+
+// Nodal: Normal+Whistle, Normal, Normal+Clap
+// Nodal sounds should override the unified clap sound
+168,256,33696,6,8,B|248:320|320:248,2,160,2|0|8
\ No newline at end of file
diff --git a/osu.Game.Tests/Visual/TestCaseBeatDivisorControl.cs b/osu.Game.Tests/Visual/TestCaseBeatDivisorControl.cs
index 1effa14e76..6c607acd11 100644
--- a/osu.Game.Tests/Visual/TestCaseBeatDivisorControl.cs
+++ b/osu.Game.Tests/Visual/TestCaseBeatDivisorControl.cs
@@ -5,7 +5,8 @@ using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
-using osu.Game.Screens.Edit.Screens.Compose;
+using osu.Game.Screens.Edit;
+using osu.Game.Screens.Edit.Compose.Components;
using OpenTK;
namespace osu.Game.Tests.Visual
diff --git a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs
index e7bcfbf500..5c53fdfac4 100644
--- a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs
+++ b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs
@@ -6,7 +6,7 @@ using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Game.Rulesets.Osu;
-using osu.Game.Screens.Edit.Screens.Compose;
+using osu.Game.Screens.Edit.Compose;
using osu.Game.Tests.Beatmaps;
namespace osu.Game.Tests.Visual
@@ -14,13 +14,13 @@ namespace osu.Game.Tests.Visual
[TestFixture]
public class TestCaseEditorCompose : EditorClockTestCase
{
- public override IReadOnlyList RequiredTypes => new[] { typeof(Compose) };
+ public override IReadOnlyList RequiredTypes => new[] { typeof(ComposeScreen) };
[BackgroundDependencyLoader]
private void load()
{
Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo);
- Child = new Compose();
+ Child = new ComposeScreen();
}
}
}
diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs
index 09f390ab74..9df36b0bc1 100644
--- a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs
+++ b/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs
@@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Graphics;
-using osu.Game.Screens.Edit.Screens.Compose.RadioButtons;
+using osu.Game.Screens.Edit.Components.RadioButtons;
namespace osu.Game.Tests.Visual
{
diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs
index 9ad8bf7b92..d2c1127f4c 100644
--- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs
+++ b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs
@@ -13,7 +13,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
-using osu.Game.Screens.Edit.Screens.Compose.Timeline;
+using osu.Game.Screens.Edit.Compose.Components.Timeline;
using OpenTK.Graphics;
namespace osu.Game.Tests.Visual
diff --git a/osu.Game.Tests/Visual/TestCaseEditorMenuBar.cs b/osu.Game.Tests/Visual/TestCaseEditorMenuBar.cs
index cb4438b2ba..eab799011d 100644
--- a/osu.Game.Tests/Visual/TestCaseEditorMenuBar.cs
+++ b/osu.Game.Tests/Visual/TestCaseEditorMenuBar.cs
@@ -8,7 +8,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.UserInterface;
-using osu.Game.Screens.Edit.Menus;
+using osu.Game.Screens.Edit.Components.Menus;
namespace osu.Game.Tests.Visual
{
diff --git a/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs b/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs
index 61647ffdc5..d894d2738e 100644
--- a/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs
+++ b/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs
@@ -11,13 +11,14 @@ using OpenTK;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
+using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Edit;
-using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks;
-using osu.Game.Rulesets.Osu.Edit.Masks.HitCircleMasks.Components;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
+using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
-using osu.Game.Screens.Edit.Screens.Compose;
-using osu.Game.Screens.Edit.Screens.Compose.Layers;
+using osu.Game.Screens.Edit.Compose;
+using osu.Game.Screens.Edit.Compose.Components;
using osu.Game.Tests.Beatmaps;
namespace osu.Game.Tests.Visual
@@ -28,15 +29,15 @@ namespace osu.Game.Tests.Visual
{
public override IReadOnlyList RequiredTypes => new[]
{
- typeof(MaskSelection),
- typeof(DragLayer),
+ typeof(SelectionBox),
+ typeof(DragBox),
typeof(HitObjectComposer),
typeof(OsuHitObjectComposer),
- typeof(HitObjectMaskLayer),
+ typeof(BlueprintContainer),
typeof(NotNullAttribute),
typeof(HitCirclePiece),
- typeof(HitCircleSelectionMask),
- typeof(HitCirclePlacementMask),
+ typeof(HitCircleSelectionBlueprint),
+ typeof(HitCirclePlacementBlueprint),
};
private HitObjectComposer composer;
@@ -53,12 +54,11 @@ namespace osu.Game.Tests.Visual
new Slider
{
Position = new Vector2(128, 256),
- ControlPoints = new[]
+ Path = new SliderPath(PathType.Linear, new[]
{
Vector2.Zero,
new Vector2(216, 0),
- },
- Distance = 216,
+ }),
Scale = 0.5f,
}
},
diff --git a/osu.Game.Tests/Visual/TestCaseLabelledTextBox.cs b/osu.Game.Tests/Visual/TestCaseLabelledTextBox.cs
index d41739bfb5..e1470a860e 100644
--- a/osu.Game.Tests/Visual/TestCaseLabelledTextBox.cs
+++ b/osu.Game.Tests/Visual/TestCaseLabelledTextBox.cs
@@ -5,9 +5,9 @@ using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
-using osu.Game.Screens.Edit.Screens.Setup.Components.LabelledComponents;
using System;
using System.Collections.Generic;
+using osu.Game.Screens.Edit.Setup.Components.LabelledComponents;
namespace osu.Game.Tests.Visual
{
diff --git a/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs b/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs
index 8bd1b79a84..3bf809ebde 100644
--- a/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs
+++ b/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs
@@ -10,7 +10,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.MathUtils;
using osu.Game.Graphics;
using osu.Game.Graphics.Cursor;
-using osu.Game.Screens.Edit.Screens.Compose.Timeline;
+using osu.Game.Screens.Edit.Compose.Components.Timeline;
using OpenTK;
using OpenTK.Graphics;
diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj
index 520e0b8940..c0f0695ff8 100644
--- a/osu.Game.Tests/osu.Game.Tests.csproj
+++ b/osu.Game.Tests/osu.Game.Tests.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs
index 13571bda84..932cfe5789 100644
--- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs
+++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs
@@ -16,8 +16,8 @@ using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.UI;
-using osu.Game.Screens.Edit.Screens.Compose.Layers;
-using osu.Game.Screens.Edit.Screens.Compose.RadioButtons;
+using osu.Game.Screens.Edit.Components.RadioButtons;
+using osu.Game.Screens.Edit.Compose.Components;
namespace osu.Game.Rulesets.Edit
{
@@ -35,8 +35,7 @@ namespace osu.Game.Rulesets.Edit
private EditRulesetContainer rulesetContainer;
- private HitObjectMaskLayer maskLayer;
- private PlacementContainer placementContainer;
+ private BlueprintContainer blueprintContainer;
internal HitObjectComposer(Ruleset ruleset)
{
@@ -62,14 +61,10 @@ namespace osu.Game.Rulesets.Edit
}
var layerBelowRuleset = CreateLayerContainer();
- layerBelowRuleset.Child = new BorderLayer { RelativeSizeAxes = Axes.Both };
+ layerBelowRuleset.Child = new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both };
var layerAboveRuleset = CreateLayerContainer();
- layerAboveRuleset.Children = new Drawable[]
- {
- maskLayer = new HitObjectMaskLayer(),
- placementContainer = new PlacementContainer(),
- };
+ layerAboveRuleset.Child = blueprintContainer = new BlueprintContainer();
layerContainers.Add(layerBelowRuleset);
layerContainers.Add(layerAboveRuleset);
@@ -112,8 +107,8 @@ namespace osu.Game.Rulesets.Edit
};
toolboxCollection.Items =
- CompositionTools.Select(t => new RadioButton(t.Name, () => placementContainer.CurrentTool = t))
- .Prepend(new RadioButton("Select", () => placementContainer.CurrentTool = null))
+ CompositionTools.Select(t => new RadioButton(t.Name, () => blueprintContainer.CurrentTool = t))
+ .Prepend(new RadioButton("Select", () => blueprintContainer.CurrentTool = null))
.ToList();
toolboxCollection.Items[0].Select();
@@ -146,29 +141,25 @@ namespace osu.Game.Rulesets.Edit
/// Adds a to the and visualises it.
///
/// The to add.
- public void Add(HitObject hitObject)
- {
- maskLayer.AddMaskFor(rulesetContainer.Add(hitObject));
- placementContainer.Refresh();
- }
+ public void Add(HitObject hitObject) => blueprintContainer.AddBlueprintFor(rulesetContainer.Add(hitObject));
- public void Remove(HitObject hitObject) => maskLayer.RemoveMaskFor(rulesetContainer.Remove(hitObject));
+ public void Remove(HitObject hitObject) => blueprintContainer.RemoveBlueprintFor(rulesetContainer.Remove(hitObject));
internal abstract EditRulesetContainer CreateRulesetContainer();
protected abstract IReadOnlyList CompositionTools { get; }
///
- /// Creates a for a specific .
+ /// Creates a for a specific .
///
/// The to create the overlay for.
- public virtual SelectionMask CreateMaskFor(DrawableHitObject hitObject) => null;
+ public virtual SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) => null;
///
- /// Creates a which outlines s
+ /// Creates a which outlines s
/// and handles hitobject pattern adjustments.
///
- public virtual MaskSelection CreateMaskSelection() => new MaskSelection();
+ public virtual SelectionBox CreateSelectionBox() => new SelectionBox();
///
/// Creates a which provides a layer above or below the .
diff --git a/osu.Game/Rulesets/Edit/PlacementMask.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs
similarity index 86%
rename from osu.Game/Rulesets/Edit/PlacementMask.cs
rename to osu.Game/Rulesets/Edit/PlacementBlueprint.cs
index 97c6a74c92..b726b683ea 100644
--- a/osu.Game/Rulesets/Edit/PlacementMask.cs
+++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs
@@ -10,15 +10,15 @@ using osu.Framework.Input.Events;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects;
-using osu.Game.Screens.Edit.Screens.Compose;
+using osu.Game.Screens.Edit.Compose;
using OpenTK;
namespace osu.Game.Rulesets.Edit
{
///
- /// A mask which governs the creation of a new to actualisation.
+ /// A blueprint which governs the creation of a new to actualisation.
///
- public abstract class PlacementMask : CompositeDrawable, IRequireHighFrequencyMousePosition
+ public abstract class PlacementBlueprint : CompositeDrawable, IRequireHighFrequencyMousePosition
{
///
/// The that is being placed.
@@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Edit
[Resolved]
private IPlacementHandler placementHandler { get; set; }
- protected PlacementMask(HitObject hitObject)
+ protected PlacementBlueprint(HitObject hitObject)
{
HitObject = hitObject;
@@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Edit
///
/// Signals that the placement of has finished.
- /// This will destroy this , and add the to the .
+ /// This will destroy this , and add the to the .
///
protected void EndPlacement()
{
diff --git a/osu.Game/Rulesets/Edit/SelectionMask.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs
similarity index 75%
rename from osu.Game/Rulesets/Edit/SelectionMask.cs
rename to osu.Game/Rulesets/Edit/SelectionBlueprint.cs
index 3b78d5aaf6..db35d47b2b 100644
--- a/osu.Game/Rulesets/Edit/SelectionMask.cs
+++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs
@@ -15,33 +15,33 @@ using OpenTK;
namespace osu.Game.Rulesets.Edit
{
///
- /// A mask placed above a adding editing functionality.
+ /// A blueprint placed above a adding editing functionality.
///
- public class SelectionMask : CompositeDrawable, IStateful
+ public abstract class SelectionBlueprint : CompositeDrawable, IStateful
{
///
- /// Invoked when this has been selected.
+ /// Invoked when this has been selected.
///
- public event Action Selected;
+ public event Action Selected;
///
- /// Invoked when this has been deselected.
+ /// Invoked when this has been deselected.
///
- public event Action Deselected;
+ public event Action Deselected;
///
- /// Invoked when this has requested selection.
+ /// Invoked when this has requested selection.
/// Will fire even if already selected. Does not actually perform selection.
///
- public event Action SelectionRequested;
+ public event Action SelectionRequested;
///
- /// Invoked when this has requested drag.
+ /// Invoked when this has requested drag.
///
- public event Action DragRequested;
+ public event Action DragRequested;
///
- /// The which this applies to.
+ /// The which this applies to.
///
public readonly DrawableHitObject HitObject;
@@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Edit
public override bool HandlePositionalInput => ShouldBeAlive;
public override bool RemoveWhenNotAlive => false;
- public SelectionMask(DrawableHitObject hitObject)
+ protected SelectionBlueprint(DrawableHitObject hitObject)
{
HitObject = hitObject;
@@ -86,12 +86,12 @@ namespace osu.Game.Rulesets.Edit
}
///
- /// Selects this , causing it to become visible.
+ /// Selects this , causing it to become visible.
///
public void Select() => State = SelectionState.Selected;
///
- /// Deselects this , causing it to become invisible.
+ /// Deselects this , causing it to become invisible.
///
public void Deselect() => State = SelectionState.NotSelected;
@@ -130,17 +130,19 @@ namespace osu.Game.Rulesets.Edit
protected override bool OnDrag(DragEvent e)
{
- DragRequested?.Invoke(this, e.Delta, e.CurrentState);
+ DragRequested?.Invoke(e);
return true;
}
+ public abstract void AdjustPosition(DragEvent dragEvent);
+
///
- /// The screen-space point that causes this to be selected.
+ /// The screen-space point that causes this to be selected.
///
public virtual Vector2 SelectionPoint => HitObject.ScreenSpaceDrawQuad.Centre;
///
- /// The screen-space quad that outlines this for selections.
+ /// The screen-space quad that outlines this for selections.
///
public virtual Quad SelectionQuad => HitObject.ScreenSpaceDrawQuad;
}
diff --git a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs
index c5d64e3d4d..1cb3c4c451 100644
--- a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs
+++ b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs
@@ -12,6 +12,6 @@ namespace osu.Game.Rulesets.Edit.Tools
Name = name;
}
- public abstract PlacementMask CreatePlacementMask();
+ public abstract PlacementBlueprint CreatePlacementBlueprint();
}
}
diff --git a/osu.Game/Rulesets/Edit/Types/IHasEditablePosition.cs b/osu.Game/Rulesets/Edit/Types/IHasEditablePosition.cs
deleted file mode 100644
index 7107b6c763..0000000000
--- a/osu.Game/Rulesets/Edit/Types/IHasEditablePosition.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2007-2018 ppy Pty Ltd .
-// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-
-using osu.Game.Rulesets.Objects.Types;
-using OpenTK;
-
-namespace osu.Game.Rulesets.Edit.Types
-{
- public interface IHasEditablePosition : IHasPosition
- {
- void OffsetPosition(Vector2 offset);
- }
-}
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index bcf84b375f..e9e9d93ed5 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -7,7 +7,6 @@ using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Extensions.TypeExtensions;
-using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Game.Audio;
using osu.Game.Graphics;
@@ -167,13 +166,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
}
}
- public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds)
- {
- if (!AllJudged)
- return false;
-
- return base.UpdateSubTreeMasking(source, maskingBounds);
- }
+ protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => AllJudged && base.ComputeIsMaskedAway(maskingBounds);
protected override void UpdateAfterChildren()
{
diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs
index f5613e927f..67a3db7a00 100644
--- a/osu.Game/Rulesets/Objects/HitObject.cs
+++ b/osu.Game/Rulesets/Objects/HitObject.cs
@@ -3,7 +3,6 @@
using System.Collections.Generic;
using Newtonsoft.Json;
-using osu.Framework.Lists;
using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
@@ -56,7 +55,7 @@ namespace osu.Game.Rulesets.Objects
///
public HitWindows HitWindows { get; set; }
- private readonly SortedList nestedHitObjects = new SortedList(compareObjects);
+ private readonly List nestedHitObjects = new List();
[JsonIgnore]
public IReadOnlyList NestedHitObjects => nestedHitObjects;
@@ -74,6 +73,8 @@ namespace osu.Game.Rulesets.Objects
CreateNestedHitObjects();
+ nestedHitObjects.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime));
+
foreach (var h in nestedHitObjects)
{
h.HitWindows = HitWindows;
@@ -114,7 +115,5 @@ namespace osu.Game.Rulesets.Objects
///
///
protected virtual HitWindows CreateHitWindows() => new HitWindows();
-
- private static int compareObjects(HitObject first, HitObject second) => first.StartTime.CompareTo(second.StartTime);
}
}
diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs
index 85efdca07b..b167812c1d 100644
--- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs
@@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
};
}
- protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> repeatSamples)
+ protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples)
{
newCombo |= forceNewCombo;
comboOffset += extraComboOffset;
@@ -50,10 +50,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
X = position.X,
NewCombo = FirstObject || newCombo,
ComboOffset = comboOffset,
- ControlPoints = controlPoints,
- Distance = length,
- PathType = pathType,
- RepeatSamples = repeatSamples,
+ Path = new SliderPath(pathType, controlPoints, length),
+ NodeSamples = nodeSamples,
RepeatCount = repeatCount
};
}
diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs
index 73f70d414f..3cc695447e 100644
--- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs
@@ -179,6 +179,9 @@ namespace osu.Game.Rulesets.Objects.Legacy
nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i]));
result = CreateSlider(pos, combo, comboOffset, points, length, pathType, repeatCount, nodeSamples);
+
+ // The samples are played when the slider ends, which is the last node
+ result.Samples = nodeSamples[nodeSamples.Count - 1];
}
else if (type.HasFlag(ConvertHitObjectType.Spinner))
{
@@ -210,7 +213,9 @@ namespace osu.Game.Rulesets.Objects.Legacy
}
result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture) + Offset;
- result.Samples = convertSoundType(soundType, bankInfo);
+
+ if (result.Samples.Count == 0)
+ result.Samples = convertSoundType(soundType, bankInfo);
FirstObject = false;
@@ -240,7 +245,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
stringAddBank = null;
bankInfo.Normal = stringBank;
- bankInfo.Add = stringAddBank;
+ bankInfo.Add = string.IsNullOrEmpty(stringAddBank) ? stringBank : stringAddBank;
if (split.Length > 2)
bankInfo.CustomSampleBank = int.Parse(split[2]);
@@ -270,9 +275,9 @@ namespace osu.Game.Rulesets.Objects.Legacy
/// The slider length.
/// The slider curve type.
/// The slider repeat count.
- /// The samples to be played when the repeat nodes are hit. This includes the head and tail of the slider.
+ /// The samples to be played when the slider nodes are hit. This includes the head and tail of the slider.
/// The hit object.
- protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> repeatSamples);
+ protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples);
///
/// Creates a legacy Spinner-type hit object.
diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs
index 6030bff427..0512a97354 100644
--- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs
@@ -3,7 +3,6 @@
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
-using OpenTK;
using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
@@ -20,13 +19,11 @@ namespace osu.Game.Rulesets.Objects.Legacy
///
/// s don't need a curve since they're converted to ruleset-specific hitobjects.
///
- public SliderPath Path { get; } = null;
- public Vector2[] ControlPoints { get; set; }
- public PathType PathType { get; set; }
+ public SliderPath Path { get; set; }
- public double Distance { get; set; }
+ public double Distance => Path.Distance;
- public List> RepeatSamples { get; set; }
+ public List> NodeSamples { get; set; }
public int RepeatCount { get; set; }
public double EndTime => StartTime + this.SpanCount() * Distance / Velocity;
diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs
index 6f10880aa2..fa5e769d3c 100644
--- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs
@@ -26,15 +26,13 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
};
}
- protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> repeatSamples)
+ protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples)
{
return new ConvertSlider
{
X = position.X,
- ControlPoints = controlPoints,
- Distance = length,
- PathType = pathType,
- RepeatSamples = repeatSamples,
+ Path = new SliderPath(pathType, controlPoints, length),
+ NodeSamples = nodeSamples,
RepeatCount = repeatCount
};
}
diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs
index 31c200eddc..e21903dc6d 100644
--- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs
@@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
};
}
- protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> repeatSamples)
+ protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples)
{
newCombo |= forceNewCombo;
comboOffset += extraComboOffset;
@@ -51,10 +51,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
Position = position,
NewCombo = FirstObject || newCombo,
ComboOffset = comboOffset,
- ControlPoints = controlPoints,
- Distance = Math.Max(0, length),
- PathType = pathType,
- RepeatSamples = repeatSamples,
+ Path = new SliderPath(pathType, controlPoints, Math.Max(0, length)),
+ NodeSamples = nodeSamples,
RepeatCount = repeatCount
};
}
diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs
index 0a244bb6c6..8e1e01a9fd 100644
--- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs
@@ -23,14 +23,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
return new ConvertHit();
}
- protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> repeatSamples)
+ protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples)
{
return new ConvertSlider
{
- ControlPoints = controlPoints,
- Distance = length,
- PathType = pathType,
- RepeatSamples = repeatSamples,
+ Path = new SliderPath(pathType, controlPoints, length),
+ NodeSamples = nodeSamples,
RepeatCount = repeatCount
};
}
diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs
index 423cd3b069..74a312698c 100644
--- a/osu.Game/Rulesets/Objects/SliderPath.cs
+++ b/osu.Game/Rulesets/Objects/SliderPath.cs
@@ -4,28 +4,140 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Newtonsoft.Json;
using osu.Framework.MathUtils;
using osu.Game.Rulesets.Objects.Types;
using OpenTK;
namespace osu.Game.Rulesets.Objects
{
- public class SliderPath
+ public struct SliderPath : IEquatable
{
- public double Distance;
+ ///
+ /// The user-set distance of the path. If non-null, will match this value,
+ /// and the path will be shortened/lengthened to match this length.
+ ///
+ public readonly double? ExpectedDistance;
- public Vector2[] ControlPoints = Array.Empty();
+ ///
+ /// The type of path.
+ ///
+ public readonly PathType Type;
- public PathType PathType = PathType.PerfectCurve;
+ [JsonProperty]
+ private Vector2[] controlPoints;
- public Vector2 Offset;
+ private List calculatedPath;
+ private List cumulativeLength;
- private readonly List calculatedPath = new List();
- private readonly List cumulativeLength = new List();
+ private bool isInitialised;
+
+ ///
+ /// Creates a new .
+ ///
+ /// The type of path.
+ /// The control points of the path.
+ /// A user-set distance of the path that may be shorter or longer than the true distance between all
+ /// . The path will be shortened/lengthened to match this length.
+ /// If null, the path will use the true distance between all .
+ [JsonConstructor]
+ public SliderPath(PathType type, Vector2[] controlPoints, double? expectedDistance = null)
+ {
+ this = default;
+ this.controlPoints = controlPoints;
+
+ Type = type;
+ ExpectedDistance = expectedDistance;
+
+ ensureInitialised();
+ }
+
+ ///
+ /// The control points of the path.
+ ///
+ [JsonIgnore]
+ public ReadOnlySpan ControlPoints
+ {
+ get
+ {
+ ensureInitialised();
+ return controlPoints.AsSpan();
+ }
+ }
+
+ ///
+ /// The distance of the path after lengthening/shortening to account for .
+ ///
+ [JsonIgnore]
+ public double Distance
+ {
+ get
+ {
+ ensureInitialised();
+ return cumulativeLength.Count == 0 ? 0 : cumulativeLength[cumulativeLength.Count - 1];
+ }
+ }
+
+ ///
+ /// Computes the slider path until a given progress that ranges from 0 (beginning of the slider)
+ /// to 1 (end of the slider) and stores the generated path in the given list.
+ ///
+ /// The list to be filled with the computed path.
+ /// Start progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider).
+ /// End progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider).
+ public void GetPathToProgress(List path, double p0, double p1)
+ {
+ ensureInitialised();
+
+ double d0 = progressToDistance(p0);
+ double d1 = progressToDistance(p1);
+
+ path.Clear();
+
+ int i = 0;
+ for (; i < calculatedPath.Count && cumulativeLength[i] < d0; ++i)
+ {
+ }
+
+ path.Add(interpolateVertices(i, d0));
+
+ for (; i < calculatedPath.Count && cumulativeLength[i] <= d1; ++i)
+ path.Add(calculatedPath[i]);
+
+ path.Add(interpolateVertices(i, d1));
+ }
+
+ ///
+ /// Computes the position on the slider at a given progress that ranges from 0 (beginning of the path)
+ /// to 1 (end of the path).
+ ///
+ /// Ranges from 0 (beginning of the path) to 1 (end of the path).
+ ///
+ public Vector2 PositionAt(double progress)
+ {
+ ensureInitialised();
+
+ double d = progressToDistance(progress);
+ return interpolateVertices(indexOfDistance(d), d);
+ }
+
+ private void ensureInitialised()
+ {
+ if (isInitialised)
+ return;
+ isInitialised = true;
+
+ controlPoints = controlPoints ?? Array.Empty();
+ calculatedPath = new List();
+ cumulativeLength = new List();
+
+ calculatePath();
+ calculateCumulativeLength();
+ }
private List calculateSubpath(ReadOnlySpan subControlPoints)
{
- switch (PathType)
+ switch (Type)
{
case PathType.Linear:
return PathApproximator.ApproximateLinear(subControlPoints);
@@ -66,7 +178,7 @@ namespace osu.Game.Rulesets.Objects
if (i == ControlPoints.Length - 1 || ControlPoints[i] == ControlPoints[i + 1])
{
- ReadOnlySpan cpSpan = ControlPoints.AsSpan().Slice(start, end - start);
+ ReadOnlySpan cpSpan = ControlPoints.Slice(start, end - start);
foreach (Vector2 t in calculateSubpath(cpSpan))
if (calculatedPath.Count == 0 || calculatedPath.Last() != t)
@@ -77,49 +189,6 @@ namespace osu.Game.Rulesets.Objects
}
}
- private void calculateCumulativeLengthAndTrimPath()
- {
- double l = 0;
-
- cumulativeLength.Clear();
- cumulativeLength.Add(l);
-
- for (int i = 0; i < calculatedPath.Count - 1; ++i)
- {
- Vector2 diff = calculatedPath[i + 1] - calculatedPath[i];
- double d = diff.Length;
-
- // Shorten slider paths that are too long compared to what's
- // in the .osu file.
- if (Distance - l < d)
- {
- calculatedPath[i + 1] = calculatedPath[i] + diff * (float)((Distance - l) / d);
- calculatedPath.RemoveRange(i + 2, calculatedPath.Count - 2 - i);
-
- l = Distance;
- cumulativeLength.Add(l);
- break;
- }
-
- l += d;
- cumulativeLength.Add(l);
- }
-
- // Lengthen slider paths that are too short compared to what's
- // in the .osu file.
- if (l < Distance && calculatedPath.Count > 1)
- {
- Vector2 diff = calculatedPath[calculatedPath.Count - 1] - calculatedPath[calculatedPath.Count - 2];
- double d = diff.Length;
-
- if (d <= 0)
- return;
-
- calculatedPath[calculatedPath.Count - 1] += diff * (float)((Distance - l) / d);
- cumulativeLength[calculatedPath.Count - 1] = Distance;
- }
- }
-
private void calculateCumulativeLength()
{
double l = 0;
@@ -132,21 +201,33 @@ namespace osu.Game.Rulesets.Objects
Vector2 diff = calculatedPath[i + 1] - calculatedPath[i];
double d = diff.Length;
+ // Shorted slider paths that are too long compared to the expected distance
+ if (ExpectedDistance.HasValue && ExpectedDistance - l < d)
+ {
+ calculatedPath[i + 1] = calculatedPath[i] + diff * (float)((ExpectedDistance - l) / d);
+ calculatedPath.RemoveRange(i + 2, calculatedPath.Count - 2 - i);
+
+ l = ExpectedDistance.Value;
+ cumulativeLength.Add(l);
+ break;
+ }
+
l += d;
cumulativeLength.Add(l);
}
- Distance = l;
- }
+ // Lengthen slider paths that are too short compared to the expected distance
+ if (ExpectedDistance.HasValue && l < ExpectedDistance && calculatedPath.Count > 1)
+ {
+ Vector2 diff = calculatedPath[calculatedPath.Count - 1] - calculatedPath[calculatedPath.Count - 2];
+ double d = diff.Length;
- public void Calculate(bool updateDistance = false)
- {
- calculatePath();
+ if (d <= 0)
+ return;
- if (!updateDistance)
- calculateCumulativeLengthAndTrimPath();
- else
- calculateCumulativeLength();
+ calculatedPath[calculatedPath.Count - 1] += diff * (float)((ExpectedDistance - l) / d);
+ cumulativeLength[calculatedPath.Count - 1] = ExpectedDistance.Value;
+ }
}
private int indexOfDistance(double d)
@@ -169,7 +250,7 @@ namespace osu.Game.Rulesets.Objects
if (i <= 0)
return calculatedPath.First();
- else if (i >= calculatedPath.Count)
+ if (i >= calculatedPath.Count)
return calculatedPath.Last();
Vector2 p0 = calculatedPath[i - 1];
@@ -186,47 +267,20 @@ namespace osu.Game.Rulesets.Objects
return p0 + (p1 - p0) * (float)w;
}
- ///
- /// Computes the slider path until a given progress that ranges from 0 (beginning of the slider)
- /// to 1 (end of the slider) and stores the generated path in the given list.
- ///
- /// The list to be filled with the computed path.
- /// Start progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider).
- /// End progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider).
- public void GetPathToProgress(List path, double p0, double p1)
+ public bool Equals(SliderPath other)
{
- if (calculatedPath.Count == 0 && ControlPoints.Length > 0)
- Calculate();
+ if (ControlPoints == null && other.ControlPoints != null)
+ return false;
+ if (other.ControlPoints == null && ControlPoints != null)
+ return false;
- double d0 = progressToDistance(p0);
- double d1 = progressToDistance(p1);
-
- path.Clear();
-
- int i = 0;
- for (; i < calculatedPath.Count && cumulativeLength[i] < d0; ++i) { }
-
- path.Add(interpolateVertices(i, d0) + Offset);
-
- for (; i < calculatedPath.Count && cumulativeLength[i] <= d1; ++i)
- path.Add(calculatedPath[i] + Offset);
-
- path.Add(interpolateVertices(i, d1) + Offset);
+ return ControlPoints.SequenceEqual(other.ControlPoints) && ExpectedDistance.Equals(other.ExpectedDistance) && Type == other.Type;
}
- ///
- /// Computes the position on the slider at a given progress that ranges from 0 (beginning of the path)
- /// to 1 (end of the path).
- ///
- /// Ranges from 0 (beginning of the path) to 1 (end of the path).
- ///
- public Vector2 PositionAt(double progress)
+ public override bool Equals(object obj)
{
- if (calculatedPath.Count == 0 && ControlPoints.Length > 0)
- Calculate();
-
- double d = progressToDistance(progress);
- return interpolateVertices(indexOfDistance(d), d) + Offset;
+ if (ReferenceEquals(null, obj)) return false;
+ return obj is SliderPath other && Equals(other);
}
}
}
diff --git a/osu.Game/Rulesets/Objects/Types/IHasCurve.cs b/osu.Game/Rulesets/Objects/Types/IHasCurve.cs
index 2a0d495e94..a097b62851 100644
--- a/osu.Game/Rulesets/Objects/Types/IHasCurve.cs
+++ b/osu.Game/Rulesets/Objects/Types/IHasCurve.cs
@@ -14,16 +14,6 @@ namespace osu.Game.Rulesets.Objects.Types
/// The curve.
///
SliderPath Path { get; }
-
- ///
- /// The control points that shape the curve.
- ///
- Vector2[] ControlPoints { get; }
-
- ///
- /// The type of curve.
- ///
- PathType PathType { get; }
}
public static class HasCurveExtensions
diff --git a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs
index 7d918ff160..ea8784db47 100644
--- a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs
+++ b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs
@@ -17,9 +17,15 @@ namespace osu.Game.Rulesets.Objects.Types
int RepeatCount { get; }
///
- /// The samples to be played when each repeat node is hit (0 -> first repeat node, 1 -> second repeat node, etc).
+ /// The samples to be played when each node of the is hit.
+ /// 0: The first node.
+ /// 1: The first repeat.
+ /// 2: The second repeat.
+ /// ...
+ /// n-1: The last repeat.
+ /// n: The last node.
///
- List> RepeatSamples { get; }
+ List> NodeSamples { get; }
}
public static class HasRepeatsExtensions
diff --git a/osu.Game/Screens/Edit/Screens/Compose/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs
similarity index 96%
rename from osu.Game/Screens/Edit/Screens/Compose/BindableBeatDivisor.cs
rename to osu.Game/Screens/Edit/BindableBeatDivisor.cs
index b7dce8c96e..3124482c73 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/BindableBeatDivisor.cs
+++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs
@@ -5,7 +5,7 @@ using System;
using System.Linq;
using osu.Framework.Configuration;
-namespace osu.Game.Screens.Edit.Screens.Compose
+namespace osu.Game.Screens.Edit
{
public class BindableBeatDivisor : BindableNumber
{
diff --git a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs
similarity index 98%
rename from osu.Game/Screens/Edit/Menus/EditorMenuBar.cs
rename to osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs
index af0a7b6694..4b5c13efbd 100644
--- a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs
+++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs
@@ -2,19 +2,18 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation;
+using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
+using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using OpenTK;
using OpenTK.Graphics;
-using osu.Framework.Configuration;
-using osu.Framework.Input.Events;
-using osu.Game.Screens.Edit.Screens;
-namespace osu.Game.Screens.Edit.Menus
+namespace osu.Game.Screens.Edit.Components.Menus
{
public class EditorMenuBar : OsuMenu
{
diff --git a/osu.Game/Screens/Edit/Menus/EditorMenuItem.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs
similarity index 92%
rename from osu.Game/Screens/Edit/Menus/EditorMenuItem.cs
rename to osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs
index 0ef1ad8c6b..1c9253cce7 100644
--- a/osu.Game/Screens/Edit/Menus/EditorMenuItem.cs
+++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs
@@ -4,7 +4,7 @@
using System;
using osu.Game.Graphics.UserInterface;
-namespace osu.Game.Screens.Edit.Menus
+namespace osu.Game.Screens.Edit.Components.Menus
{
public class EditorMenuItem : OsuMenuItem
{
diff --git a/osu.Game/Screens/Edit/Menus/EditorMenuItemSpacer.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItemSpacer.cs
similarity index 86%
rename from osu.Game/Screens/Edit/Menus/EditorMenuItemSpacer.cs
rename to osu.Game/Screens/Edit/Components/Menus/EditorMenuItemSpacer.cs
index 91b40a2cfb..17ee88241e 100644
--- a/osu.Game/Screens/Edit/Menus/EditorMenuItemSpacer.cs
+++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItemSpacer.cs
@@ -1,7 +1,7 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-namespace osu.Game.Screens.Edit.Menus
+namespace osu.Game.Screens.Edit.Components.Menus
{
public class EditorMenuItemSpacer : EditorMenuItem
{
diff --git a/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs b/osu.Game/Screens/Edit/Components/Menus/ScreenSelectionTabControl.cs
similarity index 96%
rename from osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs
rename to osu.Game/Screens/Edit/Components/Menus/ScreenSelectionTabControl.cs
index f58e5b39eb..4ff01c0f90 100644
--- a/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs
+++ b/osu.Game/Screens/Edit/Components/Menus/ScreenSelectionTabControl.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using OpenTK.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
@@ -9,10 +8,10 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
-using osu.Game.Screens.Edit.Screens;
using OpenTK;
+using OpenTK.Graphics;
-namespace osu.Game.Screens.Edit.Menus
+namespace osu.Game.Screens.Edit.Components.Menus
{
public class ScreenSelectionTabControl : OsuTabControl
{
diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs
similarity index 98%
rename from osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs
rename to osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs
index 2c7e2043fc..22f8417735 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs
+++ b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs
@@ -2,8 +2,6 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
-using OpenTK;
-using OpenTK.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
@@ -14,8 +12,10 @@ using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
+using OpenTK;
+using OpenTK.Graphics;
-namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons
+namespace osu.Game.Screens.Edit.Components.RadioButtons
{
public class DrawableRadioButton : TriangleButton
{
diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs
similarity index 95%
rename from osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs
rename to osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs
index 09fe34bedc..c671fa71c2 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs
+++ b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs
@@ -4,7 +4,7 @@
using System;
using osu.Framework.Configuration;
-namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons
+namespace osu.Game.Screens.Edit.Components.RadioButtons
{
public class RadioButton
{
diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButtonCollection.cs
similarity index 96%
rename from osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs
rename to osu.Game/Screens/Edit/Components/RadioButtons/RadioButtonCollection.cs
index 7ba16b3d3e..9bb2e11430 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs
+++ b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButtonCollection.cs
@@ -2,12 +2,12 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
-using OpenTK;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
+using OpenTK;
-namespace osu.Game.Screens.Edit.Screens.Compose.RadioButtons
+namespace osu.Game.Screens.Edit.Components.RadioButtons
{
public class RadioButtonCollection : CompositeDrawable
{
diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs
index 4b57e1e92d..11e9ecddc6 100644
--- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs
+++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs
@@ -7,6 +7,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
+using osu.Framework.Threading;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
@@ -43,17 +44,23 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
return true;
}
+ private ScheduledDelegate scheduledSeek;
+
///
/// Seeks the to the time closest to a position on the screen relative to the .
///
/// The position in screen coordinates.
private void seekToPosition(Vector2 screenPosition)
{
- if (Beatmap.Value == null)
- return;
+ scheduledSeek?.Cancel();
+ scheduledSeek = Schedule(() =>
+ {
+ if (Beatmap.Value == null)
+ return;
- float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth);
- adjustableClock.Seek(markerPos / DrawWidth * Beatmap.Value.Track.Length);
+ float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth);
+ adjustableClock.Seek(markerPos / DrawWidth * Beatmap.Value.Track.Length);
+ });
}
protected override void Update()
diff --git a/osu.Game/Screens/Edit/Screens/Compose/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs
similarity index 99%
rename from osu.Game/Screens/Edit/Screens/Compose/BeatDivisorControl.cs
rename to osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs
index e46be9f7c1..a5a1f590bf 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/BeatDivisorControl.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs
@@ -19,7 +19,7 @@ using OpenTK;
using OpenTK.Graphics;
using OpenTK.Input;
-namespace osu.Game.Screens.Edit.Screens.Compose
+namespace osu.Game.Screens.Edit.Compose.Components
{
public class BeatDivisorControl : CompositeDrawable
{
diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs
new file mode 100644
index 0000000000..acbfd1f1d6
--- /dev/null
+++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs
@@ -0,0 +1,191 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System.Collections.Generic;
+using System.Linq;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Primitives;
+using osu.Framework.Input.Events;
+using osu.Framework.Input.States;
+using osu.Game.Rulesets.Edit;
+using osu.Game.Rulesets.Edit.Tools;
+using osu.Game.Rulesets.Objects.Drawables;
+
+namespace osu.Game.Screens.Edit.Compose.Components
+{
+ public class BlueprintContainer : CompositeDrawable
+ {
+ private SelectionBlueprintContainer selectionBlueprints;
+ private Container placementBlueprintContainer;
+ private SelectionBox selectionBox;
+
+ private IEnumerable selections => selectionBlueprints.Children.Where(c => c.IsAlive);
+
+ [Resolved]
+ private HitObjectComposer composer { get; set; }
+
+ public BlueprintContainer()
+ {
+ RelativeSizeAxes = Axes.Both;
+ }
+
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ selectionBox = composer.CreateSelectionBox();
+ selectionBox.DeselectAll = deselectAll;
+
+ var dragBox = new DragBox(select);
+ dragBox.DragEnd += () => selectionBox.UpdateVisibility();
+
+ InternalChildren = new[]
+ {
+ dragBox,
+ selectionBox,
+ selectionBlueprints = new SelectionBlueprintContainer { RelativeSizeAxes = Axes.Both },
+ placementBlueprintContainer = new Container { RelativeSizeAxes = Axes.Both },
+ dragBox.CreateProxy()
+ };
+
+ foreach (var obj in composer.HitObjects)
+ AddBlueprintFor(obj);
+ }
+
+ private HitObjectCompositionTool currentTool;
+
+ ///
+ /// The current placement tool.
+ ///
+ public HitObjectCompositionTool CurrentTool
+ {
+ get => currentTool;
+ set
+ {
+ if (currentTool == value)
+ return;
+ currentTool = value;
+
+ refreshTool();
+ }
+ }
+
+ ///
+ /// Adds a blueprint for a which adds movement support.
+ ///
+ /// The to create a blueprint for.
+ public void AddBlueprintFor(DrawableHitObject hitObject)
+ {
+ refreshTool();
+
+ var blueprint = composer.CreateBlueprintFor(hitObject);
+ if (blueprint == null)
+ return;
+
+ blueprint.Selected += onBlueprintSelected;
+ blueprint.Deselected += onBlueprintDeselected;
+ blueprint.SelectionRequested += onSelectionRequested;
+ blueprint.DragRequested += onDragRequested;
+
+ selectionBlueprints.Add(blueprint);
+ }
+
+ ///
+ /// Removes a blueprint for a .
+ ///
+ /// The for which to remove the blueprint.
+ public void RemoveBlueprintFor(DrawableHitObject hitObject)
+ {
+ var blueprint = selectionBlueprints.Single(m => m.HitObject == hitObject);
+ if (blueprint == null)
+ return;
+
+ blueprint.Deselect();
+
+ blueprint.Selected -= onBlueprintSelected;
+ blueprint.Deselected -= onBlueprintDeselected;
+ blueprint.SelectionRequested -= onSelectionRequested;
+ blueprint.DragRequested -= onDragRequested;
+
+ selectionBlueprints.Remove(blueprint);
+ }
+
+ protected override bool OnClick(ClickEvent e)
+ {
+ deselectAll();
+ return true;
+ }
+
+ ///
+ /// Refreshes the current placement tool.
+ ///
+ private void refreshTool()
+ {
+ placementBlueprintContainer.Clear();
+
+ var blueprint = CurrentTool?.CreatePlacementBlueprint();
+ if (blueprint != null)
+ placementBlueprintContainer.Child = blueprint;
+ }
+
+
+ ///
+ /// Select all masks in a given rectangle selection area.
+ ///
+ /// The rectangle to perform a selection on in screen-space coordinates.
+ private void select(RectangleF rect)
+ {
+ foreach (var blueprint in selections.ToList())
+ {
+ if (blueprint.IsPresent && rect.Contains(blueprint.SelectionPoint))
+ blueprint.Select();
+ else
+ blueprint.Deselect();
+ }
+ }
+
+ ///
+ /// Deselects all selected s.
+ ///
+ private void deselectAll() => selections.ToList().ForEach(m => m.Deselect());
+
+ private void onBlueprintSelected(SelectionBlueprint blueprint)
+ {
+ selectionBox.HandleSelected(blueprint);
+ selectionBlueprints.ChangeChildDepth(blueprint, 1);
+ }
+
+ private void onBlueprintDeselected(SelectionBlueprint blueprint)
+ {
+ selectionBox.HandleDeselected(blueprint);
+ selectionBlueprints.ChangeChildDepth(blueprint, 0);
+ }
+
+ private void onSelectionRequested(SelectionBlueprint blueprint, InputState state) => selectionBox.HandleSelectionRequested(blueprint, state);
+
+ private void onDragRequested(DragEvent dragEvent) => selectionBox.HandleDrag(dragEvent);
+
+ private class SelectionBlueprintContainer : Container
+ {
+ protected override int Compare(Drawable x, Drawable y)
+ {
+ if (!(x is SelectionBlueprint xBlueprint) || !(y is SelectionBlueprint yBlueprint))
+ return base.Compare(x, y);
+ return Compare(xBlueprint, yBlueprint);
+ }
+
+ public int Compare(SelectionBlueprint x, SelectionBlueprint y)
+ {
+ // dpeth is used to denote selected status (we always want selected blueprints to handle input first).
+ int d = x.Depth.CompareTo(y.Depth);
+ if (d != 0)
+ return d;
+
+ // Put earlier hitobjects towards the end of the list, so they handle input first
+ int i = y.HitObject.HitObject.StartTime.CompareTo(x.HitObject.HitObject.StartTime);
+ return i == 0 ? CompareReverseChildID(x, y) : i;
+ }
+ }
+ }
+}
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/DragLayer.cs b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs
similarity index 82%
rename from osu.Game/Screens/Edit/Screens/Compose/Layers/DragLayer.cs
rename to osu.Game/Screens/Edit/Compose/Components/DragBox.cs
index fdc0dee0ce..1a58f476ac 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/Layers/DragLayer.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs
@@ -8,15 +8,14 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
-using osu.Game.Rulesets.Edit;
using OpenTK.Graphics;
-namespace osu.Game.Screens.Edit.Screens.Compose.Layers
+namespace osu.Game.Screens.Edit.Compose.Components
{
///
- /// A layer that handles and displays drag selection for a collection of s.
+ /// A box that displays the drag selection and provides selection events for users to handle.
///
- public class DragLayer : CompositeDrawable
+ public class DragBox : CompositeDrawable
{
private readonly Action performSelection;
@@ -28,10 +27,10 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
private Drawable box;
///
- /// Creates a new .
+ /// Creates a new .
///
- /// The selectable s.
- public DragLayer(Action performSelection)
+ /// A delegate that performs drag selection.
+ public DragBox(Action performSelection)
{
this.performSelection = performSelection;
@@ -47,7 +46,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
{
Masking = true,
BorderColour = Color4.White,
- BorderThickness = MaskSelection.BORDER_RADIUS,
+ BorderThickness = SelectionBox.BORDER_RADIUS,
Child = new Box
{
RelativeSizeAxes = Axes.Both,
diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorPlayfieldBorder.cs b/osu.Game/Screens/Edit/Compose/Components/EditorPlayfieldBorder.cs
new file mode 100644
index 0000000000..4956b7759f
--- /dev/null
+++ b/osu.Game/Screens/Edit/Compose/Components/EditorPlayfieldBorder.cs
@@ -0,0 +1,32 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using OpenTK.Graphics;
+
+namespace osu.Game.Screens.Edit.Compose.Components
+{
+ ///
+ /// Provides a border around the playfield.
+ ///
+ public class EditorPlayfieldBorder : CompositeDrawable
+ {
+ public EditorPlayfieldBorder()
+ {
+ RelativeSizeAxes = Axes.Both;
+
+ Masking = true;
+ BorderColour = Color4.White;
+ BorderThickness = 2;
+
+ InternalChild = new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Alpha = 0,
+ AlwaysPresent = true
+ };
+ }
+ }
+}
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs
similarity index 62%
rename from osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs
rename to osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs
index 17b34bfb49..8732672723 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs
@@ -12,29 +12,28 @@ using osu.Framework.Input.Events;
using osu.Framework.Input.States;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
-using osu.Game.Rulesets.Edit.Types;
using OpenTK;
using OpenTK.Input;
-namespace osu.Game.Screens.Edit.Screens.Compose.Layers
+namespace osu.Game.Screens.Edit.Compose.Components
{
///
- /// A box which surrounds s and provides interactive handles, context menus etc.
+ /// A box which surrounds s and provides interactive handles, context menus etc.
///
- public class MaskSelection : CompositeDrawable
+ public class SelectionBox : CompositeDrawable
{
public const float BORDER_RADIUS = 2;
- private readonly List selectedMasks;
+ private readonly List selectedBlueprints;
private Drawable outline;
[Resolved]
private IPlacementHandler placementHandler { get; set; }
- public MaskSelection()
+ public SelectionBox()
{
- selectedMasks = new List();
+ selectedBlueprints = new List();
RelativeSizeAxes = Axes.Both;
AlwaysPresent = true;
@@ -60,19 +59,12 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
#region User Input Handling
- public void HandleDrag(SelectionMask m, Vector2 delta, InputState state)
+ public void HandleDrag(DragEvent dragEvent)
{
// Todo: Various forms of snapping
- foreach (var mask in selectedMasks)
- {
- switch (mask.HitObject.HitObject)
- {
- case IHasEditablePosition editablePosition:
- editablePosition.OffsetPosition(delta);
- break;
- }
- }
+ foreach (var blueprint in selectedBlueprints)
+ blueprint.AdjustPosition(dragEvent);
}
protected override bool OnKeyDown(KeyDownEvent e)
@@ -83,7 +75,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
switch (e.Key)
{
case Key.Delete:
- foreach (var h in selectedMasks.ToList())
+ foreach (var h in selectedBlueprints.ToList())
placementHandler.Delete(h.HitObject.HitObject);
return true;
}
@@ -96,49 +88,49 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
#region Selection Handling
///
- /// Bind an action to deselect all selected masks.
+ /// Bind an action to deselect all selected blueprints.
///
public Action DeselectAll { private get; set; }
///
- /// Handle a mask becoming selected.
+ /// Handle a blueprint becoming selected.
///
- /// The mask.
- public void HandleSelected(SelectionMask mask) => selectedMasks.Add(mask);
+ /// The blueprint.
+ public void HandleSelected(SelectionBlueprint blueprint) => selectedBlueprints.Add(blueprint);
///
- /// Handle a mask becoming deselected.
+ /// Handle a blueprint becoming deselected.
///
- /// The mask.
- public void HandleDeselected(SelectionMask mask)
+ /// The blueprint.
+ public void HandleDeselected(SelectionBlueprint blueprint)
{
- selectedMasks.Remove(mask);
+ selectedBlueprints.Remove(blueprint);
- // We don't want to update visibility if > 0, since we may be deselecting masks during drag-selection
- if (selectedMasks.Count == 0)
+ // We don't want to update visibility if > 0, since we may be deselecting blueprints during drag-selection
+ if (selectedBlueprints.Count == 0)
UpdateVisibility();
}
///
- /// Handle a mask requesting selection.
+ /// Handle a blueprint requesting selection.
///
- /// The mask.
- public void HandleSelectionRequested(SelectionMask mask, InputState state)
+ /// The blueprint.
+ public void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state)
{
if (state.Keyboard.ControlPressed)
{
- if (mask.IsSelected)
- mask.Deselect();
+ if (blueprint.IsSelected)
+ blueprint.Deselect();
else
- mask.Select();
+ blueprint.Select();
}
else
{
- if (mask.IsSelected)
+ if (blueprint.IsSelected)
return;
DeselectAll?.Invoke();
- mask.Select();
+ blueprint.Select();
}
UpdateVisibility();
@@ -147,11 +139,11 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
#endregion
///
- /// Updates whether this is visible.
+ /// Updates whether this is visible.
///
internal void UpdateVisibility()
{
- if (selectedMasks.Count > 0)
+ if (selectedBlueprints.Count > 0)
Show();
else
Hide();
@@ -161,7 +153,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
{
base.Update();
- if (selectedMasks.Count == 0)
+ if (selectedBlueprints.Count == 0)
return;
// Move the rectangle to cover the hitobjects
@@ -170,10 +162,10 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
bool hasSelection = false;
- foreach (var mask in selectedMasks)
+ foreach (var blueprint in selectedBlueprints)
{
- topLeft = Vector2.ComponentMin(topLeft, ToLocalSpace(mask.SelectionQuad.TopLeft));
- bottomRight = Vector2.ComponentMax(bottomRight, ToLocalSpace(mask.SelectionQuad.BottomRight));
+ topLeft = Vector2.ComponentMin(topLeft, ToLocalSpace(blueprint.SelectionQuad.TopLeft));
+ bottomRight = Vector2.ComponentMax(bottomRight, ToLocalSpace(blueprint.SelectionQuad.BottomRight));
}
topLeft -= new Vector2(5);
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/CentreMarker.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs
similarity index 96%
rename from osu.Game/Screens/Edit/Screens/Compose/Timeline/CentreMarker.cs
rename to osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs
index 8e932f307d..b2c6f02058 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/CentreMarker.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs
@@ -8,7 +8,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using OpenTK;
-namespace osu.Game.Screens.Edit.Screens.Compose.Timeline
+namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{
public class CentreMarker : CompositeDrawable
{
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs
similarity index 98%
rename from osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs
rename to osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs
index da95564975..0c626f2c54 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs
@@ -12,7 +12,7 @@ using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
-namespace osu.Game.Screens.Edit.Screens.Compose.Timeline
+namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{
public class Timeline : ZoomableScrollContainer
{
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs
similarity index 98%
rename from osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineArea.cs
rename to osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs
index ecf760be8e..5b98140a3b 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineArea.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs
@@ -1,14 +1,14 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
+using OpenTK;
-namespace osu.Game.Screens.Edit.Screens.Compose.Timeline
+namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{
public class TimelineArea : CompositeDrawable
{
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineButton.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs
similarity index 96%
rename from osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineButton.cs
rename to osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs
index 5928fbaa1b..d481934347 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineButton.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs
@@ -2,15 +2,15 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
-using OpenTK;
-using OpenTK.Graphics;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
+using OpenTK;
+using OpenTK.Graphics;
-namespace osu.Game.Screens.Edit.Screens.Compose.Timeline
+namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{
public class TimelineButton : CompositeDrawable
{
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs
similarity index 99%
rename from osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs
rename to osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs
index bbba439ca7..8d39f61d89 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs
@@ -9,7 +9,7 @@ using osu.Framework.Input.Events;
using osu.Framework.MathUtils;
using OpenTK;
-namespace osu.Game.Screens.Edit.Screens.Compose.Timeline
+namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{
public class ZoomableScrollContainer : ScrollContainer
{
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs
similarity index 96%
rename from osu.Game/Screens/Edit/Screens/Compose/Compose.cs
rename to osu.Game/Screens/Edit/Compose/ComposeScreen.cs
index ae42942d24..30962d5536 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs
+++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs
@@ -3,7 +3,6 @@
using JetBrains.Annotations;
using osu.Framework.Allocation;
-using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@@ -11,12 +10,14 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Logging;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
-using osu.Game.Screens.Edit.Screens.Compose.Timeline;
+using osu.Game.Screens.Edit.Compose.Components;
+using osu.Game.Screens.Edit.Compose.Components.Timeline;
+using OpenTK.Graphics;
-namespace osu.Game.Screens.Edit.Screens.Compose
+namespace osu.Game.Screens.Edit.Compose
{
[Cached(Type = typeof(IPlacementHandler))]
- public class Compose : EditorScreen, IPlacementHandler
+ public class ComposeScreen : EditorScreen, IPlacementHandler
{
private const float vertical_margins = 10;
private const float horizontal_margins = 20;
diff --git a/osu.Game/Screens/Edit/Screens/Compose/IPlacementHandler.cs b/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs
similarity index 95%
rename from osu.Game/Screens/Edit/Screens/Compose/IPlacementHandler.cs
rename to osu.Game/Screens/Edit/Compose/IPlacementHandler.cs
index cd213c2885..f93b294536 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/IPlacementHandler.cs
+++ b/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs
@@ -3,7 +3,7 @@
using osu.Game.Rulesets.Objects;
-namespace osu.Game.Screens.Edit.Screens.Compose
+namespace osu.Game.Screens.Edit.Compose
{
public interface IPlacementHandler
{
diff --git a/osu.Game/Screens/Edit/Screens/Design/Design.cs b/osu.Game/Screens/Edit/Design/DesignScreen.cs
similarity index 93%
rename from osu.Game/Screens/Edit/Screens/Design/Design.cs
rename to osu.Game/Screens/Edit/Design/DesignScreen.cs
index 052a1c1d90..e99e352653 100644
--- a/osu.Game/Screens/Edit/Screens/Design/Design.cs
+++ b/osu.Game/Screens/Edit/Design/DesignScreen.cs
@@ -7,11 +7,11 @@ using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics.Sprites;
using OpenTK.Graphics;
-namespace osu.Game.Screens.Edit.Screens.Design
+namespace osu.Game.Screens.Edit.Design
{
- public class Design : EditorScreen
+ public class DesignScreen : EditorScreen
{
- public Design()
+ public DesignScreen()
{
Add(new Container
{
diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs
index 62cf76ef69..524f049284 100644
--- a/osu.Game/Screens/Edit/Editor.cs
+++ b/osu.Game/Screens/Edit/Editor.cs
@@ -8,7 +8,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
-using osu.Game.Screens.Edit.Menus;
using osu.Game.Screens.Edit.Components.Timelines.Summary;
using osu.Framework.Allocation;
using osu.Framework.Graphics.UserInterface;
@@ -16,10 +15,10 @@ using osu.Framework.Input.Events;
using osu.Framework.Platform;
using osu.Framework.Timing;
using osu.Game.Graphics.UserInterface;
-using osu.Game.Screens.Edit.Screens;
-using osu.Game.Screens.Edit.Screens.Compose;
-using osu.Game.Screens.Edit.Screens.Design;
using osu.Game.Screens.Edit.Components;
+using osu.Game.Screens.Edit.Components.Menus;
+using osu.Game.Screens.Edit.Compose;
+using osu.Game.Screens.Edit.Design;
namespace osu.Game.Screens.Edit
{
@@ -169,10 +168,10 @@ namespace osu.Game.Screens.Edit
switch (mode)
{
case EditorScreenMode.Compose:
- currentScreen = new Compose();
+ currentScreen = new ComposeScreen();
break;
case EditorScreenMode.Design:
- currentScreen = new Design();
+ currentScreen = new DesignScreen();
break;
default:
currentScreen = new EditorScreen();
diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs
index 1c40181ec9..5fa29d6005 100644
--- a/osu.Game/Screens/Edit/EditorClock.cs
+++ b/osu.Game/Screens/Edit/EditorClock.cs
@@ -7,7 +7,6 @@ using osu.Framework.MathUtils;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
-using osu.Game.Screens.Edit.Screens.Compose;
using OpenTK;
namespace osu.Game.Screens.Edit
diff --git a/osu.Game/Screens/Edit/Screens/EditorScreen.cs b/osu.Game/Screens/Edit/EditorScreen.cs
similarity index 97%
rename from osu.Game/Screens/Edit/Screens/EditorScreen.cs
rename to osu.Game/Screens/Edit/EditorScreen.cs
index f8402b9a9f..3a8fc3ef80 100644
--- a/osu.Game/Screens/Edit/Screens/EditorScreen.cs
+++ b/osu.Game/Screens/Edit/EditorScreen.cs
@@ -7,7 +7,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
-namespace osu.Game.Screens.Edit.Screens
+namespace osu.Game.Screens.Edit
{
///
/// TODO: eventually make this inherit Screen and add a local scren stack inside the Editor.
diff --git a/osu.Game/Screens/Edit/Screens/EditorScreenMode.cs b/osu.Game/Screens/Edit/EditorScreenMode.cs
similarity index 91%
rename from osu.Game/Screens/Edit/Screens/EditorScreenMode.cs
rename to osu.Game/Screens/Edit/EditorScreenMode.cs
index be8363680d..17de6c4125 100644
--- a/osu.Game/Screens/Edit/Screens/EditorScreenMode.cs
+++ b/osu.Game/Screens/Edit/EditorScreenMode.cs
@@ -3,7 +3,7 @@
using System.ComponentModel;
-namespace osu.Game.Screens.Edit.Screens
+namespace osu.Game.Screens.Edit
{
public enum EditorScreenMode
{
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/BorderLayer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/BorderLayer.cs
deleted file mode 100644
index c46f9a1b7f..0000000000
--- a/osu.Game/Screens/Edit/Screens/Compose/Layers/BorderLayer.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2007-2018 ppy Pty Ltd .
-// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Containers;
-using osu.Framework.Graphics.Shapes;
-using OpenTK.Graphics;
-
-namespace osu.Game.Screens.Edit.Screens.Compose.Layers
-{
- public class BorderLayer : Container
- {
- protected override Container Content => content;
- private readonly Container content;
-
- public BorderLayer()
- {
- InternalChildren = new Drawable[]
- {
- new Container
- {
- Name = "Border",
- RelativeSizeAxes = Axes.Both,
- Masking = true,
- BorderColour = Color4.White,
- BorderThickness = 2,
- Child = new Box
- {
- RelativeSizeAxes = Axes.Both,
- Alpha = 0,
- AlwaysPresent = true
- }
- },
- content = new Container { RelativeSizeAxes = Axes.Both }
- };
- }
- }
-}
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs
deleted file mode 100644
index 0392cb5952..0000000000
--- a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2007-2018 ppy Pty Ltd .
-// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-
-using System.Linq;
-using osu.Framework.Allocation;
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Containers;
-using osu.Framework.Input.Events;
-using osu.Game.Rulesets.Edit;
-using osu.Game.Rulesets.Objects.Drawables;
-
-namespace osu.Game.Screens.Edit.Screens.Compose.Layers
-{
- public class HitObjectMaskLayer : CompositeDrawable
- {
- private MaskContainer maskContainer;
-
- [Resolved]
- private HitObjectComposer composer { get; set; }
-
- public HitObjectMaskLayer()
- {
- RelativeSizeAxes = Axes.Both;
- }
-
- [BackgroundDependencyLoader]
- private void load()
- {
- maskContainer = new MaskContainer();
-
- var maskSelection = composer.CreateMaskSelection();
-
- maskContainer.MaskSelected += maskSelection.HandleSelected;
- maskContainer.MaskDeselected += maskSelection.HandleDeselected;
- maskContainer.MaskSelectionRequested += maskSelection.HandleSelectionRequested;
- maskContainer.MaskDragRequested += maskSelection.HandleDrag;
-
- maskSelection.DeselectAll = maskContainer.DeselectAll;
-
- var dragLayer = new DragLayer(maskContainer.Select);
- dragLayer.DragEnd += () => maskSelection.UpdateVisibility();
-
- InternalChildren = new[]
- {
- dragLayer,
- maskSelection,
- maskContainer,
- dragLayer.CreateProxy()
- };
-
- foreach (var obj in composer.HitObjects)
- AddMaskFor(obj);
- }
-
- protected override bool OnClick(ClickEvent e)
- {
- maskContainer.DeselectAll();
- return true;
- }
-
- ///
- /// Adds a mask for a which adds movement support.
- ///
- /// The to create a mask for.
- public void AddMaskFor(DrawableHitObject hitObject)
- {
- var mask = composer.CreateMaskFor(hitObject);
- if (mask == null)
- return;
-
- maskContainer.Add(mask);
- }
-
- ///
- /// Removes a mask for a .
- ///
- /// The for which to remove the mask.
- public void RemoveMaskFor(DrawableHitObject hitObject)
- {
- var maskToRemove = maskContainer.Single(m => m.HitObject == hitObject);
- if (maskToRemove == null)
- return;
-
- maskToRemove.Deselect();
- maskContainer.Remove(maskToRemove);
- }
- }
-}
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs
deleted file mode 100644
index 42a7757721..0000000000
--- a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2007-2018 ppy Pty Ltd .
-// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Containers;
-using osu.Framework.Input.States;
-using osu.Game.Rulesets.Edit;
-using OpenTK;
-using RectangleF = osu.Framework.Graphics.Primitives.RectangleF;
-
-namespace osu.Game.Screens.Edit.Screens.Compose.Layers
-{
- public class MaskContainer : Container
- {
- ///
- /// Invoked when any is selected.
- ///
- public event Action MaskSelected;
-
- ///
- /// Invoked when any is deselected.
- ///
- public event Action MaskDeselected;
-
- ///
- /// Invoked when any requests selection.
- ///
- public event Action MaskSelectionRequested;
-
- ///
- /// Invoked when any requests drag.
- ///
- public event Action MaskDragRequested;
-
- private IEnumerable aliveMasks => AliveInternalChildren.Cast();
-
- public MaskContainer()
- {
- RelativeSizeAxes = Axes.Both;
- }
-
- public override void Add(SelectionMask drawable)
- {
- if (drawable == null) throw new ArgumentNullException(nameof(drawable));
-
- base.Add(drawable);
-
- drawable.Selected += onMaskSelected;
- drawable.Deselected += onMaskDeselected;
- drawable.SelectionRequested += onSelectionRequested;
- drawable.DragRequested += onDragRequested;
- }
-
- public override bool Remove(SelectionMask drawable)
- {
- if (drawable == null) throw new ArgumentNullException(nameof(drawable));
-
- var result = base.Remove(drawable);
-
- if (result)
- {
- drawable.Selected -= onMaskSelected;
- drawable.Deselected -= onMaskDeselected;
- drawable.SelectionRequested -= onSelectionRequested;
- drawable.DragRequested -= onDragRequested;
- }
-
- return result;
- }
-
- ///
- /// Select all masks in a given rectangle selection area.
- ///
- /// The rectangle to perform a selection on in screen-space coordinates.
- public void Select(RectangleF rect)
- {
- foreach (var mask in aliveMasks.ToList())
- {
- if (mask.IsPresent && rect.Contains(mask.SelectionPoint))
- mask.Select();
- else
- mask.Deselect();
- }
- }
-
- ///
- /// Deselects all selected s.
- ///
- public void DeselectAll() => aliveMasks.ToList().ForEach(m => m.Deselect());
-
- private void onMaskSelected(SelectionMask mask)
- {
- MaskSelected?.Invoke(mask);
- ChangeChildDepth(mask, 1);
- }
-
- private void onMaskDeselected(SelectionMask mask)
- {
- MaskDeselected?.Invoke(mask);
- ChangeChildDepth(mask, 0);
- }
-
- private void onSelectionRequested(SelectionMask mask, InputState state) => MaskSelectionRequested?.Invoke(mask, state);
- private void onDragRequested(SelectionMask mask, Vector2 delta, InputState state) => MaskDragRequested?.Invoke(mask, delta, state);
-
- protected override int Compare(Drawable x, Drawable y)
- {
- if (!(x is SelectionMask xMask) || !(y is SelectionMask yMask))
- return base.Compare(x, y);
- return Compare(xMask, yMask);
- }
-
- public int Compare(SelectionMask x, SelectionMask y)
- {
- // dpeth is used to denote selected status (we always want selected masks to handle input first).
- int d = x.Depth.CompareTo(y.Depth);
- if (d != 0)
- return d;
-
- // Put earlier hitobjects towards the end of the list, so they handle input first
- int i = y.HitObject.HitObject.StartTime.CompareTo(x.HitObject.HitObject.StartTime);
- return i == 0 ? CompareReverseChildID(x, y) : i;
- }
- }
-}
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/PlacementContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/PlacementContainer.cs
deleted file mode 100644
index ea167a5c6b..0000000000
--- a/osu.Game/Screens/Edit/Screens/Compose/Layers/PlacementContainer.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2007-2018 ppy Pty Ltd .
-// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Containers;
-using osu.Game.Rulesets.Edit.Tools;
-using Container = System.ComponentModel.Container;
-
-namespace osu.Game.Screens.Edit.Screens.Compose.Layers
-{
- public class PlacementContainer : CompositeDrawable
- {
- private readonly Container maskContainer;
-
- public PlacementContainer()
- {
- RelativeSizeAxes = Axes.Both;
- }
-
- private HitObjectCompositionTool currentTool;
-
- ///
- /// The current placement tool.
- ///
- public HitObjectCompositionTool CurrentTool
- {
- get => currentTool;
- set
- {
- if (currentTool == value)
- return;
- currentTool = value;
-
- Refresh();
- }
- }
-
- ///
- /// Refreshes the current placement tool.
- ///
- public void Refresh()
- {
- ClearInternal();
-
- var mask = CurrentTool?.CreatePlacementMask();
- if (mask != null)
- InternalChild = mask;
- }
- }
-}
diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/LabelledComponents/LabelledTextBox.cs b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs
similarity index 98%
rename from osu.Game/Screens/Edit/Screens/Setup/Components/LabelledComponents/LabelledTextBox.cs
rename to osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs
index 94200b7f4e..626c59981c 100644
--- a/osu.Game/Screens/Edit/Screens/Setup/Components/LabelledComponents/LabelledTextBox.cs
+++ b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation;
-using OpenTK.Graphics;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
@@ -10,8 +9,9 @@ using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
+using OpenTK.Graphics;
-namespace osu.Game.Screens.Edit.Screens.Setup.Components.LabelledComponents
+namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents
{
public class LabelledTextBox : CompositeDrawable
{
diff --git a/osu.Game/Tests/Visual/EditorClockTestCase.cs b/osu.Game/Tests/Visual/EditorClockTestCase.cs
index ebede74171..479ed385e2 100644
--- a/osu.Game/Tests/Visual/EditorClockTestCase.cs
+++ b/osu.Game/Tests/Visual/EditorClockTestCase.cs
@@ -7,7 +7,6 @@ using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Screens.Edit;
-using osu.Game.Screens.Edit.Screens.Compose;
namespace osu.Game.Tests.Visual
{
diff --git a/osu.Game/Tests/Visual/EditorTestCase.cs b/osu.Game/Tests/Visual/EditorTestCase.cs
index 2ab121fcc9..2d02509b58 100644
--- a/osu.Game/Tests/Visual/EditorTestCase.cs
+++ b/osu.Game/Tests/Visual/EditorTestCase.cs
@@ -6,7 +6,6 @@ using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Game.Rulesets;
using osu.Game.Screens.Edit;
-using osu.Game.Screens.Edit.Screens;
using osu.Game.Tests.Beatmaps;
namespace osu.Game.Tests.Visual
diff --git a/osu.Game/Tests/Visual/HitObjectPlacementMaskTestCase.cs b/osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs
similarity index 78%
rename from osu.Game/Tests/Visual/HitObjectPlacementMaskTestCase.cs
rename to osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs
index adf74b9a7d..f893d8456b 100644
--- a/osu.Game/Tests/Visual/HitObjectPlacementMaskTestCase.cs
+++ b/osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs
@@ -8,17 +8,17 @@ using osu.Framework.Timing;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
-using osu.Game.Screens.Edit.Screens.Compose;
+using osu.Game.Screens.Edit.Compose;
namespace osu.Game.Tests.Visual
{
[Cached(Type = typeof(IPlacementHandler))]
- public abstract class HitObjectPlacementMaskTestCase : OsuTestCase, IPlacementHandler
+ public abstract class PlacementBlueprintTestCase : OsuTestCase, IPlacementHandler
{
private readonly Container hitObjectContainer;
- private PlacementMask currentMask;
+ private PlacementBlueprint currentBlueprint;
- protected HitObjectPlacementMaskTestCase()
+ protected PlacementBlueprintTestCase()
{
Beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize = 2;
@@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual
[BackgroundDependencyLoader]
private void load()
{
- Add(currentMask = CreateMask());
+ Add(currentBlueprint = CreateBlueprint());
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
@@ -51,8 +51,8 @@ namespace osu.Game.Tests.Visual
{
hitObjectContainer.Add(CreateHitObject(hitObject));
- Remove(currentMask);
- Add(currentMask = CreateMask());
+ Remove(currentBlueprint);
+ Add(currentBlueprint = CreateBlueprint());
}
public void Delete(HitObject hitObject)
@@ -60,6 +60,6 @@ namespace osu.Game.Tests.Visual
}
protected abstract DrawableHitObject CreateHitObject(HitObject hitObject);
- protected abstract PlacementMask CreateMask();
+ protected abstract PlacementBlueprint CreateBlueprint();
}
}
diff --git a/osu.Game/Tests/Visual/HitObjectSelectionMaskTestCase.cs b/osu.Game/Tests/Visual/SelectionBlueprintTestCase.cs
similarity index 64%
rename from osu.Game/Tests/Visual/HitObjectSelectionMaskTestCase.cs
rename to osu.Game/Tests/Visual/SelectionBlueprintTestCase.cs
index 3ba6841280..b1df849a67 100644
--- a/osu.Game/Tests/Visual/HitObjectSelectionMaskTestCase.cs
+++ b/osu.Game/Tests/Visual/SelectionBlueprintTestCase.cs
@@ -10,14 +10,14 @@ using osu.Game.Rulesets.Edit;
namespace osu.Game.Tests.Visual
{
- public abstract class HitObjectSelectionMaskTestCase : OsuTestCase
+ public abstract class SelectionBlueprintTestCase : OsuTestCase
{
- private SelectionMask mask;
+ private SelectionBlueprint blueprint;
protected override Container Content => content ?? base.Content;
private readonly Container content;
- protected HitObjectSelectionMaskTestCase()
+ protected SelectionBlueprintTestCase()
{
base.Content.Add(content = new Container
{
@@ -29,19 +29,19 @@ namespace osu.Game.Tests.Visual
[BackgroundDependencyLoader]
private void load()
{
- base.Content.Add(mask = CreateMask());
- mask.SelectionRequested += (_, __) => mask.Select();
+ base.Content.Add(blueprint = CreateBlueprint());
+ blueprint.SelectionRequested += (_, __) => blueprint.Select();
- AddStep("Select", () => mask.Select());
- AddStep("Deselect", () => mask.Deselect());
+ AddStep("Select", () => blueprint.Select());
+ AddStep("Deselect", () => blueprint.Deselect());
}
protected override bool OnClick(ClickEvent e)
{
- mask.Deselect();
+ blueprint.Deselect();
return true;
}
- protected abstract SelectionMask CreateMask();
+ protected abstract SelectionBlueprint CreateBlueprint();
}
}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index b4cd8f9b66..9f7996a5fd 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -18,7 +18,7 @@
-
+