226 lines
6.0 KiB
C#
226 lines
6.0 KiB
C#
|
|
using Edia;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using TMPro;
|
|
using UXF;
|
|
using System.Collections.Generic;
|
|
|
|
public class TaskNavigation : XBlock {
|
|
/*
|
|
* Xblock order of execution:
|
|
* 1. OnBlockStart
|
|
* 2. OnTrialStart
|
|
* 3. first step method
|
|
* 4. InBetweenSteps
|
|
* 5. next step method
|
|
* 6. ...
|
|
* 7. OnTrialEnd
|
|
* 8. OnBlockEnd
|
|
* 9. OnBlockOutro
|
|
*/
|
|
|
|
[SerializeField] private VideoClipPicker videoPicker;
|
|
[SerializeField] private Material skybox360Video;
|
|
private int _currentVideoIndex;
|
|
|
|
[SerializeField] private ScreenInVR messageCanvas;
|
|
[SerializeField] private Button doneButton;
|
|
[SerializeField] private TextMeshProUGUI timerText;
|
|
|
|
[Header("Cheat Controls")]
|
|
[SerializeField] private GameObject cheatPanel;
|
|
[SerializeField] private List<Button> videoButtons;
|
|
[SerializeField] private Button playResumeButton;
|
|
|
|
|
|
private float _timer;
|
|
private bool _isNavigating;
|
|
|
|
private void Awake() {
|
|
/*
|
|
Each trial exists out of a sequence of steps.
|
|
Each step is a standalone part of the experiment task.
|
|
I.e. Show a message to the user, show a fixation cross, wait for user input, etc.
|
|
In order to use the steps, they need to be defined in the trial sequence.
|
|
|
|
A common approach within a trial is as follows:
|
|
*/
|
|
|
|
RenderSettings.skybox = null;
|
|
DynamicGI.UpdateEnvironment();
|
|
|
|
AddToTrialSequence(Setup); // #1 Set up environment / Generate Stimuli / etc
|
|
AddToTrialSequence(ShowVideoReference);
|
|
AddToTrialSequence(PlayVideoReference);
|
|
AddToTrialSequence(FinishedPlayingVideo);
|
|
AddToTrialSequence(Cleanup);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (_isNavigating)
|
|
{
|
|
_timer += Time.deltaTime;
|
|
timerText.text = _timer.ToString("F2");
|
|
}
|
|
|
|
}
|
|
|
|
#region TASK STEPS
|
|
|
|
/*
|
|
The framework provides a set of tools to make it easier to implement the task.
|
|
For example:
|
|
* XRManager.Instance.xxxxx => All things XR related
|
|
* Experiment.instance.xxxxx => All things related to the progress of the experiment, logging data, etc
|
|
|
|
See documentation for more details.
|
|
*/
|
|
|
|
// -------------------------------------------------------------------------------------------
|
|
// #1
|
|
/// <summary>Prepare and show stimuli</summary>
|
|
[ContextMenu("Setup")]
|
|
void Setup() {
|
|
/*
|
|
* A step always ends with either a 'PROCEED' and/or 'WAITONPROCEED'
|
|
*/
|
|
|
|
Camera.main.clearFlags = CameraClearFlags.Skybox;
|
|
|
|
_timer = 0;
|
|
_isNavigating = false;
|
|
timerText.text = "0.0";
|
|
messageCanvas.Show(true);
|
|
|
|
for (int i = 0; i < videoButtons.Count; i++)
|
|
{
|
|
int index = i; // Capture the current value of i
|
|
videoButtons[i].onClick.AddListener(() => ForceChangeVideoReference(index));
|
|
}
|
|
playResumeButton.onClick.AddListener(PauseResumeVideo);
|
|
doneButton.onClick.AddListener(NavigationDone);
|
|
|
|
XRManager.Instance.EnableAllInteraction(true);
|
|
|
|
Experiment.Instance.WaitOnProceed();
|
|
}
|
|
|
|
private void PauseResumeVideo()
|
|
{
|
|
videoPicker.TogglePause();
|
|
Experiment.Instance.StoreMarker("VideoPaused" + _timer.ToString("F2"));
|
|
}
|
|
|
|
private void NavigationDone()
|
|
{
|
|
_isNavigating = false;
|
|
|
|
Experiment.Instance.AddToTrialResults("Index", "Video_" + _currentVideoIndex);
|
|
Experiment.Instance.AddToTrialResults("NavigationTime", _timer.ToString("F2"));
|
|
|
|
Experiment.Instance.WaitOnProceed();
|
|
}
|
|
|
|
private void ShowVideoReference() {
|
|
var videoIndex = Session.instance.CurrentTrial.settings.GetInt("videoId");
|
|
|
|
_currentVideoIndex = videoIndex;
|
|
|
|
// Show 360 skybox
|
|
RenderSettings.skybox = skybox360Video;
|
|
DynamicGI.UpdateEnvironment();
|
|
|
|
videoPicker.SelectClip(videoIndex);
|
|
videoPicker.StartCountdown(); // start on the first frame; press Proceed to Play
|
|
|
|
// Add results and relevant data to trial results
|
|
Experiment.Instance.AddToTrialResults("Navigating Video ID", _currentVideoIndex.ToString());
|
|
Experiment.Instance.WaitOnProceed();
|
|
}
|
|
|
|
void PlayVideoReference()
|
|
{
|
|
_isNavigating = true;
|
|
|
|
// Resume video
|
|
videoPicker.Resume();
|
|
Experiment.Instance.StoreMarker("Playing video " + _currentVideoIndex);
|
|
|
|
Experiment.Instance.WaitOnProceed();
|
|
}
|
|
|
|
void FinishedPlayingVideo()
|
|
{
|
|
_isNavigating = false;
|
|
Experiment.Instance.StoreMarker("Finished video " + _currentVideoIndex);
|
|
|
|
Experiment.Instance.WaitOnProceed();
|
|
}
|
|
|
|
private void Cleanup()
|
|
{
|
|
doneButton.onClick.RemoveAllListeners();
|
|
messageCanvas.Show(false);
|
|
|
|
Camera.main.clearFlags = CameraClearFlags.SolidColor;
|
|
|
|
foreach (var button in videoButtons)
|
|
{
|
|
button.onClick.RemoveAllListeners();
|
|
}
|
|
|
|
cheatPanel.SetActive(false);
|
|
|
|
RenderSettings.skybox = null;
|
|
DynamicGI.UpdateEnvironment();
|
|
|
|
Experiment.Instance.WaitOnProceed();
|
|
}
|
|
|
|
private void ForceChangeVideoReference(int videoIndex)
|
|
{
|
|
_currentVideoIndex = videoIndex;
|
|
|
|
videoPicker.SelectClip(_currentVideoIndex);
|
|
videoPicker.StartCountdown();
|
|
videoPicker.Resume();
|
|
Experiment.Instance.StoreMarker("Forced Change to Video " + _currentVideoIndex);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region STATEMACHINE OVERRIDES
|
|
|
|
public override void OnBlockStart() {
|
|
/*
|
|
* Shows message to the user if there is a value defined in the configs with the key "_intro"
|
|
*/
|
|
|
|
}
|
|
|
|
public override void OnStartTrial() {
|
|
}
|
|
|
|
public override void OnEndTrial() {
|
|
}
|
|
|
|
public override void OnBetweenSteps() {
|
|
}
|
|
|
|
public override void OnBlockEnd()
|
|
{
|
|
/*
|
|
* Shows message to the user if there is a value defined in the configs with the key "_outro"
|
|
*/
|
|
|
|
}
|
|
|
|
public override void OnBlockOutro() {
|
|
|
|
}
|
|
|
|
#endregion
|
|
}
|