diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs
index 5f22ef5c12..1e63d32c41 100644
--- a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs
+++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs
@@ -17,6 +17,8 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
private double placementStartTime;
private double placementEndTime;
+ protected override bool IsValidForPlacement => HitObject.Duration > 0;
+
public BananaShowerPlacementBlueprint()
{
InternalChild = outline = new TimeSpanOutline();
@@ -49,7 +51,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
case PlacementState.Active:
if (e.Button != MouseButton.Right) break;
- EndPlacement(HitObject.Duration > 0);
+ EndPlacement(true);
return true;
}
diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs
index 03ec674abb..9e50b5a80f 100644
--- a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs
+++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs
@@ -24,6 +24,8 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
private InputManager inputManager = null!;
+ protected override bool IsValidForPlacement => HitObject.Duration > 0;
+
public JuiceStreamPlacementBlueprint()
{
InternalChildren = new Drawable[]
@@ -70,7 +72,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
return true;
case MouseButton.Right:
- EndPlacement(HitObject.Duration > 0);
+ EndPlacement(true);
return true;
}
diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs
index 21beee0769..381af8be7f 100644
--- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs
+++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs
@@ -25,6 +25,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
[Resolved]
private IScrollingInfo scrollingInfo { get; set; }
+ protected override bool IsValidForPlacement => HitObject.Duration > 0;
+
public HoldNotePlacementBlueprint()
: base(new HoldNote())
{
@@ -75,7 +77,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
return;
base.OnMouseUp(e);
- EndPlacement(HitObject.Duration > 0);
+ EndPlacement(true);
}
private double originalStartTime;
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs
index 50514865e1..28ceb80627 100644
--- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs
@@ -41,6 +41,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
[Resolved(CanBeNull = true)]
private IDistanceSnapProvider snapProvider { get; set; }
+ protected override bool IsValidForPlacement => HitObject.Path.HasValidLength;
+
public SliderPlacementBlueprint()
: base(new Slider())
{
@@ -150,7 +152,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
private void endCurve()
{
updateSlider();
- EndPlacement(HitObject.Path.HasValidLength);
+ EndPlacement(true);
}
protected override void Update()
diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs
index fcf2573d64..bc4129c982 100644
--- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs
+++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs
@@ -25,6 +25,8 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints
private readonly IHasDuration spanPlacementObject;
+ protected override bool IsValidForPlacement => spanPlacementObject.Duration > 0;
+
public TaikoSpanPlacementBlueprint(HitObject hitObject)
: base(hitObject)
{
@@ -73,7 +75,7 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints
return;
base.OnMouseUp(e);
- EndPlacement(spanPlacementObject.Duration > 0);
+ EndPlacement(true);
}
public override void UpdateTimeAndPosition(SnapResult result)
diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs
index bdcb334738..253d59751d 100644
--- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs
+++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs
@@ -47,6 +47,15 @@ namespace osu.Game.Rulesets.Edit
[Resolved]
private IPlacementHandler placementHandler { get; set; }
+ ///
+ /// Whether this blueprint is currently in a state that can be committed.
+ ///
+ ///
+ /// Override this with any preconditions that should be double-checked on committing.
+ /// If false is returned and a commit is attempted, the blueprint will be destroyed instead.
+ ///
+ protected virtual bool IsValidForPlacement => true;
+
protected PlacementBlueprint(HitObject hitObject)
{
HitObject = hitObject;
@@ -88,7 +97,7 @@ namespace osu.Game.Rulesets.Edit
/// Signals that the placement of has finished.
/// This will destroy this , and add the HitObject.StartTime to the .
///
- /// Whether the object should be committed.
+ /// Whether the object should be committed. Note that a commit may fail if is false.
public void EndPlacement(bool commit)
{
switch (PlacementActive)
@@ -102,7 +111,7 @@ namespace osu.Game.Rulesets.Edit
break;
}
- placementHandler.EndPlacement(HitObject, commit);
+ placementHandler.EndPlacement(HitObject, IsValidForPlacement && commit);
PlacementActive = PlacementState.Finished;
}