mirror of
https://github.com/ppy/osu
synced 2024-12-28 09:52:56 +00:00
Split out classes and simplify construction of buttons
This commit is contained in:
parent
db1ad4243e
commit
1aff263419
@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
|
|
||||||
public TestSceneComposeSelectBox()
|
public TestSceneComposeSelectBox()
|
||||||
{
|
{
|
||||||
ComposeSelectionBox selectionBox = null;
|
SelectionBox selectionBox = null;
|
||||||
|
|
||||||
AddStep("create box", () =>
|
AddStep("create box", () =>
|
||||||
Child = selectionArea = new Container
|
Child = selectionArea = new Container
|
||||||
@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
selectionBox = new ComposeSelectionBox
|
selectionBox = new SelectionBox
|
||||||
{
|
{
|
||||||
CanRotate = true,
|
CanRotate = true,
|
||||||
CanScaleX = true,
|
CanScaleX = true,
|
||||||
|
@ -1,374 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Cursor;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Framework.Input.Events;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit.Compose.Components
|
|
||||||
{
|
|
||||||
public class ComposeSelectionBox : CompositeDrawable
|
|
||||||
{
|
|
||||||
public Action<float> OnRotation;
|
|
||||||
public Action<Vector2, Anchor> OnScale;
|
|
||||||
public Action<Direction> OnFlip;
|
|
||||||
|
|
||||||
public Action OperationStarted;
|
|
||||||
public Action OperationEnded;
|
|
||||||
|
|
||||||
private bool canRotate;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether rotation support should be enabled.
|
|
||||||
/// </summary>
|
|
||||||
public bool CanRotate
|
|
||||||
{
|
|
||||||
get => canRotate;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
canRotate = value;
|
|
||||||
recreate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool canScaleX;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether vertical scale support should be enabled.
|
|
||||||
/// </summary>
|
|
||||||
public bool CanScaleX
|
|
||||||
{
|
|
||||||
get => canScaleX;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
canScaleX = value;
|
|
||||||
recreate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool canScaleY;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether horizontal scale support should be enabled.
|
|
||||||
/// </summary>
|
|
||||||
public bool CanScaleY
|
|
||||||
{
|
|
||||||
get => canScaleY;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
canScaleY = value;
|
|
||||||
recreate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private FillFlowContainer buttons;
|
|
||||||
|
|
||||||
public const float BORDER_RADIUS = 3;
|
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private OsuColour colours { get; set; }
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
|
||||||
|
|
||||||
recreate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void recreate()
|
|
||||||
{
|
|
||||||
if (LoadState < LoadState.Loading)
|
|
||||||
return;
|
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
|
||||||
{
|
|
||||||
new Container
|
|
||||||
{
|
|
||||||
Masking = true,
|
|
||||||
BorderThickness = BORDER_RADIUS,
|
|
||||||
BorderColour = colours.YellowDark,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
|
|
||||||
AlwaysPresent = true,
|
|
||||||
Alpha = 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
buttons = new FillFlowContainer
|
|
||||||
{
|
|
||||||
Y = 20,
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Direction = FillDirection.Horizontal,
|
|
||||||
Anchor = Anchor.BottomCentre,
|
|
||||||
Origin = Anchor.Centre
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (CanScaleX) addXScaleComponents();
|
|
||||||
if (CanScaleX && CanScaleY) addFullScaleComponents();
|
|
||||||
if (CanScaleY) addYScaleComponents();
|
|
||||||
if (CanRotate) addRotationComponents();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addRotationComponents()
|
|
||||||
{
|
|
||||||
const float separation = 40;
|
|
||||||
|
|
||||||
buttons.Insert(-1, new DragHandleButton(FontAwesome.Solid.Undo, "Rotate 90 degrees counter-clockwise")
|
|
||||||
{
|
|
||||||
OperationStarted = operationStarted,
|
|
||||||
OperationEnded = operationEnded,
|
|
||||||
Action = () => OnRotation?.Invoke(-90)
|
|
||||||
});
|
|
||||||
|
|
||||||
buttons.Add(new DragHandleButton(FontAwesome.Solid.Redo, "Rotate 90 degrees clockwise")
|
|
||||||
{
|
|
||||||
OperationStarted = operationStarted,
|
|
||||||
OperationEnded = operationEnded,
|
|
||||||
Action = () => OnRotation?.Invoke(90)
|
|
||||||
});
|
|
||||||
|
|
||||||
AddRangeInternal(new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
Depth = float.MaxValue,
|
|
||||||
Colour = colours.YellowLight,
|
|
||||||
Blending = BlendingParameters.Additive,
|
|
||||||
Alpha = 0.3f,
|
|
||||||
Size = new Vector2(BORDER_RADIUS, separation),
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
},
|
|
||||||
new DragHandleButton(FontAwesome.Solid.Redo, "Free rotate")
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Y = -separation,
|
|
||||||
HandleDrag = e => OnRotation?.Invoke(e.Delta.X),
|
|
||||||
OperationStarted = operationStarted,
|
|
||||||
OperationEnded = operationEnded
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addYScaleComponents()
|
|
||||||
{
|
|
||||||
buttons.Add(new DragHandleButton(FontAwesome.Solid.ArrowsAltV, "Flip vertically")
|
|
||||||
{
|
|
||||||
OperationStarted = operationStarted,
|
|
||||||
OperationEnded = operationEnded,
|
|
||||||
Action = () => OnFlip?.Invoke(Direction.Vertical)
|
|
||||||
});
|
|
||||||
|
|
||||||
AddRangeInternal(new[]
|
|
||||||
{
|
|
||||||
createDragHandle(Anchor.TopCentre),
|
|
||||||
createDragHandle(Anchor.BottomCentre),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addFullScaleComponents()
|
|
||||||
{
|
|
||||||
AddRangeInternal(new[]
|
|
||||||
{
|
|
||||||
createDragHandle(Anchor.TopLeft),
|
|
||||||
createDragHandle(Anchor.TopRight),
|
|
||||||
createDragHandle(Anchor.BottomLeft),
|
|
||||||
createDragHandle(Anchor.BottomRight),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addXScaleComponents()
|
|
||||||
{
|
|
||||||
buttons.Add(new DragHandleButton(FontAwesome.Solid.ArrowsAltH, "Flip horizontally")
|
|
||||||
{
|
|
||||||
OperationStarted = operationStarted,
|
|
||||||
OperationEnded = operationEnded,
|
|
||||||
Action = () => OnFlip?.Invoke(Direction.Horizontal)
|
|
||||||
});
|
|
||||||
|
|
||||||
AddRangeInternal(new[]
|
|
||||||
{
|
|
||||||
createDragHandle(Anchor.CentreLeft),
|
|
||||||
createDragHandle(Anchor.CentreRight),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private DragHandle createDragHandle(Anchor anchor) =>
|
|
||||||
new DragHandle
|
|
||||||
{
|
|
||||||
Anchor = anchor,
|
|
||||||
HandleDrag = e => OnScale?.Invoke(e.Delta, anchor),
|
|
||||||
OperationStarted = operationStarted,
|
|
||||||
OperationEnded = operationEnded
|
|
||||||
};
|
|
||||||
|
|
||||||
private int activeOperations;
|
|
||||||
|
|
||||||
private void operationEnded()
|
|
||||||
{
|
|
||||||
if (--activeOperations == 0)
|
|
||||||
OperationEnded?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void operationStarted()
|
|
||||||
{
|
|
||||||
if (activeOperations++ == 0)
|
|
||||||
OperationStarted?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class DragHandleButton : DragHandle, IHasTooltip
|
|
||||||
{
|
|
||||||
private SpriteIcon icon;
|
|
||||||
|
|
||||||
private readonly IconUsage iconUsage;
|
|
||||||
|
|
||||||
public Action Action;
|
|
||||||
|
|
||||||
public DragHandleButton(IconUsage iconUsage, string tooltip)
|
|
||||||
{
|
|
||||||
this.iconUsage = iconUsage;
|
|
||||||
|
|
||||||
TooltipText = tooltip;
|
|
||||||
|
|
||||||
Anchor = Anchor.Centre;
|
|
||||||
Origin = Anchor.Centre;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
Size *= 2;
|
|
||||||
AddInternal(icon = new SpriteIcon
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Size = new Vector2(0.5f),
|
|
||||||
Icon = iconUsage,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnClick(ClickEvent e)
|
|
||||||
{
|
|
||||||
OperationStarted?.Invoke();
|
|
||||||
Action?.Invoke();
|
|
||||||
OperationEnded?.Invoke();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UpdateHoverState()
|
|
||||||
{
|
|
||||||
base.UpdateHoverState();
|
|
||||||
icon.Colour = !HandlingMouse && IsHovered ? Color4.White : Color4.Black;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string TooltipText { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DragHandle : Container
|
|
||||||
{
|
|
||||||
public Action OperationStarted;
|
|
||||||
public Action OperationEnded;
|
|
||||||
|
|
||||||
public Action<DragEvent> HandleDrag { get; set; }
|
|
||||||
|
|
||||||
private Circle circle;
|
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private OsuColour colours { get; set; }
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
Size = new Vector2(10);
|
|
||||||
Origin = Anchor.Centre;
|
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
|
||||||
{
|
|
||||||
circle = new Circle
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
UpdateHoverState();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
|
||||||
{
|
|
||||||
UpdateHoverState();
|
|
||||||
return base.OnHover(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
|
||||||
{
|
|
||||||
base.OnHoverLost(e);
|
|
||||||
UpdateHoverState();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected bool HandlingMouse;
|
|
||||||
|
|
||||||
protected override bool OnMouseDown(MouseDownEvent e)
|
|
||||||
{
|
|
||||||
HandlingMouse = true;
|
|
||||||
UpdateHoverState();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnDragStart(DragStartEvent e)
|
|
||||||
{
|
|
||||||
OperationStarted?.Invoke();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDrag(DragEvent e)
|
|
||||||
{
|
|
||||||
HandleDrag?.Invoke(e);
|
|
||||||
base.OnDrag(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDragEnd(DragEndEvent e)
|
|
||||||
{
|
|
||||||
HandlingMouse = false;
|
|
||||||
OperationEnded?.Invoke();
|
|
||||||
|
|
||||||
UpdateHoverState();
|
|
||||||
base.OnDragEnd(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnMouseUp(MouseUpEvent e)
|
|
||||||
{
|
|
||||||
HandlingMouse = false;
|
|
||||||
UpdateHoverState();
|
|
||||||
base.OnMouseUp(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void UpdateHoverState()
|
|
||||||
{
|
|
||||||
circle.Colour = HandlingMouse ? colours.GrayF : (IsHovered ? colours.Red : colours.YellowDark);
|
|
||||||
this.ScaleTo(HandlingMouse || IsHovered ? 1.5f : 1, 100, Easing.OutQuint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -45,7 +45,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
{
|
{
|
||||||
Masking = true,
|
Masking = true,
|
||||||
BorderColour = Color4.White,
|
BorderColour = Color4.White,
|
||||||
BorderThickness = ComposeSelectionBox.BORDER_RADIUS,
|
BorderThickness = SelectionBox.BORDER_RADIUS,
|
||||||
Child = new Box
|
Child = new Box
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
210
osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs
Normal file
210
osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Compose.Components
|
||||||
|
{
|
||||||
|
public class SelectionBox : CompositeDrawable
|
||||||
|
{
|
||||||
|
public Action<float> OnRotation;
|
||||||
|
public Action<Vector2, Anchor> OnScale;
|
||||||
|
public Action<Direction> OnFlip;
|
||||||
|
|
||||||
|
public Action OperationStarted;
|
||||||
|
public Action OperationEnded;
|
||||||
|
|
||||||
|
private bool canRotate;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether rotation support should be enabled.
|
||||||
|
/// </summary>
|
||||||
|
public bool CanRotate
|
||||||
|
{
|
||||||
|
get => canRotate;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
canRotate = value;
|
||||||
|
recreate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool canScaleX;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether vertical scale support should be enabled.
|
||||||
|
/// </summary>
|
||||||
|
public bool CanScaleX
|
||||||
|
{
|
||||||
|
get => canScaleX;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
canScaleX = value;
|
||||||
|
recreate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool canScaleY;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether horizontal scale support should be enabled.
|
||||||
|
/// </summary>
|
||||||
|
public bool CanScaleY
|
||||||
|
{
|
||||||
|
get => canScaleY;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
canScaleY = value;
|
||||||
|
recreate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FillFlowContainer buttons;
|
||||||
|
|
||||||
|
public const float BORDER_RADIUS = 3;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuColour colours { get; set; }
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
recreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recreate()
|
||||||
|
{
|
||||||
|
if (LoadState < LoadState.Loading)
|
||||||
|
return;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Masking = true,
|
||||||
|
BorderThickness = BORDER_RADIUS,
|
||||||
|
BorderColour = colours.YellowDark,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
|
||||||
|
AlwaysPresent = true,
|
||||||
|
Alpha = 0
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buttons = new FillFlowContainer
|
||||||
|
{
|
||||||
|
Y = 20,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (CanScaleX) addXScaleComponents();
|
||||||
|
if (CanScaleX && CanScaleY) addFullScaleComponents();
|
||||||
|
if (CanScaleY) addYScaleComponents();
|
||||||
|
if (CanRotate) addRotationComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addRotationComponents()
|
||||||
|
{
|
||||||
|
const float separation = 40;
|
||||||
|
|
||||||
|
addButton(FontAwesome.Solid.Undo, "Rotate 90 degrees counter-clockwise", () => OnRotation?.Invoke(-90));
|
||||||
|
addButton(FontAwesome.Solid.Redo, "Rotate 90 degrees clockwise", () => OnRotation?.Invoke(90));
|
||||||
|
|
||||||
|
AddRangeInternal(new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Depth = float.MaxValue,
|
||||||
|
Colour = colours.YellowLight,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Alpha = 0.3f,
|
||||||
|
Size = new Vector2(BORDER_RADIUS, separation),
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
},
|
||||||
|
new SelectionBoxDragHandleButton(FontAwesome.Solid.Redo, "Free rotate")
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Y = -separation,
|
||||||
|
HandleDrag = e => OnRotation?.Invoke(e.Delta.X),
|
||||||
|
OperationStarted = operationStarted,
|
||||||
|
OperationEnded = operationEnded
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addYScaleComponents()
|
||||||
|
{
|
||||||
|
addButton(FontAwesome.Solid.ArrowsAltV, "Flip vertically", () => OnFlip?.Invoke(Direction.Vertical));
|
||||||
|
|
||||||
|
addDragHandle(Anchor.TopCentre);
|
||||||
|
addDragHandle(Anchor.BottomCentre);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFullScaleComponents()
|
||||||
|
{
|
||||||
|
addDragHandle(Anchor.TopLeft);
|
||||||
|
addDragHandle(Anchor.TopRight);
|
||||||
|
addDragHandle(Anchor.BottomLeft);
|
||||||
|
addDragHandle(Anchor.BottomRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addXScaleComponents()
|
||||||
|
{
|
||||||
|
addButton(FontAwesome.Solid.ArrowsAltH, "Flip horizontally", () => OnFlip?.Invoke(Direction.Horizontal));
|
||||||
|
|
||||||
|
addDragHandle(Anchor.CentreLeft);
|
||||||
|
addDragHandle(Anchor.CentreRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addButton(IconUsage icon, string tooltip, Action action)
|
||||||
|
{
|
||||||
|
buttons.Add(new SelectionBoxDragHandleButton(icon, tooltip)
|
||||||
|
{
|
||||||
|
OperationStarted = operationStarted,
|
||||||
|
OperationEnded = operationEnded,
|
||||||
|
Action = action
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addDragHandle(Anchor anchor) => AddInternal(new SelectionBoxDragHandle
|
||||||
|
{
|
||||||
|
Anchor = anchor,
|
||||||
|
HandleDrag = e => OnScale?.Invoke(e.Delta, anchor),
|
||||||
|
OperationStarted = operationStarted,
|
||||||
|
OperationEnded = operationEnded
|
||||||
|
});
|
||||||
|
|
||||||
|
private int activeOperations;
|
||||||
|
|
||||||
|
private void operationEnded()
|
||||||
|
{
|
||||||
|
if (--activeOperations == 0)
|
||||||
|
OperationEnded?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void operationStarted()
|
||||||
|
{
|
||||||
|
if (activeOperations++ == 0)
|
||||||
|
OperationStarted?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Compose.Components
|
||||||
|
{
|
||||||
|
public class SelectionBoxDragHandle : Container
|
||||||
|
{
|
||||||
|
public Action OperationStarted;
|
||||||
|
public Action OperationEnded;
|
||||||
|
|
||||||
|
public Action<DragEvent> HandleDrag { get; set; }
|
||||||
|
|
||||||
|
private Circle circle;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuColour colours { get; set; }
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Size = new Vector2(10);
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
circle = new Circle
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
UpdateHoverState();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
{
|
||||||
|
UpdateHoverState();
|
||||||
|
return base.OnHover(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
|
{
|
||||||
|
base.OnHoverLost(e);
|
||||||
|
UpdateHoverState();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool HandlingMouse;
|
||||||
|
|
||||||
|
protected override bool OnMouseDown(MouseDownEvent e)
|
||||||
|
{
|
||||||
|
HandlingMouse = true;
|
||||||
|
UpdateHoverState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnDragStart(DragStartEvent e)
|
||||||
|
{
|
||||||
|
OperationStarted?.Invoke();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDrag(DragEvent e)
|
||||||
|
{
|
||||||
|
HandleDrag?.Invoke(e);
|
||||||
|
base.OnDrag(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDragEnd(DragEndEvent e)
|
||||||
|
{
|
||||||
|
HandlingMouse = false;
|
||||||
|
OperationEnded?.Invoke();
|
||||||
|
|
||||||
|
UpdateHoverState();
|
||||||
|
base.OnDragEnd(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseUp(MouseUpEvent e)
|
||||||
|
{
|
||||||
|
HandlingMouse = false;
|
||||||
|
UpdateHoverState();
|
||||||
|
base.OnMouseUp(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdateHoverState()
|
||||||
|
{
|
||||||
|
circle.Colour = HandlingMouse ? colours.GrayF : (IsHovered ? colours.Red : colours.YellowDark);
|
||||||
|
this.ScaleTo(HandlingMouse || IsHovered ? 1.5f : 1, 100, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Compose.Components
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A drag "handle" which shares the visual appearance but behaves more like a clickable button.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class SelectionBoxDragHandleButton : SelectionBoxDragHandle, IHasTooltip
|
||||||
|
{
|
||||||
|
private SpriteIcon icon;
|
||||||
|
|
||||||
|
private readonly IconUsage iconUsage;
|
||||||
|
|
||||||
|
public Action Action;
|
||||||
|
|
||||||
|
public SelectionBoxDragHandleButton(IconUsage iconUsage, string tooltip)
|
||||||
|
{
|
||||||
|
this.iconUsage = iconUsage;
|
||||||
|
|
||||||
|
TooltipText = tooltip;
|
||||||
|
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Size *= 2;
|
||||||
|
AddInternal(icon = new SpriteIcon
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Size = new Vector2(0.5f),
|
||||||
|
Icon = iconUsage,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnClick(ClickEvent e)
|
||||||
|
{
|
||||||
|
OperationStarted?.Invoke();
|
||||||
|
Action?.Invoke();
|
||||||
|
OperationEnded?.Invoke();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateHoverState()
|
||||||
|
{
|
||||||
|
base.UpdateHoverState();
|
||||||
|
icon.Colour = !HandlingMouse && IsHovered ? Color4.White : Color4.Black;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string TooltipText { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -43,7 +43,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
|
|
||||||
private OsuSpriteText selectionDetailsText;
|
private OsuSpriteText selectionDetailsText;
|
||||||
|
|
||||||
protected ComposeSelectionBox SelectionBox { get; private set; }
|
protected SelectionBox SelectionBox { get; private set; }
|
||||||
|
|
||||||
[Resolved(CanBeNull = true)]
|
[Resolved(CanBeNull = true)]
|
||||||
protected EditorBeatmap EditorBeatmap { get; private set; }
|
protected EditorBeatmap EditorBeatmap { get; private set; }
|
||||||
@ -94,8 +94,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComposeSelectionBox CreateSelectionBox()
|
public SelectionBox CreateSelectionBox()
|
||||||
=> new ComposeSelectionBox
|
=> new SelectionBox
|
||||||
{
|
{
|
||||||
OperationStarted = OnOperationBegan,
|
OperationStarted = OnOperationBegan,
|
||||||
OperationEnded = OnOperationEnded,
|
OperationEnded = OnOperationEnded,
|
||||||
|
Loading…
Reference in New Issue
Block a user