using UnityEngine;
using UnityEngine.Events;
using System.Collections.Generic;
using Lean.Common;
using FSA = UnityEngine.Serialization.FormerlySerializedAsAttribute;
namespace Lean.Touch
{
/// This component allows you to select LeanSelectable components.
/// To use it, you can call the SelectScreenPosition method from somewhere (e.g. the LeanFingerTap.OnTap event).
[HelpURL(LeanTouch.HelpUrlPrefix + "LeanSelectByFinger")]
[AddComponentMenu(LeanTouch.ComponentPathPrefix + "Select By Finger")]
public class LeanSelectByFinger : LeanSelect
{
[System.Serializable] public class LeanSelectableLeanFingerEvent : UnityEvent {}
public LeanScreenQuery ScreenQuery = new LeanScreenQuery(LeanScreenQuery.MethodType.Raycast);
/// If you enable this then any selected object will automatically be deselected if the finger used to select it is no longer touching the screen.
public bool DeselectWithFingers { set { deselectWithFingers = value; } get { return deselectWithFingers; } } [SerializeField] private bool deselectWithFingers;
/// This is invoked when an object is selected.
public LeanSelectableLeanFingerEvent OnSelectedFinger { get { if (onSelectedFinger == null) onSelectedFinger = new LeanSelectableLeanFingerEvent(); return onSelectedFinger; } } [SerializeField] private LeanSelectableLeanFingerEvent onSelectedFinger;
public static event System.Action OnAnySelectedFinger;
/// This method allows you to initiate selection at the finger's StartScreenPosition.
/// NOTE: This method be called from somewhere for this component to work (e.g. LeanFingerTap).
public void SelectStartScreenPosition(LeanFinger finger)
{
SelectScreenPosition(finger, finger.StartScreenPosition);
}
/// This method allows you to initiate selection at the finger's current ScreenPosition.
/// NOTE: This method be called from somewhere for this component to work (e.g. LeanFingerTap).
public void SelectScreenPosition(LeanFinger finger)
{
SelectScreenPosition(finger, finger.ScreenPosition);
}
/// This method allows you to initiate selection of a finger at a custom screen position.
/// NOTE: This method be called from a custom script for this component to work.
public void SelectScreenPosition(LeanFinger finger, Vector2 screenPosition)
{
var result = ScreenQuery.Query(gameObject, screenPosition);
Select(result, finger);
}
/// This method allows you to manually select an object with the specified finger using this component's selection settings.
public void Select(LeanSelectable selectable, LeanFinger finger)
{
if (TrySelect(selectable) == true)
{
var selectableByFinger = selectable as LeanSelectableByFinger;
if (selectableByFinger != null)
{
if (selectableByFinger.SelectingFingers.Contains(finger) == false)
{
selectableByFinger.SelectingFingers.Add(finger);
}
selectableByFinger.OnSelectedFinger.Invoke(finger);
LeanSelectableByFinger.InvokeAnySelectedFinger(this, selectableByFinger, finger);
if (finger.Up == true)
{
selectableByFinger.OnSelectedFingerUp.Invoke(finger);
selectableByFinger.SelectingFingers.Remove(finger);
}
}
if (onSelectedFinger != null) onSelectedFinger.Invoke(selectable, finger);
if (OnAnySelectedFinger != null) OnAnySelectedFinger.Invoke(this, selectable, finger);
}
else
{
if (finger.Up == false)
{
var selectableByFinger = selectable as LeanSelectableByFinger;
if (selectableByFinger != null)
{
if (selectableByFinger.SelectingFingers.Contains(finger) == false)
{
selectableByFinger.SelectingFingers.Add(finger);
}
}
}
}
}
protected virtual void Update()
{
if (deselectWithFingers == true && selectables != null)
{
for (var i = selectables.Count - 1; i >= 0; i--)
{
var selectable = selectables[i];
if (ShouldRemoveSelectable(selectable) == true)
{
Deselect(selectable);
}
}
}
}
private bool ShouldRemoveSelectable(LeanSelectable selectable)
{
var selectableByFinger = selectable as LeanSelectableByFinger;
if (selectableByFinger != null)
{
foreach (var finger in selectableByFinger.SelectingFingers)
{
if (finger.Up == false)
{
return false;
}
}
}
return true;
}
/// This allows you to replace the currently selected objects with the ones in the specified list. This is useful if you're doing box selection or switching selection groups.
public void ReplaceSelection(List newSelectables, LeanFinger finger)
{
if (newSelectables != null)
{
// Deselect missing selectables
if (selectables != null)
{
for (var i = selectables.Count - 1; i >= 0; i--)
{
var selectable = selectables[i];
if (newSelectables.Contains(selectable) == false)
{
Deselect(selectable);
}
}
}
// Select new selectables
foreach (var selectable in newSelectables)
{
if (selectables == null || selectables.Contains(selectable) == false)
{
var selectableByFinger = selectable as LeanSelectableByFinger;
if (selectableByFinger != null)
{
Select(selectableByFinger, finger);
}
else
{
Select(selectable);
}
}
}
}
else
{
DeselectAll();
}
}
}
}
#if UNITY_EDITOR
namespace Lean.Touch.Editor
{
using TARGET = LeanSelectByFinger;
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(TARGET))]
public class LeanSelectByFinger_Editor : Common.Editor.LeanSelect_Editor
{
[System.NonSerialized] TARGET tgt; [System.NonSerialized] TARGET[] tgts;
protected override void OnInspector()
{
GetTargets(out tgt, out tgts);
Draw("ScreenQuery");
Draw("deselectWithFingers", "If you enable this then any selected object will automatically be deselected if the finger used to select it is no longer touching the screen.");
base.OnInspector();
}
protected override void DrawEvents(bool showUnusedEvents)
{
base.DrawEvents(showUnusedEvents);
if (Any(tgts, t => t.OnSelectedFinger.GetPersistentEventCount() > 0) == true || showUnusedEvents == true)
{
Draw("onSelectedFinger");
}
}
}
}
#endif