using Newtonsoft.Json; 
 | 
using Newtonsoft.Json.Linq; 
 | 
using Poco; 
 | 
using System; 
 | 
using System.Collections.Generic; 
 | 
using System.Diagnostics; 
 | 
using System.Runtime.InteropServices; 
 | 
using System.Text; 
 | 
using System.Threading; 
 | 
using TcpServer; 
 | 
using UnityEngine; 
 | 
using Debug = UnityEngine.Debug; 
 | 
  
 | 
public class VRSupport 
 | 
{ 
 | 
    private static Queue<Action> commands = new Queue<Action>(); 
 | 
  
 | 
    public VRSupport() 
 | 
    { 
 | 
        commands = new Queue<Action>(); 
 | 
    } 
 | 
  
 | 
    public void ClearCommands() 
 | 
    { 
 | 
        commands.Clear(); 
 | 
    } 
 | 
  
 | 
    public void PeekCommand() 
 | 
    { 
 | 
        if (null != commands && commands.Count > 0) 
 | 
        { 
 | 
            Debug.Log("command executed " + commands.Count); 
 | 
            commands.Peek()(); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    public object isVRSupported(List<object> param) 
 | 
    { 
 | 
#if UNITY_3 || UNITY_4 
 | 
            return false; 
 | 
#elif UNITY_5 || UNITY_2017_1 
 | 
            return UnityEngine.VR.VRSettings.loadedDeviceName.Equals("CARDBOARD"); 
 | 
#else 
 | 
        return UnityEngine.XR.XRSettings.loadedDeviceName.Equals("CARDBOARD"); 
 | 
#endif 
 | 
    } 
 | 
  
 | 
    public object IsQueueEmpty(List<object> param) 
 | 
    { 
 | 
        Debug.Log("Checking queue"); 
 | 
        if (commands != null && commands.Count > 0) 
 | 
        { 
 | 
            return null; 
 | 
        } 
 | 
        else 
 | 
        { 
 | 
            Thread.Sleep(1000); // we wait a bit and check again just in case we run in between calls 
 | 
            if (commands != null && commands.Count > 0) 
 | 
            { 
 | 
                return null; 
 | 
            } 
 | 
        } 
 | 
  
 | 
        return commands.Count; 
 | 
    } 
 | 
  
 | 
    public object RotateObject(List<object> param) 
 | 
    { 
 | 
        var xRotation = Convert.ToSingle(param[0]); 
 | 
        var yRotation = Convert.ToSingle(param[1]); 
 | 
        var zRotation = Convert.ToSingle(param[2]); 
 | 
        float speed = 0f; 
 | 
        if (param.Count > 5) 
 | 
            speed = Convert.ToSingle(param[5]); 
 | 
        Vector3 mousePosition = new Vector3(xRotation, yRotation, zRotation); 
 | 
        foreach (GameObject cameraContainer in GameObject.FindObjectsOfType<GameObject>()) 
 | 
        { 
 | 
            if (cameraContainer.name.Equals(param[3])) 
 | 
            { 
 | 
                foreach (GameObject cameraFollower in GameObject.FindObjectsOfType<GameObject>()) 
 | 
                { 
 | 
                    if (cameraFollower.name.Equals(param[4])) 
 | 
                    { 
 | 
                        lock (commands) 
 | 
                        { 
 | 
                            commands.Enqueue(() => recoverOffset(cameraFollower, cameraContainer, speed)); 
 | 
                        } 
 | 
  
 | 
                        lock (commands) 
 | 
                        { 
 | 
                            var currentRotation = cameraContainer.transform.rotation; 
 | 
                            commands.Enqueue(() => rotate(cameraContainer, currentRotation, mousePosition, speed)); 
 | 
                        } 
 | 
                        return true; 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                return true; 
 | 
            } 
 | 
        } 
 | 
        return false; 
 | 
    } 
 | 
  
 | 
    public object ObjectLookAt(List<object> param) 
 | 
    { 
 | 
        float speed = 0f; 
 | 
        if (param.Count > 3) 
 | 
            speed = Convert.ToSingle(param[3]); 
 | 
        foreach (GameObject toLookAt in GameObject.FindObjectsOfType<GameObject>()) 
 | 
        { 
 | 
            if (toLookAt.name.Equals(param[0])) 
 | 
            { 
 | 
                foreach (GameObject cameraContainer in GameObject.FindObjectsOfType<GameObject>()) 
 | 
                { 
 | 
                    if (cameraContainer.name.Equals(param[1])) 
 | 
                    { 
 | 
                        foreach (GameObject cameraFollower in GameObject.FindObjectsOfType<GameObject>()) 
 | 
                        { 
 | 
                            if (cameraFollower.name.Equals(param[2])) 
 | 
                            { 
 | 
                                lock (commands) 
 | 
                                { 
 | 
                                    commands.Enqueue(() => recoverOffset(cameraFollower, cameraContainer, speed)); 
 | 
                                } 
 | 
  
 | 
                                lock (commands) 
 | 
                                { 
 | 
                                    commands.Enqueue(() => objectLookAt(cameraContainer, toLookAt, speed)); 
 | 
                                } 
 | 
  
 | 
                                return true; 
 | 
                            } 
 | 
                        } 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
        return false; 
 | 
    } 
 | 
  
 | 
    protected void rotate(GameObject go, Quaternion originalRotation, Vector3 mousePosition, float speed) 
 | 
    { 
 | 
        Debug.Log("rotating"); 
 | 
        if (!RotateObject(originalRotation, mousePosition, go, speed)) 
 | 
        { 
 | 
            lock (commands) 
 | 
            { 
 | 
                commands.Dequeue(); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    protected void objectLookAt(GameObject go, GameObject toLookAt, float speed) 
 | 
    { 
 | 
        Debug.Log("looking at " + toLookAt.name); 
 | 
        Debug.Log("from " + go.name); 
 | 
        if (!ObjectLookAtObject(toLookAt, go, speed)) 
 | 
        { 
 | 
            lock (commands) 
 | 
            { 
 | 
                commands.Dequeue(); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    protected void recoverOffset(GameObject subcontainter, GameObject cameraContainer, float speed) 
 | 
    { 
 | 
        Debug.Log("recovering " + cameraContainer.name); 
 | 
        if (!ObjectRecoverOffset(subcontainter, cameraContainer, speed)) 
 | 
        { 
 | 
            lock (commands) 
 | 
            { 
 | 
                commands.Dequeue(); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    protected bool RotateObject(Quaternion originalPosition, Vector3 mousePosition, GameObject cameraContainer, float rotationSpeed = 0.125f) 
 | 
    { 
 | 
        if (null == cameraContainer) 
 | 
        { 
 | 
            return false; 
 | 
        } 
 | 
  
 | 
        var expectedx = originalPosition.eulerAngles.x + mousePosition.x; 
 | 
        var expectedy = originalPosition.eulerAngles.y + mousePosition.y; 
 | 
        var expectedz = originalPosition.eulerAngles.z + mousePosition.z; 
 | 
  
 | 
        var toRotation = Quaternion.Euler(new Vector3(expectedx, expectedy, expectedz)); 
 | 
        cameraContainer.transform.rotation = Quaternion.Lerp(cameraContainer.transform.rotation, toRotation, rotationSpeed * Time.deltaTime); 
 | 
        var angle = Quaternion.Angle(cameraContainer.transform.rotation, toRotation); 
 | 
  
 | 
        if (angle == 0) 
 | 
        { 
 | 
            return false; 
 | 
        } 
 | 
  
 | 
        return true; 
 | 
    } 
 | 
  
 | 
    protected bool ObjectLookAtObject(GameObject go, GameObject cameraContainer, float rotationSpeed = 0.125f) 
 | 
    { 
 | 
        if (null == go || null == cameraContainer) 
 | 
        { 
 | 
            Debug.Log("exception - item null"); 
 | 
            return false; 
 | 
        } 
 | 
  
 | 
        var toRotation = Quaternion.LookRotation(go.transform.position - (cameraContainer.transform.localPosition)); 
 | 
        cameraContainer.transform.rotation = Quaternion.Lerp(cameraContainer.transform.rotation, toRotation, rotationSpeed * Time.deltaTime); 
 | 
        // It should not be needed but sometimes the difference of eurlerAngles might be small and this would ensure it works fine 
 | 
        if (Quaternion.Angle(cameraContainer.transform.rotation, toRotation) == 0) 
 | 
        { 
 | 
  
 | 
            return false; 
 | 
        } 
 | 
  
 | 
        return true; 
 | 
    } 
 | 
  
 | 
    protected bool ObjectRecoverOffset(GameObject subcontainer, GameObject cameraContainer, float rotationSpeed = 0.125f) 
 | 
    { 
 | 
        if (null == cameraContainer) 
 | 
        { 
 | 
            Debug.Log("exception - item null"); 
 | 
            return false; 
 | 
        } 
 | 
  
 | 
        // add offset with the camera 
 | 
        var cameraRotation = Camera.main.transform.localRotation; 
 | 
  
 | 
        var toRotate = new Quaternion(-cameraRotation.x, -cameraRotation.y, -cameraRotation.z, cameraRotation.w); 
 | 
        subcontainer.transform.localRotation = Quaternion.Lerp(subcontainer.transform.localRotation, toRotate, rotationSpeed * Time.deltaTime); 
 | 
  
 | 
        // It should not be needed but sometimes the difference of eurlerAngles might be small and this would ensure it works fine 
 | 
        if (Quaternion.Angle(subcontainer.transform.localRotation, toRotate) == 0) 
 | 
        { 
 | 
            return false; 
 | 
        } 
 | 
  
 | 
        return true; 
 | 
    } 
 | 
} 
 |