mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 23:24:04 +09:00
Begin refactoring SelectionBlueprint to handle non-drawable HitObjects
This commit is contained in:
@ -59,7 +59,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
{
|
||||
DragBox = CreateDragBox(select),
|
||||
selectionHandler,
|
||||
selectionBlueprints = new SelectionBlueprintContainer { RelativeSizeAxes = Axes.Both },
|
||||
selectionBlueprints = CreateSelectionBlueprintContainer(),
|
||||
DragBox.CreateProxy().With(p => p.Depth = float.MinValue)
|
||||
});
|
||||
|
||||
@ -67,6 +67,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
AddBlueprintFor(obj);
|
||||
}
|
||||
|
||||
protected virtual SelectionBlueprintContainer CreateSelectionBlueprintContainer() => new SelectionBlueprintContainer { RelativeSizeAxes = Axes.Both };
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
@ -118,7 +120,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
if (clickedBlueprint == null)
|
||||
return false;
|
||||
|
||||
adjustableClock?.Seek(clickedBlueprint.DrawableObject.HitObject.StartTime);
|
||||
adjustableClock?.Seek(clickedBlueprint.HitObject.StartTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -208,7 +210,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
|
||||
private void removeBlueprintFor(HitObject hitObject)
|
||||
{
|
||||
var blueprint = selectionBlueprints.SingleOrDefault(m => m.DrawableObject.HitObject == hitObject);
|
||||
var blueprint = selectionBlueprints.SingleOrDefault(m => m.HitObject == hitObject);
|
||||
if (blueprint == null)
|
||||
return;
|
||||
|
||||
@ -346,8 +348,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
return false;
|
||||
|
||||
// Movement is tracked from the blueprint of the earliest hitobject, since it only makes sense to distance snap from that hitobject
|
||||
movementBlueprint = selectionHandler.SelectedBlueprints.OrderBy(b => b.DrawableObject.HitObject.StartTime).First();
|
||||
screenSpaceMovementStartPosition = movementBlueprint.DrawableObject.ToScreenSpace(movementBlueprint.DrawableObject.OriginPosition);
|
||||
movementBlueprint = selectionHandler.SelectedBlueprints.OrderBy(b => b.HitObject.StartTime).First();
|
||||
screenSpaceMovementStartPosition = movementBlueprint.SelectionPoint; // todo: unsure if correct
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -365,14 +367,14 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
Debug.Assert(screenSpaceMovementStartPosition != null);
|
||||
|
||||
Vector2 startPosition = screenSpaceMovementStartPosition.Value;
|
||||
HitObject draggedObject = movementBlueprint.DrawableObject.HitObject;
|
||||
HitObject draggedObject = movementBlueprint.HitObject;
|
||||
|
||||
// The final movement position, relative to screenSpaceMovementStartPosition
|
||||
Vector2 movePosition = startPosition + e.ScreenSpaceMousePosition - e.ScreenSpaceMouseDownPosition;
|
||||
(Vector2 snappedPosition, double snappedTime) = snapProvider.GetSnappedPosition(ToLocalSpace(movePosition), draggedObject.StartTime);
|
||||
|
||||
// Move the hitobjects
|
||||
if (!selectionHandler.HandleMovement(new MoveSelectionEvent(movementBlueprint, startPosition, ToScreenSpace(snappedPosition))))
|
||||
if (!selectionHandler.HandleMovement(new MoveSelectionEvent((OverlaySelectionBlueprint)movementBlueprint, startPosition, ToScreenSpace(snappedPosition))))
|
||||
return true;
|
||||
|
||||
// Apply the start time at the newly snapped-to position
|
||||
@ -411,29 +413,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
}
|
||||
}
|
||||
|
||||
private class SelectionBlueprintContainer : Container<SelectionBlueprint>
|
||||
protected class SelectionBlueprintContainer : Container<SelectionBlueprint>
|
||||
{
|
||||
public IEnumerable<SelectionBlueprint> AliveBlueprints => AliveInternalChildren.Cast<SelectionBlueprint>();
|
||||
|
||||
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.DrawableObject.HitObject.StartTime.CompareTo(x.DrawableObject.HitObject.StartTime);
|
||||
return i == 0 ? CompareReverseChildID(x, y) : i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
return CreateBlueprintFor(drawable);
|
||||
}
|
||||
|
||||
public virtual SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) => null;
|
||||
public virtual OverlaySelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) => null;
|
||||
|
||||
protected override void AddBlueprintFor(HitObject hitObject)
|
||||
{
|
||||
|
@ -7,14 +7,14 @@ using osuTK;
|
||||
namespace osu.Game.Screens.Edit.Compose.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// An event which occurs when a <see cref="SelectionBlueprint"/> is moved.
|
||||
/// An event which occurs when a <see cref="OverlaySelectionBlueprint"/> is moved.
|
||||
/// </summary>
|
||||
public class MoveSelectionEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="SelectionBlueprint"/> that triggered this <see cref="MoveSelectionEvent"/>.
|
||||
/// The <see cref="OverlaySelectionBlueprint"/> that triggered this <see cref="MoveSelectionEvent"/>.
|
||||
/// </summary>
|
||||
public readonly SelectionBlueprint Blueprint;
|
||||
public readonly OverlaySelectionBlueprint Blueprint;
|
||||
|
||||
/// <summary>
|
||||
/// The starting screen-space position of the hitobject.
|
||||
@ -34,7 +34,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
/// </remarks>
|
||||
public readonly Vector2 InstantDelta;
|
||||
|
||||
public MoveSelectionEvent(SelectionBlueprint blueprint, Vector2 screenSpaceStartPosition, Vector2 screenSpacePosition)
|
||||
public MoveSelectionEvent(OverlaySelectionBlueprint blueprint, Vector2 screenSpaceStartPosition, Vector2 screenSpacePosition)
|
||||
{
|
||||
Blueprint = blueprint;
|
||||
ScreenSpaceStartPosition = screenSpaceStartPosition;
|
||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
public IEnumerable<SelectionBlueprint> SelectedBlueprints => selectedBlueprints;
|
||||
private readonly List<SelectionBlueprint> selectedBlueprints;
|
||||
|
||||
public IEnumerable<HitObject> SelectedHitObjects => selectedBlueprints.Select(b => b.DrawableObject.HitObject);
|
||||
public IEnumerable<HitObject> SelectedHitObjects => selectedBlueprints.Select(b => b.HitObject);
|
||||
|
||||
private Drawable outline;
|
||||
|
||||
@ -146,7 +146,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
private void deleteSelected()
|
||||
{
|
||||
foreach (var h in selectedBlueprints.ToList())
|
||||
placementHandler.Delete(h.DrawableObject.HitObject);
|
||||
placementHandler.Delete(h.HitObject);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -2,13 +2,12 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
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 osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts;
|
||||
@ -19,32 +18,21 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
{
|
||||
internal class TimelineHitObjectDisplay : BlueprintContainer
|
||||
{
|
||||
private EditorBeatmap beatmap { get; }
|
||||
|
||||
private readonly TimelinePart content;
|
||||
|
||||
public TimelineHitObjectDisplay(EditorBeatmap beatmap)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
this.beatmap = beatmap;
|
||||
|
||||
AddInternal(content = new TimelinePart { RelativeSizeAxes = Axes.Both });
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
foreach (var h in beatmap.HitObjects)
|
||||
add(h);
|
||||
protected override SelectionBlueprintContainer CreateSelectionBlueprintContainer() => new TimelineSelectionBlueprintContainer { RelativeSizeAxes = Axes.Both };
|
||||
|
||||
beatmap.HitObjectAdded += add;
|
||||
beatmap.HitObjectRemoved += remove;
|
||||
beatmap.StartTimeChanged += h =>
|
||||
protected class TimelineSelectionBlueprintContainer : SelectionBlueprintContainer
|
||||
{
|
||||
protected override Container<SelectionBlueprint> Content { get; }
|
||||
|
||||
public TimelineSelectionBlueprintContainer()
|
||||
{
|
||||
remove(h);
|
||||
add(h);
|
||||
};
|
||||
AddInternal(new TimelinePart<SelectionBlueprint>(Content = new Container<SelectionBlueprint> { RelativeSizeAxes = Axes.Both }) { RelativeSizeAxes = Axes.Both });
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@ -53,24 +41,19 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
DragBox.Alpha = 0;
|
||||
}
|
||||
|
||||
private void remove(HitObject h)
|
||||
protected override SelectionBlueprint CreateBlueprintFor(HitObject hitObject)
|
||||
{
|
||||
foreach (var d in content.OfType<TimelineHitObjectRepresentation>().Where(c => c.HitObject == h))
|
||||
d.Expire();
|
||||
}
|
||||
//var yOffset = content.Count(d => d.X == h.StartTime);
|
||||
var yOffset = 0;
|
||||
|
||||
private void add(HitObject h)
|
||||
{
|
||||
var yOffset = content.Count(d => d.X == h.StartTime);
|
||||
|
||||
content.Add(new TimelineHitObjectRepresentation(h) { Y = -yOffset * TimelineHitObjectRepresentation.THICKNESS });
|
||||
return new TimelineHitObjectRepresentation(hitObject) { Y = -yOffset * TimelineHitObjectRepresentation.THICKNESS };
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
base.OnMouseDown(e);
|
||||
|
||||
return false; // tempoerary until we correctly handle selections.
|
||||
return false; // temporary until we correctly handle selections.
|
||||
}
|
||||
|
||||
protected override DragBox CreateDragBox(Action<RectangleF> performSelect) => new NoDragDragBox(performSelect);
|
||||
@ -85,15 +68,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
public override bool UpdateDrag(MouseButtonEvent e) => false;
|
||||
}
|
||||
|
||||
private class TimelineHitObjectRepresentation : CompositeDrawable
|
||||
private class TimelineHitObjectRepresentation : SelectionBlueprint
|
||||
{
|
||||
public const float THICKNESS = 3;
|
||||
|
||||
public readonly HitObject HitObject;
|
||||
|
||||
public TimelineHitObjectRepresentation(HitObject hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
HitObject = hitObject;
|
||||
Anchor = Anchor.CentreLeft;
|
||||
Origin = Anchor.CentreLeft;
|
||||
|
||||
|
Reference in New Issue
Block a user