Permalink
Browse files

import from imola-fun

  • Loading branch information...
1 parent 63c8554 commit 5acacf4ce28b0ae7e5600e80c59e268ee40e636e @windhood windhood committed Jun 30, 2012
Showing with 4,643 additions and 0 deletions.
  1. BIN Assets/Imola/Fonts/C64.ttf
  2. BIN Assets/Imola/Fonts/xirod.ttf
  3. BIN Assets/Imola/GUI Skins/Menu Button Skin.guiskin
  4. BIN Assets/Imola/Graphical assets/Images/avatar-icon.png
  5. BIN Assets/Imola/Graphical assets/Images/clone-icon.png
  6. BIN Assets/Imola/Graphical assets/Images/clone.png
  7. BIN Assets/Imola/Graphical assets/Images/clubs-icon.png
  8. BIN Assets/Imola/Graphical assets/Images/exit-icon.png
  9. BIN Assets/Imola/Graphical assets/Images/exitpose.png
  10. BIN Assets/Imola/Graphical assets/Images/fire-icon.png
  11. BIN Assets/Imola/Graphical assets/Images/fullbodyturn.jpg
  12. BIN Assets/Imola/Graphical assets/Images/shield-icon.png
  13. BIN Assets/Imola/Graphical assets/Images/teleport-icon.png
  14. BIN Assets/Imola/Graphical assets/Images/view-icon.png
  15. BIN Assets/Imola/Graphical assets/transparentbar.mat
  16. BIN Assets/Imola/Prefabs/BlankMenuItem.prefab
  17. BIN Assets/Imola/Prefabs/CoverflowMenu.prefab
  18. BIN Assets/Imola/Prefabs/HandPositionIndicator.prefab
  19. BIN Assets/Imola/Prefabs/Slide.prefab
  20. BIN Assets/Imola/Scenes/MainMenu.unity
  21. BIN Assets/Imola/Scenes/SlideShowDemo.unity
  22. +34 −0 Assets/Imola/Scripts/ChangeColor.cs
  23. +33 −0 Assets/Imola/Scripts/DummyFeed.cs
  24. +39 −0 Assets/Imola/Scripts/ExitOnEscape.cs
  25. +79 −0 Assets/Imola/Scripts/HandpointControls/Fader.cs
  26. +75 −0 Assets/Imola/Scripts/HandpointControls/FollowHandPoint.cs
  27. +75 −0 Assets/Imola/Scripts/HandpointControls/HandPointControl.cs
  28. +146 −0 Assets/Imola/Scripts/HandpointControls/ItemSelector.cs
  29. +117 −0 Assets/Imola/Scripts/HandpointControls/Navigator.cs
  30. +110 −0 Assets/Imola/Scripts/HandpointControls/PushDetector.cs
  31. +393 −0 Assets/Imola/Scripts/HandpointControls/ScrollingMenu.cs
  32. +18 −0 Assets/Imola/Scripts/HandpointControls/SessionManagerVisualizer.cs
  33. +114 −0 Assets/Imola/Scripts/HandpointControls/StaticMenu.cs
  34. +122 −0 Assets/Imola/Scripts/HandpointControls/SwipeDetector.cs
  35. +22 −0 Assets/Imola/Scripts/LoadScenetest.cs
  36. +278 −0 Assets/Imola/Scripts/MainMenu/GUIBuilder.cs
  37. +10 −0 Assets/Imola/Scripts/Math/MathHelper.cs
  38. +60 −0 Assets/Imola/Scripts/Math/Vector2.cs
  39. +60 −0 Assets/Imola/Scripts/Math/Vector3.cs
  40. +48 −0 Assets/Imola/Scripts/MenuItemChangeColor.cs
  41. +199 −0 Assets/Imola/Scripts/OpenNIDepthmapToMesh.cs
  42. +270 −0 Assets/Imola/Scripts/OpenNIExt/HandupPoseDetector.cs
  43. +32 −0 Assets/Imola/Scripts/OpenNIExt/HandupPoseGestureFactory.cs
  44. +66 −0 Assets/Imola/Scripts/OpenNIExt/InputGestureDetector.cs
  45. +145 −0 Assets/Imola/Scripts/OpenNIExt/LeanPoseDetector.cs
  46. +19 −0 Assets/Imola/Scripts/OpenNIExt/LeanPoseGestureFactory.cs
  47. +97 −0 Assets/Imola/Scripts/OpenNIExt/NIFloorNormalCalculator.cs
  48. +324 −0 Assets/Imola/Scripts/OpenNIExt/SwipeGestureDetector.cs
  49. +43 −0 Assets/Imola/Scripts/OpenNIExt/SwipeGestureFactory.cs
  50. +269 −0 Assets/Imola/Scripts/OpenNIExt/TPoseDetector.cs
  51. +32 −0 Assets/Imola/Scripts/OpenNIExt/TPoseGestureFactory.cs
  52. +18 −0 Assets/Imola/Scripts/OpenNIExt/TurnAroundGestureFactory.cs
  53. +197 −0 Assets/Imola/Scripts/OpenNIExt/TurnaroundTracker.cs
  54. +369 −0 Assets/Imola/Scripts/OpenNISessionManager.cs
  55. +53 −0 Assets/Imola/Scripts/SampleLoader/SampleLoaderFeed.cs
  56. +24 −0 Assets/Imola/Scripts/SampleLoader/SampleLoaderItem.cs
  57. +90 −0 Assets/Imola/Scripts/SlideView/ImageFeed.cs
  58. +134 −0 Assets/Imola/Scripts/SlideView/SlidingView.cs
  59. +19 −0 Assets/Imola/Scripts/SlideViewer/ImageItem.cs
  60. +68 −0 Assets/Imola/Scripts/SlideViewer/ImageViewerVisualizer.cs
  61. +28 −0 Assets/Imola/Scripts/SlideViewer/ImagesFeed.cs
  62. +20 −0 Assets/Imola/Scripts/SlideViewer/SetColor.cs
  63. +13 −0 Assets/Imola/Scripts/StartSessionMessage.cs
  64. +28 −0 Assets/Imola/Scripts/Utilities/FadeOut.cs
  65. +93 −0 Assets/Imola/Scripts/Utilities/TextTools.cs
  66. +67 −0 Assets/Imola/Scripts/Utilities/TimedPointList.cs
  67. +31 −0 Assets/Imola/Scripts/enableOnSession.cs
  68. +13 −0 Assets/Imola/Scripts/enableRegistration.cs
  69. +49 −0 Assets/Imola/Scripts/objectPerUser.cs
View
BIN Assets/Imola/Fonts/C64.ttf
Binary file not shown.
View
BIN Assets/Imola/Fonts/xirod.ttf
Binary file not shown.
View
BIN Assets/Imola/GUI Skins/Menu Button Skin.guiskin
Binary file not shown.
View
BIN Assets/Imola/Graphical assets/Images/avatar-icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Assets/Imola/Graphical assets/Images/clone-icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Assets/Imola/Graphical assets/Images/clone.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Assets/Imola/Graphical assets/Images/clubs-icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Assets/Imola/Graphical assets/Images/exit-icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Assets/Imola/Graphical assets/Images/exitpose.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Assets/Imola/Graphical assets/Images/fire-icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Assets/Imola/Graphical assets/Images/fullbodyturn.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Assets/Imola/Graphical assets/Images/shield-icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Assets/Imola/Graphical assets/Images/teleport-icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Assets/Imola/Graphical assets/Images/view-icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Assets/Imola/Graphical assets/transparentbar.mat
Binary file not shown.
View
BIN Assets/Imola/Prefabs/BlankMenuItem.prefab
Binary file not shown.
View
BIN Assets/Imola/Prefabs/CoverflowMenu.prefab
Binary file not shown.
View
BIN Assets/Imola/Prefabs/HandPositionIndicator.prefab
Binary file not shown.
View
BIN Assets/Imola/Prefabs/Slide.prefab
Binary file not shown.
View
BIN Assets/Imola/Scenes/MainMenu.unity
Binary file not shown.
View
BIN Assets/Imola/Scenes/SlideShowDemo.unity
Binary file not shown.
View
34 Assets/Imola/Scripts/ChangeColor.cs
@@ -0,0 +1,34 @@
+using UnityEngine;
+using System.Collections;
+
+public class ChangeColor : MonoBehaviour {
+ public Color defaultColor = Color.white;
+ public Color highlightColor = Color.green;
+ public Color selectColor = Color.blue;
+
+
+ // Use this for initialization
+ void Start () {
+ StaticMenu menu = GetComponent<StaticMenu>();
+ if (menu) {
+ foreach (Transform item in menu.items) {
+ item.renderer.material.color = defaultColor;
+ }
+ }
+ }
+
+ void Menu_Highlight(Transform item)
+ {
+ item.renderer.material.color = highlightColor;
+ }
+
+ void Menu_Unhighlight(Transform item)
+ {
+ item.renderer.material.color = defaultColor;
+ }
+
+ void Menu_Select(Transform item)
+ {
+ item.renderer.material.color = selectColor;
+ }
+}
View
33 Assets/Imola/Scripts/DummyFeed.cs
@@ -0,0 +1,33 @@
+using UnityEngine;
+using System.Collections;
+
+public class DummyFeed : MonoBehaviour {
+ public ScrollingMenu menu;
+ public Transform menuItem;
+ public int count = 10;
+
+ void Awake()
+ {
+ if (null == menu) {
+ menu = GetComponent<ScrollingMenu>();
+ }
+ if (null == menu) {
+ Debug.LogError("No menu attached to " + gameObject.name);
+ }
+ }
+
+ // Use this for initialization
+ void Start()
+ {
+ if (!menu) return;
+
+ for (int i = 0; i < count; i++) {
+ Transform newObj = Instantiate(menuItem) as Transform;
+ TextMesh tm = newObj.GetComponentInChildren<TextMesh>();
+ if (tm) {
+ tm.text = "Testing " + i;
+ }
+ menu.Add(newObj);
+ }
+ }
+}
View
39 Assets/Imola/Scripts/ExitOnEscape.cs
@@ -0,0 +1,39 @@
+using UnityEngine;
+using System.Collections;
+
+public class ExitOnEscape : MonoBehaviour {
+
+ string GetScreenshotFilename()
+ {
+ System.IO.Directory.CreateDirectory("Screenshots");
+ int i=1;
+ while (System.IO.File.Exists(System.IO.Path.Combine("Screenshots", "Screenshot" + i + ".png"))) {
+ i++;
+ }
+ return System.IO.Path.Combine("Screenshots", "Screenshot" + i + ".png");
+ }
+
+ void Start()
+ {
+ foreach (string cmd in System.Environment.GetCommandLineArgs())
+ {
+ if ("wide" == cmd) {
+ Screen.SetResolution(1280, 720, true);
+ }
+ }
+ }
+
+ void OnGUI()
+ {
+ if (Event.current.Equals(Event.KeyboardEvent("escape"))) {
+ print("Quitting");
+ Application.Quit();
+ }
+
+ if (Event.current.Equals(Event.KeyboardEvent("f10"))) {
+ string filename = GetScreenshotFilename();
+ print("Writing screenshot to " + filename);
+ Application.CaptureScreenshot(filename);
+ }
+ }
+}
View
79 Assets/Imola/Scripts/HandpointControls/Fader.cs
@@ -0,0 +1,79 @@
+using UnityEngine;
+using System.Collections;
+
+[RequireComponent(typeof(HandPointControl))]
+public class Fader : MonoBehaviour {
+ public Vector3 direction = Vector3.right;
+ public float size = 200;
+ public float initialValue = 0.5f;
+
+ public float value { get; private set; }
+
+ Vector3 mirrorIndependentDirection {
+ get {
+ return (NIContext.Instance.Mirror) ? direction : Vector3.Scale(direction, new Vector3(-1, 1, 1));
+ }
+ }
+
+ Vector3 start;
+
+ // move the slider to contain pos within its bounds
+ public void MoveToContain(Vector3 pos)
+ {
+ float dot = Vector3.Dot(mirrorIndependentDirection, pos - start);
+ if (dot > size)
+ {
+ start += mirrorIndependentDirection * (dot - size);
+ }
+ if (dot < 0)
+ {
+ start += mirrorIndependentDirection * dot;
+ }
+ }
+
+ // move the slider so that pos will be mapped to val (0-1)
+ public void MoveTo(Vector3 pos, float val)
+ {
+ start = pos - (mirrorIndependentDirection * (val * size));
+ }
+
+ public float GetValue(Vector3 pos)
+ {
+ float dot = Vector3.Dot(mirrorIndependentDirection, pos - start);
+ float val = Mathf.Clamp01(dot / size);
+ return val;
+ }
+
+ public Vector3 GetPosition(float val)
+ {
+ return start + (mirrorIndependentDirection * (val * size));
+ }
+
+ // hand point control messages
+ void Hand_Create(Vector3 pos)
+ {
+ MoveTo(OpenNISessionManager.FocusPoint, initialValue);
+ value = initialValue;
+ }
+
+ public void Hand_Update(Vector3 pos)
+ {
+ value = GetValue(pos);
+ }
+
+ void Hand_Destroy()
+ {
+ value = initialValue;
+ }
+
+ void Start()
+ {
+ value = initialValue;
+ }
+
+ void SessionManager_Visualize()
+ {
+ GUILayout.Label("- Fader");
+ GUILayout.HorizontalSlider(value, 0.0f, 1.0f);
+ }
+}
View
75 Assets/Imola/Scripts/HandpointControls/FollowHandPoint.cs
@@ -0,0 +1,75 @@
+using UnityEngine;
+using System;
+
+public class FollowHandPoint : MonoBehaviour
+{
+ // default scale convert openni (millimeters) to unity (meters)
+ public Vector3 Scale = new Vector3(0.02f, 0.02f, -0.02f);
+ public Vector3 bias;
+ public float damping = 5;
+
+ public Vector3 bounds = new Vector3(10, 10, 10);
+
+ private Vector3 desiredPos;
+ public bool Absolute = false;
+
+ void Start()
+ {
+ // make sure we get hand points
+ if (null == GetComponent<HandPointControl>())
+ {
+ gameObject.AddComponent<HandPointControl>();
+ }
+
+ desiredPos = transform.localPosition;
+ }
+
+ void Update()
+ {
+ transform.localPosition = Vector3.Lerp(transform.localPosition, desiredPos, damping * Time.deltaTime);
+ }
+
+ Vector3 ClampVector(Vector3 vec, Vector3 min, Vector3 max)
+ {
+ return new Vector3(Mathf.Clamp(vec.x, min.x, max.x),
+ Mathf.Clamp(vec.y, min.y, max.y),
+ Mathf.Clamp(vec.z, min.z, max.z));
+ }
+
+ Vector3 OpenNIToUnity (Vector3 pos)
+ {
+ Vector3 result = pos;
+ if (!Absolute) {
+ result -= OpenNISessionManager.FocusPoint;
+ }
+ result = Vector3.Scale(result, Scale) + bias;
+ return ClampVector(result, -0.5f * bounds, 0.5f * bounds);
+ }
+
+ void Hand_Create(Vector3 pos)
+ {
+
+ desiredPos = OpenNIToUnity(pos);
+ }
+
+ void Hand_Update(Vector3 pos)
+ {
+ desiredPos = OpenNIToUnity(pos);
+ }
+
+ void Hand_Destroy()
+ {
+ desiredPos = Vector3.zero;
+ }
+
+ void OnDrawGizmos()
+ {
+ Gizmos.color = Color.blue;
+ if (transform.parent) {
+ Gizmos.DrawWireCube(transform.parent.position, bounds);
+ }
+ else {
+ //TODO
+ }
+ }
+}
View
75 Assets/Imola/Scripts/HandpointControls/HandPointControl.cs
@@ -0,0 +1,75 @@
+using UnityEngine;
+using System;
+
+public class HandPointControl : MonoBehaviour
+{
+ public bool ActiveOnStart = true;
+ public bool IsActive { get; private set; }
+
+ bool started = false;
+
+ void Hand_Create(Vector3 pos)
+ {
+
+ }
+
+ void Hand_Update(Vector3 pos)
+ {
+
+ }
+
+ void Hand_Destroy()
+ {
+
+ }
+
+ void Start()
+ {
+ if (ActiveOnStart) {
+ OpenNISessionManager.AddListener(this.gameObject);
+ IsActive = true;
+ }
+ started = true;
+ }
+
+ public void Activate()
+ {
+ IsActive = true;
+ OpenNISessionManager.AddListener(this.gameObject);
+ }
+
+ public void Deactivate()
+ {
+ IsActive = false;
+ OpenNISessionManager.RemoveListener(this.gameObject);
+ }
+
+ void OnEnable()
+ {
+ // only add to session manager by default if not navigable
+ // we test "started" since OnEnable is called before Start and we dont
+ // want to cause openni to init just yet (it messes up the singleton)
+ if (IsActive && started)
+ {
+ OpenNISessionManager.AddListener(this.gameObject);
+ IsActive = true;
+ }
+ }
+
+ void OnDisable()
+ {
+ OpenNISessionManager.RemoveListener(this.gameObject);
+ }
+
+ void Navigator_Activate()
+ {
+ Activate();
+ }
+
+ void Navigator_Deactivate()
+ {
+ Deactivate();
+ }
+
+ protected Vector3 FocusPoint { get { return OpenNISessionManager.FocusPoint; } }
+}
View
146 Assets/Imola/Scripts/HandpointControls/ItemSelector.cs
@@ -0,0 +1,146 @@
+using UnityEngine;
+using System.Collections;
+
+public class ItemSelector : MonoBehaviour {
+ public Fader fader;
+ public int numItems = 3;
+ public float hysterisis = .1f;
+ public float scrollRegion = .2f;
+ public bool dontUpdateWhenPushed = true;
+
+ // vars for scrolling repeat logic.
+ // TODO: possibly use an Input axis for this functionality
+ public bool RepeatScrolling = true;
+ public float InitialWaitTime = 0.6f;
+ public float WaitTimeModifier = 0.75f;
+ public float MinWaitTime = 0.15f;
+ public float MaxWaitTime = 2.0f;
+
+ public bool scrolling { get; private set; }
+
+ int index;
+ public int selectionIndex {
+ get {
+ return index;
+ }
+ private set {
+ index = Mathf.Clamp(value, 0, numItems-1);
+ SendMessage("ItemSelector_Select", selectionIndex, SendMessageOptions.DontRequireReceiver);
+ }
+ }
+
+ public float minValue {
+ get {
+ return (selectionIndex == 0) ? scrollRegion : scrollRegion + (selectionIndex * itemWidth) - hysterisis;
+ }
+ }
+
+ public float maxValue {
+ get {
+ return (selectionIndex == numItems - 1) ? 1.0f - scrollRegion : scrollRegion + ((selectionIndex + 1) * itemWidth) + hysterisis;
+ }
+ }
+
+ public float itemWidth {
+ get {
+ return (1.0f - (2 * scrollRegion)) / (float)numItems;
+ }
+ }
+
+ // push protection
+ bool pushed;
+ void PushDetector_Push()
+ {
+ if (dontUpdateWhenPushed) {
+ pushed = true;
+ }
+ }
+
+ void PushDetector_Release()
+ {
+ pushed = false;
+ }
+
+ void Start()
+ {
+ if (null == fader) {
+ Debug.LogError("You need a fader!");
+ }
+ }
+
+ void Hand_Update(Vector3 pos)
+ {
+ UpdateSelector(fader.value);
+ }
+
+ // scrolling logic
+
+ void UpdateSelector(float value)
+ {
+ bool scrollingForwards = value > 1.0 - scrollRegion;
+ bool scrollingBackwards = value < scrollRegion;
+ bool scrollingInThisFrame = scrollingForwards || scrollingBackwards;
+
+ if (!scrolling && scrollingInThisFrame) {
+ scrolling = true;
+ StartScrolling(scrollingForwards);
+ } else if (scrolling && !scrollingInThisFrame) {
+ StopScrolling();
+ scrolling = false;
+ selectionIndex = selectionIndex; // Force a resend of the select msg
+ }
+
+ if (!scrolling) {
+ if (fader.value < minValue && !pushed) {
+ selectionIndex--;
+ } else if (fader.value > maxValue && !pushed) {
+ selectionIndex++;
+ }
+ }
+ }
+
+ IEnumerator ScrollLoop(string eventName)
+ {
+ float waitTime = InitialWaitTime;
+ while (scrolling) {
+ SendMessage(eventName, SendMessageOptions.DontRequireReceiver);
+
+ if (!RepeatScrolling) {
+ break;
+ }
+
+ yield return new WaitForSeconds(waitTime);
+ waitTime = Mathf.Clamp(waitTime * WaitTimeModifier, MinWaitTime, MaxWaitTime);
+ }
+ }
+
+ void StartScrolling(bool forward)
+ {
+ SendMessage("ItemSelector_StartScrolling", forward, SendMessageOptions.DontRequireReceiver);
+ StartCoroutine("ScrollLoop", (forward) ? "ItemSelector_Next" : "ItemSelector_Prev");
+ }
+
+ void StopScrolling()
+ {
+ StopCoroutine("ScrollLoop");
+ SendMessage("ItemSelector_StopScrolling", SendMessageOptions.DontRequireReceiver);
+ }
+
+ void Hand_Destroy()
+ {
+ if (scrolling) {
+ StopScrolling();
+ scrolling = false;
+ }
+ }
+
+ void SessionManager_Visualize()
+ {
+ GUILayout.Label("- Item Selector");
+ if (scrolling) {
+ GUILayout.Label("SCROLLING");
+ } else {
+ GUILayout.HorizontalSlider(selectionIndex, 0.0f, numItems - 1);
+ }
+ }
+}
View
117 Assets/Imola/Scripts/HandpointControls/Navigator.cs
@@ -0,0 +1,117 @@
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+
+[RequireComponent(typeof(HandPointControl))]
+public class Navigator : MonoBehaviour {
+ public bool ActiveOnStart = false;
+ public bool NavigateHomeOnActivate = false;
+ public bool NavigateHomeOnSessionEnd = false;
+ public Transform HomeScreen;
+ public Transform ActiveItem { get; private set; }
+
+ public bool TriggerCooldown = false;
+ public float CooldownTime = 0.5f;
+
+ List<Transform> historyStack = new List<Transform>();
+
+ public void NavigateTo(string name)
+ {
+ Transform obj = transform.Find(name);
+ if (!obj) {
+ Debug.LogError("Cannot navigate to " + name);
+ return;
+ }
+ NavigateTo(obj);
+ }
+ public void NavigateTo(Transform obj)
+ {
+ DeactivateItem(ActiveItem);
+ historyStack.Add(obj);
+ ActivateItem(obj);
+ }
+
+ public void NavigateBack()
+ {
+ if (historyStack.Count <= 1) return;
+
+ //deactivate and remove from history
+ DeactivateItem(ActiveItem);
+ int lastIndex = historyStack.Count - 1;
+ historyStack.RemoveAt(lastIndex);
+
+ //activate new item without adding it to history
+ lastIndex = historyStack.Count - 1;
+ ActivateItem(historyStack[lastIndex]);
+ }
+
+ public void NavigateHome()
+ {
+ historyStack.Clear();
+ NavigateTo(HomeScreen);
+ }
+
+ void ActivateItem(Transform obj)
+ {
+ if (TriggerCooldown) {
+ OpenNISessionManager.Instance.StartCooldown(CooldownTime);
+ }
+ ActiveItem = obj;
+ obj.SendMessage("Navigator_Activate", SendMessageOptions.DontRequireReceiver);
+ SendMessage("Navigator_ActivatedItem", obj, SendMessageOptions.DontRequireReceiver);
+ }
+
+ void DeactivateItem(Transform obj)
+ {
+ if (!obj) return;
+ obj.SendMessage("Navigator_Deactivate", SendMessageOptions.DontRequireReceiver);
+ }
+
+ void Start()
+ {
+ // make sure we get hand points
+ if (null == GetComponent<HandPointControl>())
+ {
+ gameObject.AddComponent<HandPointControl>();
+ }
+ if (ActiveOnStart)
+ {
+ NavigateHome();
+ }
+ }
+
+ // allow nesting of NavigatorController's
+ void Navigator_Activate()
+ {
+ if (NavigateHomeOnActivate || null == ActiveItem)
+ {
+ NavigateHome();
+ }
+ else if (null != ActiveItem)
+ {
+ ActivateItem(ActiveItem);
+ }
+ }
+
+ void Navigator_Deactivate()
+ {
+ if (null != ActiveItem)
+ {
+ DeactivateItem(ActiveItem);
+ }
+ }
+
+ void Session_End()
+ {
+ if (NavigateHomeOnSessionEnd)
+ {
+ NavigateHome();
+ }
+ }
+
+ void SessionManager_Visualize()
+ {
+ GUILayout.Label("- Navigator");
+ GUILayout.Label("Active: " + ((null == ActiveItem) ? "[null]" : ActiveItem.name));
+ }
+}
View
110 Assets/Imola/Scripts/HandpointControls/PushDetector.cs
@@ -0,0 +1,110 @@
+using UnityEngine;
+using System.Collections;
+
+[RequireComponent(typeof(HandPointControl))]
+public class PushDetector : MonoBehaviour {
+ public float size = 150.0f;
+ public float initialValue = 0.2f;
+ public float driftSpeed = 0.05f;
+
+ public float clickTimeFrame = 1.0f;
+ public float clickMaxDistance = 100; //??
+
+ public float clickPushTime { get; private set; }
+ public bool IsClicked { get; private set; }
+ public Vector3 ClickPosition { get; private set; }
+ public float ClickProgress {
+ get {
+ return pushFader.value;
+ }
+ }
+
+ Fader pushFader;
+
+ void Start()
+ {
+ pushFader = gameObject.AddComponent<Fader>();
+ pushFader.direction = -Vector3.forward;
+ }
+
+ void Hand_Create(Vector3 pos)
+ {
+ pushFader.size = size;
+ pushFader.initialValue = initialValue;
+ pushFader.MoveTo(pos, initialValue);
+
+ Hand_Update(pos);
+ }
+
+ bool sent_push;
+ void Hand_Update(Vector3 pos)
+ {
+ // move slider if hand is out of its bounds (that way it always feels responsive)
+ pushFader.MoveToContain(pos);
+ pushFader.Hand_Update(pos);
+
+
+ // quick out if in cooldown
+ if (OpenNISessionManager.Instance.CoolingDown) return;
+
+ // click logic
+ if (!IsClicked)
+ {
+ if (ClickProgress == 1.0f) {
+ ClickPosition = pos;
+ IsClicked = true;
+ clickPushTime = Time.time;
+ //SendMessage("PushDetector_Push", SendMessageOptions.DontRequireReceiver);
+ }
+ }
+ else // clicked
+ {
+ if (ClickProgress < 0.5) {
+ if (IsClick(clickPushTime, ClickPosition, Time.time, pos)) {
+ SendMessage("PushDetector_Click",SendMessageOptions.DontRequireReceiver);
+ }
+
+ SendMessage("PushDetector_Release", SendMessageOptions.DontRequireReceiver);
+ IsClicked = false;
+ sent_push = false;
+ }
+ else
+ {
+ if (!sent_push && !IsClick(clickPushTime, ClickPosition, Time.time, pos))
+ {
+ SendMessage("PushDetector_Push", SendMessageOptions.DontRequireReceiver);
+ sent_push = true;
+ }
+ }
+ }
+
+ // drift the slider to the initial position, if we aren't clicked
+ if (!IsClicked) {
+ float delta = initialValue - ClickProgress;
+ pushFader.MoveTo(pos, ClickProgress + (delta * driftSpeed));
+ }
+ }
+
+ void Hand_Destroy()
+ {
+ if (IsClicked) {
+ SendMessage("PushDetector_Release", SendMessageOptions.DontRequireReceiver);
+ IsClicked = false;
+ }
+ }
+
+ bool IsClick(float t1, Vector3 p1, float t2, Vector3 p2)
+ {
+ Vector3 delta = (p2 - p1);
+ delta.z = 0;
+ return ((t2 - t1 < clickTimeFrame) && (delta.magnitude < clickMaxDistance));
+ }
+
+ void SessionManager_Visualize()
+ {
+ GUILayout.Label("- PushDetector");
+ GUILayout.Toggle(IsClicked, "PUSH");
+ }
+
+
+}
View
393 Assets/Imola/Scripts/HandpointControls/ScrollingMenu.cs
@@ -0,0 +1,393 @@
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+
+[RequireComponent(typeof(Fader))]
+public class ScrollingMenu : MonoBehaviour
+{
+ public Fader fader;
+ public Vector3 direction = Vector3.down;
+ public int WindowSize;
+ public float damping = 5.0f;
+ public float scrollRegionSize = 0.15f;
+ public bool RepositionBasedOnBounds = false;
+ public bool RepositionItemsOnUpdate;
+ public bool SelectOnPush;
+ public bool PushSlide;
+ public float pushSliderSize = 200;
+ public float pushSliderSensitiviy = 10.0f;
+
+ List<Transform> items = new List<Transform>();
+ ItemSelector selector;
+ GameObject itemsContainer;
+ Vector3 itemsContainerTargetPos;
+
+ Fader pushslideFader;
+ bool pushSliding;
+ float centerIndexBase;
+
+ float centerIndex = 0;
+ public float CenterIndex
+ {
+ get { return centerIndex; }
+ private set
+ {
+ if (items.Count == 0) {
+ centerIndex = 0;
+ return;
+ }
+
+ // make sure we're not out o'range
+ centerIndex = Mathf.Clamp(value, 0, items.Count - 1);
+ int centerIndexFloored = Mathf.FloorToInt(centerIndex);
+
+ // find the target position. this is the position we want to be at the center of the menu
+ Vector3 target;
+ Vector3 omercy1 = items[centerIndexFloored].position;
+ if (centerIndexFloored + 1 < items.Count - 1) {
+ Vector3 omercy2 = items[centerIndexFloored + 1].position;
+ target = Vector3.Lerp(omercy1, omercy2, centerIndex - centerIndexFloored);
+ } else {
+ target = omercy1;
+ }
+
+ // convert the world target to local position (relative to items container)
+ target = itemsContainer.transform.InverseTransformPoint(target);
+
+ // only use the component of target in our menu's direction
+ target = direction.normalized * Mathf.Abs(Vector3.Dot(direction.normalized, target));
+
+ // position the items container so that target will be at local 0,0,0
+ itemsContainerTargetPos = -target;
+ }
+ }
+
+ int firstOnScreenIndex = 0;
+ int lastActiveItemIndex = 0;
+ public int activeItemIndex = -1;
+ public int ActiveItemIndex
+ {
+ get { return activeItemIndex; }
+ set
+ {
+ if (items.Count == 0) {
+ return;
+ }
+
+ // clamp
+ int clamped = Mathf.Clamp(value, 0, items.Count - 1);
+
+ // send activate/deactivate messages
+ if (clamped != activeItemIndex) {
+ Unhighlight();
+ HighlightItem(clamped);
+ }
+
+ // OOB
+ if (clamped != value) {
+ SendMessage("Menu_OutOfBounds", (value > 0), SendMessageOptions.DontRequireReceiver);
+ }
+
+ // see if we should scroll our sliding window
+ if (activeItemIndex < firstOnScreenIndex) {
+ firstOnScreenIndex = activeItemIndex;
+ }
+ if (activeItemIndex > firstOnScreenIndex + (WindowSize - 1)) {
+ firstOnScreenIndex = activeItemIndex - (WindowSize - 1);
+ }
+
+ // reposition items container to reflect the newly highlighted item
+ CenterIndex = (float)firstOnScreenIndex + (((float)WindowSize - 1) / 2.0f);
+ }
+ }
+
+ public bool CanScrollForward {
+ get {
+ return (items.Count > 0 && ActiveItemIndex < items.Count - 1);
+ }
+ }
+
+ public bool CanScrollBack {
+ get {
+ return (items.Count > 0 && ActiveItemIndex > 0);
+ }
+ }
+
+ void Awake()
+ {
+ // init the items container
+ Transform t = transform.Find("ItemsContainer");
+ if (t) {
+ itemsContainer = t.gameObject;
+ } else {
+ itemsContainer = new GameObject("ItemsContainer");
+ }
+ itemsContainer.transform.parent = transform;
+ itemsContainer.transform.localPosition = Vector3.zero;
+ itemsContainer.transform.localRotation = Quaternion.identity;
+ itemsContainerTargetPos = itemsContainer.transform.localPosition;
+
+ // fader
+ if (!fader) {
+ fader = GetComponent<Fader>();
+ }
+ if (!fader) {
+ Debug.LogError("Please add a fader to " + gameObject.name);
+ return;
+ }
+
+ // init the itemselector
+ selector = gameObject.AddComponent<ItemSelector>();
+ selector.fader = fader;
+
+ // push detector, if we need one
+ if (SelectOnPush || PushSlide) {
+ if (null == GetComponent<PushDetector>()) {
+ gameObject.AddComponent<PushDetector>();
+ }
+ }
+
+ // fader for the pushslider, if we need one
+ if (PushSlide) {
+ pushslideFader = gameObject.AddComponent<Fader>() as Fader;
+ pushslideFader.direction = fader.direction;
+ pushslideFader.size = pushSliderSize;
+ }
+ }
+
+ // Update is called once per frame
+ void Update()
+ {
+ // push sliding
+ if (pushSliding) {
+ // convert 0-1 slider to -1 to 1 slider
+ float pushedOffset = (pushslideFader.value - 0.5f) * 2;
+ CenterIndex = centerIndexBase + (pushedOffset * pushSliderSensitiviy);
+ }
+
+ // move itemscontainer
+ itemsContainer.transform.localPosition = Vector3.Lerp(itemsContainer.transform.localPosition, itemsContainerTargetPos, Time.deltaTime * damping);
+
+ if (RepositionItemsOnUpdate) {
+ RepositionItems();
+ }
+ }
+
+ // Backwards compatibility
+ void Menu_Add(Transform item)
+ {
+ Add(item);
+ }
+
+ void Menu_Reposition()
+ {
+ RepositionItems();
+ }
+
+ public void Add(Transform item)
+ {
+ item.parent = itemsContainer.transform;
+ items.Add(item);
+ RepositionItems();
+
+ // first item
+ if (items.Count == 1) {
+ HighlightItem(0);
+ }
+
+ ActiveItemIndex = ActiveItemIndex;
+ }
+
+ public void Clear()
+ {
+ foreach (Transform item in items)
+ {
+ Destroy(item.gameObject);
+ }
+ items.Clear();
+ }
+
+ void RepositionItems()
+ {
+ // update window size & itemselector
+ WindowSize = Mathf.Max(WindowSize, 1);
+ selector.numItems = WindowSize;
+ selector.scrollRegion = scrollRegionSize;
+
+ // position of next item
+ Vector3 current = Vector3.zero;
+ Bounds currentBounds = new Bounds();
+
+ foreach (Transform item in items) {
+ // get the bounds for this item BEFORE moving item. The bounds includes both
+ // the old & new positions if we change localPosition first
+ if (RepositionBasedOnBounds) {
+ currentBounds = GetBoundingBox(item.gameObject);
+ }
+
+ // reposition this item
+ item.localPosition = current;
+
+ // update "current" for next item
+ if (RepositionBasedOnBounds) {
+ current += Mathf.Abs(Vector3.Dot(direction.normalized, currentBounds.size)) * direction.normalized;
+ }
+ current += direction;
+ }
+ }
+
+ Bounds GetBoundingBox(GameObject go)
+ {
+ Bounds newBounds = new Bounds(go.transform.position, Vector3.zero);
+ foreach (Renderer child in go.GetComponentsInChildren<Renderer>()) {
+ newBounds.Encapsulate(child.bounds);
+ }
+ return newBounds;
+ }
+
+ void SelectActive()
+ {
+ items[ActiveItemIndex].SendMessage("MenuItem_Select", SendMessageOptions.DontRequireReceiver);
+ SendMessage("Menu_Select", items[ActiveItemIndex], SendMessageOptions.DontRequireReceiver);
+ }
+
+ //-------------------------------------------------------------------------
+ // ItemSelector messages
+ //-------------------------------------------------------------------------
+
+ void ItemSelector_Select(int index)
+ {
+ if (pushSliding) return;
+ ActiveItemIndex = firstOnScreenIndex + index;
+ }
+
+ void ItemSelector_Next()
+ {
+ if (pushSliding) return;
+ ActiveItemIndex++;
+ }
+
+ void ItemSelector_Prev()
+ {
+ if (pushSliding) return;
+ ActiveItemIndex--;
+ }
+
+ //-------------------------------------------------------------------------
+ // PushDetector messages
+ //-------------------------------------------------------------------------
+
+ void PushDetector_Push()
+ {
+ if (PushSlide) {
+ pushslideFader.MoveTo(gameObject.GetComponent<PushDetector>().ClickPosition, 0.5f);
+ centerIndexBase = CenterIndex;
+ pushSliding = true;
+ }
+ }
+
+ void PushDetector_Release()
+ {
+ if (PushSlide) {
+ pushSliding = false;
+ ActiveItemIndex = Mathf.FloorToInt(CenterIndex);
+ }
+ }
+
+ void PushDetector_Click()
+ {
+ if (SelectOnPush) {
+ SelectActive();
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ // Hand point messages
+ //-------------------------------------------------------------------------
+
+ void Hand_Create(Vector3 pos)
+ {
+ HighlightItem(lastActiveItemIndex);
+ }
+
+ void Hand_Update(Vector3 pos)
+ {
+ }
+
+ void Hand_Destroy()
+ {
+ Unhighlight();
+ }
+
+ //-------------------------------------------------------------------------
+ // Highlighting/Unhighlighting items
+ //-------------------------------------------------------------------------
+
+ void HighlightItem(int index)
+ {
+ if (items.Count == 0) {
+ return;
+ }
+
+ activeItemIndex = index;
+ items[index].SendMessage("MenuItem_Highlight", SendMessageOptions.DontRequireReceiver);
+ SendMessage("Menu_Highlight", items[index], SendMessageOptions.DontRequireReceiver);
+ }
+
+ void Unhighlight()
+ {
+ if (ActiveItemIndex == -1 || items.Count == 0) {
+ return;
+ }
+
+ items[ActiveItemIndex].SendMessage("MenuItem_Unhighlight", SendMessageOptions.DontRequireReceiver);
+ SendMessage("Menu_Unhighlight", items[activeItemIndex], SendMessageOptions.DontRequireReceiver);
+ lastActiveItemIndex = ActiveItemIndex;
+ activeItemIndex = -1;
+ }
+
+ //-------------------------------------------------------------------------
+ // Keyboard support
+ //-------------------------------------------------------------------------
+
+ void OnGUI()
+ {
+ if (Event.current.type == EventType.KeyDown) {
+ if (!GetComponent<HandPointControl>().IsActive) { return; }
+
+ if (Event.current.keyCode == KeyCode.UpArrow ||
+ Event.current.keyCode == KeyCode.LeftArrow) {
+ ActiveItemIndex--;
+ Event.current.Use();
+ }
+
+ if (Event.current.keyCode == KeyCode.DownArrow ||
+ Event.current.keyCode == KeyCode.RightArrow) {
+ ActiveItemIndex++;
+ Event.current.Use();
+ }
+
+ if (Event.current.keyCode == KeyCode.Return) {
+ SelectActive();
+ Event.current.Use();
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ // Debug visualization
+ //-------------------------------------------------------------------------
+
+ void OnDrawGizmos()
+ {
+ // draw bounding box for each item
+ int i = 0;
+ foreach (Transform item in items) {
+ Gizmos.color = (i == ActiveItemIndex) ? Color.red : Color.white;
+ Bounds bbox = GetBoundingBox(item.gameObject);
+ Gizmos.DrawWireCube(bbox.center, bbox.size);
+ i++;
+ }
+ }
+
+}
View
18 Assets/Imola/Scripts/HandpointControls/SessionManagerVisualizer.cs
@@ -0,0 +1,18 @@
+using UnityEngine;
+using System.Collections;
+using System.Reflection;
+
+public class SessionManagerVisualizer : MonoBehaviour {
+ public bool Visible;
+ void OnGUI()
+ {
+ if (Event.current.Equals(Event.KeyboardEvent("f1"))) {
+ Visible = !Visible;
+ Event.current.Use();
+ }
+
+ if (Visible) {
+ OpenNISessionManager.Instance.DebugDrawListeners();
+ }
+ }
+}
View
114 Assets/Imola/Scripts/HandpointControls/StaticMenu.cs
@@ -0,0 +1,114 @@
+using UnityEngine;
+using System.Collections;
+
+[RequireComponent(typeof(Fader))]
+public class StaticMenu : MonoBehaviour {
+ public Transform[] items;
+ public bool SelectOnPush;
+ public Fader fader;
+
+ ItemSelector selector;
+
+ int lastActiveItemIndex = 0;
+ int activeItemIndex = -1;
+ public int ActiveItemIndex
+ {
+ get { return activeItemIndex; }
+ set
+ {
+ if (items.Length == 0) {
+ return;
+ }
+
+ // clamp
+ int clamped = Mathf.Clamp(value, 0, items.Length - 1);
+
+ // send activate/deactivate messages
+ if (clamped != activeItemIndex) {
+ Unhighlight();
+ HighlightItem(clamped);
+ }
+ }
+ }
+
+
+ // Use this for initialization
+ void Start () {
+ if (!fader) {
+ fader = GetComponent<Fader>();
+ }
+ if (!fader) {
+ Debug.LogError("Please add a fader to " + gameObject.name);
+ return;
+ }
+
+ selector = gameObject.AddComponent<ItemSelector>();
+ selector.numItems = items.Length;
+ selector.scrollRegion = 0.0f;
+ selector.fader = fader;
+
+ if (SelectOnPush) {
+ if (null == GetComponent<PushDetector>()) {
+ gameObject.AddComponent<PushDetector>();
+ }
+ }
+ }
+
+ void ItemSelector_Select(int index)
+ {
+ ActiveItemIndex = index;
+ }
+
+ void PushDetector_Click()
+ {
+ if (SelectOnPush) {
+ items[ActiveItemIndex].SendMessage("MenuItem_Select", SendMessageOptions.DontRequireReceiver);
+ SendMessage("Menu_Select", items[ActiveItemIndex], SendMessageOptions.DontRequireReceiver);
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ // Highlighting/Unhighlighting items
+ //-------------------------------------------------------------------------
+
+ void HighlightItem(int index)
+ {
+ if (items.Length == 0) {
+ return;
+ }
+
+ activeItemIndex = index;
+ items[index].SendMessage("MenuItem_Highlight", SendMessageOptions.DontRequireReceiver);
+ SendMessage("Menu_Highlight", items[index], SendMessageOptions.DontRequireReceiver);
+ }
+
+ void Unhighlight()
+ {
+ if (ActiveItemIndex == -1 || items.Length == 0) {
+ return;
+ }
+
+ items[ActiveItemIndex].SendMessage("MenuItem_Unhighlight", SendMessageOptions.DontRequireReceiver);
+ SendMessage("Menu_Unhighlight", items[activeItemIndex], SendMessageOptions.DontRequireReceiver);
+ lastActiveItemIndex = ActiveItemIndex;
+ activeItemIndex = -1;
+ }
+
+ //-------------------------------------------------------------------------
+ // Hand point events
+ //-------------------------------------------------------------------------
+
+ void Hand_Create(Vector3 pos)
+ {
+ HighlightItem(lastActiveItemIndex);
+ }
+
+ void Hand_Update(Vector3 pos)
+ {
+ }
+
+ void Hand_Destroy()
+ {
+ Unhighlight();
+ }
+}
View
122 Assets/Imola/Scripts/HandpointControls/SwipeDetector.cs
@@ -0,0 +1,122 @@
+using UnityEngine;
+using System.Collections;
+
+public enum SwipeDetectorDirection
+{
+ Horizontal,
+ Vertical,
+}
+
+[RequireComponent(typeof(HandPointControl))]
+public class SwipeDetector : MonoBehaviour {
+ public float size = 250.0f;
+ public SwipeDetectorDirection direction = SwipeDetectorDirection.Horizontal;
+
+ public Fader swipeFader { get; private set; }
+ string dirStr;
+
+ public bool IsSwiped { get; private set; }
+ float swipedValue;
+
+ // Use this for initialization
+ void Awake () {
+ swipeFader = gameObject.AddComponent<Fader>();
+ swipeFader.direction = SwipeDirectionToVector(direction);
+ }
+
+ // Update is called once per frame
+ void Update () {
+
+ }
+
+ void Hand_Create(Vector3 pos)
+ {
+ swipeFader.size = size;
+ swipeFader.initialValue = 0.5f;
+ swipeFader.MoveTo(pos, 0.5f);
+
+ Hand_Update(pos);
+ }
+
+ void Hand_Update(Vector3 pos)
+ {
+ // move fader if hand is out of its bounds (that way it always feels responsive)
+ swipeFader.MoveToContain(pos);
+ swipeFader.Hand_Update(pos);
+
+ // quick out if in cooldown
+ if (OpenNISessionManager.Instance.CoolingDown) return;
+
+ // swipe logic
+ if (!IsSwiped) {
+
+ if (Mathf.Approximately(swipeFader.value, 1.0f) ||
+ Mathf.Approximately(swipeFader.value, 0.0f)) {
+
+ IsSwiped = true;
+ swipedValue = swipeFader.value;
+ SendMessage("SwipeDetector_Swipe", swipedValue, SendMessageOptions.DontRequireReceiver);
+ dirStr = FaderValueToEventName(swipedValue, direction);
+ SendMessage("SwipeDetector_" + dirStr, SendMessageOptions.DontRequireReceiver);
+ }
+ }
+ else { // Swiped
+ if (Mathf.Abs(swipedValue - swipeFader.value) >= 0.5f) {
+ IsSwiped = false;
+ SendMessage("SwipeDetector_Release", SendMessageOptions.DontRequireReceiver);
+ }
+ }
+
+ // drift the slider to the initial position, if we aren't in a swipe
+ if (!IsSwiped) {
+ float delta = 0.5f - swipeFader.value;
+ swipeFader.MoveTo(pos, swipeFader.value + (delta * 0.02f));
+ }
+ }
+
+ void Hand_Destroy()
+ {
+ if (IsSwiped) {
+ SendMessage("SwipeDetector_Release", SendMessageOptions.DontRequireReceiver);
+ IsSwiped = false;
+ }
+ }
+
+ string FaderValueToEventName(float val, SwipeDetectorDirection dir)
+ {
+ if (Mathf.Approximately(val, 1.0f)) {
+ switch (dir) {
+ case SwipeDetectorDirection.Horizontal : return "Right";
+ case SwipeDetectorDirection.Vertical : return "Up";
+ }
+ }
+
+ if (Mathf.Approximately(val, 0.0f)) {
+ switch (dir) {
+ case SwipeDetectorDirection.Horizontal : return "Left";
+ case SwipeDetectorDirection.Vertical : return "Down";
+ }
+ }
+
+ return "";
+ }
+
+ Vector3 SwipeDirectionToVector(SwipeDetectorDirection dir)
+ {
+ switch (dir) {
+ case SwipeDetectorDirection.Horizontal: return (NIContext.Instance.Mirror) ? Vector3.left : Vector3.right;
+ case SwipeDetectorDirection.Vertical: return Vector3.up;
+ }
+ return Vector3.zero;
+ }
+
+ void SessionManager_Visualize()
+ {
+ GUILayout.Label("- Swipe Detector");
+ if (IsSwiped) {
+ GUILayout.Label(dirStr);
+ } else {
+ GUILayout.HorizontalSlider(swipeFader.value, 0.0f, 1.0f);
+ }
+ }
+}
View
22 Assets/Imola/Scripts/LoadScenetest.cs
@@ -0,0 +1,22 @@
+using UnityEngine;
+using System.Collections;
+
+public class LoadScenetest : MonoBehaviour {
+
+ // Use this for initialization
+ void Start () {
+
+ }
+
+ // Update is called once per frame
+ void Update () {
+
+ }
+
+ void OnGUI()
+ {
+ if (Event.current.Equals(Event.KeyboardEvent("l"))) {
+ Application.LoadLevel(1);
+ }
+ }
+}
View
278 Assets/Imola/Scripts/MainMenu/GUIBuilder.cs
@@ -0,0 +1,278 @@
+using UnityEngine;
+using System.Collections;
+using OpenNI;
+using ImolaNI;
+
+public class GUIBuilder : MonoBehaviour
+{
+ private string buttonPressedMessage = "Nothing was pressed yet";
+ private InputGestureDetector swipeRightDetector;
+ private InputGestureDetector swipeLeftDetector;
+ private InputGestureDetector crossHandDetector;
+ private InputGestureDetector pushDetector;
+ private InputGestureDetector waveDetector;
+ private InputGestureDetector steadyDetector;
+ private InputGestureDetector leftHandupDetector;
+ private int waves = 0;
+ private int pushes = 0;
+ private int crossHands = 0;
+ private int swipeLefts = 0;
+ private int swipeRights = 0;
+ private int steadys = 0;
+ private int leftHandups = 0;
+
+
+ private Rect myRect = new Rect (0, 0, 300, 100);
+ NIInput m_input; ///< @brief The input we get the axes from.
+ NISkeletonTracker m_tracker;
+
+ public GUISkin menuSkin;
+ public Rect menuArea;
+ public Rect playButton;
+ public Rect instructionsButton;
+ public Rect quitButton;
+ Rect menuAreaNormalized;
+ /// mono-behavior start - initializes the input
+ public void Start ()
+ {
+ if(m_input==null)
+ {
+ m_input = FindObjectOfType(typeof(NIInput)) as NIInput;
+ if (m_input == null)
+ throw new System.Exception("Please add an NIInput object to the scene");
+ }
+
+ if(m_tracker == null) {
+ m_tracker = FindObjectOfType(typeof(NISkeletonTracker)) as NISkeletonTracker;
+ }
+
+ swipeRightDetector = new InputGestureDetector(m_input, "NIGUI_SWIPE_RIGHT");
+ swipeLeftDetector = new InputGestureDetector(m_input, "NIGUI_SWIPE_LEFT");
+ crossHandDetector = new InputGestureDetector(m_input, "NIGUI_CROSS_HAND");
+ pushDetector = new InputGestureDetector(m_input, "NIGUI_PUSH");
+ waveDetector = new InputGestureDetector(m_input, "NIGUI_WAVE");
+ steadyDetector = new InputGestureDetector(m_input, "NIGUI_CLICK");
+ leftHandupDetector = new InputGestureDetector(m_input, "NIGUI_LEFT_HANDUP");
+ menuAreaNormalized =
+ new Rect (menuArea.x * Screen.width - (menuArea.width * 0.5f),
+ menuArea.y * Screen.height - (menuArea.height * 0.5f),
+ menuArea.width, menuArea.height);
+ }
+
+ void OnGUI1 ()
+ {
+ GUI.skin = menuSkin;
+
+ // place the button pressed label
+ myRect.x = (Screen.width / 2) - 125;
+
+ myRect.y = (Screen.height / 2) - 20;
+ myRect.width = 600;
+ myRect.height = 60;
+ GUI.Box (myRect, buttonPressedMessage);
+
+ GUI.BeginGroup (menuAreaNormalized);
+
+
+ if (NIGUI.Button (new Rect (playButton), "Play")) {
+ buttonPressedMessage = "Play was pressed at time=" + Time.time;
+ }
+ if (NIGUI.Button (new Rect (instructionsButton), "Instructions")) {
+ buttonPressedMessage = "Instructions was pressed at time=" + Time.time;
+ }
+ if (NIGUI.Button (new Rect (quitButton), "Quit")) {
+ Application.Quit ();
+ }
+
+ GUI.EndGroup ();
+
+ }
+
+ /// mono-behavior OnGUI to show GUI elements
+ public void OnGUI ()
+ {
+ /*if (DetectGesture("NIGUI_CROSS_HAND", ref currentCrossHand)) {
+ crossHands++;
+ }
+ if (DetectGesture("NIGUI_PUSH", ref currentPush)) {
+ pushes++;
+ }
+ if(DetectGesture("NIGUI_WAVE", ref currentWave)) {
+ waves++;
+ }
+ //DetectGesture("NIGUI_RAISE_HAND");
+ if(DetectGesture("NIGUI_CLICK", ref currentSteady)) {
+ steadys++;
+ }*/
+ if (swipeRightDetector.Detect())
+ {
+ swipeRights++;
+ }
+ if (swipeLeftDetector.Detect())
+ {
+ swipeLefts++;
+ }
+ if (crossHandDetector.Detect())
+ {
+ crossHands++;
+ }
+ if (pushDetector.Detect())
+ {
+ pushes++;
+ }
+ if (waveDetector.Detect())
+ {
+ waves++;
+ }
+ if (steadyDetector.Detect())
+ {
+ steadys++;
+ }
+ if (leftHandupDetector.Detect())
+ {
+ leftHandups++;
+ }
+ DrawGUI();
+ }
+
+ private bool DetectGesture(string gesture, ref bool currentGestureChecked)
+ {
+
+ float val = m_input.GetAxis (gesture);
+ Debug.Log("current gesture " + gesture + " value is " + val + " and checked is " + currentGestureChecked +
+ "swipeRight number is " + swipeRights);
+ if (val >= 1.0f) {
+ if(currentGestureChecked) {
+ Debug.Log("ignore duplicated " + gesture);
+ return false;
+ } else {
+ buttonPressedMessage = gesture + " has been detected value =" + val;
+ Debug.Log("Fired:" + gesture);
+ currentGestureChecked = true;
+ return true;
+ }
+
+ }
+ if (val > 0) {
+ // The value is between 0 and 1 so we have detected the exit pose and are waiting
+ // for it to continue long enough.
+ // Just pop up a message telling the user to continue holding the pose...
+ buttonPressedMessage = "Hold the " + gesture + " pose until " + val + " reaches 1";
+ currentGestureChecked = false;
+ }
+ currentGestureChecked = false;
+ return false;
+ }
+
+ private bool DetectGesture(string gesture, ref float lastHappenTime)
+ {
+ if (lastHappenTime == 0) {
+ lastHappenTime = Time.time;
+ }
+
+ float val = m_input.GetAxis (gesture);
+
+ if (val >= 1.0f) {
+ if(m_input.HasFiredSinceTime(lastHappenTime, gesture)) {
+ return false;
+ } else {
+ buttonPressedMessage = gesture + " has been detected value =" + val;
+ Debug.Log("Fired:" + gesture);
+ lastHappenTime = Time.time;
+ return true;
+ }
+
+ }
+ if (val > 0) {
+ // The value is between 0 and 1 so we have detected the exit pose and are waiting
+ // for it to continue long enough.
+ // Just pop up a message telling the user to continue holding the pose...
+ buttonPressedMessage = "Hold the " + gesture + " pose until " + val + " reaches 1";
+ }
+
+ return false;
+ }
+
+ private void DrawGUI()
+ {
+ GUI.skin = menuSkin;
+ // place the first button
+ myRect.x = Screen.width - 300;
+ myRect.y = 100;
+ myRect.width = 200;
+ myRect.height = 80;
+ if (NIGUI.Button (myRect, "Play")) {
+ buttonPressedMessage = "Button Play was pressed at time=" + Time.time;
+ }
+
+ // place the second button
+ //myRect.x = Screen.width - 200;;
+ myRect.y = 300;
+ if (NIGUI.Button (myRect, "Demo")) {
+ buttonPressedMessage = "Button Demo was pressed at time=" + Time.time;
+ }
+
+ //myRect.x = Screen.width - 200;;
+ myRect.y = 500;
+ if (NIGUI.Button (myRect, "Quit")) {
+ buttonPressedMessage = "Button Quit was pressed at time=" + Time.time;
+ Application.Quit ();
+ }
+
+ // place the button pressed label
+ myRect.x = Screen.width / 2 - 300;
+ myRect.y = 20;
+ myRect.width = 800;
+ myRect.height = 50;
+ GUI.Box (myRect, buttonPressedMessage);
+
+ myRect.x = 100;
+ myRect.y = 100;
+ myRect.width = 240;
+ myRect.height = 40;
+ GUI.Box(myRect, "CrossHand:" + crossHands);
+
+ myRect.x += 280;
+ GUI.Box(myRect, "Wave:" + waves);
+
+ myRect.x += 280;
+ GUI.Box(myRect, "Push:" + pushes);
+
+ myRect.x += 280;
+ GUI.Box(myRect, "Steady:" + steadys);
+
+ myRect.x = 100;
+ myRect.y = 240;
+ GUI.Box(myRect, "SwipeLeft:" + swipeLefts);
+
+ myRect.x += 280;
+ myRect.y = 240;
+ GUI.Box(myRect, "SwipeRight:" + swipeRights);
+
+ myRect.x += 280;
+ myRect.y = 240;
+ GUI.Box(myRect, "HandupL:" + leftHandups);
+
+ NISelectedPlayer player = m_tracker.GetTrackedPlayer();
+ SkeletonJointPosition rightHand;
+ if(player.GetSkeletonJointPosition(SkeletonJoint.RightHand,out rightHand)==false || rightHand.Confidence<=0.5f)
+ return ;
+
+ Vector3 pos = NIConvertCoordinates.ConvertPos(rightHand.Position);
+ myRect.x = 400;
+ myRect.y = 300;
+ GUI.Box(myRect, "" + pos.x);
+
+ myRect.x = 400;
+ myRect.y = 400;
+ GUI.Box(myRect, "" + pos.y);
+ // Click axis value label
+ /*
+ myRect.x = 50;
+ myRect.y = (Screen.height / 2) + 20;
+ myRect.width = 250;
+ myRect.height = 30;
+ GUI.Box (myRect, "value=" + m_input.GetAxis ("NIGUI_CLICK"));
+ */
+ }
+}
View
10 Assets/Imola/Scripts/Math/MathHelper.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Kinect.Toolbox
+{
+ public static class MathHelper
+ {
+ public const float PiOver4 = (float)Math.PI / 4.0f;
+ public const float PiOver2 = (float)Math.PI / 2.0f;
+ }
+}
View
60 Assets/Imola/Scripts/Math/Vector2.cs
@@ -0,0 +1,60 @@
+using System;
+
+namespace Kinect.Toolbox
+{
+ [Serializable]
+ public struct Vector2
+ {
+ public float X;
+ public float Y;
+
+ public static Vector2 Zero
+ {
+ get
+ {
+ return new Vector2(0, 0);
+ }
+ }
+
+ public Vector2(float x, float y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ public float Length
+ {
+ get
+ {
+ return (float)Math.Sqrt(X * X + Y * Y);
+ }
+ }
+
+ public static Vector2 operator -(Vector2 left, Vector2 right)
+ {
+ return new Vector2(left.X - right.X, left.Y - right.Y);
+ }
+
+ public static Vector2 operator +(Vector2 left, Vector2 right)
+ {
+ return new Vector2(left.X + right.X, left.Y + right.Y);
+ }
+
+ public static Vector2 operator *(Vector2 left, float value)
+ {
+ return new Vector2(left.X * value, left.Y * value);
+ }
+
+ public static Vector2 operator *(float value, Vector2 left)
+ {
+ return left * value;
+ }
+
+ public static Vector2 operator /(Vector2 left, float value)
+ {
+ return new Vector2(left.X / value, left.Y / value);
+ }
+
+ }
+
+}
View
60 Assets/Imola/Scripts/Math/Vector3.cs
@@ -0,0 +1,60 @@
+using System;
+
+namespace Kinect.Toolbox
+{
+ [Serializable]
+ public struct Vector3
+ {
+ public float X;
+ public float Y;
+ public float Z;
+
+ public static Vector3 Zero
+ {
+ get
+ {
+ return new Vector3(0, 0, 0);
+ }
+ }
+
+ public Vector3(float x, float y, float z)
+ {
+ X = x;
+ Y = y;
+ Z = z;
+ }
+
+ public float Length
+ {
+ get
+ {
+ return (float)Math.Sqrt(X * X + Y * Y + Z * Z);
+ }
+ }
+
+ public static Vector3 operator -(Vector3 left, Vector3 right)
+ {
+ return new Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
+ }
+
+ public static Vector3 operator +(Vector3 left, Vector3 right)
+ {
+ return new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
+ }
+
+ public static Vector3 operator *(Vector3 left, float value)
+ {
+ return new Vector3(left.X * value, left.Y * value, left.Z * value);
+ }
+
+ public static Vector3 operator *(float value, Vector3 left)
+ {
+ return left * value;
+ }
+
+ public static Vector3 operator /(Vector3 left, float value)
+ {
+ return new Vector3(left.X / value, left.Y / value, left.Z / value);
+ }
+ }
+}
View
48 Assets/Imola/Scripts/MenuItemChangeColor.cs
@@ -0,0 +1,48 @@
+using UnityEngine;
+using System.Collections;
+
+public class MenuItemChangeColor : MonoBehaviour
+{
+ public Color defaultColor = Color.white;
+ public Color highlightColor = Color.green;
+ public Color selectColor = Color.blue;
+ public Renderer target;
+ public float damping = 5.0f;
+ Color targetColor;
+
+ // Use this for initialization
+ void Awake()
+ {
+ if (null == target) {
+ target = GetComponent<Renderer>();
+ }
+ if (null == target) {
+ Debug.LogError("Missing a renderer for MenuItemChangeColor");
+ return;
+ }
+ targetColor = defaultColor;
+ target.material.color = defaultColor;
+ }
+
+ void Update()
+ {
+ if (!target) return;
+
+ target.material.color = Color.Lerp(target.material.color, targetColor, Time.deltaTime * damping);
+ }
+
+ void MenuItem_Highlight()
+ {
+ targetColor = highlightColor;
+ }
+
+ void MenuItem_Unhighlight()
+ {
+ targetColor = defaultColor;
+ }
+
+ void MenuItem_Select()
+ {
+ targetColor = selectColor;
+ }
+}
View
199 Assets/Imola/Scripts/OpenNIDepthmapToMesh.cs
@@ -0,0 +1,199 @@
+
+using UnityEngine;
+using System;
+using System.Collections;
+using System.Runtime.InteropServices;
+using OpenNI;
+
+public class OpenNIDepthmapToMesh : MonoBehaviour
+{
+ public Vector3 gridScale = Vector3.one;
+ public bool GenerateNormals = false;
+ public bool GenerateUVs = true;
+ public bool RealWorldPoints = true; // perform perspective transform on depth-map
+
+ public Vector2 DesiredResolution = new Vector2(160, 120); // should be a divisor of 640x480
+ // and 320x240 is too high (too many vertices)
+ int factorX;
+ int factorY;
+
+ short[] rawDepthMap;
+ float[] depthHistogramMap;
+ int XRes;
+ int YRes;
+ Mesh mesh;
+ MeshFilter meshFilter;
+
+ Vector2[] uvs;
+ Vector3[] verts;
+ int[] tris;
+ Point3D[] pts;
+ // Use this for initialization
+ void Start()
+ {
+ // init stuff
+ MapOutputMode mom = NIContext.Instance.Depth.MapOutputMode;
+ YRes = mom.YRes;
+ XRes = mom.XRes;
+ factorX = (int)(XRes / DesiredResolution.x);
+ factorY = (int)(YRes / DesiredResolution.y);
+ // depthmap data
+ rawDepthMap = new short[(int)(mom.XRes * mom.YRes)];
+
+ // the actual mesh we'll use
+
+ mesh = new Mesh();
+
+ meshFilter = (MeshFilter)GetComponent(typeof(MeshFilter));
+ meshFilter.mesh = mesh;
+
+ int YScaled = YRes / factorY;
+ int XScaled = XRes / factorX;
+
+ verts = new Vector3[XScaled * YScaled];
+ uvs = new Vector2[verts.Length];
+ tris = new int[(XScaled - 1) * (YScaled - 1) * 2 * 3];
+ pts = new Point3D[XScaled * YScaled];
+ CalculateTriangleIndices(YScaled, XScaled);
+ CalculateUVs(YScaled, XScaled);
+ }
+
+ void UpdateDepthmapMesh()
+ {
+ if (meshFilter == null)
+ return;
+ Profiler.BeginSample("UpdateDepthmapMesh");
+ mesh.Clear();
+
+ // flip the depthmap as we create the texture
+ int YScaled = YRes / factorY;
+ int XScaled = XRes / factorX;
+ // first stab, generate all vertices (next time, only vertices for 'valid' depths)
+ // first stab, decimate rather than average depth pixels
+ UpdateVertices(YScaled, XScaled);
+ if (GenerateUVs) {
+ UpdateUVs(YScaled, XScaled);
+ }
+ UpdateTriangleIndices();
+ // normals - if we generate we need to update them according to the new mesh
+ if (GenerateNormals) {
+ mesh.RecalculateNormals();
+ }
+
+ Profiler.EndSample();
+ }
+
+ private void UpdateUVs(int YScaled, int XScaled)
+ {
+ Profiler.BeginSample("UpdateUVs");
+ mesh.uv = uvs;
+ Profiler.EndSample();
+ }
+
+ private void CalculateUVs(int YScaled, int XScaled)
+ {
+ for (int y = 0; y < YScaled; y++) {
+ for (int x = 0; x < XScaled; x++) {
+ //uvs[y * XScaled + x] = new Vector2((float)x / (float)XScaled,
+ // (float)y / (float)YScaled);
+ uvs[y * XScaled + x].x = (float)x / (float)XScaled;
+ uvs[y * XScaled + x].y = ((float)(YScaled - 1 - y) / (float)YScaled);
+ }
+ }
+ }
+
+ private void UpdateVertices(int YScaled, int XScaled)
+ {
+ int depthIndex = 0;
+ Profiler.BeginSample("UpdateVertices");
+
+ Profiler.BeginSample("FillPoint3Ds");
+ DepthGenerator dg = NIContext.Instance.Depth;
+ short maxDepth = (short)NIContext.Instance.Depth.DeviceMaxDepth;
+ Vector3 vec = new Vector3();
+ Point3D pt = new Point3D();
+ for (int y = 0; y < YScaled; y++) {
+ for (int x = 0; x < XScaled; x++, depthIndex += factorX) {
+ short pixel = rawDepthMap[depthIndex];
+ if (pixel == 0) pixel = maxDepth; // if there's no depth, default to max depth
+
+ // RW coordinates
+ pt.X = x * factorX;
+ pt.Y = y * factorY;
+ pt.Z = pixel;
+ pts[x + y * XScaled] = pt; // in structs, assignment is a copy, so modifying the same variable
+ // every iteration is okay
+ }
+ // Skip lines
+ depthIndex += (factorY - 1) * XRes;
+ }
+ Profiler.EndSample();
+ Profiler.BeginSample("ProjectiveToRW");
+ if (RealWorldPoints) {
+ pts = dg.ConvertProjectiveToRealWorld(pts);
+ }
+ else {
+ for (int i = 0; i < pts.Length; i++) {
+ pts[i].X -= XRes / 2;
+ pts[i].Y = (YRes / 2) - pts[i].Y; // flip Y axis in projective
+ }
+ }
+ Profiler.EndSample();
+ Profiler.BeginSample("PointsToVertices");
+ for (int y = 0; y < YScaled; y++) {
+ for (int x = 0; x < XScaled; x++) {
+ pt = pts[x + y * XScaled];
+ vec.x = pt.X * gridScale.x;
+ vec.y = pt.Y * gridScale.y;
+ vec.z = -pt.Z * gridScale.z;
+ verts[y * XScaled + x] = vec;
+ }
+ }
+ Profiler.EndSample();
+ Profiler.BeginSample("AssignVerticesToMesh");
+ mesh.vertices = verts;
+ Profiler.EndSample();
+
+ Profiler.EndSample();
+ }
+
+ private void UpdateTriangleIndices()
+ {
+ Profiler.BeginSample("UpdateTriangleIndices");
+
+ mesh.triangles = tris;
+ Profiler.EndSample();
+ }
+
+ private void CalculateTriangleIndices(int YScaled, int XScaled)
+ {
+ int triIndex = 0;
+ int posIndex = 0;
+ for (int y = 0; y < (YScaled - 1); y++) {
+ for (int x = 0; x < (XScaled - 1); x++, posIndex++) {
+ // Counter-clockwise triangles
+
+ tris[triIndex++] = posIndex + 1; // bottom right
+ tris[triIndex++] = posIndex; // bottom left
+ tris[triIndex++] = posIndex + XScaled; // top left
+
+ tris[triIndex++] = posIndex + 1; // bottom right
+ tris[triIndex++] = posIndex + XScaled; // top left
+ tris[triIndex++] = posIndex + XScaled + 1; // top right
+ }
+ posIndex++; // finish row
+ }
+ }
+
+ int lastFrameId;
+ void FixedUpdate()
+ {
+ // update only if we have a new depth frame
+ if (lastFrameId != NIContext.Instance.Depth.FrameID) {
+ lastFrameId = NIContext.Instance.Depth.FrameID;
+ Marshal.Copy(NIContext.Instance.Depth.DepthMapPtr,
+ rawDepthMap, 0, rawDepthMap.Length);
+ UpdateDepthmapMesh();
+ }
+ }
+}
View
270 Assets/Imola/Scripts/OpenNIExt/HandupPoseDetector.cs
@@ -0,0 +1,270 @@
+using UnityEngine;
+using System.Collections;
+using OpenNI;
+
+public class HandupPoseDetector : NIGestureTracker
+{
+
+ /// Release the gesture
+ public override void ReleaseGesture()
+ {
+ m_pointTracker = null;
+ }
+
+ /// base constructor
+ /// @param timeToHoldPose the time the user is required to hold the pose.
+ /// @param maxMoveSpeed the maximum speed (in mm/sec) allowed for each of the relevant joints.
+ /// @param angleTolerance This is the allowed tolerance in degrees
+ /// @param timeToSavePoints the time we use to average points
+ public HandupPoseDetector(bool useRightHand, float timeToHoldPose, float maxMoveSpeed, float angleTolerance, float timeToSavePoints)
+ {
+ m_useRightHand = useRightHand;
+ m_maxMoveSpeed = maxMoveSpeed;
+ m_timeToHoldPose = timeToHoldPose;
+ m_timeToSavePoints = timeToSavePoints;
+ m_angleTolerance = angleTolerance;
+ m_holdingPose = false;
+ m_timeDetectedPose = 0;
+ m_firedEvent = false;
+ m_pointsHand = new NITimedPointSpeedListUtility(timeToSavePoints);
+ m_pointsElbow = new NITimedPointSpeedListUtility(timeToSavePoints);
+ m_pointsShoulder = new NITimedPointSpeedListUtility(timeToSavePoints);
+ }
+
+ /// This is true if the gesture is in the middle of doing (i.e. it has detected but not gone out of the gesture).
+ /// for our purposes this means the steady event has occurred and the unsteady has not occurred yet
+ /// @return a value between 0 and 1. 0 means no pose, 1 means the pose has been detected and held
+ /// for a while. a value in the middle means the pose has been detected and has been held this
+ /// portion of the time required to fire the trigger (@ref m_timeToHoldPose).
+ public override float GestureInProgress()
+ {
+ if (m_holdingPose == false)
+ return 0.0f;
+ float diffTime = Time.time - m_timeDetectedPose;
+ if (diffTime >= m_timeToHoldPose || m_timeToHoldPose <= 0)
+ return 1.0f;
+ return diffTime / m_timeToHoldPose;
+ }
+
+ /// used for updating every frame
+ /// @note While we are still steady (i.e. we haven't gotten a "not steady" event) we update
+ /// the time and frame every frame!
+ public override void UpdateFrame()
+ {
+ if (FillPoints() == false)
+ return;
+ int numPoints;
+ bool foundPos = TestHandupPose(out numPoints);
+ if (numPoints < 1)
+ return; // we don't have enough points to make a decision
+
+ if (foundPos == false)
+ {
+ m_holdingPose = false;
+ return;
+ }
+ // now we know we have found a pose.
+
+ // first time of the pose since last we didn't have a pose
+ if (m_holdingPose==false)
+ {
+ m_holdingPose = true;
+ m_timeDetectedPose = Time.time;
+ m_firedEvent = false;
+ }
+
+
+ float diffTime = Time.time - m_timeDetectedPose;
+ if (diffTime >= m_timeToHoldPose || m_timeToHoldPose <= 0)
+ {
+ InternalFireDetectEvent();
+ }
+ }
+
+ // protected methods
+
+ /// this method tries to fill a new point on each of the relevant joints.
+ /// It returns true if it succeed and false otherwise
+ /// @note it will fail if even one of the points has a low confidence!
+ /// @return true on success, false on failure.
+ protected bool FillPoints()
+ {
+ // first we find a reference to the skeleton capability
+ NISkeletonTracker hand = m_pointTracker as NISkeletonTracker;
+ if (hand == null)
+ return false; // no hand to track
+ NISelectedPlayer player = hand.GetTrackedPlayer();
+ if (player == null || player.Valid == false || player.Tracking == false)
+ return false; // no player to work with...
+
+ // We need to figure out if we have a good confidence on all joints
+ if(m_useRightHand)
+ {
+ SkeletonJointPosition rightHand;
+ SkeletonJointPosition rightElbow;
+ SkeletonJointPosition rightShoulder;
+
+ if(player.GetSkeletonJointPosition(SkeletonJoint.RightHand,out rightHand) == false || rightHand.Confidence <= 0.5f)
+ return false;
+
+ if(player.GetSkeletonJointPosition(SkeletonJoint.RightElbow,out rightElbow) == false || rightElbow.Confidence <= 0.5f)
+ return false;
+
+ if(player.GetSkeletonJointPosition(SkeletonJoint.RightShoulder,out rightShoulder) == false || rightShoulder.Confidence <= 0.5f)
+ return false;
+
+ Vector3 pos = NIConvertCoordinates.ConvertPos(rightHand.Position);
+ m_pointsHand.AddPoint(ref pos);
+
+ pos = NIConvertCoordinates.ConvertPos(rightElbow.Position);
+ m_pointsElbow.AddPoint(ref pos);
+
+ pos = NIConvertCoordinates.ConvertPos(rightShoulder.Position);
+ m_pointsShoulder.AddPoint(ref pos);
+ }
+ else
+ {
+ SkeletonJointPosition leftHand;
+ SkeletonJointPosition leftElbow;
+ SkeletonJointPosition leftShoulder;
+
+ if(player.GetSkeletonJointPosition(SkeletonJoint.LeftHand,out leftHand) == false || leftHand.Confidence <= 0.5f)
+ return false;
+
+ if(player.GetSkeletonJointPosition(SkeletonJoint.LeftElbow,out leftElbow) == false || leftElbow.Confidence <= 0.5f)
+ return false;
+
+ if(player.GetSkeletonJointPosition(SkeletonJoint.LeftShoulder,out leftShoulder) == false || leftShoulder.Confidence <= 0.5f)
+ return false;
+
+ Vector3 pos = NIConvertCoordinates.ConvertPos(leftHand.Position);
+ m_pointsHand.AddPoint(ref pos);
+
+ pos = NIConvertCoordinates.ConvertPos(leftElbow.Position);
+ m_pointsElbow.AddPoint(ref pos);
+
+ pos = NIConvertCoordinates.ConvertPos(leftShoulder.Position);
+ m_pointsShoulder.AddPoint(ref pos);
+ }
+
+ return true;
+ }
+
+ /// this method tests if we are relatively steady (i.e. our speed is low).
+ /// In order to be steady, all relevant joints must move very slowly.
+ /// @param numPoints the number of points tested
+ /// @return true if we are steady and false otherwise
+ /// @note we assume the number of points is the same for all joints
+ protected virtual bool IsSteady(out int numPoints)
+ {
+ Vector3 curSpeed = m_pointsHand.GetAvgSpeed(m_timeToHoldPose, out numPoints);
+
+ if (curSpeed.magnitude > m_maxMoveSpeed)
+ return false; // we are moving
+
+ if (numPoints < 1)
+ return false; // we assume the number of points is the same for all joints (although speed would have 1 more point than positions)
+
+ curSpeed = m_pointsElbow.GetAvgSpeed(m_timeToHoldPose, out numPoints);
+ if (curSpeed.magnitude > m_maxMoveSpeed)
+ return false;
+
+ curSpeed = m_pointsShoulder.GetAvgSpeed(m_timeToHoldPose, out numPoints);
+ if (curSpeed.magnitude > m_maxMoveSpeed)
+ return false;
+
+ return true;
+ }
+
+ /// this method tests the current point to figure out if we are in an exit pose
+ /// @param numPoints the number of points tested
+ /// @return true if we found the exit pose
+ /// @note we assume the number of points is the same for all joints
+ protected bool TestHandupPose(out int numPoints)
+ {
+
+ if (IsSteady(out numPoints) == false)
+ return false;
+
+ Vector3 handPos = m_pointsHand.GetAvgPos(m_timeToHoldPose, out numPoints);
+ Vector3 elbowPos = m_pointsElbow.GetAvgPos(m_timeToHoldPose, out numPoints);
+ Vector3 shoulderPos = m_pointsShoulder.GetAvgPos(m_timeToHoldPose, out numPoints);
+
+ Vector3 handDir = handPos - elbowPos;
+ Vector3 elbowDir = elbowPos - shoulderPos;
+
+ float handAngle = Vector3.Angle(handDir.normalized, Vector3.up);
+
+ if(Mathf.Abs(handAngle) > m_angleTolerance)
+ return false;
+
+ float elbowAngle = Vector3.Angle(elbowDir.normalized, Vector3.up);
+ if(Mathf.Abs(elbowAngle) > m_angleTolerance)
+ return false;
+
+ return true;
+ }
+
+
+ /// Gesture initialization
+ ///
+ /// This method is responsible for initializing the gesture to work with a specific hand tracker
+ /// @param hand the hand tracker to work with
+ /// @return true on success, false on failure (e.g. if the hand tracker does not work with the gesture).
+ protected override bool InternalInit(NIPointTracker hand)
+ {
+ NISkeletonTracker curHand = hand as NISkeletonTracker;
+ if (curHand == null)
+ return false;
+ return true;
+ }
+
+ // protected members
+
+ protected bool m_useRightHand;
+
+ /// the maximum speed (in mm/sec) allowed for each of the relevant joints.
+ protected float m_maxMoveSpeed;
+
+ /// the hands are supposed to be at about 45 degrees in each direction. This is the allowed
+ /// tolerance in degrees (i.e. a tolerance of 10 means everything from 35 degrees to 55 degrees is ok
+ protected float m_angleTolerance;
+
+ /// the time we need to hold the pose
+ protected float m_timeToHoldPose;
+
+ /// the time we need to hold the points
+ protected float m_timeToSavePoints;
+
+ /// if this is true then we found the pose
+ protected bool m_holdingPose;
+
+ /// the time we first detected the pose (and not lost it since)
+ protected float m_timeDetectedPose;
+
+ /// this holds true if we already fired the event
+ protected bool m_firedEvent;
+
+ /// this holds the points we are tracking on the hand
+ protected NITimedPointSpeedListUtility m_pointsHand;
+ /// this holds the points we are tracking on the elbow
+ protected NITimedPointSpeedListUtility m_pointsElbow;
+ /// this holds the points we are tracking on the shoulder
+ protected NITimedPointSpeedListUtility m_pointsShoulder;
+
+
+ /// this marks the result as clicked by updating the time and frame and the first
+ /// time after the last change it also fires the gesture event.
+ protected virtual void InternalFireDetectEvent()
+ {
+
+ m_timeDetected = Time.time;
+ m_frameDetected = Time.frameCount;
+ if (m_firedEvent == false)
+ {
+ DetectGesture();
+ m_firedEvent = true;
+ }
+ }
+