2020-01-20 15:53:59 +00:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2019-01-24 08:43:03 +00:00
// See the LICENCE file in the repository root for full licence text.
2018-04-13 09:19:50 +00:00
2022-06-17 07:37:17 +00:00
#nullable disable
2018-03-29 13:06:45 +00:00
using System ;
2023-01-23 05:13:46 +00:00
using System.Linq ;
2023-10-30 06:10:10 +00:00
using JetBrains.Annotations ;
2018-04-04 11:44:07 +00:00
using osu.Framework ;
2018-10-25 09:16:25 +00:00
using osu.Framework.Graphics ;
2018-02-20 09:01:45 +00:00
using osu.Framework.Graphics.Containers ;
2018-03-29 13:06:45 +00:00
using osu.Framework.Graphics.Primitives ;
2019-11-12 04:38:42 +00:00
using osu.Framework.Graphics.UserInterface ;
2018-05-11 01:48:07 +00:00
using osu.Game.Graphics.UserInterface ;
2018-11-20 07:51:59 +00:00
using osuTK ;
2018-04-13 09:19:50 +00:00
2018-03-14 06:18:21 +00:00
namespace osu.Game.Rulesets.Edit
2018-02-20 09:01:45 +00:00
{
2018-03-14 06:18:21 +00:00
/// <summary>
2021-04-27 09:33:47 +00:00
/// A blueprint placed above a displaying item adding editing functionality.
2018-03-14 06:18:21 +00:00
/// </summary>
2021-04-27 06:40:35 +00:00
public abstract partial class SelectionBlueprint < T > : CompositeDrawable , IStateful < SelectionState >
2018-02-20 09:01:45 +00:00
{
2021-04-27 06:40:35 +00:00
public readonly T Item ;
2020-01-20 15:53:59 +00:00
2018-03-29 13:27:14 +00:00
/// <summary>
2021-04-27 06:40:35 +00:00
/// Invoked when this <see cref="SelectionBlueprint{T}"/> has been selected.
2018-03-29 13:27:14 +00:00
/// </summary>
2021-04-27 06:40:35 +00:00
public event Action < SelectionBlueprint < T > > Selected ;
2018-04-13 09:19:50 +00:00
2018-03-29 13:27:14 +00:00
/// <summary>
2021-04-27 06:40:35 +00:00
/// Invoked when this <see cref="SelectionBlueprint{T}"/> has been deselected.
2018-03-29 13:27:14 +00:00
/// </summary>
2021-04-27 06:40:35 +00:00
public event Action < SelectionBlueprint < T > > Deselected ;
2018-04-13 09:19:50 +00:00
2023-07-25 09:13:35 +00:00
public override bool HandlePositionalInput = > IsSelectable ;
2018-04-04 10:51:56 +00:00
public override bool RemoveWhenNotAlive = > false ;
2018-04-13 09:19:50 +00:00
2021-04-27 06:40:35 +00:00
protected SelectionBlueprint ( T item )
2018-02-20 09:01:45 +00:00
{
2021-04-27 06:40:35 +00:00
Item = item ;
2020-01-24 08:51:24 +00:00
2018-10-25 09:16:25 +00:00
RelativeSizeAxes = Axes . Both ;
2020-01-24 08:51:24 +00:00
AlwaysPresent = true ;
2020-01-21 08:36:21 +00:00
}
2018-10-25 09:16:25 +00:00
2020-01-24 08:51:24 +00:00
protected override void LoadComplete ( )
2020-01-21 08:36:21 +00:00
{
2020-01-24 08:51:24 +00:00
base . LoadComplete ( ) ;
updateState ( ) ;
2018-04-04 11:44:07 +00:00
}
2018-04-13 09:19:50 +00:00
2018-04-04 11:44:07 +00:00
private SelectionState state ;
2018-04-13 09:19:50 +00:00
2023-10-30 06:10:10 +00:00
[CanBeNull]
2018-04-04 11:44:07 +00:00
public event Action < SelectionState > StateChanged ;
2018-04-13 09:19:50 +00:00
2018-04-04 11:44:07 +00:00
public SelectionState State
{
get = > state ;
set
{
2019-04-25 08:36:17 +00:00
if ( state = = value )
return ;
2018-04-13 09:19:50 +00:00
2018-04-04 11:44:07 +00:00
state = value ;
2019-04-01 03:16:05 +00:00
2020-01-24 08:51:24 +00:00
if ( IsLoaded )
updateState ( ) ;
2019-04-25 08:36:17 +00:00
StateChanged ? . Invoke ( state ) ;
2018-04-04 11:44:07 +00:00
}
2018-03-09 14:12:34 +00:00
}
2018-04-13 09:19:50 +00:00
2020-01-24 08:51:24 +00:00
private void updateState ( )
{
switch ( state )
{
case SelectionState . Selected :
OnSelected ( ) ;
Selected ? . Invoke ( this ) ;
break ;
case SelectionState . NotSelected :
OnDeselected ( ) ;
Deselected ? . Invoke ( this ) ;
break ;
}
}
2020-10-09 05:03:13 +00:00
protected virtual void OnDeselected ( )
{
2021-04-27 09:33:47 +00:00
// selection blueprints are AlwaysPresent while the related item is visible
2020-10-09 05:03:13 +00:00
// set the body piece's alpha directly to avoid arbitrarily rendering frame buffers etc. of children.
foreach ( var d in InternalChildren )
d . Hide ( ) ;
}
2020-01-21 05:21:00 +00:00
2020-10-09 05:03:13 +00:00
protected virtual void OnSelected ( )
{
foreach ( var d in InternalChildren )
d . Show ( ) ;
}
2020-01-21 05:21:00 +00:00
2019-11-05 02:33:37 +00:00
// When not selected, input is only required for the blueprint itself to receive IsHovering
protected override bool ShouldBeConsideredForInput ( Drawable child ) = > State = = SelectionState . Selected ;
2018-03-29 13:06:45 +00:00
/// <summary>
2021-05-18 04:11:58 +00:00
/// Selects this <see cref="SelectionBlueprint{T}"/>, causing it to become visible.
2018-03-29 13:06:45 +00:00
/// </summary>
2018-04-04 11:44:07 +00:00
public void Select ( ) = > State = SelectionState . Selected ;
2018-04-13 09:19:50 +00:00
2018-04-04 11:44:07 +00:00
/// <summary>
2021-05-13 10:53:32 +00:00
/// Deselects this <see cref="HitObjectSelectionBlueprint"/>, causing it to become invisible.
2018-04-04 11:44:07 +00:00
/// </summary>
public void Deselect ( ) = > State = SelectionState . NotSelected ;
2018-04-13 09:19:50 +00:00
2020-10-26 21:16:28 +00:00
/// <summary>
2021-05-13 10:53:32 +00:00
/// Toggles the selection state of this <see cref="HitObjectSelectionBlueprint"/>.
2020-10-26 21:16:28 +00:00
/// </summary>
public void ToggleSelection ( ) = > State = IsSelected ? SelectionState . NotSelected : SelectionState . Selected ;
2018-04-04 11:44:07 +00:00
public bool IsSelected = > State = = SelectionState . Selected ;
2018-04-13 09:19:50 +00:00
2019-11-12 04:38:42 +00:00
/// <summary>
2021-05-13 10:53:32 +00:00
/// The <see cref="MenuItem"/>s to be displayed in the context menu for this <see cref="HitObjectSelectionBlueprint"/>.
2019-11-12 04:38:42 +00:00
/// </summary>
public virtual MenuItem [ ] ContextMenuItems = > Array . Empty < MenuItem > ( ) ;
2023-07-25 09:13:35 +00:00
/// <summary>
/// Whether the <see cref="SelectionBlueprint{T}"/> can be currently selected via a click or a drag box.
/// </summary>
public virtual bool IsSelectable = > ShouldBeAlive & & IsPresent ;
2018-03-29 13:06:45 +00:00
/// <summary>
2023-01-18 20:34:23 +00:00
/// The screen-space main point that causes this <see cref="HitObjectSelectionBlueprint"/> to be selected via a drag.
2018-03-29 13:06:45 +00:00
/// </summary>
2020-05-20 08:48:43 +00:00
public virtual Vector2 ScreenSpaceSelectionPoint = > ScreenSpaceDrawQuad . Centre ;
2018-04-13 09:19:50 +00:00
2023-01-23 05:13:46 +00:00
/// <summary>
/// Any points that should be used for snapping purposes in addition to <see cref="ScreenSpaceSelectionPoint"/>. Exposed via <see cref="ScreenSpaceSnapPoints"/>.
/// </summary>
protected virtual Vector2 [ ] ScreenSpaceAdditionalNodes = > Array . Empty < Vector2 > ( ) ;
2023-01-10 20:20:09 +00:00
/// <summary>
2023-01-23 20:22:18 +00:00
/// The screen-space collection of base points on this <see cref="HitObjectSelectionBlueprint"/> that other objects can be snapped to.
2023-01-18 20:34:23 +00:00
/// The first element of this collection is <see cref="ScreenSpaceSelectionPoint"/>
2023-01-10 20:20:09 +00:00
/// </summary>
2023-01-23 05:13:46 +00:00
public Vector2 [ ] ScreenSpaceSnapPoints = > ScreenSpaceAdditionalNodes . Prepend ( ScreenSpaceSelectionPoint ) . ToArray ( ) ;
2023-01-10 20:20:09 +00:00
2018-03-29 13:06:45 +00:00
/// <summary>
2021-05-13 10:53:32 +00:00
/// The screen-space quad that outlines this <see cref="HitObjectSelectionBlueprint"/> for selections.
2018-03-29 13:06:45 +00:00
/// </summary>
2020-01-20 15:53:59 +00:00
public virtual Quad SelectionQuad = > ScreenSpaceDrawQuad ;
2020-01-21 08:36:21 +00:00
2020-11-03 11:45:48 +00:00
/// <summary>
/// Handle to perform a partial deletion when the user requests a quick delete (Shift+Right Click).
/// </summary>
/// <returns>True if the deletion operation was handled by this blueprint. Returning false will delete the full blueprint.</returns>
public virtual bool HandleQuickDeletion ( ) = > false ;
2018-02-20 09:01:45 +00:00
}
}