// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using osu.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; namespace osu.Game.Rulesets.Edit { /// /// A blueprint placed above a adding editing functionality. /// public class SelectionBlueprint : CompositeDrawable, IStateful { /// /// Invoked when this has been selected. /// public event Action Selected; /// /// Invoked when this has been deselected. /// public event Action Deselected; /// /// Invoked when this has requested selection. /// Will fire even if already selected. Does not actually perform selection. /// public event Action SelectionRequested; /// /// Invoked when this has requested drag. /// public event Action DragRequested; /// /// The which this applies to. /// public readonly DrawableHitObject HitObject; protected override bool ShouldBeAlive => HitObject.IsAlive && HitObject.IsPresent || State == SelectionState.Selected; public override bool HandlePositionalInput => ShouldBeAlive; public override bool RemoveWhenNotAlive => false; public SelectionBlueprint(DrawableHitObject hitObject) { HitObject = hitObject; RelativeSizeAxes = Axes.Both; AlwaysPresent = true; Alpha = 0; } private SelectionState state; public event Action StateChanged; public SelectionState State { get => state; set { if (state == value) return; state = value; switch (state) { case SelectionState.Selected: Show(); Selected?.Invoke(this); break; case SelectionState.NotSelected: Hide(); Deselected?.Invoke(this); break; } } } /// /// Selects this , causing it to become visible. /// public void Select() => State = SelectionState.Selected; /// /// Deselects this , causing it to become invisible. /// public void Deselect() => State = SelectionState.NotSelected; public bool IsSelected => State == SelectionState.Selected; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => HitObject.ReceivePositionalInputAt(screenSpacePos); private bool selectionRequested; protected override bool OnMouseDown(MouseDownEvent e) { selectionRequested = false; if (State == SelectionState.NotSelected) { SelectionRequested?.Invoke(this, e.CurrentState); selectionRequested = true; } return IsSelected; } protected override bool OnClick(ClickEvent e) { if (State == SelectionState.Selected && !selectionRequested) { selectionRequested = true; SelectionRequested?.Invoke(this, e.CurrentState); return true; } return base.OnClick(e); } protected override bool OnDragStart(DragStartEvent e) => true; protected override bool OnDrag(DragEvent e) { DragRequested?.Invoke(this, e.Delta, e.CurrentState); return true; } /// /// The screen-space point that causes this to be selected. /// public virtual Vector2 SelectionPoint => HitObject.ScreenSpaceDrawQuad.Centre; /// /// The screen-space quad that outlines this for selections. /// public virtual Quad SelectionQuad => HitObject.ScreenSpaceDrawQuad; } }