Ejemplo n.º 1
0
    void Update()
    {
        bool isVR = VRDevices.loadedSdk != VRDevices.LoadedSdk.None;

        Seekbar.instance.gameObject.SetActive(!isVR);
        Seekbar.instanceVR.gameObject.SetActive(isVR);

        //NOTE(Simon): Sync videoController/videoMesh pos with camera pos.
        videoController.transform.position = Camera.main.transform.position;

        var interactionpointRay = new Ray();

        //NOTE(Kristof): Deciding on which object the Ray will be based on
        //NOTE(Simon): Prefers right over left controller
        {
            if (trackedControllerLeft != null && trackedControllerLeft.triggerPressed)
            {
                interactionpointRay = trackedControllerLeft.CastRay();
            }

            if (trackedControllerRight != null && trackedControllerRight.triggerPressed)
            {
                interactionpointRay = trackedControllerRight.CastRay();
            }

            if (VRDevices.hasNoControllers && Input.GetMouseButtonUp(0))
            {
                interactionpointRay = Camera.main.ScreenPointToRay(Input.mousePosition);
            }
        }

        if (playerState == PlayerState.Watching)
        {
            RefreshShownInteractionPoints();

            if (Input.GetKeyDown(KeyCode.Space) && !isVR)
            {
                videoController.TogglePlay();
            }

            if (isVR)
            {
                Seekbar.instanceVR.RenderBlips(shownInteractionPoints);
            }
            else
            {
                Seekbar.instance.RenderBlips(shownInteractionPoints);
            }

            //Note(Simon): Interaction with points
            if (!chapterTransitionActive)
            {
                var reversedRay = interactionpointRay.ReverseRay();
                //Note(Simon): Create a reversed raycast to find positions on the sphere with
                Physics.Raycast(reversedRay, out var hit, 100, 1 << LayerMask.NameToLayer("interactionPoints"));

                //NOTE(Simon): Update visible interactionpoints
                foreach (var point in shownInteractionPoints)
                {
                    point.point.SetActive(true);
                    point.point.GetComponent <InteractionPointRenderer>().SetPingActive(!point.isSeen);
                }

                foreach (var point in GetInactiveInteractionPoints())
                {
                    point.point.SetActive(false);
                }

                //NOTE(Simon): Activate hit interactionPoint
                if (activeInteractionPoint == null && hit.transform != null)
                {
                    var pointGO = hit.transform.gameObject;
                    InteractionPointPlayer point = null;

                    for (int i = 0; i < interactionPoints.Count; i++)
                    {
                        if (pointGO == interactionPoints[i].point)
                        {
                            point = interactionPoints[i];
                            break;
                        }
                    }

                    ActivateInteractionPoint(point);
                }

                //NOTE(Simon): Disable active interactionPoint if playback was started through seekbar
                if (videoController.playing && activeInteractionPoint != null)
                {
                    DeactivateActiveInteractionPoint();
                }
            }

            //NOTE(Simon): Handle mandatory interactionPoints
            if (!chapterTransitionActive)
            {
                double timeToNextPause       = Double.MaxValue;
                var    interactionsInChapter = MandatoryInteractionsForTime(videoController.currentTime);

                //NOTE(Simon): Find the next unseen mandatory interaction in this chapter
                for (int i = 0; i < interactionsInChapter.Count; i++)
                {
                    if (!interactionsInChapter[i].isSeen && interactionsInChapter[i].endTime > videoController.currentTime)
                    {
                        timeToNextPause = interactionsInChapter[i].endTime - videoController.currentTime;
                        break;
                    }
                }

                if (timeToNextPause < pauseFadeTime)
                {
                    videoController.SetPlaybackSpeed(0f);
                    if (!mandatoryPauseActive)
                    {
                        ShowMandatoryInteractionMessage();
                        mandatoryPauseActive = true;
                    }
                }
                else
                {
                    if (mandatoryPauseActive)
                    {
                        mandatoryPauseActive = false;
                        HideMandatoryInteractionMessage();
                    }

                    videoController.SetPlaybackSpeed(1f);
                }
            }

            //NOTE(Simon): Handle chapter transitions
            if (!chapterTransitionActive && !mandatoryPauseActive)
            {
                var currentChapter = ChapterManager.Instance.ChapterForTime(videoController.currentTime);
                if (currentChapter != previousChapter)
                {
                    videoController.SetPlaybackSpeed(0);
                    chapterTransitionActive = true;
                    chapterTransitionPanel.SetChapter(currentChapter);
                    chapterTransitionPanel.StartTransition(OnChapterTransitionFinish);
                    previousChapter = currentChapter;
                }
            }
        }

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

            if (panel.answered)
            {
                var projectPath = Path.Combine(Application.persistentDataPath, panel.answerVideoId);
                if (OpenFile(projectPath))
                {
                    Destroy(indexPanel);
                    playerState = PlayerState.Watching;
                    Canvass.modalBackground.SetActive(false);

                    chapterTransitionActive = false;
                    chapterSelector         = Instantiate(chapterSelectorPrefab, Canvass.main.transform, false).GetComponent <ChapterSelectorPanel>();
                    if (isVR)
                    {
                        chapterSelector.transform.SetParent(chapterSelectorHolderVR.transform, false);
                        chapterSelector.transform.localPosition = Vector3.zero;
                    }
                    chapterSelector.Init(videoController);
                }
                else
                {
                    Debug.LogError("Couldn't open savefile");
                }
            }
        }

        //NOTE(Simon): Interaction with Hittables
        {
            Physics.Raycast(interactionpointRay, out var hit, 100, LayerMask.GetMask("UI", "WorldUI"));

            var controllerList = new List <Controller>
            {
                trackedControllerLeft,
                trackedControllerRight
            };

            //NOTE(Simon): Reset all hittables
            foreach (var hittable in hittables)
            {
                if (hittable == null)
                {
                    continue;
                }

                //NOTE(Jitse): Check if a hittable is being held down
                if (!(controllerList[0].triggerDown || controllerList[1].triggerDown))
                {
                    hittable.hitting = false;
                }

                hittable.hovering = false;
            }

            //NOTE(Simon): Set hover state when hovered by controllers
            foreach (var con in controllerList)
            {
                if (con.uiHovering && con.hoveredGo != null)
                {
                    var hittable = con.hoveredGo.GetComponent <Hittable>();
                    if (hittable != null)
                    {
                        hittable.hovering = true;
                    }
                }
            }

            //NOTE(Simon): Set hitting and hovering in hittables
            if (hit.transform != null)
            {
                var hittable = hit.transform.GetComponent <Hittable>();
                if (hittable != null)
                {
                    hittable.hitting = true;
                }
            }
        }
    }
Ejemplo n.º 2
0
    void Update()
    {
        //NOTE(Kristof): VR specific behaviour
        {
            if (XRSettings.enabled)
            {
                videoController.transform.position = Camera.main.transform.position;
                Canvass.seekbar.gameObject.SetActive(true);

                //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 (isSeekbarOutOfView)
                    {
                        if (angle < 2.5f)
                        {
                            isSeekbarOutOfView = false;
                        }
                    }
                    else
                    {
                        if (angle > fov)
                        {
                            isSeekbarOutOfView = true;
                        }
                    }

                    if (isSeekbarOutOfView)
                    {
                        float 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
                        float radianAngle = (-newAngle + 90) * Mathf.PI / 180;
                        float x           = 1.8f * Mathf.Cos(radianAngle);
                        float y           = Camera.main.transform.position.y - 2f;
                        float z           = 1.8f * Mathf.Sin(radianAngle);

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

        //NOTE(Simon): Zoom when not using HMD
        if (!XRSettings.enabled)
        {
            if (Input.mouseScrollDelta.y != 0)
            {
                Camera.main.fieldOfView = Mathf.Clamp(Camera.main.fieldOfView - Input.mouseScrollDelta.y * 5, 20, 120);
            }
        }

        Ray interactionpointRay = new Ray();

        //NOTE(Kristof): Deciding on which object the Ray will be based on
        //TODO(Simon): Prefers right over left controller
        {
            if (trackedControllerLeft != null && trackedControllerLeft.triggerPressed)
            {
                interactionpointRay = trackedControllerLeft.CastRay();
            }

            if (trackedControllerRight != null && trackedControllerRight.triggerPressed)
            {
                interactionpointRay = trackedControllerRight.CastRay();
            }

            if (VRDevices.loadedControllerSet == VRDevices.LoadedControllerSet.NoControllers && Input.GetMouseButtonUp(0))
            {
                interactionpointRay = Camera.main.ScreenPointToRay(Input.mousePosition);
            }
        }

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

            Seekbar.instance.RenderBlips(interactionPoints, trackedControllerLeft, trackedControllerRight);

            //Note(Simon): Interaction with points
            {
                var reversedRay = interactionpointRay.ReverseRay();
                //Note(Simon): Create a reversed raycast to find positions on the sphere with

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

                //NOTE(Simon): Update visible interactionpoints
                for (int i = 0; i < interactionPoints.Count; i++)
                {
                    bool pointActive = videoController.currentTime >= interactionPoints[i].startTime &&
                                       videoController.currentTime <= interactionPoints[i].endTime;
                    interactionPoints[i].point.SetActive(pointActive);
                    interactionPoints[i].point.GetComponentInChildren <MeshRenderer>(includeInactive: true).gameObject.SetActive(!interactionPoints[i].isSeen);
                }

                //NOTE(Simon): Interact with inactive interactionpoints
                if (activeInteractionPoint == null && hit.transform != null)
                {
                    var pointGO = hit.transform.gameObject;
                    InteractionPointPlayer point = null;

                    for (int i = 0; i < interactionPoints.Count; i++)
                    {
                        if (pointGO == interactionPoints[i].point)
                        {
                            point = interactionPoints[i];
                            break;
                        }
                    }

                    ActivateInteractionPoint(point);
                }

                //NOTE(Simon): Disable active interactionPoint if playback was started through seekbar
                if (videoController.playing && activeInteractionPoint != null)
                {
                    DeactivateActiveInteractionPoint();
                }
            }

            //NOTE(Simon): Handle mandatory interactionPoints
            {
                double timeToNextPause       = Double.MaxValue;
                var    interactionsInChapter = MandatoryInteractionsForTime(videoController.currentTime);

                //NOTE(Simon): Find the next unseen mandatory interaction in this chapter
                for (int i = 0; i < interactionsInChapter.Count; i++)
                {
                    if (!interactionsInChapter[i].isSeen && interactionsInChapter[i].endTime > videoController.currentTime)
                    {
                        timeToNextPause = interactionsInChapter[i].endTime - videoController.currentTime;
                        break;
                    }
                }

                //NOTE(Simon): Set the playbackspeed. Speed will get lower the closer to the next pause we are.
                if (timeToNextPause < mandatoryPauseFadeTime)
                {
                    float speed = (float)(timeToNextPause / mandatoryPauseFadeTime);
                    if (timeToNextPause < .05f)
                    {
                        speed = 0;
                    }

                    videoController.SetPlaybackSpeed(speed);
                    if (!mandatoryPauseActive)
                    {
                        ShowMandatoryInteractionMessage();
                        mandatoryPauseActive = true;
                    }
                }
                else
                {
                    if (mandatoryPauseActive)
                    {
                        mandatoryPauseActive = false;
                        HideMandatoryInteractionMessage();
                    }

                    videoController.SetPlaybackSpeed(1f);
                }
            }
        }

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

            if (panel.answered)
            {
                var projectPath = Path.Combine(Application.persistentDataPath, panel.answerVideoId);
                if (OpenFile(projectPath))
                {
                    Destroy(indexPanel);
                    playerState = PlayerState.Watching;
                    Canvass.modalBackground.SetActive(false);
                    SetCanvasesActive(true);
                    chapterSelector = Instantiate(chapterSelectorPrefab, Canvass.main.transform, false).GetComponent <ChapterSelectorPanel>();

                    if (VRDevices.loadedSdk > VRDevices.LoadedSdk.None)
                    {
                        StartCoroutine(FadevideoCanvasOut(videoCanvas));
                        EventManager.OnSpace();
                        videoPositions.Clear();
                        Seekbar.ReattachCompass();
                    }
                }
                else
                {
                    Debug.LogError("Couldn't open savefile");
                }
            }
        }

        //NOTE(Simon): Interaction with Hittables
        {
            Physics.Raycast(interactionpointRay, out var hit, 100, LayerMask.GetMask("UI", "WorldUI"));

            var controllerList = new List <Controller>
            {
                trackedControllerLeft,
                trackedControllerRight
            };

            //NOTE(Simon): Reset all hittables
            foreach (var hittable in hittables)
            {
                if (hittable == null)
                {
                    continue;
                }

                //NOTE(Jitse): Check if a hittable is being held down
                if (!(controllerList[0].triggerDown || controllerList[1].triggerDown))
                {
                    hittable.hitting = false;
                }

                hittable.hovering = false;
            }

            //NOTE(Simon): Set hover state when hovered by controllers
            foreach (var con in controllerList)
            {
                if (con.uiHovering && con.hoveredGo != null)
                {
                    var hittable = con.hoveredGo.GetComponent <Hittable>();
                    if (hittable != null)
                    {
                        hittable.hovering = true;
                    }
                }
            }

            //NOTE(Simon): Set hitting and hovering in hittables
            if (hit.transform != null)
            {
                hit.transform.GetComponent <Hittable>().hitting = true;
            }
        }
    }