Пример #1
0
    private void ActivateInteractionPoint(InteractionPointPlayer point)
    {
        float pointAngle = Mathf.Rad2Deg * Mathf.Atan2(point.position.x, point.position.z) - 90;

        Canvass.sphereUIRenderer.GetComponent <UISphere>().Activate(pointAngle);

        point.panel.SetActive(true);

        //NOTE(Simon): We do this here, because each interactionType has its own script. So that mean adding the event in many places
        var button = point.panel.transform.Find("CloseSpherePanelButton").GetComponent <Button>();

        button.onClick.RemoveAllListeners();
        button.onClick.AddListener(DeactivateActiveInteractionPoint);

        activeInteractionPoint = point;
        point.isSeen           = true;

        videoController.Pause();

        InteractionPointers.Instance.ShouldRender(false);

        //NOTE(Simon): No two eventsystems can be active at the same, so disable the main one. The main one is used for all screenspace UI.
        //NOTE(Simon): The other eventsystem, that remains active, handles input for the spherical UI.
        mainEventSystem.enabled = false;
    }
Пример #2
0
 private void RemoveInteractionPoint(InteractionPointPlayer point)
 {
     interactionPoints.Remove(point);
     Destroy(point.point);
     if (point.panel != null)
     {
         Destroy(point.panel);
     }
 }
Пример #3
0
    public void DeactivateActiveInteractionPoint()
    {
        Canvass.sphereUIRenderer.GetComponent <UISphere>().Deactivate();
        activeInteractionPoint.panel.SetActive(false);
        activeInteractionPoint = null;
        videoController.Play();

        mainEventSystem.enabled = true;
    }
Пример #4
0
    private bool OpenFile(string path)
    {
        var data = SaveFile.OpenFile(path);

        openVideo = Path.Combine(Application.persistentDataPath, Path.Combine(data.meta.guid.ToString(), SaveFile.videoFilename));
        fileLoader.LoadFile(openVideo);

        for (var j = interactionPoints.Count - 1; j >= 0; j--)
        {
            RemoveInteractionPoint(interactionPoints[j]);
        }

        interactionPoints.Clear();

        foreach (var point in data.points)
        {
            var newPoint = Instantiate(interactionPointPrefab, point.position, point.rotation);

            var newInteractionPoint = new InteractionPointPlayer
            {
                startTime = point.startTime,
                endTime   = point.endTime,
                title     = point.title,
                body      = point.body,
                filename  = "file:///" + Path.Combine(Application.persistentDataPath, Path.Combine(data.meta.guid.ToString(), point.filename)),
                type      = point.type,
                point     = newPoint
            };

            switch (newInteractionPoint.type)
            {
            case InteractionType.Text:
            {
                var panel = Instantiate(textPanelPrefab);
                panel.GetComponent <TextPanel>().Init(point.position, newInteractionPoint.title, newInteractionPoint.body);
                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.Image:
            {
                var panel = Instantiate(imagePanelPrefab);
                panel.GetComponent <ImagePanel>().Init(point.position, newInteractionPoint.title, newInteractionPoint.filename, false);
                newInteractionPoint.panel = panel;
                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }

            AddInteractionPoint(newInteractionPoint);
        }

        return(true);
    }
Пример #5
0
    private void SetInteractionPointTag(InteractionPointPlayer point)
    {
        var shape = point.point.GetComponent <SpriteRenderer>();
        var interactionTypeRenderer = point.point.GetComponentInChildren <SpriteRenderer>(excludeSelf: true);
        var tag = TagManager.Instance.GetTagById(point.tagId);

        shape.sprite = TagManager.Instance.ShapeForIndex(tag.shapeIndex);
        shape.color  = tag.color;
        interactionTypeRenderer.color = tag.color.IdealTextColor();
    }
Пример #6
0
    private void AddInteractionPoint(InteractionPointPlayer point)
    {
        point.point.transform.LookAt(Vector3.zero, Vector3.up);
        point.point.transform.RotateAround(point.point.transform.position, point.point.transform.up, 180);

        //NOTE(Simon): Add a number to interaction points
        //TODO(Simon): Make sure these are numbered chronologically
        point.point.transform.GetChild(0).gameObject.SetActive(true);
        point.point.GetComponentInChildren <TextMesh>().text = (++interactionPointCount).ToString();
        point.panel.SetActive(false);
        interactionPoints.Add(point);
    }
Пример #7
0
    private void AddInteractionPoint(InteractionPointPlayer point)
    {
        point.point.transform.LookAt(Vector3.zero, Vector3.up);
        point.point.transform.RotateAround(point.point.transform.position, point.point.transform.up, 180);

        //NOTE(Simon): Add a sprite to interaction points, indicating InteractionType
        point.point.GetComponentInChildren <SpriteRenderer>(excludeSelf: true).sprite = InteractionTypeSprites.GetSprite(point.type);
        point.point.transform.GetChild(0).gameObject.SetActive(true);
        point.panel.SetActive(false);
        interactionPoints.Add(point);

        SetInteractionPointTag(point);
    }
Пример #8
0
    public void Init(InteractionPointPlayer point)
    {
        point.point.transform.LookAt(Vector3.zero, Vector3.up);
        point.point.transform.RotateAround(point.point.transform.position, point.point.transform.up, 180);

        //NOTE(Simon): Add a sprite to interaction points, indicating InteractionType
        interactionType.sprite = InteractionTypeSprites.GetSprite(point.type);
        ping.SetActive(false);
        point.panel.SetActive(false);

        mandatory.enabled = point.mandatory;

        SetInteractionPointTag(point.point, point.tagId);
    }
Пример #9
0
 private void AddInteractionPoint(InteractionPointPlayer point)
 {
     point.point.GetComponent <InteractionPointRenderer>().Init(point);
     interactionPoints.Add(point);
 }
Пример #10
0
    private bool OpenFile(string projectPath)
    {
        data = SaveFile.OpenFile(projectPath);

        openVideo = Path.Combine(Application.persistentDataPath, Path.Combine(data.meta.guid.ToString(), SaveFile.videoFilename));
        fileLoader.LoadFile(openVideo);

        var tagsPath = Path.Combine(Application.persistentDataPath, data.meta.guid.ToString());
        var tags     = SaveFile.ReadTags(tagsPath);

        TagManager.Instance.SetTags(tags);

        var chaptersPath = Path.Combine(Application.persistentDataPath, data.meta.guid.ToString());
        var chapters     = SaveFile.ReadChapters(chaptersPath);

        ChapterManager.Instance.SetChapters(chapters);

        //NOTE(Simon): Sort all interactionpoints based on their timing
        data.points.Sort((x, y) => x.startTime != y.startTime
                                                                                ? x.startTime.CompareTo(y.startTime)
                                                                                : x.endTime.CompareTo(y.endTime));

        foreach (var point in data.points)
        {
            var newPoint = Instantiate(interactionPointPrefab);

            var newInteractionPoint = new InteractionPointPlayer
            {
                startTime          = point.startTime,
                endTime            = point.endTime,
                title              = point.title,
                body               = point.body,
                filename           = point.filename,
                type               = point.type,
                point              = newPoint,
                tagId              = point.tagId,
                mandatory          = point.mandatory,
                returnRayOrigin    = point.returnRayOrigin,
                returnRayDirection = point.returnRayDirection
            };

            bool isValidPoint = true;

            switch (newInteractionPoint.type)
            {
            case InteractionType.None:
            {
                isValidPoint = false;
                Debug.Log("InteractionPoint with Type None encountered");
                break;
            }

            case InteractionType.Text:
            {
                var panel = Instantiate(textPanelPrefab, Canvass.sphereUIPanelWrapper.transform);
                panel.GetComponent <TextPanel>().Init(newInteractionPoint.title, newInteractionPoint.body);
                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.Image:
            {
                var panel     = Instantiate(imagePanelPrefab, Canvass.sphereUIPanelWrapper.transform);
                var filenames = newInteractionPoint.filename.Split('\f');
                var urls      = new List <string>();
                foreach (var file in filenames)
                {
                    string url = Path.Combine(Application.persistentDataPath, Path.Combine(data.meta.guid.ToString(), file));
                    urls.Add(url);
                }
                panel.GetComponent <ImagePanel>().Init(newInteractionPoint.title, urls);
                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.Video:
            {
                var    panel = Instantiate(videoPanelPrefab, Canvass.sphereUIPanelWrapper.transform);
                string url   = Path.Combine(Application.persistentDataPath, data.meta.guid.ToString(), newInteractionPoint.filename);
                panel.GetComponent <VideoPanel>().Init(newInteractionPoint.title, url);
                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.MultipleChoice:
            {
                var split   = newInteractionPoint.body.Split(new[] { '\f' }, 2);
                int correct = Int32.Parse(split[0]);
                var panel   = Instantiate(multipleChoicePrefab, Canvass.sphereUIPanelWrapper.transform);
                panel.GetComponent <MultipleChoicePanelSphere>().Init(newInteractionPoint.title, correct, split[1].Split('\f'));
                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.Audio:
            {
                var    panel = Instantiate(audioPanelPrefab, Canvass.sphereUIPanelWrapper.transform);
                string url   = Path.Combine(Application.persistentDataPath, data.meta.guid.ToString(), newInteractionPoint.filename);
                panel.GetComponent <AudioPanel>().Init(newInteractionPoint.title, url);
                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.FindArea:
            {
                var panel = Instantiate(findAreaPanelPrefab, Canvass.sphereUIPanelWrapper.transform);
                var areas = Area.ParseFromSave(newInteractionPoint.filename, newInteractionPoint.body);

                panel.GetComponent <FindAreaPanelSphere>().Init(newInteractionPoint.title, areas);
                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.MultipleChoiceArea:
            {
                var    split    = newInteractionPoint.body.Split(new[] { '\f' }, 2);
                int    correct  = Int32.Parse(split[0]);
                string areaJson = split[1];
                var    panel    = Instantiate(multipleChoiceAreaPanelPrefab, Canvass.sphereUIPanelWrapper.transform);
                var    areas    = Area.ParseFromSave(newInteractionPoint.filename, areaJson);

                panel.GetComponent <MultipleChoiceAreaPanelSphere>().Init(newInteractionPoint.title, areas, correct);
                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.MultipleChoiceImage:
            {
                var panel     = Instantiate(multipleChoiceImagePanelPrefab, Canvass.sphereUIPanelWrapper.transform);
                var filenames = newInteractionPoint.filename.Split('\f');
                int correct   = Int32.Parse(newInteractionPoint.body);
                var urls      = new List <string>();
                foreach (string file in filenames)
                {
                    string url = Path.Combine(Application.persistentDataPath, Path.Combine(data.meta.guid.ToString(), file));
                    urls.Add(url);
                }
                panel.GetComponent <MultipleChoiceImagePanelSphere>().Init(newInteractionPoint.title, urls, correct);
                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.TabularData:
            {
                var      panel   = Instantiate(tabularDataPanelPrefab, Canvass.sphereUIPanelWrapper.transform);
                string[] body    = newInteractionPoint.body.Split(new[] { '\f' }, 3);
                int      rows    = Int32.Parse(body[0]);
                int      columns = Int32.Parse(body[1]);

                panel.GetComponent <TabularDataPanelSphere>().Init(newInteractionPoint.title, rows, columns, body[2].Split('\f'));

                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.Chapter:
            {
                var panel     = Instantiate(chapterPanelPrefab, Canvass.sphereUIPanelWrapper.transform);
                int chapterId = Int32.Parse(newInteractionPoint.body);
                panel.GetComponent <ChapterPanelSphere>().Init(newInteractionPoint.title, chapterId, this);
                newInteractionPoint.panel = panel;
                break;
            }

            default:
            {
                isValidPoint = false;
                Debug.LogError("Invalid interactionPoint encountered");
                break;
            }
            }

            if (isValidPoint)
            {
                if (newInteractionPoint.mandatory)
                {
                    mandatoryInteractionPoints.Add(newInteractionPoint);
                }

                AddInteractionPoint(newInteractionPoint);
            }
            else
            {
                Destroy(newPoint);
            }
        }

        //NOTE(Simon): For mandatoryInteractionPoints it makes more sense to sort by endTime
        mandatoryInteractionPoints.Sort((x, y) => x.endTime.CompareTo(y.endTime));

        StartCoroutine(UpdatePointPositions());

        if (VRDevices.loadedSdk == VRDevices.LoadedSdk.None)
        {
            Seekbar.instance.compass.SetActive(true);
        }
        else
        {
            Seekbar.instanceVR.compass.SetActive(true);
        }

        return(true);
    }
Пример #11
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;
                }
            }
        }
    }
Пример #12
0
    private bool OpenFile(string path)
    {
        data = SaveFile.OpenFile(path);

        openVideo = Path.Combine(Application.persistentDataPath, Path.Combine(data.meta.guid.ToString(), SaveFile.videoFilename));
        fileLoader.LoadFile(openVideo);

        //NOTE(Kristof): Add the 4 interactionpoints used for the mini-tutorial and starting the video, then load the InteractionPoints
        {
            startPointGroup.SetActive(true);

            foreach (var startPoint in startPoints)
            {
                interactionPoints.Add(new InteractionPointPlayer
                {
                    point        = startPoint,
                    isStartPoint = true,
                    startTime    = -1,
                    endTime      = -1,
                    isTouched    = false
                });

                var content = startPoint.GetComponentInChildren <Text>();
                if (VRDevices.loadedControllerSet > VRDevices.LoadedControllerSet.NoControllers)
                {
                    content.text = "Aim at the white point below and press the trigger";
                }
                else
                {
                    content.text = "Align the central circle with the white point below";
                }
            }
        }

        data.points.Sort((x, y) => x.startTime != y.startTime
                                                                                ? x.startTime.CompareTo(y.startTime)
                                                                                : x.endTime.CompareTo(y.endTime));

        foreach (var point in data.points)
        {
            var newPoint = Instantiate(interactionPointPrefab /*, point.position, Quaternion.identity*/);

            var newInteractionPoint = new InteractionPointPlayer
            {
                startTime          = point.startTime,
                endTime            = point.endTime,
                title              = point.title,
                body               = point.body,
                filename           = Path.Combine(Application.persistentDataPath, Path.Combine(data.meta.guid.ToString(), point.filename)),
                type               = point.type,
                point              = newPoint,
                returnRayOrigin    = point.returnRayOrigin,
                returnRayDirection = point.returnRayDirection
            };

            // NOTE(Lander): Add file protocol for images, ignore for the rest.
            newInteractionPoint.filename = (newInteractionPoint.type == InteractionType.Image ? "file:///" : "") + newInteractionPoint.filename;

            switch (newInteractionPoint.type)
            {
            case InteractionType.Text:
            {
                var panel = Instantiate(textPanelPrefab);
                panel.GetComponent <TextPanel>().Init(newInteractionPoint.title, newInteractionPoint.body);
                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.Image:
            {
                var panel = Instantiate(imagePanelPrefab);
                panel.GetComponent <ImagePanel>().Init(newInteractionPoint.title, newInteractionPoint.filename, false);
                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.Video:
            {
                var panel = Instantiate(videoPanelPrefab);
                panel.GetComponent <VideoPanel>().Init(newInteractionPoint.title, newInteractionPoint.filename, data.meta.guid.ToString(), false);
                newInteractionPoint.panel = panel;
                break;
            }

            case InteractionType.MultipleChoice:
            {
                var panel = Instantiate(multipleChoicePrefab);
                panel.GetComponent <MultipleChoicePanel>().Init(newInteractionPoint.title, newInteractionPoint.body.Split('\f'));
                newInteractionPoint.panel = panel;
                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }

            AddInteractionPoint(newInteractionPoint);
        }
        StartCoroutine(UpdatePointPositions());

        return(true);
    }
Пример #13
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;
            }
        }
    }
Пример #14
0
 private void AddInteractionPoint(InteractionPointPlayer point)
 {
     interactionPoints.Add(point);
 }