2026-06-24 02:33:48 +08:00
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
|
|
|
|
|
public class UIManager : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
[Header("管理器引用")]
|
|
|
|
|
[SerializeField] private StepManager _stepManager;
|
|
|
|
|
[SerializeField] private InteractionSystem _interactionSystem;
|
|
|
|
|
|
|
|
|
|
[Header("=== 顶部提示栏 ===")]
|
|
|
|
|
[SerializeField] private GameObject _tipPanel;
|
2026-06-24 02:44:58 +08:00
|
|
|
[SerializeField] private Text _tipText;
|
2026-06-24 02:33:48 +08:00
|
|
|
|
2026-06-24 02:44:58 +08:00
|
|
|
[Header("=== 详细操作说明面板 ===")]
|
2026-06-24 02:33:48 +08:00
|
|
|
[SerializeField] private GameObject _detailPanel;
|
2026-06-24 02:44:58 +08:00
|
|
|
[SerializeField] private Text _detailText;
|
2026-06-24 02:33:48 +08:00
|
|
|
|
|
|
|
|
[Header("=== 对话气泡 ===")]
|
|
|
|
|
[SerializeField] private GameObject _dialogueBubble;
|
2026-06-24 02:44:58 +08:00
|
|
|
[SerializeField] private Text _dialogueText;
|
2026-06-24 02:33:48 +08:00
|
|
|
|
|
|
|
|
[Header("=== 画中画视频 ===")]
|
2026-07-10 05:01:29 +08:00
|
|
|
[SerializeField] private GameObject _videoPanel;
|
2026-06-24 02:33:48 +08:00
|
|
|
|
2026-07-12 07:03:36 +08:00
|
|
|
[Header("=== 仿真导航栏按钮 ===")]
|
2026-06-24 02:33:48 +08:00
|
|
|
[SerializeField] private Button _btnFullScreen;
|
|
|
|
|
[SerializeField] private Button _btnPrevious;
|
|
|
|
|
[SerializeField] private Button _btnNext;
|
|
|
|
|
[SerializeField] private Button _btnSwitchMode;
|
|
|
|
|
[SerializeField] private Button _btnReturn;
|
2026-06-24 02:44:58 +08:00
|
|
|
[SerializeField] private Text _btnSwitchModeLabel;
|
2026-06-24 02:33:48 +08:00
|
|
|
|
|
|
|
|
[Header("=== 底部进度条 ===")]
|
|
|
|
|
[SerializeField] private Slider _progressBar;
|
2026-06-24 02:44:58 +08:00
|
|
|
[SerializeField] private Text _progressText;
|
2026-06-24 02:33:48 +08:00
|
|
|
|
|
|
|
|
[Header("=== 弹窗 ===")]
|
|
|
|
|
[SerializeField] private ExamPopup _examPopup;
|
2026-07-12 07:03:36 +08:00
|
|
|
[SerializeField] private GameObject _endPanel;
|
2026-06-24 02:33:48 +08:00
|
|
|
|
|
|
|
|
private void Start()
|
|
|
|
|
{
|
2026-06-29 20:25:57 +08:00
|
|
|
Debug.Log("=== UIManager 初始化开始 ===");
|
2026-07-10 05:01:29 +08:00
|
|
|
HideVideo();
|
2026-07-12 07:03:36 +08:00
|
|
|
if (_endPanel != null) _endPanel.SetActive(false);
|
2026-06-29 20:25:57 +08:00
|
|
|
|
2026-06-24 02:44:58 +08:00
|
|
|
if (_stepManager == null)
|
|
|
|
|
_stepManager = FindObjectOfType<StepManager>();
|
2026-07-12 07:03:36 +08:00
|
|
|
|
2026-06-24 02:44:58 +08:00
|
|
|
if (_interactionSystem == null)
|
|
|
|
|
_interactionSystem = FindObjectOfType<InteractionSystem>();
|
|
|
|
|
|
2026-06-24 02:33:48 +08:00
|
|
|
BindEvents();
|
2026-07-12 07:03:36 +08:00
|
|
|
BindButtons();
|
|
|
|
|
BindNavbarButtons();
|
2026-06-29 20:25:57 +08:00
|
|
|
Debug.Log("=== UIManager 初始化完成 ===");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void BindNavbarButtons()
|
|
|
|
|
{
|
|
|
|
|
var experimentPanel = GameObject.Find("ExperimentPanel");
|
2026-07-12 07:03:36 +08:00
|
|
|
if (experimentPanel == null) return;
|
2026-06-29 20:25:57 +08:00
|
|
|
var navbar = experimentPanel.transform.Find("Navbar");
|
2026-07-12 07:03:36 +08:00
|
|
|
if (navbar == null) return;
|
2026-06-29 20:25:57 +08:00
|
|
|
|
|
|
|
|
var btnFS = navbar.Find("FullScreen");
|
2026-07-12 07:03:36 +08:00
|
|
|
if (btnFS != null) { var btn = btnFS.GetComponent<Button>(); if (btn != null) { btn.onClick.RemoveListener(ToggleFullScreen); btn.onClick.AddListener(ToggleFullScreen); } }
|
2026-06-29 20:25:57 +08:00
|
|
|
|
|
|
|
|
var btnPrev = navbar.Find("Previous");
|
2026-07-12 07:03:36 +08:00
|
|
|
if (btnPrev != null) { var btn = btnPrev.GetComponent<Button>(); if (btn != null) { btn.onClick.RemoveListener(OnPreviousClicked); btn.onClick.AddListener(OnPreviousClicked); } }
|
2026-06-29 20:25:57 +08:00
|
|
|
|
|
|
|
|
var btnNext = navbar.Find("Next");
|
2026-07-12 07:03:36 +08:00
|
|
|
if (btnNext != null) { var btn = btnNext.GetComponent<Button>(); if (btn != null) { btn.onClick.RemoveListener(OnNextClicked); btn.onClick.AddListener(OnNextClicked); } }
|
2026-06-29 20:25:57 +08:00
|
|
|
|
2026-07-12 07:03:36 +08:00
|
|
|
var btnReturn = navbar.Find("BtnBack");
|
|
|
|
|
if (btnReturn != null) { var btn = btnReturn.GetComponent<Button>(); if (btn != null) { btn.onClick.RemoveListener(OnReturnClicked); btn.onClick.AddListener(OnReturnClicked); } }
|
2026-06-24 02:33:48 +08:00
|
|
|
}
|
|
|
|
|
|
2026-07-12 07:03:36 +08:00
|
|
|
private void BindButtons()
|
|
|
|
|
{
|
|
|
|
|
if (_btnFullScreen != null) { _btnFullScreen.onClick.RemoveListener(ToggleFullScreen); _btnFullScreen.onClick.AddListener(ToggleFullScreen); }
|
|
|
|
|
if (_btnPrevious != null) { _btnPrevious.onClick.RemoveListener(OnPreviousClicked); _btnPrevious.onClick.AddListener(OnPreviousClicked); }
|
|
|
|
|
if (_btnNext != null) { _btnNext.onClick.RemoveListener(OnNextClicked); _btnNext.onClick.AddListener(OnNextClicked); }
|
|
|
|
|
if (_btnSwitchMode != null) { _btnSwitchMode.onClick.RemoveListener(OnSwitchModeClicked); _btnSwitchMode.onClick.AddListener(OnSwitchModeClicked); }
|
|
|
|
|
if (_btnReturn != null) { _btnReturn.onClick.RemoveListener(OnReturnClicked); _btnReturn.onClick.AddListener(OnReturnClicked); }
|
|
|
|
|
}
|
2026-06-24 02:33:48 +08:00
|
|
|
|
|
|
|
|
private void BindEvents()
|
|
|
|
|
{
|
|
|
|
|
if (_stepManager == null) return;
|
|
|
|
|
_stepManager.OnStepChanged.AddListener(OnStepChanged);
|
2026-07-12 07:03:36 +08:00
|
|
|
_stepManager.OnTipChanged.AddListener(UpdateTipContent);
|
|
|
|
|
_stepManager.OnDialogueChanged.AddListener(UpdateDialogueContent);
|
2026-06-24 02:33:48 +08:00
|
|
|
_stepManager.OnDetailedContent.AddListener(UpdateDetailContent);
|
2026-07-12 07:03:36 +08:00
|
|
|
_stepManager.OnVideoToggle.AddListener(ToggleVideo);
|
2026-06-24 02:33:48 +08:00
|
|
|
_stepManager.OnExamPopup.AddListener(ShowExamPopup);
|
|
|
|
|
_stepManager.OnExperimentComplete.AddListener(OnExperimentComplete);
|
2026-07-12 07:03:36 +08:00
|
|
|
_stepManager.OnModeUIUpdate.AddListener(UpdateModeUI);
|
2026-06-24 02:33:48 +08:00
|
|
|
}
|
|
|
|
|
|
2026-07-12 07:03:36 +08:00
|
|
|
private void UpdateModeUI(bool isExamMode)
|
2026-06-24 02:33:48 +08:00
|
|
|
{
|
2026-07-12 07:03:36 +08:00
|
|
|
if (_btnSwitchModeLabel != null)
|
|
|
|
|
_btnSwitchModeLabel.text = isExamMode ? "切换到:练习模式" : "切换到:考核模式";
|
2026-06-24 02:33:48 +08:00
|
|
|
}
|
|
|
|
|
|
2026-07-12 07:03:36 +08:00
|
|
|
private void OnStepChanged(int stepIndex)
|
2026-06-24 02:33:48 +08:00
|
|
|
{
|
|
|
|
|
UpdateProgressBar();
|
|
|
|
|
UpdateNavigationButtons();
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-12 07:03:36 +08:00
|
|
|
private void UpdateTipContent(string text)
|
2026-06-24 02:33:48 +08:00
|
|
|
{
|
|
|
|
|
if (_tipPanel != null) _tipPanel.SetActive(!string.IsNullOrEmpty(text));
|
|
|
|
|
if (_tipText != null) _tipText.text = text;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-12 07:03:36 +08:00
|
|
|
private void UpdateDialogueContent(string text)
|
2026-06-24 02:33:48 +08:00
|
|
|
{
|
2026-07-12 07:03:36 +08:00
|
|
|
if (_dialogueBubble == null)
|
|
|
|
|
{
|
|
|
|
|
var t = GameObject.Find("Canvas")?.transform.Find("DialogueBubble");
|
|
|
|
|
if (t != null) _dialogueBubble = t.gameObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_dialogueBubble != null)
|
|
|
|
|
{
|
|
|
|
|
_dialogueBubble.SetActive(!string.IsNullOrEmpty(text));
|
|
|
|
|
var txt = _dialogueBubble.GetComponentInChildren<Text>();
|
|
|
|
|
if (txt != null) txt.text = text;
|
|
|
|
|
}
|
2026-06-24 02:33:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateDetailContent(string text)
|
|
|
|
|
{
|
|
|
|
|
if (_detailPanel != null) _detailPanel.SetActive(!string.IsNullOrEmpty(text));
|
|
|
|
|
if (_detailText != null) _detailText.text = text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ToggleVideo(string fileName, bool active)
|
|
|
|
|
{
|
2026-07-12 07:03:36 +08:00
|
|
|
if (active && !string.IsNullOrEmpty(fileName)) ShowVideo(fileName);
|
|
|
|
|
else HideVideo();
|
2026-07-10 05:01:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ShowVideo(string fileName)
|
|
|
|
|
{
|
|
|
|
|
if (_videoPanel != null)
|
|
|
|
|
{
|
|
|
|
|
_videoPanel.SetActive(true);
|
|
|
|
|
var vp = _videoPanel.GetComponentInChildren<UnityEngine.Video.VideoPlayer>(true);
|
2026-07-12 07:03:36 +08:00
|
|
|
if (vp != null) vp.Play();
|
2026-07-10 05:01:29 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void HideVideo()
|
|
|
|
|
{
|
|
|
|
|
if (_videoPanel != null)
|
|
|
|
|
{
|
|
|
|
|
var vp = _videoPanel.GetComponentInChildren<UnityEngine.Video.VideoPlayer>(true);
|
|
|
|
|
if (vp != null) vp.Stop();
|
|
|
|
|
_videoPanel.SetActive(false);
|
|
|
|
|
}
|
2026-06-24 02:33:48 +08:00
|
|
|
}
|
|
|
|
|
|
2026-07-12 07:03:36 +08:00
|
|
|
public void ShowEndPanel()
|
|
|
|
|
{
|
|
|
|
|
if (_endPanel == null)
|
|
|
|
|
{
|
|
|
|
|
var t = GameObject.Find("Canvas")?.transform.Find("EndPanel");
|
|
|
|
|
if (t != null) _endPanel = t.gameObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_endPanel != null)
|
|
|
|
|
{
|
|
|
|
|
_endPanel.SetActive(true);
|
|
|
|
|
|
|
|
|
|
// 绑定返回首页按钮
|
|
|
|
|
var btnRet = _endPanel.transform.Find("BtnReturn")?.GetComponent<Button>();
|
|
|
|
|
if (btnRet != null)
|
|
|
|
|
{
|
|
|
|
|
btnRet.onClick.RemoveAllListeners();
|
|
|
|
|
btnRet.onClick.AddListener(OnReturnClicked);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-24 02:33:48 +08:00
|
|
|
private void UpdateProgressBar()
|
|
|
|
|
{
|
|
|
|
|
if (_stepManager == null) return;
|
|
|
|
|
int cur = _stepManager.CurrentStepIndex + 1;
|
|
|
|
|
int total = _stepManager.TotalSteps;
|
|
|
|
|
if (_progressBar != null) _progressBar.value = (float)cur / total;
|
2026-06-24 02:44:58 +08:00
|
|
|
if (_progressText != null) _progressText.text = cur + "/" + total;
|
2026-06-24 02:33:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateNavigationButtons()
|
|
|
|
|
{
|
|
|
|
|
if (_stepManager == null) return;
|
2026-07-08 09:38:42 +08:00
|
|
|
if (_btnPrevious != null) _btnPrevious.interactable = true;
|
2026-06-29 20:25:57 +08:00
|
|
|
if (_btnNext != null)
|
2026-06-24 02:33:48 +08:00
|
|
|
{
|
2026-06-24 02:44:58 +08:00
|
|
|
var label = _btnNext.GetComponentInChildren<Text>();
|
2026-07-08 09:38:42 +08:00
|
|
|
if (label != null) label.text = "下一步";
|
2026-06-24 02:33:48 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ShowExamPopup(StepData step)
|
|
|
|
|
{
|
|
|
|
|
if (_examPopup == null) return;
|
|
|
|
|
_examPopup.Show(step, OnExamAnswer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnExamAnswer(float proportion, string feedback)
|
|
|
|
|
{
|
|
|
|
|
_stepManager?.OnStepInteractionComplete(proportion, feedback);
|
|
|
|
|
_stepManager?.NextStep();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnExperimentComplete()
|
|
|
|
|
{
|
2026-07-12 07:03:36 +08:00
|
|
|
ShowEndPanel();
|
2026-06-24 02:33:48 +08:00
|
|
|
}
|
|
|
|
|
|
2026-07-12 07:03:36 +08:00
|
|
|
private void ToggleFullScreen() { Screen.fullScreen = !Screen.fullScreen; }
|
2026-06-24 02:33:48 +08:00
|
|
|
|
|
|
|
|
private void OnNextClicked()
|
|
|
|
|
{
|
2026-07-12 07:03:36 +08:00
|
|
|
if (_stepManager == null) _stepManager = FindObjectOfType<StepManager>();
|
2026-07-08 09:38:42 +08:00
|
|
|
|
2026-06-24 02:44:58 +08:00
|
|
|
if (_stepManager != null && _stepManager.Mode == ExperimentMode.Exam)
|
2026-06-24 02:33:48 +08:00
|
|
|
{
|
|
|
|
|
var step = _stepManager.GetCurrentStep();
|
|
|
|
|
if (step != null && step.CompleteType != StepCompleteType.MultipleChoice)
|
|
|
|
|
_stepManager.OnStepInteractionComplete(1f);
|
|
|
|
|
}
|
2026-06-24 02:44:58 +08:00
|
|
|
_stepManager?.NextStep();
|
2026-06-24 02:33:48 +08:00
|
|
|
}
|
|
|
|
|
|
2026-07-08 09:38:42 +08:00
|
|
|
private void OnPreviousClicked()
|
|
|
|
|
{
|
|
|
|
|
if (_stepManager == null) _stepManager = FindObjectOfType<StepManager>();
|
|
|
|
|
_stepManager?.PreviousStep();
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-24 02:33:48 +08:00
|
|
|
private void OnSwitchModeClicked()
|
|
|
|
|
{
|
2026-06-24 02:44:58 +08:00
|
|
|
if (_stepManager == null) return;
|
2026-06-29 20:25:57 +08:00
|
|
|
var oldMode = _stepManager.Mode;
|
|
|
|
|
var newMode = oldMode == ExperimentMode.Learn ? ExperimentMode.Exam : ExperimentMode.Learn;
|
2026-06-24 02:33:48 +08:00
|
|
|
_stepManager.SwitchMode(newMode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnReturnClicked()
|
|
|
|
|
{
|
2026-07-12 07:03:36 +08:00
|
|
|
// 先隐藏面板
|
|
|
|
|
if (_endPanel != null) _endPanel.SetActive(false);
|
|
|
|
|
|
2026-06-25 04:37:45 +08:00
|
|
|
var pageCtrl = FindObjectOfType<PageController>();
|
2026-07-12 07:03:36 +08:00
|
|
|
if (pageCtrl != null) pageCtrl.ReturnToHome();
|
2026-06-24 02:33:48 +08:00
|
|
|
}
|
|
|
|
|
}
|