using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR; using UnityEngine.XR.Interaction.Toolkit; using PDollarGestureRecognizer; using System.IO; using UnityEngine.Events; public class GestureRecognizer : MonoBehaviour { public InputDevice rightHandController; public XRNode rightHandSource; public InputHelpers.Button rightInputButton; public InputHelpers.Button rightControlButton; public float inputThreshold = 0.1f; public Transform movementSource; public float newPositionThresholdDistance = 0.05f; public GameObject debugCubePrefab; public bool creationMode = true; public string newGestureName; public float recognitionThreshold = 0.8f; [System.Serializable] public class UnityStringEvent : UnityEvent { } public UnityStringEvent OnRecognized; private List trainingSet = new List(); private bool isMoving = false; private List positionsList = new List(); // Start is called before the first frame update void Start() { // Path = ..\AppData\LocalLow\DefaultCompany\Heroes of Hiis SCM Debug.Log(Application.persistentDataPath); string[] gestureFiles = Directory.GetFiles(Application.persistentDataPath, "*.xml"); foreach (var item in gestureFiles) { trainingSet.Add(GestureIO.ReadGestureFromFile(item)); } foreach (var item in trainingSet) { Debug.Log(item.Name); } } // Update is called once per frame void Update() { InputHelpers.IsPressed(InputDevices.GetDeviceAtXRNode(rightHandSource), rightInputButton, out bool isPressed, inputThreshold); InputHelpers.IsPressed(InputDevices.GetDeviceAtXRNode(rightHandSource), rightControlButton, out bool isControlPressed, inputThreshold); bool startGesture = isPressed && isControlPressed; // Start the movement if (!isMoving && startGesture) { StartMovement(); StartCoroutine("Haptics"); } // Ending the movement else if (isMoving && !startGesture) { EndMovement(); StopCoroutine("Haptics"); } // Updating the movement else if (isMoving && startGesture) { UpdateMovement(); } } // Still needs to be tested IEnumerator Haptics() { while (true) { rightHandController.SendHapticImpulse(0u, 0.7f, 0.2f); } } void StartMovement() { Debug.Log("Movement started"); isMoving = true; positionsList.Clear(); positionsList.Add(movementSource.position); if (debugCubePrefab) { Destroy(Instantiate(debugCubePrefab, movementSource.position, Quaternion.identity), 3); } } void EndMovement() { Debug.Log("Movement ended"); isMoving = false; // Create gesture from position list Point[] pointArray = new Point[positionsList.Count]; for (int i = 0; i < positionsList.Count; i++) { Vector2 screenPoint = Camera.main.WorldToScreenPoint(positionsList[i]); pointArray[i] = new Point(screenPoint.x, screenPoint.y, 0); } Gesture newGesture = new Gesture(pointArray); // Add gesture to training set. (only for demo) if (creationMode) { newGesture.Name = newGestureName; trainingSet.Add(newGesture); string fileName = Application.persistentDataPath + "/" + newGestureName + ".xml"; GestureIO.WriteGesture(pointArray, newGestureName, fileName); } // Recognize else { Result result = PointCloudRecognizer.Classify(newGesture, trainingSet.ToArray()); if (result.Score > recognitionThreshold) { OnRecognized.Invoke(result.GestureClass); } } } void UpdateMovement() { Vector3 lastPosition = positionsList[positionsList.Count - 1]; if (Vector3.Distance(movementSource.position, lastPosition) > newPositionThresholdDistance) { positionsList.Add(movementSource.position); if (debugCubePrefab) { Destroy(Instantiate(debugCubePrefab, movementSource.position, Quaternion.identity), 3); } } } }