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 9559d13328..8c371db257 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
@@ -2,7 +2,7 @@
-
+
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 dea6e6c0fb..6855b99f28 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
@@ -2,7 +2,7 @@
-
+
diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs
index 7a3b42914e..362d6d40a8 100644
--- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs
+++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs
@@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
protected override void OnMouseUp(MouseUpEvent e)
{
- EndPlacement();
+ EndPlacement(true);
base.OnMouseUp(e);
}
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 9d4e016eae..217707b180 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
@@ -2,7 +2,7 @@
-
+
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs
index bb47c7e464..407f5f540e 100644
--- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs
@@ -30,12 +30,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
protected override bool OnClick(ClickEvent e)
{
- EndPlacement();
+ EndPlacement(true);
return true;
}
public override void UpdatePosition(Vector2 screenSpacePosition)
{
+ BeginPlacement();
HitObject.Position = ToLocalSpace(screenSpacePosition);
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs
index 90512849d4..75d05b9b6c 100644
--- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs
@@ -68,6 +68,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
switch (state)
{
case PlacementState.Initial:
+ BeginPlacement();
HitObject.Position = ToLocalSpace(screenSpacePosition);
break;
@@ -132,7 +133,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
private void endCurve()
{
updateSlider();
- EndPlacement();
+ EndPlacement(true);
}
protected override void Update()
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs
index 48c1ce11e0..2c125aa7c3 100644
--- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs
@@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners
return false;
HitObject.EndTime = EditorClock.CurrentTime;
- EndPlacement();
+ EndPlacement(true);
}
else
{
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 d728d65bfd..f6054a5d6f 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
@@ -2,7 +2,7 @@
-
+
diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj
index 6c799e5e90..35eb3fa161 100644
--- a/osu.Game.Tests/osu.Game.Tests.csproj
+++ b/osu.Game.Tests/osu.Game.Tests.csproj
@@ -3,7 +3,7 @@
-
+
diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj
index 7ecfd6ef70..3b45fc83fd 100644
--- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj
+++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index ff3dee55af..79616ef97c 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -446,7 +446,7 @@ namespace osu.Game
///
/// The action to perform once we are in the correct state.
/// An optional collection of valid screen types. If any of these screens are already current we can perform the action immediately, else the first valid parent will be made current before performing the action. is used if not specified.
- protected void PerformFromScreen(Action action, IEnumerable validScreens = null)
+ public void PerformFromScreen(Action action, IEnumerable validScreens = null)
{
performFromMainMenuTask?.Cancel();
diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs
index 6c9f0b0321..a7066c4827 100644
--- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs
+++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs
@@ -118,26 +118,42 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
{
AutoSizeAxes = Axes.Both;
- InternalChild = new FillFlowContainer
+ InternalChild = new GridContainer
{
AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Vertical,
- Spacing = new Vector2(0, 1),
- Children = new[]
+ ColumnDimensions = new[]
{
- text = new OsuSpriteText
+ new Dimension(GridSizeMode.AutoSize, minSize: minWidth ?? 0)
+ },
+ RowDimensions = new[]
+ {
+ new Dimension(GridSizeMode.AutoSize),
+ new Dimension(GridSizeMode.Absolute, 4),
+ new Dimension(GridSizeMode.AutoSize)
+ },
+ Content = new[]
+ {
+ new Drawable[]
{
- Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold),
- Text = title.ToUpper()
+ text = new OsuSpriteText
+ {
+ Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold),
+ Text = title.ToUpper()
+ }
},
- separator = new Box
+ new Drawable[]
{
- RelativeSizeAxes = minWidth == null ? Axes.X : Axes.None,
- Width = minWidth ?? 1f,
- Height = 2,
- Margin = new MarginPadding { Top = 2 }
+ separator = new Box
+ {
+ Anchor = Anchor.CentreLeft,
+ RelativeSizeAxes = Axes.X,
+ Height = 2
+ }
},
- content
+ new[]
+ {
+ content
+ }
}
};
}
diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs
index f6c73d5e4c..fb4e945701 100644
--- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs
+++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs
@@ -251,15 +251,22 @@ namespace osu.Game.Rulesets.Edit
public void BeginPlacement(HitObject hitObject)
{
+ EditorBeatmap.PlacementObject.Value = hitObject;
+
if (distanceSnapGrid != null)
hitObject.StartTime = GetSnappedPosition(distanceSnapGrid.ToLocalSpace(inputManager.CurrentState.Mouse.Position), hitObject.StartTime).time;
}
- public void EndPlacement(HitObject hitObject)
+ public void EndPlacement(HitObject hitObject, bool commit)
{
- EditorBeatmap.Add(hitObject);
+ EditorBeatmap.PlacementObject.Value = null;
- adjustableClock.Seek(hitObject.StartTime);
+ if (commit)
+ {
+ EditorBeatmap.Add(hitObject);
+
+ adjustableClock.Seek(hitObject.GetEndTime());
+ }
showGridFor(Enumerable.Empty());
}
diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs
index 07283d2245..24fa96e1c5 100644
--- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs
+++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs
@@ -103,11 +103,12 @@ namespace osu.Game.Rulesets.Edit
/// Signals that the placement of has finished.
/// This will destroy this , and add the to the .
///
- protected void EndPlacement()
+ /// Whether the object should be committed.
+ public void EndPlacement(bool commit)
{
if (!PlacementBegun)
BeginPlacement();
- placementHandler.EndPlacement(HitObject);
+ placementHandler.EndPlacement(HitObject, commit);
}
///
diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs
index 675b2b648d..417d32ca4f 100644
--- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs
@@ -32,7 +32,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
protected DragBox DragBox { get; private set; }
- private Container selectionBlueprints;
+ protected Container SelectionBlueprints { get; private set; }
private SelectionHandler selectionHandler;
@@ -62,7 +62,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
{
DragBox = CreateDragBox(select),
selectionHandler,
- selectionBlueprints = CreateSelectionBlueprintContainer(),
+ SelectionBlueprints = CreateSelectionBlueprintContainer(),
DragBox.CreateProxy().With(p => p.Depth = float.MinValue)
});
@@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
selectedHitObjects.ItemsAdded += objects =>
{
foreach (var o in objects)
- selectionBlueprints.FirstOrDefault(b => b.HitObject == o)?.Select();
+ SelectionBlueprints.FirstOrDefault(b => b.HitObject == o)?.Select();
SelectionChanged?.Invoke(selectedHitObjects);
};
@@ -81,7 +81,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
selectedHitObjects.ItemsRemoved += objects =>
{
foreach (var o in objects)
- selectionBlueprints.FirstOrDefault(b => b.HitObject == o)?.Deselect();
+ SelectionBlueprints.FirstOrDefault(b => b.HitObject == o)?.Deselect();
SelectionChanged?.Invoke(selectedHitObjects);
};
@@ -230,7 +230,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
private void removeBlueprintFor(HitObject hitObject)
{
- var blueprint = selectionBlueprints.SingleOrDefault(m => m.HitObject == hitObject);
+ var blueprint = SelectionBlueprints.SingleOrDefault(m => m.HitObject == hitObject);
if (blueprint == null)
return;
@@ -239,7 +239,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
blueprint.Selected -= onBlueprintSelected;
blueprint.Deselected -= onBlueprintDeselected;
- selectionBlueprints.Remove(blueprint);
+ SelectionBlueprints.Remove(blueprint);
}
protected virtual void AddBlueprintFor(HitObject hitObject)
@@ -251,7 +251,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
blueprint.Selected += onBlueprintSelected;
blueprint.Deselected += onBlueprintDeselected;
- selectionBlueprints.Add(blueprint);
+ SelectionBlueprints.Add(blueprint);
}
#endregion
@@ -278,7 +278,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
if (!allowDeselection && selectionHandler.SelectedBlueprints.Any(s => s.IsHovered))
return;
- foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveChildren)
+ foreach (SelectionBlueprint blueprint in SelectionBlueprints.AliveChildren)
{
if (blueprint.IsHovered)
{
@@ -308,7 +308,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// The rectangle to perform a selection on in screen-space coordinates.
private void select(RectangleF rect)
{
- foreach (var blueprint in selectionBlueprints)
+ foreach (var blueprint in SelectionBlueprints)
{
if (blueprint.IsAlive && blueprint.IsPresent && rect.Contains(blueprint.SelectionPoint))
blueprint.Select();
@@ -322,7 +322,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
///
private void selectAll()
{
- selectionBlueprints.ToList().ForEach(m => m.Select());
+ SelectionBlueprints.ToList().ForEach(m => m.Select());
selectionHandler.UpdateVisibility();
}
@@ -334,14 +334,14 @@ namespace osu.Game.Screens.Edit.Compose.Components
private void onBlueprintSelected(SelectionBlueprint blueprint)
{
selectionHandler.HandleSelected(blueprint);
- selectionBlueprints.ChangeChildDepth(blueprint, 1);
+ SelectionBlueprints.ChangeChildDepth(blueprint, 1);
beatmap.SelectedHitObjects.Add(blueprint.HitObject);
}
private void onBlueprintDeselected(SelectionBlueprint blueprint)
{
selectionHandler.HandleDeselected(blueprint);
- selectionBlueprints.ChangeChildDepth(blueprint, 0);
+ SelectionBlueprints.ChangeChildDepth(blueprint, 0);
beatmap.SelectedHitObjects.Remove(blueprint.HitObject);
}
diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs
index 3c41dead5d..b257688568 100644
--- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs
@@ -63,6 +63,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
private void refreshTool()
{
placementBlueprintContainer.Clear();
+
+ currentPlacement?.EndPlacement(false);
currentPlacement = null;
var blueprint = CurrentTool?.CreatePlacementBlueprint();
diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs
index 9f3d776e5c..84328466c3 100644
--- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs
@@ -3,6 +3,7 @@
using System;
using osu.Framework.Allocation;
+using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
@@ -21,8 +22,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
[Resolved(CanBeNull = true)]
private Timeline timeline { get; set; }
+ [Resolved]
+ private EditorBeatmap beatmap { get; set; }
+
private DragEvent lastDragEvent;
+ private Bindable placement;
+
+ private SelectionBlueprint placementBlueprint;
+
public TimelineBlueprintContainer()
{
RelativeSizeAxes = Axes.Both;
@@ -43,6 +51,29 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{
base.LoadComplete();
DragBox.Alpha = 0;
+
+ placement = beatmap.PlacementObject.GetBoundCopy();
+ placement.ValueChanged += placementChanged;
+ }
+
+ private void placementChanged(ValueChangedEvent obj)
+ {
+ if (obj.NewValue == null)
+ {
+ if (placementBlueprint != null)
+ {
+ SelectionBlueprints.Remove(placementBlueprint);
+ placementBlueprint = null;
+ }
+ }
+ else
+ {
+ placementBlueprint = CreateBlueprintFor(obj.NewValue);
+
+ placementBlueprint.Colour = Color4.MediumPurple;
+
+ SelectionBlueprints.Add(placementBlueprint);
+ }
}
protected override Container CreateSelectionBlueprintContainer() => new TimelineSelectionBlueprintContainer { RelativeSizeAxes = Axes.Both };
diff --git a/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs b/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs
index 47a4277430..aefcbc6542 100644
--- a/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs
+++ b/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs
@@ -17,7 +17,8 @@ namespace osu.Game.Screens.Edit.Compose
/// Notifies that a placement has finished.
///
/// The that has been placed.
- void EndPlacement(HitObject hitObject);
+ /// Whether the object should be committed.
+ void EndPlacement(HitObject hitObject, bool commit);
///
/// Deletes a .
diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs
index cacb539891..5216e85903 100644
--- a/osu.Game/Screens/Edit/EditorBeatmap.cs
+++ b/osu.Game/Screens/Edit/EditorBeatmap.cs
@@ -33,7 +33,15 @@ namespace osu.Game.Screens.Edit
///
public event Action StartTimeChanged;
- public BindableList SelectedHitObjects { get; } = new BindableList();
+ ///
+ /// All currently selected s.
+ ///
+ public readonly BindableList SelectedHitObjects = new BindableList();
+
+ ///
+ /// The current placement. Null if there's no active placement.
+ ///
+ public readonly Bindable PlacementObject = new Bindable();
public readonly IBeatmap PlayableBeatmap;
diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs
index cb5ceefb0f..c70fbb67a4 100644
--- a/osu.Game/Screens/Menu/MainMenu.cs
+++ b/osu.Game/Screens/Menu/MainMenu.cs
@@ -141,12 +141,15 @@ namespace osu.Game.Screens.Menu
preloadSongSelect();
}
+ [Resolved]
+ private OsuGame game { get; set; }
+
private void confirmAndExit()
{
if (exitConfirmed) return;
exitConfirmed = true;
- this.Exit();
+ game.PerformFromScreen(menu => menu.Exit());
}
private void preloadSongSelect()
diff --git a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs
index 0688620b8e..ce95dfa62f 100644
--- a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs
+++ b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs
@@ -53,9 +53,10 @@ namespace osu.Game.Tests.Visual
{
}
- public void EndPlacement(HitObject hitObject)
+ public void EndPlacement(HitObject hitObject, bool commit)
{
- AddHitObject(CreateHitObject(hitObject));
+ if (commit)
+ AddHitObject(CreateHitObject(hitObject));
Remove(currentBlueprint);
Add(currentBlueprint = CreateBlueprint());
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 21c9eab4c6..389fbe8210 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -24,7 +24,7 @@
-
+