Example #1
0
    //https://stackoverflow.com/questions/36702228/enable-disable-vr-from-code
    public IEnumerator EnableVR()
    {
        Instantiate(XRInputPrefab);
        if (XRGeneralSettings.Instance.Manager.activeLoader == null)
        {
            StartCoroutine(XRGeneralSettings.Instance.Manager.InitializeLoader());
        }

        if (XRGeneralSettings.Instance.Manager.activeLoader != null)
        {
            XRGeneralSettings.Instance.Manager.StartSubsystems();
            VRDevices.loadedSdk = VRDevices.LoadedSdk.OpenVr;

            VRDevices.BeginHandlingVRDeviceEvents();
            controllerLeft.SetActive(true);
            controllerRight.SetActive(true);
        }
        else
        {
            VRDevices.loadedSdk = VRDevices.LoadedSdk.None;
            controllerLeft.SetActive(false);
            controllerRight.SetActive(false);
        }

        trackedControllerLeft  = controllerLeft.GetComponent <Controller>();
        trackedControllerRight = controllerRight.GetComponent <Controller>();

        yield return(null);
    }
Example #2
0
 void Start()
 {
     if (UnityEngine.XR.XRDevice.model == "Oculus Rift CV1")
     {
         device = VRDevices.OculusRift;
     }
     else if (UnityEngine.XR.XRDevice.model == "Vive MV")
     {
         device = VRDevices.Vive;
     }
 }
Example #3
0
    private IEnumerator EnableVr()
    {
        var supportedDevices = XRSettings.supportedDevices;

        //NOTE(Simon): We start with None as the default in the player settings. But in player we want to load OpenVR first (and in the future other APIs?) so reverse the array
        Array.Reverse(supportedDevices);
        XRSettings.LoadDeviceByName(supportedDevices);

        //NOTE(Kristof): wait one frame to allow the device to be loaded
        yield return(null);

        if (XRSettings.loadedDeviceName.Equals("OpenVR"))
        {
            VRDevices.loadedSdk = VRDevices.LoadedSdk.OpenVr;
            XRSettings.enabled  = true;
            SteamVR.Initialize(true);

            //NOTE(Kristof): Instantiate the projector
            {
                projector = Instantiate(projectorPrefab);
                projector.transform.position    = new Vector3(4.5f, 0, 0);
                projector.transform.eulerAngles = new Vector3(0, 270, 0);
                projector.transform.localScale  = new Vector3(0.5f, 0.5f, 0.5f);

                projector.GetComponent <AnimateProjector>().Subscribe(this);
            }

            //NOTE(Kristof): Hide the main and seekbar canvas when in VR (they are toggled back on again after the lobby)
            SetCanvasesActive(false);

            Canvass.seekbar.transform.position = new Vector3(1.8f, Camera.main.transform.position.y - 2f, 0);

            fileLoader.MoveSeekbarToVRPos();
            VRDevices.BeginHandlingVRDeviceEvents();
        }
        else if (XRSettings.loadedDeviceName.Equals(""))
        {
            VRDevices.loadedSdk = VRDevices.LoadedSdk.None;
            controllerLeft.SetActive(false);
            controllerRight.SetActive(false);
        }
    }
Example #4
0
    void Update()
    {
        VRDevices.DetectDevices();

        //NOTE(Kristof): VR specific behaviour
        {
            if (XRSettings.enabled)
            {
                videoController.transform.position = Camera.main.transform.position;

                //NOTE(Lander): enable the highlight in the tutorial mode
                VRDevices.SetControllersTutorialMode(new[] { controllerLeft, controllerRight }, videoController.videoState == VideoController.VideoState.Intro);

                //NOTE(Kristof): Rotating the seekbar
                {
                    //NOTE(Kristof): Seekbar rotation is the same as the seekbar's angle on the circle
                    var seekbarAngle = Vector2.SignedAngle(new Vector2(Canvass.seekbar.transform.position.x, Canvass.seekbar.transform.position.z), Vector2.up);

                    var fov = Camera.main.fieldOfView;
                    //NOTE(Kristof): Camera rotation tells you to which angle on the circle the camera is looking towards
                    var cameraAngle = Camera.main.transform.eulerAngles.y;

                    //NOTE(Kristof): Calculate the absolute degree angle from the camera to the seekbar
                    var distanceLeft  = Mathf.Abs((cameraAngle - seekbarAngle + 360) % 360);
                    var distanceRight = Mathf.Abs((cameraAngle - seekbarAngle - 360) % 360);

                    var angle = Mathf.Min(distanceLeft, distanceRight);

                    if (isOutofView)
                    {
                        if (angle < 2.5f)
                        {
                            isOutofView = false;
                        }
                    }
                    else
                    {
                        if (angle > fov)
                        {
                            isOutofView = true;
                        }
                    }

                    if (isOutofView)
                    {
                        var newAngle = Mathf.LerpAngle(seekbarAngle, cameraAngle, 0.025f);

                        //NOTE(Kristof): Angle needs to be reversed, in Unity postive angles go clockwise while they go counterclockwise in the unit circle (cos and sin)
                        //NOTE(Kristof): We also need to add an offset of 90 degrees because in Unity 0 degrees is in front of you, in the unit circle it is (1,0) on the axis
                        var radianAngle = (-newAngle + 90) * Mathf.PI / 180;
                        var x           = 1.8f * Mathf.Cos(radianAngle);
                        var y           = Camera.main.transform.position.y - 2f;
                        var z           = 1.8f * Mathf.Sin(radianAngle);

                        Canvass.seekbar.transform.position    = new Vector3(x, y, z);
                        Canvass.seekbar.transform.eulerAngles = new Vector3(30, newAngle, 0);
                    }
                }

                //NOTE(Kristof): Rotating the Crosshair canvas
                {
                    Ray cameraRay = Camera.main.ViewportPointToRay(new Vector2(0.5f, 0.5f));
                    Canvass.crosshair.transform.position = cameraRay.GetPoint(90);
                    Canvass.crosshair.transform.LookAt(Camera.main.transform);
                }
            }
            else
            {
                Canvass.seekbar.gameObject.SetActive(false);
                Canvass.crosshair.gameObject.SetActive(false);
            }
        }

        //NOTE(Kristof): Controller specific behaviour
        {
            if (VRDevices.loadedControllerSet != VRDevices.LoadedControllerSet.NoControllers)
            {
                crosshair.enabled      = false;
                crosshairTimer.enabled = false;
            }
            else
            {
                crosshair.enabled      = true;
                crosshairTimer.enabled = true;
            }

            if (Input.mouseScrollDelta.y != 0)
            {
                Camera.main.fieldOfView = Mathf.Clamp(Camera.main.fieldOfView - Input.mouseScrollDelta.y * 5, 20, 120);
            }
        }

        Ray ray;

        //NOTE(Kristof): Deciding on which object the Ray will be based on
        {
            Ray cameraRay     = Camera.main.ViewportPointToRay(new Vector2(0.5f, 0.5f));
            Ray controllerRay = new Ray();

            const ulong ulTriggerValue = (ulong)1 << 33;

            if (trackedControllerLeft.controllerState.ulButtonPressed == controllerLeftOldState.ulButtonPressed + ulTriggerValue)
            {
                controllerRay = controllerLeft.GetComponent <Controller>().CastRay();
            }

            if (trackedControllerRight.controllerState.ulButtonPressed == controllerRightOldState.ulButtonPressed + ulTriggerValue)
            {
                controllerRay = controllerRight.GetComponent <Controller>().CastRay();
            }

            controllerLeftOldState  = trackedControllerLeft.controllerState;
            controllerRightOldState = trackedControllerRight.controllerState;

            if (VRDevices.loadedControllerSet > VRDevices.LoadedControllerSet.NoControllers)
            {
                ray = controllerRay;
            }
            else
            {
                ray = cameraRay;
            }
        }

        interacting = false;

        if (playerState == PlayerState.Watching)
        {
            if (Input.GetKeyDown(KeyCode.Space) && VRDevices.loadedSdk == VRDevices.LoadedSdk.None)
            {
                videoController.TogglePlay();
            }

            //Note(Simon): Interaction with points
            {
                var reversedRay = ray;
                //Note(Simon): Create a reversed raycast to find positions on the sphere with
                reversedRay.origin    = ray.GetPoint(100);
                reversedRay.direction = -ray.direction;

                RaycastHit hit;
                Physics.Raycast(reversedRay, out hit, 100, 1 << LayerMask.NameToLayer("interactionPoints"));

                var left  = controllerLeft.GetComponent <Controller>();
                var right = controllerRight.GetComponent <Controller>();

                float forwardAngle;
                //Note(lander): Turn the blips with the correct angle.
                {
                    if (left || right)
                    {
                        forwardAngle = right.compassAttached
                                                        ? right.transform.eulerAngles.y
                                                        : left.transform.eulerAngles.y;
                    }
                    else
                    {
                        forwardAngle = Seekbar.compass.transform.parent.localEulerAngles.y;
                    }
                }

                //NOTE(Kristof): The startpoints are removed in the for loop, so we need to loop in reverse
                for (var i = interactionPoints.Count - 1; i >= 0; i--)
                {
                    var point = interactionPoints[i];

                    var pointActive = point.startTime <= videoController.currentTime && point.endTime >= videoController.currentTime;
                    point.point.SetActive(pointActive);

                    var textMesh = point.point.GetComponentInChildren <TextMesh>();

                    // Note(Lander): highlight the untouched interaction points
                    if (!point.isStartPoint && pointActive && !point.isTouched)
                    {
                        if (textMesh != null)
                        {
                            textMesh.color = Color.black;
                        }

                        var blipAngle = point.point.transform.eulerAngles.y;

                        // TODO(Lander): Rely on a start position of a video instead
                        var angle = (XRSettings.enabled ? forwardAngle : 90) - blipAngle;

                        if (point.blip == null)
                        {
                            point.blip = Seekbar.CreateBlip(-angle, Instantiate(compassBlipPrefab));
                            remainingPoints++;
                        }
                        point.blip.transform.localEulerAngles = new Vector3(0, 0, angle);
                    }
                    else
                    {
                        if (textMesh != null)
                        {
                            textMesh.color = Color.white;
                        }
                        if (point.blip != null)
                        {
                            Destroy(point.blip);
                            point.blip = null;
                            remainingPoints--;
                        }
                    }

                    if (!point.isStartPoint && point.isTouched)
                    {
                        point.point.GetComponent <Renderer>().material.color = GRAY;
                    }
                    blipCounter.text = remainingPoints != 0
                                                ? remainingPoints.ToString()
                                                : "";

                    //NOTE(Lander): current point is hit with the raycast
                    if (hit.transform != null && hit.transform.gameObject == point.point)
                    {
                        //NOTE(Kristof): Interacting with controller
                        if (VRDevices.loadedControllerSet > VRDevices.LoadedControllerSet.NoControllers)
                        {
                            //NOTE(Kristof): The controllers only raycast on trigger down
                            //NOTE(Kristof): Interacting with StartPoints
                            if (point.isStartPoint)
                            {
                                videoController.videoState = VideoController.VideoState.Watching;
                                startPointGroup.SetActive(false);
                                Togglecanvasses();
                                interactionPoints.RemoveRange(0, 4);
                            }
                            //NOTE(Kristof): Interacting with InteractionPoints
                            else
                            {
                                point.panel.SetActive(!point.panel.activeSelf);

                                if (point.panel.activeSelf)
                                {
                                    activePoints++;
                                    point.isTouched = true;
                                }
                                else
                                {
                                    activePoints--;
                                }

                                videoController.Pause();

                                //NOTE(Kristof): Play the video when you deactivate the last point
                                if (activePoints == 0 && VideoController.autoResume)
                                {
                                    videoController.TogglePlay();
                                }
                            }
                        }
                        //NOTE(Kristof): Interacting without controllers
                        else
                        {
                            interacting = true;

                            if (timeToInteract < interactionTimer)
                            {
                                //NOTE(Kristof): Interacting with StartPoints
                                if (point.isStartPoint)
                                {
                                    videoController.videoState = VideoController.VideoState.Watching;
                                    startPointGroup.SetActive(false);
                                    Togglecanvasses();
                                }
                                //NOTE(Kristof): Interacting with InteractionPoints
                                else
                                {
                                    //NOTE(Kristof): Making a panel active
                                    if (!point.panel.activeSelf)
                                    {
                                        if (VRDevices.loadedSdk > VRDevices.LoadedSdk.None)
                                        {
                                            interactionTimer = -1;
                                            activePoints++;
                                        }
                                        else
                                        {
                                            //HACK(Kristof): Set to to double of timeToInteract to ensure no funky business happens (like disabling the panel right away)
                                            interactionTimer = timeToInteract * 2;
                                        }
                                        point.isTouched = true;
                                        point.panel.SetActive(true);
                                        videoController.Pause();
                                    }
                                    //NOTE(Kristof): Making a panel inactive
                                    //NOTE This only needs to be the done the same frame that the interactiontimer exceeds the timeToInteract, on this frame point.interactionTimer
                                    //NOTE will be between timeToInteract and timeToInteract + deltaTime
                                    //NOTE(Kristof): This condition will occasionally cause bugs (see HACK above)
                                    else if (timeToInteract < interactionTimer && interactionTimer < timeToInteract + Time.deltaTime)
                                    {
                                        point.panel.SetActive(false);
                                        activePoints--;

                                        interactionTimer = -1;

                                        if (activePoints == 0 && VideoController.autoResume)
                                        {
                                            videoController.TogglePlay();
                                        }
                                    }
                                }
                            }
                        }
                    }
                    //NOTE(Kristof): Gets executed for the point.panels that the user made active before but are not currently being interacted with (no hit)
                    else if (point.panel != null && point.panel.activeSelf)
                    {
                        //NOTE(Kristof): Disable all panels when using the Seekbar play button to resume play
                        if (videoController.playing)
                        {
                            point.panel.SetActive(false);
                            activePoints--;
                        }

                        //NOTE(Kristof): Video can resume if the user is not using VR
                        if (VRDevices.loadedSdk == VRDevices.LoadedSdk.None)
                        {
                            point.panel.SetActive(false);
                            videoController.TogglePlay();
                        }
                    }
                }
            }
        }

        if (playerState == PlayerState.Opening)
        {
            var panel = indexPanel.GetComponent <IndexPanel>();

            if (panel.answered)
            {
                var metaFilename = Path.Combine(Application.persistentDataPath, Path.Combine(panel.answerVideoId, SaveFile.metaFilename));
                if (OpenFile(metaFilename))
                {
                    Destroy(indexPanel);
                    playerState = PlayerState.Watching;
                    Canvass.modalBackground.SetActive(false);
                    if (VRDevices.loadedSdk > VRDevices.LoadedSdk.None)
                    {
                        EventManager.OnSpace();
                        videoPositions.Clear();
                    }
                }
                else
                {
                    Debug.Log("Couldn't open savefile");
                }
            }
        }

        //NOTE(Kristof): Interaction with UI
        {
            RaycastHit hit;
            Physics.Raycast(ray, out hit, 100, LayerMask.GetMask("UI", "WorldUI"));

            var controllerList = new List <Controller>
            {
                controllerLeft.GetComponent <Controller>(),
                controllerRight.GetComponent <Controller>()
            };

            //NOTE(Kristof): Looping over hittable UI scripts
            foreach (var hittable in hittables)
            {
                if (hittable == null)
                {
                    continue;
                }
                hittable.hitting  = false;
                hittable.hovering = false;

                //NOTE(Kristof): Checking for controller hover needs to happen independently of controller interactions
                foreach (var con in controllerList)
                {
                    if (con.uiHovering && con.hovered == hittable.gameObject)
                    {
                        hittable.hovering = true;
                    }
                }

                if (hit.transform != null && hit.transform.gameObject == hittable.gameObject)
                {
                    //NOTE(Kristof): Interacting with controller
                    if (VRDevices.loadedControllerSet > VRDevices.LoadedControllerSet.NoControllers)
                    {
                        hittable.hitting = true;
                    }
                    //NOTE(Kristof): Interacting without controllers
                    else
                    {
                        interacting       = true;
                        hittable.hovering = true;
                        if (interactionTimer >= timeToInteract)
                        {
                            interactionTimer = -1;
                            hittable.hitting = true;
                        }
                    }
                }
            }
        }

        //NOTE(Kristof): Interaction interactionTimer and Crosshair behaviour
        {
            if (interacting)
            {
                interactionTimer         += Time.deltaTime;
                crosshairTimer.fillAmount = interactionTimer / timeToInteract;
                crosshair.fillAmount      = 1 - (interactionTimer / timeToInteract);
            }
            else
            {
                interactionTimer          = 0;
                crosshairTimer.fillAmount = 0;
                crosshair.fillAmount      = 1;
            }
        }

        //NOTE(Kristof): Turning CameraRig
        {
            var controllers = new[]
            {
                controllerLeft.GetComponent <SteamVR_TrackedObject>(),
                controllerRight.GetComponent <SteamVR_TrackedObject>()
            };

            for (var index = 0; index < controllers.Length; index++)
            {
                var controller = controllers[index];
                if (controller.index > SteamVR_TrackedObject.EIndex.None)
                {
                    var device = SteamVR_Controller.Input((int)controller.index);

                    switch (VRDevices.loadedControllerSet)
                    {
                    case VRDevices.LoadedControllerSet.Oculus:
                    {
                        var touchpad = device.GetAxis();

                        if (-0.7f < touchpad.x && touchpad.x < 0.7f)
                        {
                            cameraRigMovable[index] = true;
                        }
                        else if (touchpad.x > 0.7f && cameraRigMovable[index])
                        {
                            cameraRig.transform.localEulerAngles += new Vector3(0, 30, 0);
                            cameraRigMovable[index] = false;
                        }
                        else if (touchpad.x < -0.7f && cameraRigMovable[index])
                        {
                            cameraRig.transform.localEulerAngles -= new Vector3(0, 30, 0);
                            cameraRigMovable[index] = false;
                        }

                        break;
                    }

                    case VRDevices.LoadedControllerSet.Vive:
                    {
                        var touchpad = device.GetAxis();
                        if (device.GetPressDown(SteamVR_Controller.ButtonMask.Touchpad))
                        {
                            if (touchpad.x > 0.7f && cameraRigMovable[index])
                            {
                                cameraRig.transform.localEulerAngles += new Vector3(0, 30, 0);
                                cameraRigMovable[index] = false;
                            }
                            else if (touchpad.x < -0.7f && cameraRigMovable[index])
                            {
                                cameraRig.transform.localEulerAngles -= new Vector3(0, 30, 0);
                                cameraRigMovable[index] = false;
                            }
                        }
                        else
                        {
                            cameraRigMovable[index] = true;
                        }

                        break;
                    }
                    }
                }
            }
        }
    }