using System; using TMPro; using UnityEngine; using UnityEngine.UI; using UnityEngine.Video; /// /// TemplateCourse scene manager /// public class TemplateCourse : MonoBehaviour { /// /// Index to indicate which camera is being used /// private int camdex = 0; /// /// This texture is used as an intermidiary between the camera output and the display image /// private WebCamTexture tex; /// /// Reference to the RawImage that will display the video /// public RawImage webcamDisplay; /// /// Reference to the button that is currently used to test the feedback-display /// public Button feedback; /// /// This is a reference to the textfield that holds the part of the feedback-window that will change: bad/good/excellent /// public TMP_Text dynamic; /// /// Reference to instructional video player /// public VideoPlayer player; /// /// Reference to pause button /// public Button button; /// /// Reference to sprite for the pause button /// public Sprite pauseSprite; /// /// Reference to the image for displaying the current words sprite /// public Image wordImage; /// /// Reference to the text object for displaying the current word /// public TMP_Text title; /// /// Reference to user list to get current user /// public UserList userList; /// /// The current user /// private User user; /// /// Current user progress for this course /// private Progress progress = null; /// /// ScriptableObject with list of all courses /// public CourseList courselist; /// /// Reference to Course ScriptableObject /// private Course course; /// /// Index of the current word/letter in the course.learnables list /// private int currentWordIndex = 0; /// /// This holds the amount of words in the course /// private int maxWords; /// /// Number of correct words so far /// (can be modified to a list or something like that to give better feedback) /// private int correctWords = 0; /// /// The "finished" screen /// public GameObject ResultPanel; /// /// Button to go back to courses list /// public Button CoursesButton; /// /// DateTime containint the start moment /// private DateTime startMoment; /// /// Reference to the timeSpent UI /// public TMP_Text timeSpent; /// /// This function is called when the script is initialised. /// It inactivatis the popup, finds a webcam to use and links it via the WebcamTexture to the display RawImage. /// It takes the correct course from the courselist, using the courseIndex. /// Then it checks whether or not the User has started the course yet, to possibly create a new progress atribute for the course. /// Then it sets up the course-screen to display relevant information from the course-scriptable. /// void Awake() { // Setting up Webcam // feedbackPopup.SetActive(false); //if (WebCamTexture.devices.Length > 0) //{ // WebCamDevice device = WebCamTexture.devices[camdex]; // tex = new WebCamTexture(device.name); // webcamDisplay.texture = tex; // tex.Play(); //} // Setting up course course = courselist.courses[courselist.currentCourseIndex]; maxWords = course.theme.learnables.Count; // Create entry in current user for keeping track of progress user = userList.GetCurrentUser(); progress = user.GetCourseProgress(course.index); if (progress == null) { progress = new Progress(); progress.AddOrUpdate("courseIndex", course.index); progress.AddOrUpdate("courseProgress", -1.0f); user.courses.Add(progress); } userList.Save(); // Force the videoplayer to add bars to preserve aspect ratio player.aspectRatio = VideoAspectRatio.FitInside; // Setup UI button.image.sprite = pauseSprite; title.text = course.name; NextVideo(); NextImage(); // Hide the result panel ResultPanel.SetActive(false); // Set the startTime startMoment = DateTime.Now; } /// /// This function uses the word_i integer to grab the correct video from the course.learnabels. /// When it has this video, it will load it into the videoplayer and set it to start. /// private void NextVideo() { player.clip = course.theme.learnables[currentWordIndex].clip; // This loads first frame, so that it can be used as a sort-of preview for the video player.Play(); // As the video will start playiing -> hide button Color col = button.image.color; col.a = 0; button.image.color = col; } /// /// This function uses the word_i integer to grab the correct image from the course.learnabels. /// Then it simply loads it into wordImage so that it can be displayed. /// private void NextImage() { wordImage.sprite = course.theme.learnables[currentWordIndex].image; } /// /// This function is called when the pause-button is pressed on the video. /// It switches between playing and pausing the video. /// It then makes the button invisible when the video is playing, or visible when it's paused. /// public void Pause() { if (!player.isPlaying) { // Play video and hide button player.Play(); Color col = button.image.color; col.a = 0; button.image.color = col; } else { // Pause video and show button player.Pause(); Color col = button.image.color; col.a = 255; button.image.color = col; } } /// /// This function is called when the next-sign button is pressed. /// It increased the wordindex and fetches new videos/images if index public void NextSign() { // If the currentindex >= maxwords, it indicated that the course is already finished, running the next code is the meaningless. if (currentWordIndex >= maxWords) { return; } // Goto the next word/letter currentWordIndex++; // TODO: fix correct word count correctWords++; progress.AddOrUpdate("courseProgress", (float)correctWords / (float)maxWords); userList.Save(); // Update UI if course is not finished yet if (currentWordIndex < maxWords) { NextVideo(); NextImage(); } // Finish course and record progress else { FinishCourse(); } } /// /// finishcourse is called to save the "finished" progress to the user. /// public void FinishCourse() { // Show the "finished" screen ResultPanel.SetActive(true); // Set the total time spent UI TimeSpan time = DateTime.Now - startMoment; timeSpent.text = time.ToString(@"hh\:mm\:ss"); // Link button CoursesButton.onClick.AddListener(() => { SystemController.GetInstance().BackToPreviousScene(); }); progress.AddOrUpdate("courseProgress", 1f); userList.Save(); } /// /// So long as there are cameras to use, you swap the camera you are using to another in the list. /// public void SwapCam() { if (WebCamTexture.devices.Length > 0) { // Stop the old camera // If there was no camera playing before, then you dont have to reset the texture, as it wasn't assigned in the first place. if (tex.isPlaying) { webcamDisplay.texture = null; tex.Stop(); tex = null; } // Find the new camera camdex += 1; camdex %= WebCamTexture.devices.Length; // Start the new camera WebCamDevice device = WebCamTexture.devices[camdex]; tex = new WebCamTexture(device.name); webcamDisplay.texture = tex; tex.Play(); } } /// /// The normal sceneChanger cannot be used here since the camera also needs to be stopped. /// This extra functionality is implemented in this function /// /// The path for the scene you want to travel to, assuming root-directory is Assets public void Back() { //webcamDisplay.texture = null; //tex.Stop(); //tex = null; SystemController.GetInstance().BackToPreviousScene(); } /// /// This function toggles between inactivity and activity for the popup panel. /// This will be changed later when the model gets integrated, probably being timed to dissapear. /// //public void ShowFeedback() //{ // if (feedbackPopup.activeSelf) // { // dynamic.text = ""; // feedbackPopup.SetActive(false); // return; // } // double index = UnityEngine.Random.value; // if (index < 0.5) // { // dynamic.text = "Poor"; // } // else if (index > 0.8) // { // dynamic.text = "Excellent"; // } // else // { // dynamic.text = "Good"; // } // feedbackPopup.SetActive(true); //} // Get currentWordIndex public int GetWordIndex() { return currentWordIndex; } }