Refactor into separate files + add xmldocs + rename some methods

This commit is contained in:
smoogipoo 2017-12-11 21:56:58 +09:00
parent c12c241633
commit 2f1063c5c0
7 changed files with 469 additions and 380 deletions

View File

@ -0,0 +1,47 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using OpenTK;
namespace osu.Game.Rulesets.Edit.Layers.Selection
{
/// <summary>
/// Represents the centre of a <see cref="MarkerContainer"/>.
/// </summary>
public class CentreMarker : CompositeDrawable
{
private const float marker_size = 10;
private const float line_width = 2;
public CentreMarker()
{
Size = new Vector2(marker_size);
InternalChildren = new[]
{
new Box
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = line_width
},
new Box
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
Width = line_width
},
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Colour = colours.Yellow;
}
}
}

View File

@ -0,0 +1,170 @@
using System;
using System.Collections.Generic;
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.Game.Graphics;
using osu.Game.Rulesets.Objects.Drawables;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Edit.Layers.Selection
{
/// <summary>
/// A box that represents a drag selection.
/// </summary>
public class DragSelector : CompositeDrawable
{
/// <summary>
/// The <see cref="DrawableHitObject"/>s that can be selected through a drag-selection.
/// </summary>
public IEnumerable<DrawableHitObject> CapturableObjects;
private readonly Container borderMask;
private readonly Drawable background;
private readonly MarkerContainer markers;
private Color4 captureFinishedColour;
private readonly Vector2 startPos;
/// <summary>
/// Creates a new <see cref="DragSelector"/>.
/// </summary>
/// <param name="startPos">The point at which the drag was initiated, in the parent's coordinates.</param>
public DragSelector(Vector2 startPos)
{
this.startPos = startPos;
InternalChildren = new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding(-1),
Child = borderMask = new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
BorderColour = Color4.White,
BorderThickness = 2,
MaskingSmoothness = 1,
Child = background = new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0.1f,
AlwaysPresent = true
},
}
},
markers = new MarkerContainer
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
GetDragRectangle = () => dragRectangle,
UpdateDragRectangle = r =>
{
updateDragRectangle(r);
BeginCapture();
},
FinishCapture = FinishCapture
}
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
captureFinishedColour = colours.Yellow;
}
/// <summary>
/// The secondary corner of the drag selection box. A rectangle will be fit between the starting position and this value.
/// </summary>
public Vector2 DragEndPosition { set => updateDragRectangle(RectangleF.FromLTRB(startPos.X, startPos.Y, value.X, value.Y)); }
private RectangleF dragRectangle;
private void updateDragRectangle(RectangleF rectangle)
{
dragRectangle = rectangle;
Position = new Vector2(
Math.Min(rectangle.Left, rectangle.Right),
Math.Min(rectangle.Top, rectangle.Bottom));
Size = new Vector2(
Math.Max(rectangle.Left, rectangle.Right) - Position.X,
Math.Max(rectangle.Top, rectangle.Bottom) - Position.Y);
}
private readonly List<DrawableHitObject> capturedHitObjects = new List<DrawableHitObject>();
public IReadOnlyList<DrawableHitObject> CapturedHitObjects => capturedHitObjects;
/// <summary>
/// Processes hitobjects to determine which ones are captured by the drag selection.
/// Captured hitobjects will be enclosed by the drag selection upon <see cref="FinishCapture"/>.
/// </summary>
public void BeginCapture()
{
capturedHitObjects.Clear();
foreach (var obj in CapturableObjects)
{
if (!obj.IsAlive || !obj.IsPresent)
continue;
var objectPosition = obj.ToScreenSpace(obj.SelectionPoint);
if (ScreenSpaceDrawQuad.Contains(objectPosition))
capturedHitObjects.Add(obj);
}
}
/// <summary>
/// Encloses hitobjects captured through <see cref="BeginCapture"/> in the drag selection box.
/// </summary>
public void FinishCapture()
{
if (CapturedHitObjects.Count == 0)
{
Hide();
return;
}
// Move the rectangle to cover the hitobjects
var topLeft = new Vector2(float.MaxValue, float.MaxValue);
var bottomRight = new Vector2(float.MinValue, float.MinValue);
foreach (var obj in capturedHitObjects)
{
topLeft = Vector2.ComponentMin(topLeft, Parent.ToLocalSpace(obj.SelectionQuad.TopLeft));
bottomRight = Vector2.ComponentMax(bottomRight, Parent.ToLocalSpace(obj.SelectionQuad.BottomRight));
}
topLeft -= new Vector2(5);
bottomRight += new Vector2(5);
this.MoveTo(topLeft, 200, Easing.OutQuint)
.ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint);
dragRectangle = RectangleF.FromLTRB(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y);
borderMask.BorderThickness = 3;
borderMask.FadeColour(captureFinishedColour, 200);
// Transform into markers to let the user modify the drag selection further.
background.Delay(50).FadeOut(200);
markers.FadeIn(200);
}
private bool isActive = true;
public override bool HandleInput => isActive;
public override void Hide()
{
isActive = false;
this.FadeOut(400, Easing.OutQuint).Expire();
}
}
}

View File

@ -0,0 +1,102 @@
using System;
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;
using osu.Game.Graphics;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Edit.Layers.Selection
{
/// <summary>
/// Represents a marker visible on the border of a <see cref="MarkerContainer"/> which exposes
/// properties that are used to resize a <see cref="DragSelector"/>.
/// </summary>
public class Marker : CompositeDrawable
{
private const float marker_size = 10;
/// <summary>
/// Invoked when this <see cref="Marker"/> requires the current drag rectangle.
/// </summary>
public Func<RectangleF> GetDragRectangle;
/// <summary>
/// Invoked when this <see cref="Marker"/> wants to update the drag rectangle.
/// </summary>
public Action<RectangleF> UpdateDragRectangle;
/// <summary>
/// Invoked when this <see cref="Marker"/> has finished updates to the drag rectangle.
/// </summary>
public Action FinishCapture;
private Color4 normalColour;
private Color4 hoverColour;
public Marker()
{
Size = new Vector2(marker_size);
InternalChild = new CircularContainer
{
RelativeSizeAxes = Axes.Both,
Masking = true,
Child = new Box { RelativeSizeAxes = Axes.Both }
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Colour = normalColour = colours.Yellow;
hoverColour = colours.YellowDarker;
}
protected override bool OnDragStart(InputState state) => true;
protected override bool OnDrag(InputState state)
{
var currentRectangle = GetDragRectangle();
float left = currentRectangle.Left;
float right = currentRectangle.Right;
float top = currentRectangle.Top;
float bottom = currentRectangle.Bottom;
// Apply modifications to the capture rectangle
if ((Anchor & Anchor.y0) > 0)
top += state.Mouse.Delta.Y;
else if ((Anchor & Anchor.y2) > 0)
bottom += state.Mouse.Delta.Y;
if ((Anchor & Anchor.x0) > 0)
left += state.Mouse.Delta.X;
else if ((Anchor & Anchor.x2) > 0)
right += state.Mouse.Delta.X;
UpdateDragRectangle(RectangleF.FromLTRB(left, top, right, bottom));
return true;
}
protected override bool OnDragEnd(InputState state)
{
FinishCapture();
return true;
}
protected override bool OnHover(InputState state)
{
this.FadeColour(hoverColour, 100);
return true;
}
protected override void OnHoverLost(InputState state)
{
this.FadeColour(normalColour, 100);
}
}
}

View File

@ -0,0 +1,89 @@
using System;
using System.Linq;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
namespace osu.Game.Rulesets.Edit.Layers.Selection
{
/// <summary>
/// A <see cref="CompositeDrawable"/> that has <see cref="Marker"/>s around its border.
/// </summary>
public class MarkerContainer : CompositeDrawable
{
/// <summary>
/// Invoked when a <see cref="Marker"/> requires the current drag rectangle.
/// </summary>
public Func<RectangleF> GetDragRectangle;
/// <summary>
/// Invoked when a <see cref="Marker"/> wants to update the drag rectangle.
/// </summary>
public Action<RectangleF> UpdateDragRectangle;
/// <summary>
/// Invoked when a <see cref="Marker"/> has finished updates to the drag rectangle.
/// </summary>
public Action FinishCapture;
public MarkerContainer()
{
InternalChildren = new Drawable[]
{
new Marker
{
Anchor = Anchor.TopLeft,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.TopCentre,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.TopRight,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.CentreRight,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.BottomRight,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.Centre
},
new CentreMarker
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre
}
};
InternalChildren.OfType<Marker>().ForEach(m =>
{
m.GetDragRectangle = () => GetDragRectangle();
m.UpdateDragRectangle = r => UpdateDragRectangle(r);
m.FinishCapture = () => FinishCapture();
});
}
}
}

View File

@ -0,0 +1,55 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// 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.Input;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Edit.Layers.Selection
{
public class SelectionLayer : CompositeDrawable
{
private readonly Playfield playfield;
public SelectionLayer(Playfield playfield)
{
this.playfield = playfield;
RelativeSizeAxes = Axes.Both;
}
private DragSelector selector;
protected override bool OnDragStart(InputState state)
{
// Hide the previous drag box - we won't be working with it any longer
selector?.Hide();
AddInternal(selector = new DragSelector(ToLocalSpace(state.Mouse.NativeState.Position))
{
CapturableObjects = playfield.HitObjects.Objects
});
return true;
}
protected override bool OnDrag(InputState state)
{
selector.DragEndPosition = ToLocalSpace(state.Mouse.NativeState.Position);
selector.BeginCapture();
return true;
}
protected override bool OnDragEnd(InputState state)
{
selector.FinishCapture();
return true;
}
protected override bool OnClick(InputState state)
{
selector?.Hide();
return true;
}
}
}

View File

@ -1,378 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input;
using OpenTK;
using OpenTK.Graphics;
using System.Collections.Generic;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.UI;
using System.Linq;
using osu.Game.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions;
namespace osu.Game.Rulesets.Edit
{
public class SelectionLayer : CompositeDrawable
{
private readonly Playfield playfield;
public SelectionLayer(Playfield playfield)
{
this.playfield = playfield;
RelativeSizeAxes = Axes.Both;
}
private DragContainer dragBox;
protected override bool OnDragStart(InputState state)
{
dragBox?.Hide();
AddInternal(dragBox = new DragContainer(ToLocalSpace(state.Mouse.NativeState.Position))
{
CapturableObjects = playfield.HitObjects.Objects
});
return true;
}
protected override bool OnDrag(InputState state)
{
dragBox.Track(ToLocalSpace(state.Mouse.NativeState.Position));
dragBox.UpdateCapture();
return true;
}
protected override bool OnDragEnd(InputState state)
{
if (dragBox.CapturedHitObjects.Count == 0)
dragBox.Hide();
else
dragBox.FinishCapture();
return true;
}
protected override bool OnClick(InputState state)
{
dragBox?.Hide();
return true;
}
}
public class DragContainer : CompositeDrawable
{
public IEnumerable<DrawableHitObject> CapturableObjects;
private readonly Container borderMask;
private readonly Drawable background;
private readonly MarkerContainer markers;
private Color4 captureFinishedColour;
private readonly Vector2 startPos;
public DragContainer(Vector2 startPos)
{
this.startPos = startPos;
InternalChildren = new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding(-1),
Child = borderMask = new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
BorderColour = Color4.White,
BorderThickness = 2,
MaskingSmoothness = 1,
Child = background = new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0.1f,
AlwaysPresent = true
},
}
},
markers = new MarkerContainer
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
GetCaptureRectangle = () => trackingRectangle,
UpdateCapture = r =>
{
trackRectangle(r);
UpdateCapture();
},
FinishCapture = FinishCapture
}
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
captureFinishedColour = colours.Yellow;
}
public void Track(Vector2 position) => trackRectangle(RectangleF.FromLTRB(startPos.X, startPos.Y, position.X, position.Y));
private RectangleF trackingRectangle;
private void trackRectangle(RectangleF rectangle)
{
trackingRectangle = rectangle;
Position = new Vector2(
Math.Min(rectangle.Left, rectangle.Right),
Math.Min(rectangle.Top, rectangle.Bottom));
Size = new Vector2(
Math.Max(rectangle.Left, rectangle.Right) - Position.X,
Math.Max(rectangle.Top, rectangle.Bottom) - Position.Y);
}
private List<DrawableHitObject> capturedHitObjects = new List<DrawableHitObject>();
public IReadOnlyList<DrawableHitObject> CapturedHitObjects => capturedHitObjects;
public void UpdateCapture()
{
capturedHitObjects.Clear();
foreach (var obj in CapturableObjects)
{
if (!obj.IsAlive || !obj.IsPresent)
continue;
var objectPosition = obj.ToScreenSpace(obj.SelectionPoint);
if (ScreenSpaceDrawQuad.Contains(objectPosition))
capturedHitObjects.Add(obj);
}
}
public void FinishCapture()
{
if (CapturedHitObjects.Count == 0)
{
Hide();
return;
}
// Move the rectangle to cover the hitobjects
var topLeft = new Vector2(float.MaxValue, float.MaxValue);
var bottomRight = new Vector2(float.MinValue, float.MinValue);
foreach (var obj in capturedHitObjects)
{
topLeft = Vector2.ComponentMin(topLeft, Parent.ToLocalSpace(obj.SelectionQuad.TopLeft));
bottomRight = Vector2.ComponentMax(bottomRight, Parent.ToLocalSpace(obj.SelectionQuad.BottomRight));
}
topLeft -= new Vector2(5);
bottomRight += new Vector2(5);
this.MoveTo(topLeft, 200, Easing.OutQuint)
.ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint);
trackingRectangle = RectangleF.FromLTRB(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y);
borderMask.BorderThickness = 3;
borderMask.FadeColour(captureFinishedColour, 200);
background.Delay(50).FadeOut(200);
markers.FadeIn(200);
}
private bool isActive = true;
public override bool HandleInput => isActive;
public override void Hide()
{
isActive = false;
this.FadeOut(400, Easing.OutQuint).Expire();
}
}
public class MarkerContainer : CompositeDrawable
{
public Func<RectangleF> GetCaptureRectangle;
public Action<RectangleF> UpdateCapture;
public Action FinishCapture;
public MarkerContainer()
{
InternalChildren = new Drawable[]
{
new Marker
{
Anchor = Anchor.TopLeft,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.TopCentre,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.TopRight,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.CentreRight,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.BottomRight,
Origin = Anchor.Centre
},
new Marker
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.Centre
},
new CentreMarker
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre
}
};
InternalChildren.OfType<Marker>().ForEach(m =>
{
m.GetCaptureRectangle = () => GetCaptureRectangle();
m.UpdateCapture = r => UpdateCapture(r);
m.FinishCapture = () => FinishCapture();
});
}
}
public class Marker : CompositeDrawable
{
private const float marker_size = 10;
public Func<RectangleF> GetCaptureRectangle;
public Action<RectangleF> UpdateCapture;
public Action FinishCapture;
private Color4 normalColour;
private Color4 hoverColour;
public Marker()
{
Size = new Vector2(marker_size);
InternalChild = new CircularContainer
{
RelativeSizeAxes = Axes.Both,
Masking = true,
Child = new Box { RelativeSizeAxes = Axes.Both }
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Colour = normalColour = colours.Yellow;
hoverColour = colours.YellowDarker;
}
protected override bool OnDragStart(InputState state) => true;
protected override bool OnDrag(InputState state)
{
var currentRectangle = GetCaptureRectangle();
float left = currentRectangle.Left;
float right = currentRectangle.Right;
float top = currentRectangle.Top;
float bottom = currentRectangle.Bottom;
// Apply modifications to the capture rectangle
if ((Anchor & Anchor.y0) > 0)
top += state.Mouse.Delta.Y;
else if ((Anchor & Anchor.y2) > 0)
bottom += state.Mouse.Delta.Y;
if ((Anchor & Anchor.x0) > 0)
left += state.Mouse.Delta.X;
else if ((Anchor & Anchor.x2) > 0)
right += state.Mouse.Delta.X;
UpdateCapture(RectangleF.FromLTRB(left, top, right, bottom));
return true;
}
protected override bool OnDragEnd(InputState state)
{
FinishCapture();
return true;
}
protected override bool OnHover(InputState state)
{
this.FadeColour(hoverColour, 100);
return true;
}
protected override void OnHoverLost(InputState state)
{
this.FadeColour(normalColour, 100);
}
}
public class CentreMarker : CompositeDrawable
{
private const float marker_size = 10;
private const float line_width = 2;
public CentreMarker()
{
Size = new Vector2(marker_size);
InternalChildren = new[]
{
new Box
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = line_width
},
new Box
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
Width = line_width
},
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Colour = colours.Yellow;
}
}
}

View File

@ -310,6 +310,11 @@
<Compile Include="Overlays\Profile\Sections\Ranks\DrawableTotalScore.cs" />
<Compile Include="Overlays\Profile\Sections\Ranks\ScoreModsContainer.cs" />
<Compile Include="Overlays\Settings\SettingsButton.cs" />
<Compile Include="Rulesets\Edit\Layers\Selection\CentreMarker.cs" />
<Compile Include="Rulesets\Edit\Layers\Selection\DragSelector.cs" />
<Compile Include="Rulesets\Edit\Layers\Selection\Marker.cs" />
<Compile Include="Rulesets\Edit\Layers\Selection\MarkerContainer.cs" />
<Compile Include="Rulesets\Edit\Layers\Selection\SelectionLayer.cs" />
<Compile Include="Screens\Edit\Components\BottomBarContainer.cs" />
<Compile Include="Screens\Edit\Components\PlaybackControl.cs" />
<Compile Include="Screens\Edit\Components\TimeInfoContainer.cs" />
@ -573,7 +578,6 @@
<Compile Include="Rulesets\Edit\Tools\HitObjectCompositionTool.cs" />
<Compile Include="Rulesets\Edit\Tools\ICompositionTool.cs" />
<Compile Include="Rulesets\Edit\HitObjectComposer.cs" />
<Compile Include="Rulesets\Edit\SelectionLayer.cs" />
<Compile Include="Rulesets\Edit\ToolboxGroup.cs" />
<Compile Include="Rulesets\Judgements\DrawableJudgement.cs" />
<Compile Include="Rulesets\Judgements\Judgement.cs" />
@ -856,4 +860,4 @@
<Import Project="$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.osx.1.1.8\build\net35\SQLitePCLRaw.lib.e_sqlite3.osx.targets" Condition="Exists('$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.osx.1.1.8\build\net35\SQLitePCLRaw.lib.e_sqlite3.osx.targets')" />
<Import Project="$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.linux.1.1.8\build\net35\SQLitePCLRaw.lib.e_sqlite3.linux.targets" Condition="Exists('$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.linux.1.1.8\build\net35\SQLitePCLRaw.lib.e_sqlite3.linux.targets')" />
<Import Project="$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.v110_xp.1.1.8\build\net35\SQLitePCLRaw.lib.e_sqlite3.v110_xp.targets" Condition="Exists('$(SolutionDir)\packages\SQLitePCLRaw.lib.e_sqlite3.v110_xp.1.1.8\build\net35\SQLitePCLRaw.lib.e_sqlite3.v110_xp.targets')" />
</Project>
</Project>