diff --git a/Assets/External/Pixelplacement.meta b/Assets/External/Pixelplacement.meta
new file mode 100644
index 00000000..3f3c5336
--- /dev/null
+++ b/Assets/External/Pixelplacement.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1c36c8454fb32e644b5d77397aabcdb4
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/External/Pixelplacement/Surge.meta b/Assets/External/Pixelplacement/Surge.meta
new file mode 100644
index 00000000..8cc0b881
--- /dev/null
+++ b/Assets/External/Pixelplacement/Surge.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 02046d5fdbe21b6438050c1580fc45dc
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/External/Pixelplacement/Surge/Chooser.meta b/Assets/External/Pixelplacement/Surge/Chooser.meta
new file mode 100644
index 00000000..5aa00495
--- /dev/null
+++ b/Assets/External/Pixelplacement/Surge/Chooser.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: dfe31349ba782e74790b285d1a724204
+folderAsset: yes
+timeCreated: 1521832879
+licenseType: Store
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/External/Pixelplacement/Surge/Chooser/Chooser.cs b/Assets/External/Pixelplacement/Surge/Chooser/Chooser.cs
new file mode 100644
index 00000000..08c675a9
--- /dev/null
+++ b/Assets/External/Pixelplacement/Surge/Chooser/Chooser.cs
@@ -0,0 +1,412 @@
+///
+/// SURGE FRAMEWORK
+/// Author: Bob Berkebile
+/// Email: bobb@pixelplacement.com
+///
+/// Simplify the act of selecting and interacting with things.
+///
+///
+
+#pragma warning disable 0649
+
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Events;
+
+namespace Pixelplacement
+{
+ public class Chooser : MonoBehaviour
+ {
+ //Public Events:
+ public GameObjectEvent OnSelected;
+ public GameObjectEvent OnDeselected;
+ public GameObjectEvent OnPressed;
+ public GameObjectEvent OnReleased;
+
+ //Public Enums:
+ public enum Method { Raycast, RaycastAll };
+
+ //Public Variables:
+ public bool _cursorPropertiesFolded;
+ public bool _unityEventsFolded;
+ public Transform source;
+ public float raycastDistance = 3;
+ public LayerMask layermask = -1;
+ public KeyCode[] pressedInput;
+ public Transform cursor;
+ public float surfaceOffset;
+ public float idleDistance = 3f;
+ public float stabilityDelta = 0.0127f;
+ public float snapDelta = 1;
+ public float stableSpeed = 2;
+ public float unstableSpeed = 20;
+ public bool flipForward;
+ public bool matchSurfaceNormal = true;
+ public bool autoHide;
+ public bool cursorHidden;
+ public bool flipCastDirection;
+ public LineRenderer lineRenderer;
+
+ //Public Properties:
+ public Transform[] Current
+ {
+ get
+ {
+ return _current.ToArray();
+ }
+ }
+
+ public bool IsHitting
+ {
+ get;
+ private set;
+ }
+
+ //Private Variables:
+ [SerializeField] Method _method;
+ [SerializeField] bool _debugView = false;
+ Transform _previousCursor;
+ List _current = new List();
+ List _previous = new List();
+ Transform _currentRaycast;
+ Transform _previousRaycast;
+ Vector3 _targetPosition;
+ bool _hidden;
+
+ //Init:
+ private void Reset()
+ {
+ source = transform;
+ pressedInput = new KeyCode[] { KeyCode.Mouse0 };
+ }
+
+ //Flow:
+ private void OnEnable()
+ {
+ if (source == null)
+ {
+ source = transform;
+ }
+
+ if (cursor != null)
+ {
+ cursor.position = source.position;
+ cursor.gameObject.SetActive(true);
+ }
+ if (lineRenderer != null)
+ {
+ lineRenderer.positionCount = 0;
+ lineRenderer.enabled = true;
+ }
+ }
+
+ private void OnDisable()
+ {
+ if (cursor != null) cursor.gameObject.SetActive(false);
+ if (lineRenderer != null) lineRenderer.enabled = false;
+ }
+
+ //Gizmos:
+ private void OnDrawGizmosSelected()
+ {
+ if (Application.isPlaying) return;
+
+ Vector3 castDirection = source.forward;
+ if (flipCastDirection) castDirection *= -1;
+ Gizmos.color = Color.green;
+ Gizmos.DrawRay(source.position, castDirection * raycastDistance);
+
+ if (cursor != null)
+ {
+ Gizmos.color = Color.yellow;
+ Gizmos.DrawLine(source.position, cursor.position);
+ }
+ }
+
+ //Public Methods:
+ public void Pressed()
+ {
+ switch (_method)
+ {
+ case Method.Raycast:
+ if (_currentRaycast != null)
+ {
+ _currentRaycast.SendMessage("Pressed", SendMessageOptions.DontRequireReceiver);
+ if (OnPressed != null) OnPressed.Invoke(_currentRaycast.gameObject);
+ }
+ break;
+
+ case Method.RaycastAll:
+ if (_current.Count > 0)
+ {
+ foreach (var item in _current)
+ {
+ item.SendMessage("Pressed", SendMessageOptions.DontRequireReceiver);
+ if (OnPressed != null) OnPressed.Invoke(item.gameObject);
+ }
+ }
+ break;
+ }
+ }
+
+ public void Released()
+ {
+ switch (_method)
+ {
+ case Method.Raycast:
+ if (_currentRaycast != null)
+ {
+ _currentRaycast.SendMessage("Released", SendMessageOptions.DontRequireReceiver);
+ if (OnReleased != null) OnReleased.Invoke(_currentRaycast.gameObject);
+ }
+ break;
+
+ case Method.RaycastAll:
+ if (_current.Count > 0)
+ {
+ foreach (var item in _current)
+ {
+ item.SendMessage("Released", SendMessageOptions.DontRequireReceiver);
+ if (OnReleased != null) OnReleased.Invoke(item.gameObject);
+ }
+ }
+ break;
+ }
+ }
+
+ //Loops:
+ private void Update()
+ {
+ //cursor setup:
+ if (cursor != _previousCursor)
+ {
+ _previousCursor = cursor;
+ if (cursor == null) return;
+
+ foreach (var item in cursor.GetComponentsInChildren())
+ {
+ Debug.Log("Cursor can not contain colliders. Disabling colliders on: " + item.name);
+ item.enabled = false;
+ }
+ }
+
+ //process input:
+ if (pressedInput != null)
+ {
+ foreach (var item in pressedInput)
+ {
+ /* if (Input.GetKeyDown(item))
+ {
+ Pressed();
+ }
+
+ if (Input.GetKeyUp(item))
+ {
+ Released();
+ } */
+ }
+ }
+
+ //clear out:
+ _current.Clear();
+
+ //raycast:
+ RaycastHit hit;
+ Vector3 castDirection = source.forward;
+ if (flipCastDirection) castDirection *= -1;
+ Physics.Raycast(source.position, castDirection, out hit, raycastDistance, layermask);
+ _currentRaycast = hit.transform;
+ IsHitting = hit.transform != null;
+
+ //cache:
+ if (_method == Method.Raycast && IsHitting)
+ {
+ _current.Clear();
+ _current.Add(hit.transform);
+ }
+
+ //debug info:
+ if (_debugView)
+ {
+ if (hit.transform != null)
+ {
+ Debug.DrawLine(source.position, hit.point, Color.green);
+ }
+ else
+ {
+ Debug.DrawRay(source.position, castDirection * raycastDistance, Color.red);
+ }
+ }
+
+ //cursor visibility:
+ if (cursor != null)
+ {
+ if (cursorHidden)
+ {
+ cursor.gameObject.SetActive(false);
+ }
+ else
+ {
+ if (autoHide)
+ {
+ cursor.gameObject.SetActive(IsHitting);
+ if (lineRenderer != null) lineRenderer.enabled = IsHitting;
+ }
+ else
+ {
+ cursor.gameObject.SetActive(true);
+ if (lineRenderer != null) lineRenderer.enabled = true;
+ }
+ }
+ }
+
+ //cursor management:
+ if (cursor != null)
+ {
+ if (hit.transform != null)
+ {
+ //get position:
+ _targetPosition = hit.point + hit.normal * surfaceOffset;
+
+ //get position speed:
+ float posSpeed = unstableSpeed;
+ float delta = Vector3.Distance(_targetPosition, cursor.position);
+ if (delta <= stabilityDelta)
+ {
+ posSpeed = stableSpeed;
+ }
+
+ if (delta >= snapDelta)
+ {
+ cursor.position = _targetPosition;
+ }
+ else
+ {
+ cursor.position = Vector3.Lerp(cursor.position, _targetPosition, Time.unscaledDeltaTime * posSpeed);
+ }
+
+ //set rotation:
+ if (matchSurfaceNormal)
+ {
+ cursor.rotation = Quaternion.LookRotation(hit.normal, source.up);
+ }
+ else
+ {
+ cursor.LookAt(source, Vector3.up);
+ }
+
+ //adjust:
+ if (flipForward)
+ {
+ cursor.Rotate(Vector3.up * 180);
+ }
+ }
+ else
+ {
+ //put out in front and face source (flip if needed):
+ Vector3 inFront = source.position + castDirection * idleDistance;
+ float delta = Vector3.Distance(inFront, cursor.position);
+ float posSpeed = unstableSpeed;
+
+ if (delta <= stabilityDelta)
+ {
+ posSpeed = stableSpeed;
+ }
+
+ if (delta >= snapDelta)
+ {
+ cursor.position = inFront;
+ }
+ else
+ {
+ cursor.position = Vector3.Lerp(cursor.position, inFront, Time.unscaledDeltaTime * posSpeed);
+ }
+
+ cursor.LookAt(source.position);
+ if (flipForward)
+ {
+ cursor.Rotate(Vector3.up * 180);
+ }
+ }
+ }
+
+ //handle raycast messages:
+ if (_method == Method.Raycast)
+ {
+ //select:
+ if (_previousRaycast == null && hit.transform != null)
+ {
+ hit.transform.SendMessage("Selected", SendMessageOptions.DontRequireReceiver);
+ if (OnSelected != null) OnSelected.Invoke(hit.transform.gameObject);
+ }
+
+ //updated select:
+ if (hit.transform != null && _previousRaycast != null && _previousRaycast != hit.transform)
+ {
+ _previousRaycast.SendMessage("Deselected", SendMessageOptions.DontRequireReceiver);
+ if (OnDeselected != null) OnDeselected.Invoke(_previousRaycast.gameObject);
+ hit.transform.SendMessage("Selected", SendMessageOptions.DontRequireReceiver);
+ if (OnSelected != null) OnSelected.Invoke(hit.transform.gameObject);
+ }
+
+ //deselect:
+ if (_previousRaycast != null && hit.transform == null)
+ {
+ _previousRaycast.SendMessage("Deselected", SendMessageOptions.DontRequireReceiver);
+ if (OnDeselected != null) OnDeselected.Invoke(_previousRaycast.gameObject);
+ }
+
+ //cache:
+ _previousRaycast = hit.transform;
+ }
+
+ //raycast all:
+ if (_method == Method.RaycastAll)
+ {
+ //catalog:
+ foreach (var item in Physics.RaycastAll(source.position, castDirection, raycastDistance, layermask))
+ {
+ _current.Add(item.transform);
+ }
+
+ //handle selects:
+ if (_current.Count > 0)
+ {
+ foreach (var item in _current)
+ {
+ if (_previous.Count == 0 || !_previous.Contains(item))
+ {
+ item.SendMessage("Selected", SendMessageOptions.DontRequireReceiver);
+ if (OnSelected != null) OnSelected.Invoke(item.gameObject);
+ }
+ }
+ }
+
+ //handle deselects:
+ if (_previous.Count > 0)
+ {
+ foreach (var item in _previous)
+ {
+ if (_current.Count == 0 || !_current.Contains(item))
+ {
+ item.SendMessage("Deselected", SendMessageOptions.DontRequireReceiver);
+ if (OnDeselected != null) OnDeselected.Invoke(item.gameObject);
+ }
+ }
+ }
+
+ //cache:
+ _previous.Clear();
+ _previous.AddRange(_current);
+ }
+
+ //line renderer:
+ if (cursor != null && cursor.gameObject.activeSelf && lineRenderer != null )
+ {
+ if (lineRenderer.positionCount != 2) lineRenderer.positionCount = 2;
+ lineRenderer.SetPosition(0, source.position);
+ lineRenderer.SetPosition(1, cursor.position);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/External/Pixelplacement/Surge/Chooser/Chooser.cs.meta b/Assets/External/Pixelplacement/Surge/Chooser/Chooser.cs.meta
new file mode 100644
index 00000000..49f09d20
--- /dev/null
+++ b/Assets/External/Pixelplacement/Surge/Chooser/Chooser.cs.meta
@@ -0,0 +1,20 @@
+fileFormatVersion: 2
+guid: db04a89df0755a04cb9d5f03bb62b19d
+timeCreated: 1521224863
+licenseType: Store
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 107312
+ packageName: Surge
+ packageVersion: 1.0.48
+ assetPath: Assets/Pixelplacement/Surge/Chooser/Chooser.cs
+ uploadId: 467433
diff --git a/Assets/External/Pixelplacement/Surge/Chooser/Editor.meta b/Assets/External/Pixelplacement/Surge/Chooser/Editor.meta
new file mode 100644
index 00000000..00451330
--- /dev/null
+++ b/Assets/External/Pixelplacement/Surge/Chooser/Editor.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 0d863bca9b2680743bd08a98ae378772
+folderAsset: yes
+timeCreated: 1522266281
+licenseType: Store
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/External/Pixelplacement/Surge/Chooser/Editor/ChooserEditor.cs b/Assets/External/Pixelplacement/Surge/Chooser/Editor/ChooserEditor.cs
new file mode 100644
index 00000000..4fe2dae1
--- /dev/null
+++ b/Assets/External/Pixelplacement/Surge/Chooser/Editor/ChooserEditor.cs
@@ -0,0 +1,106 @@
+///
+/// SURGE FRAMEWORK
+/// Author: Bob Berkebile
+/// Email: bobb@pixelplacement.com
+///
+/// Custom inspector Chooser.
+///
+///
+
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace Pixelplacement
+{
+ [CustomEditor(typeof(Chooser), true)]
+ [CanEditMultipleObjects]
+ public class ChooserEditor : UnityEditor.Editor
+ {
+ //Private Variables:
+ Chooser _target;
+
+ //Flow:
+ void OnEnable()
+ {
+ _target = target as Chooser;
+ }
+
+ //Inspector GUI:
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ DrawPropertiesExcluding(serializedObject, new string[] {
+ "OnSelected",
+ "OnDeselected",
+ "OnPressed",
+ "OnReleased",
+ "_cursorPropertiesFolded",
+ "_unityEventsFolded",
+ "source",
+ "raycastDistance",
+ "layermask",
+ "pressedInput",
+ "cursor",
+ "surfaceOffset",
+ "idleDistance",
+ "stabilityDelta",
+ "snapDelta",
+ "stableSpeed",
+ "unstableSpeed",
+ "flipForward",
+ "matchSurfaceNormal",
+ "autoHide",
+ "cursorHidden",
+ "flipCastDirection",
+ "lineRenderer",
+ "_debugView",
+ "_method"
+ });
+
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("source"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("raycastDistance"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("flipCastDirection"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("layermask"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("_method"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("_debugView"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("pressedInput"), true);
+
+ _target._cursorPropertiesFolded = EditorGUILayout.Foldout(_target._cursorPropertiesFolded, "Cursor Properties", true);
+ if (_target._cursorPropertiesFolded)
+ {
+ EditorGUI.indentLevel = 1;
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("cursor"));
+ GUI.enabled = _target.cursor != null;
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("cursorHidden"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("lineRenderer"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("surfaceOffset"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("idleDistance"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("stabilityDelta"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("snapDelta"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("stableSpeed"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("unstableSpeed"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("flipForward"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("matchSurfaceNormal"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("autoHide"));
+ EditorGUI.indentLevel = 0;
+ GUI.enabled = true;
+ EditorGUILayout.Space();
+ }
+
+ _target._unityEventsFolded = EditorGUILayout.Foldout(_target._unityEventsFolded, "Unity Events", true);
+ if (_target._unityEventsFolded)
+ {
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("OnSelected"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("OnPressed"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("OnReleased"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("OnDeselected"));
+ EditorGUILayout.Space();
+ }
+
+ serializedObject.ApplyModifiedProperties();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/External/Pixelplacement/Surge/Chooser/Editor/ChooserEditor.cs.meta b/Assets/External/Pixelplacement/Surge/Chooser/Editor/ChooserEditor.cs.meta
new file mode 100644
index 00000000..05981be9
--- /dev/null
+++ b/Assets/External/Pixelplacement/Surge/Chooser/Editor/ChooserEditor.cs.meta
@@ -0,0 +1,19 @@
+fileFormatVersion: 2
+guid: ad17b9c71d7903743aa42f462c8826fb
+timeCreated: 1522266293
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 107312
+ packageName: Surge
+ packageVersion: 1.0.48
+ assetPath: Assets/Pixelplacement/Surge/Chooser/Editor/ChooserEditor.cs
+ uploadId: 467433
diff --git a/Assets/External/Pixelplacement/Surge/Chooser/Interfaces.meta b/Assets/External/Pixelplacement/Surge/Chooser/Interfaces.meta
new file mode 100644
index 00000000..5e504091
--- /dev/null
+++ b/Assets/External/Pixelplacement/Surge/Chooser/Interfaces.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 5e72ba21481229f4d94aad43a786efae
+folderAsset: yes
+timeCreated: 1524507533
+licenseType: Store
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/External/Pixelplacement/Surge/Chooser/Interfaces/IChooser.cs b/Assets/External/Pixelplacement/Surge/Chooser/Interfaces/IChooser.cs
new file mode 100644
index 00000000..cb757cf3
--- /dev/null
+++ b/Assets/External/Pixelplacement/Surge/Chooser/Interfaces/IChooser.cs
@@ -0,0 +1,10 @@
+namespace Pixelplacement
+{
+ interface IChooser
+ {
+ void Selected();
+ void Deselected();
+ void Pressed();
+ void Released();
+ }
+}
\ No newline at end of file
diff --git a/Assets/External/Pixelplacement/Surge/Chooser/Interfaces/IChooser.cs.meta b/Assets/External/Pixelplacement/Surge/Chooser/Interfaces/IChooser.cs.meta
new file mode 100644
index 00000000..1ee9e1b6
--- /dev/null
+++ b/Assets/External/Pixelplacement/Surge/Chooser/Interfaces/IChooser.cs.meta
@@ -0,0 +1,19 @@
+fileFormatVersion: 2
+guid: fbf5a06b4e893814c8820c3be2ddcb66
+timeCreated: 1524507546
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 107312
+ packageName: Surge
+ packageVersion: 1.0.48
+ assetPath: Assets/Pixelplacement/Surge/Chooser/Interfaces/IChooser.cs
+ uploadId: 467433
diff --git a/Assets/External/Pixelplacement/Surge/ColliderButton.meta b/Assets/External/Pixelplacement/Surge/ColliderButton.meta
new file mode 100644
index 00000000..4affc9a1
--- /dev/null
+++ b/Assets/External/Pixelplacement/Surge/ColliderButton.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: f3f82fb6566d9794596b84cdda70c461
+folderAsset: yes
+timeCreated: 1521855968
+licenseType: Store
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/External/Pixelplacement/Surge/ColliderButton/ColliderButton.cs b/Assets/External/Pixelplacement/Surge/ColliderButton/ColliderButton.cs
new file mode 100644
index 00000000..1407f3dd
--- /dev/null
+++ b/Assets/External/Pixelplacement/Surge/ColliderButton/ColliderButton.cs
@@ -0,0 +1,608 @@
+///
+/// SURGE FRAMEWORK
+/// Author: Bob Berkebile
+/// Email: bobb@pixelplacement.com
+///
+/// Simple system for turning anything into a button.
+///
+///
+
+using UnityEngine;
+using UnityEngine.UI;
+using UnityEngine.Events;
+using UnityEngine.EventSystems;
+using System;
+using Pixelplacement.TweenSystem;
+#if UNITY_2017_2_OR_NEWER
+using UnityEngine.XR;
+#else
+using UnityEngine.VR;
+#endif
+
+namespace Pixelplacement
+{
+ [RequireComponent(typeof(Collider))]
+ [RequireComponent(typeof(Rigidbody))]
+ [ExecuteInEditMode]
+ public sealed class ColliderButton : MonoBehaviour
+ {
+ //Public Events:
+ public ColliderButtonEvent OnSelected;
+ public ColliderButtonEvent OnDeselected;
+ public ColliderButtonEvent OnClick;
+ public ColliderButtonEvent OnPressed;
+ public ColliderButtonEvent OnReleased;
+ public static event Action OnSelectedGlobal;
+ public static event Action OnDeselectedGlobal;
+ public static event Action OnClickGlobal;
+ public static event Action OnPressedGlobal;
+ public static event Action OnReleasedGlobal;
+
+ //Public Enums:
+ public enum EaseType { EaseOut, EaseOutBack };
+
+ //Public Properties:
+ public bool IsSelected
+ {
+ get;
+ private set;
+ }
+
+ //Public Variables:
+ public KeyCode[] keyInput;
+ public bool _unityEventsFolded;
+ public bool _scaleResponseFolded;
+ public bool _colorResponseFolded;
+ public bool applyColor;
+ public bool applyScale;
+ public LayerMask collisionLayerMask = -1;
+ public Renderer colorRendererTarget;
+ public Image colorImageTarget;
+ public Color selectedColor = Color.gray;
+ public Color pressedColor = Color.green;
+ public Color disabledColor = new Color(.5f, .5f, .5f, .5f);
+ public float colorDuration = .1f;
+ public Transform scaleTarget;
+ public Vector3 normalScale;
+ public Vector3 selectedScale;
+ public Vector3 pressedScale;
+ public float scaleDuration = .1f;
+ public EaseType scaleEaseType;
+ public bool resizeGUIBoxCollider = true;
+ public bool centerGUIBoxCollider = true;
+ public Vector2 guiBoxColliderPadding;
+ public bool interactable = true;
+
+ //Private Variables:
+ bool _clicking;
+ int _selectedCount;
+ bool _colliderSelected;
+ bool _pressed;
+ bool _released;
+ bool _vrRunning;
+ RectTransform _rectTransform;
+ EventTrigger _eventTrigger;
+ EventTrigger.Entry _pressedEventTrigger;
+ EventTrigger.Entry _releasedEventTrigger;
+ EventTrigger.Entry _enterEventTrigger;
+ EventTrigger.Entry _exitEventTrigger;
+ int _colliderCount;
+ BoxCollider _boxCollider;
+ TweenBase _colorTweenImage = null;
+ TweenBase _colorTweenMaterial;
+ TweenBase _scaleTween;
+ Color _normalColorRenderer;
+ Color _normalColorImage;
+ bool _interactableStatus = true;
+
+ //Init:
+ private void Reset()
+ {
+ //var sets:
+ applyColor = true;
+ keyInput = new KeyCode[] { KeyCode.Mouse0 };
+
+ //hook up image to help users:
+ Image image = GetComponent();
+ if (image != null)
+ {
+ colorImageTarget = image;
+ }
+
+ //hook up renderer to help users:
+ Renderer renderer = GetComponent();
+ if (renderer != null && renderer.sharedMaterial.HasProperty("_Color"))
+ {
+ colorRendererTarget = renderer;
+ }
+ }
+
+ private void Awake()
+ {
+ if (Application.isPlaying)
+ {
+ //color setups:
+ if (colorRendererTarget != null)
+ {
+ if (colorRendererTarget.material.HasProperty("_Color"))
+ {
+ _normalColorRenderer = colorRendererTarget.material.color;
+ }
+ }
+ if (colorImageTarget != null)
+ {
+ _normalColorImage = colorImageTarget.color;
+ }
+ }
+
+ //scale setup:
+ scaleTarget = transform;
+ normalScale = transform.localScale;
+
+ //set initial size on gui collider:
+ _rectTransform = GetComponent();
+ _boxCollider = GetComponent();
+ if (_rectTransform != null && _boxCollider != null) ResizeGUIBoxCollider(_boxCollider);
+
+ //set up rigidbody:
+ GetComponent().isKinematic = true;
+
+ //refs:
+ _rectTransform = GetComponent();
+ _boxCollider = GetComponent();
+
+ if (!Application.isPlaying) return;
+
+ //rect and event triggers:
+ _rectTransform = GetComponent();
+ if (_rectTransform != null)
+ {
+ _eventTrigger = gameObject.AddComponent();
+ _pressedEventTrigger = new EventTrigger.Entry();
+ _pressedEventTrigger.eventID = EventTriggerType.PointerDown;
+ _releasedEventTrigger = new EventTrigger.Entry();
+ _releasedEventTrigger.eventID = EventTriggerType.PointerUp;
+ _enterEventTrigger = new EventTrigger.Entry();
+ _enterEventTrigger.eventID = EventTriggerType.PointerEnter;
+ _exitEventTrigger = new EventTrigger.Entry();
+ _exitEventTrigger.eventID = EventTriggerType.PointerExit;
+ }
+
+ //events:
+ if (_rectTransform != null)
+ {
+ //event registrations:
+ _pressedEventTrigger.callback.AddListener((data) => { OnPointerDownDelegate((PointerEventData)data); });
+ _eventTrigger.triggers.Add(_pressedEventTrigger);
+ _releasedEventTrigger.callback.AddListener((data) => { OnPointerUpDelegate((PointerEventData)data); });
+ _eventTrigger.triggers.Add(_releasedEventTrigger);
+ _enterEventTrigger.callback.AddListener((data) => { OnPointerEnterDelegate((PointerEventData)data); });
+ _eventTrigger.triggers.Add(_enterEventTrigger);
+ _exitEventTrigger.callback.AddListener((data) => { OnPointerExitDelegate((PointerEventData)data); });
+ _eventTrigger.triggers.Add(_exitEventTrigger);
+ }
+ }
+
+ //Flow:
+ private void OnEnable()
+ {
+ if (!Application.isPlaying) return;
+
+ ColorReset();
+ }
+
+ private void OnDisable()
+ {
+ if (!Application.isPlaying) return;
+
+ //resets:
+ _pressed = false;
+ _released = false;
+ _clicking = false;
+ _colliderSelected = false;
+ _selectedCount = 0;
+ _colliderCount = 0;
+
+ ColorReset();
+ ScaleReset();
+ }
+
+ //Loops:
+ private void Update()
+ {
+ //disabled?
+ if (_interactableStatus != interactable)
+ {
+ if (interactable)
+ {
+ ColorNormal();
+ }
+ else
+ {
+ ColorDisabled();
+ }
+
+ //handle a Unity GUI button in case it is also attached:
+ Button button = GetComponent