/// <summary> /// Attempts to process any other valid snappable objects against any other potential SnapZones if their primary activating zone is snapped by another object. /// </summary> public virtual void ProcessOtherSnappablesOnSnap() { foreach (GameObject snappable in SnappableInteractables) { if (snappable == null || snappable == SnappedInteractable) { continue; } InteractableFacade snappableInteractable = snappable.TryGetComponent <InteractableFacade>(true, true); if (snappableInteractable == null) { continue; } foreach (GameObject collidingWith in snappableInteractable.ActiveCollisions.SubscribableElements) { SnapZoneActivator activatingZone = collidingWith.GetComponent <SnapZoneActivator>(); if (activatingZone == null || activatingZone == ActivationArea || activatingZone.Facade.ZoneState == SnapZoneFacade.SnapZoneState.ZoneIsActivated) { continue; } activatingZone.Facade.Configuration.GrabStateEmitter.DoIsGrabbed(snappableInteractable); } } }
/// <summary> /// Attempts activate this SnapZone with the given <see cref="GameObject"/>. /// </summary> /// <param name="activator">The colliding interactable.</param> /// <param name="activatingZone">The SnapZone that was previously being activated by the colliding interactable.</param> protected virtual void AttemptReactivation(GameObject activator, SnapZoneActivator activatingZone) { activator.TryGetComponent <InteractableFacade>(true, true).ActiveCollisions.Remove(activatingZone.Facade.Configuration.ActivationArea.gameObject); ListenerKey listenerKey = new ListenerKey(activator, activatingZone); activatingZoneListeners.TryGetValue(listenerKey, out UnityAction <GameObject> activatingZoneListener); if (activatingZoneListener != null) { activatingZone.Facade.Exited.RemoveListener(activatingZoneListener); } activatingZoneListeners.Remove(listenerKey); Activate(activator); }
/// <summary> /// Cancels the attempt to activate the SnapZone upon the previous activating SnapZone becoming deactivated. /// </summary> /// <param name="activator">The colliding interactable.</param> /// <param name="activatingZone">The SnapZone that was previously being activated by the colliding interactable.</param> protected virtual void CancelAttemptReactivation(GameObject activator, SnapZoneActivator activatingZone) { ListenerKey listenerKey = new ListenerKey(activator, activatingZone); activatingZoneListeners.TryGetValue(listenerKey, out UnityAction <GameObject> onExitActivatingZoneListener); if (onExitActivatingZoneListener != null) { activatingZone.Facade.Exited.RemoveListener(onExitActivatingZoneListener); activatingZoneListeners.Remove(listenerKey); } currentZoneListeners.TryGetValue(listenerKey, out UnityAction <GameObject> onExitCurrentZoneListener); if (onExitCurrentZoneListener != null) { Facade.Exited.RemoveListener(onExitCurrentZoneListener); currentZoneListeners.Remove(listenerKey); } }
/// <summary> /// Attempts to activate the SnapZone if the colliding <see cref="GameObject"/> is not already activating another SnapZone. /// </summary> /// <param name="activator">The colliding interactable.</param> public virtual void Activate(GameObject activator) { IsActivated = false; TrySetInteractableFacade(activator); if (currentActivatingInteractable == null || Facade.Configuration.ActivationArea == null || !Facade.Configuration.CollidingObjectsList.Contains(currentActivatingInteractable.gameObject)) { return; } currentActivatingInteractable.ActiveCollisions.AddUnique(Facade.Configuration.ActivationArea.gameObject); invalidSnapZoneCollisions.Clear(); foreach (GameObject collidingObject in currentActivatingInteractable.ActiveCollisions.SubscribableElements) { if (collidingObject == null) { continue; } SnapZoneActivator activatingZone = collidingObject.GetComponent <SnapZoneActivator>(); if (activatingZone == null) { continue; } if (!activatingZone.Facade.Configuration.CollidingObjectsList.Contains(currentActivatingInteractable.gameObject)) { invalidSnapZoneCollisions.Add(activatingZone.Facade.Configuration.ActivationArea.gameObject); continue; } if (activatingZone == Facade.Configuration.ActivationArea) { if (!IsActivated) { Facade.Configuration.EmitActivated(activator); } IsActivated = true; Validated?.Invoke(activator); ClearInvalidSnapZoneCollisions(currentActivatingInteractable, ref invalidSnapZoneCollisions); break; } else { ListenerKey listenerKey = new ListenerKey(activator, activatingZone); if (!activatingZoneListeners.ContainsKey(listenerKey)) { UnityAction <GameObject> onExitActivatingZoneListener = activatingInteractable => AttemptReactivation(activatingInteractable, activatingZone); activatingZone.Facade.Exited.AddListener(onExitActivatingZoneListener); activatingZoneListeners.Add(listenerKey, onExitActivatingZoneListener); } if (!currentZoneListeners.ContainsKey(listenerKey)) { UnityAction <GameObject> onExitCurrentZoneListener = activatingInteractable => CancelAttemptReactivation(activatingInteractable, activatingZone); Facade.Exited.AddListener(onExitCurrentZoneListener); currentZoneListeners.Add(listenerKey, onExitCurrentZoneListener); } ClearInvalidSnapZoneCollisions(currentActivatingInteractable, ref invalidSnapZoneCollisions); break; } } ClearInvalidSnapZoneCollisions(currentActivatingInteractable, ref invalidSnapZoneCollisions); }
public ListenerKey(GameObject interactable, SnapZoneActivator zone) { this.interactable = interactable; this.zone = zone; }