using UnityEngine; using UnityEngine.Events; using FSA = UnityEngine.Serialization.FormerlySerializedAsAttribute; namespace Lean.Common { /// This component allows you to detect when a specific amount of selectable objects in the scene have been selected. [HelpURL(LeanHelper.PlusHelpUrlPrefix + "LeanSelectedCount")] [AddComponentMenu(LeanHelper.ComponentPathPrefix + "Selected Count")] public class LeanSelectedCount : MonoBehaviour { [System.Serializable] public class IntEvent : UnityEvent {} /// When the amount of selected objects changes, this event is invoked with the current count. public IntEvent OnCount { get { if (onCount == null) onCount = new IntEvent(); return onCount; } } [SerializeField] private IntEvent onCount; /// The minimum amount of objects that must be selected for a match. /// -1 = Max. public int MatchMin { set { matchMin = value; } get { return matchMin; } } [FSA("MatchMin")] [SerializeField] private int matchMin = -1; /// The maximum amount of objects that can be selected for a match. /// -1 = Max. public int MatchMax { set { matchMax = value; } get { return matchMax; } } [FSA("MatchMax")] [SerializeField] private int matchMax = -1; /// When the amount of selected objects matches the RequiredCount, this event will be invoked. public UnityEvent OnMatch { get { if (onMatch == null) onMatch = new UnityEvent(); return onMatch; } } [SerializeField] private UnityEvent onMatch; /// When the amount of selected objects no longer matches the RequiredCount, this event will be invoked. public UnityEvent OnUnmatch { get { if (onUnmatch == null) onUnmatch = new UnityEvent(); return onUnmatch; } } [SerializeField] private UnityEvent onUnmatch; [SerializeField] private bool inside; protected virtual void OnEnable() { LeanSelectable.OnAnySelected += HandleAnyA; LeanSelectable.OnAnyDeselected += HandleAnyA; LeanSelectable.OnAnyEnabled += HandleAnyB; LeanSelectable.OnAnyDisabled += HandleAnyB; } protected virtual void OnDisable() { LeanSelectable.OnAnySelected -= HandleAnyA; LeanSelectable.OnAnyEnabled -= HandleAnyB; LeanSelectable.OnAnyDisabled -= HandleAnyB; } private void HandleAnyA(LeanSelect select, LeanSelectable selectable) { UpdateState(); } private void HandleAnyB(LeanSelectable selectable) { UpdateState(); } private void UpdateState() { var min = matchMin >= 0 ? matchMin : LeanSelectable.Instances.Count; var max = matchMax >= 0 ? matchMax : LeanSelectable.Instances.Count; var raw = LeanSelectable.IsSelectedCount; var newInside = raw >= min && raw <= max; if (newInside != inside) { inside = newInside; if (inside == true) { if (onMatch != null) { onMatch.Invoke(); } } else { if (onUnmatch != null) { onUnmatch.Invoke(); } } } } } } #if UNITY_EDITOR namespace Lean.Common.Editor { using TARGET = LeanSelectedCount; [UnityEditor.CanEditMultipleObjects] [UnityEditor.CustomEditor(typeof(TARGET))] public class LeanSelectedCount_Editor : LeanEditor { protected override void OnInspector() { TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts); var usedA = Any(tgts, t => t.OnCount.GetPersistentEventCount() > 0); var usedB = Any(tgts, t => t.OnMatch.GetPersistentEventCount() > 0); var usedC = Any(tgts, t => t.OnUnmatch.GetPersistentEventCount() > 0); var showUnusedEvents = DrawFoldout("Show Unused Events", "Show all events?"); if (usedA == true || showUnusedEvents == true) { Draw("onCount"); } if (usedB == true || usedC == true || showUnusedEvents == true) { Draw("matchMin", "The minimum amount of objects that must be selected for a match.\n\n-1 = Max."); Draw("matchMax", "The maximum amount of objects that can be selected for a match.\n\n-1 = Max."); } if (usedB == true || showUnusedEvents == true) { Draw("onMatch"); } if (usedC == true || showUnusedEvents == true) { Draw("onUnmatch"); } } } } #endif