/Assets/LeapMotion/Modules/InteractionEngine/Scripts/UI/Anchors/Anchor.cs
https://bitbucket.org/jonathondhartunisa/firstpersonsquared · C# · 238 lines · 152 code · 56 blank · 30 comment · 15 complexity · 23c53ea611a8f4c30089924674c41f92 MD5 · raw file
- /******************************************************************************
- * Copyright (C) Leap Motion, Inc. 2011-2017. *
- * Leap Motion proprietary and confidential. *
- * *
- * Use subject to the terms of the Leap Motion SDK Agreement available at *
- * https://developer.leapmotion.com/sdk_agreement, or another agreement *
- * between Leap Motion and you, your company or other organization. *
- ******************************************************************************/
- using Leap.Unity.Attributes;
- using Leap.Unity.RuntimeGizmos;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Events;
- namespace Leap.Unity.Interaction {
- public class Anchor : MonoBehaviour {
- private static HashSet<Anchor> _allAnchors;
- public static HashSet<Anchor> allAnchors {
- get {
- if (_allAnchors == null) {
- _allAnchors = new HashSet<Anchor>();
- }
- return _allAnchors;
- }
- }
- [Tooltip("Should this anchor allow multiple objects to be attached to it at the same time? "
- + "This property is enforced by AnchorGroups and AnchorableBehaviours.")]
- public bool allowMultipleObjects = false;
- [Tooltip("Should this anchor attempt to enable and disable the GameObjects of attached "
- + "AnchorableBehaviours when its own active state changes? If this setting is enabled, "
- + "the Anchor will deactivate the attached objects when its own GameObject is deactivated "
- + "or if its script is disabled, and similarly for becoming active or enabled.")]
- public bool matchActiveStateWithAttachedObjects = false;
- private HashSet<AnchorGroup> _groups = new HashSet<AnchorGroup>();
- public HashSet<AnchorGroup> groups { get { return _groups; } }
- private HashSet<AnchorableBehaviour> _preferringAnchorables = new HashSet<AnchorableBehaviour>();
- private HashSet<AnchorableBehaviour> _anchoredObjects = new HashSet<AnchorableBehaviour>();
- /// <summary>
- /// Gets the set of AnchorableBehaviours currently attached to this anchor.
- /// </summary>
- public HashSet<AnchorableBehaviour> anchoredObjects { get { return _anchoredObjects; } }
- public bool isPreferred { get { return _preferringAnchorables.Count > 0; } }
- public bool hasAnchoredObjects { get { return _anchoredObjects.Count > 0; } }
- #region Events
- /// <summary>
- /// Called as soon as any anchorable objects prefer this anchor if they were to try to
- /// attach to an anchor.
- /// </summary>
- public Action OnAnchorPreferred = () => { };
- /// <summary>
- /// Called when no anchorable objects prefer this anchor any more.
- /// </summary>
- public Action OnAnchorNotPreferred = () => { };
- /// <summary>
- /// Called every Update() that an AnchorableBehaviour prefers this anchor.
- /// </summary>
- public Action WhileAnchorPreferred = () => { };
- /// <summary>
- /// Called as soon as any anchorables become attached to this anchor.
- /// </summary>
- public Action OnAnchorablesAttached = () => { };
- /// <summary>
- /// Called when there are no anchorables attached to this anchor.
- /// </summary>
- public Action OnNoAnchorablesAttached = () => { };
- /// <summary>
- /// Called every Update() that one or more AnchorableBehaviours is attached to this anchor.
- /// </summary>
- public Action WhileAnchorablesAttached = () => { };
- #endregion
- void Awake() {
- allAnchors.Add(this);
- }
- void OnEnable() {
- if (matchActiveStateWithAttachedObjects) {
- foreach (var anchObj in _anchoredObjects) {
- anchObj.gameObject.SetActive(true);
- }
- }
- }
- void Start() {
- initUnityEvents();
- }
- void Update() {
- updateAnchorCallbacks();
- }
- void OnAnchorDisabled() {
- if (matchActiveStateWithAttachedObjects) {
- foreach (var anchObj in _anchoredObjects) {
- anchObj.gameObject.SetActive(false);
- }
- }
- }
- void OnDestroy() {
- foreach (var group in groups) {
- group.Remove(this);
- }
- allAnchors.Remove(this);
- }
- #region Anchor Callbacks
- public void NotifyAttached(AnchorableBehaviour anchObj) {
- _anchoredObjects.Add(anchObj);
- if (_anchoredObjects.Count == 1) {
- OnAnchorablesAttached();
- }
- }
- public void NotifyDetached(AnchorableBehaviour anchObj) {
- _anchoredObjects.Remove(anchObj);
- if (_anchoredObjects.Count == 0) {
- OnNoAnchorablesAttached();
- }
- }
- private void updateAnchorCallbacks() {
- WhileAnchorPreferred();
- WhileAnchorablesAttached();
- }
- public void NotifyAnchorPreference(AnchorableBehaviour anchObj) {
- _preferringAnchorables.Add(anchObj);
- if (_preferringAnchorables.Count == 1) {
- OnAnchorPreferred();
- }
- }
- public void NotifyEndAnchorPreference(AnchorableBehaviour anchObj) {
- _preferringAnchorables.Remove(anchObj);
- if (_preferringAnchorables.Count == 0) {
- OnAnchorNotPreferred();
- }
- }
- #endregion
- #region Gizmos
- public static Color AnchorGizmoColor = new Color(0.6F, 0.2F, 0.8F);
- void OnDrawGizmosSelected() {
- Matrix4x4 origMatrix = Gizmos.matrix;
- Gizmos.matrix = this.transform.localToWorldMatrix;
- Gizmos.color = AnchorGizmoColor;
- float radius = 0.015F;
- drawWireSphereGizmo(Vector3.zero, radius);
- drawSphereCirclesGizmo(5, Vector3.zero, radius, Vector3.forward);
- Gizmos.matrix = origMatrix;
- }
- private static Vector3[] worldDirs = new Vector3[] { Vector3.right, Vector3.up, Vector3.forward };
- private void drawWireSphereGizmo(Vector3 pos, float radius) {
- foreach (var dir in worldDirs) {
- if (dir == Vector3.forward) continue;
- Utils.DrawCircle(pos, dir, radius, AnchorGizmoColor, quality: 24, depthTest: true);
- }
- }
- private void drawSphereCirclesGizmo(int numCircles, Vector3 pos, float radius, Vector3 poleDir) {
- float dTheta = 180F / numCircles;
- float halfTheta = dTheta / 2F;
- for (int i = 0; i < numCircles; i++) {
- float curTheta = (dTheta * i) + halfTheta;
- Utils.DrawCircle(pos + poleDir * Mathf.Cos(curTheta * Mathf.Deg2Rad) * radius, poleDir, Mathf.Sin(curTheta * Mathf.Deg2Rad) * radius, AnchorGizmoColor, quality: 16, depthTest: true);
- }
- }
- #endregion
- #region Unity Events (Internal)
- [SerializeField]
- private EnumEventTable _eventTable;
- public enum EventType {
- OnAnchorPreferred = 100,
- OnAnchorNotPreferred = 110,
- WhileAnchorPreferred = 120,
- OnAnchorablesAttached = 130,
- OnNoAnchorablesAttached = 140,
- WhileAnchorablesAttached = 150,
- }
- private void initUnityEvents() {
- setupCallback(ref OnAnchorPreferred, EventType.OnAnchorPreferred);
- setupCallback(ref OnAnchorNotPreferred, EventType.OnAnchorNotPreferred);
- setupCallback(ref WhileAnchorPreferred, EventType.WhileAnchorPreferred);
- setupCallback(ref OnAnchorablesAttached, EventType.OnAnchorablesAttached);
- setupCallback(ref OnNoAnchorablesAttached, EventType.OnNoAnchorablesAttached);
- setupCallback(ref WhileAnchorablesAttached, EventType.WhileAnchorablesAttached);
- }
- private void setupCallback(ref Action action, EventType type) {
- action += () => _eventTable.Invoke((int)type);
- }
- #endregion
- }
- }