Files
VFSUnity/Assets/Scripts/UI/UIManager.cs
T
2026-07-14 00:16:34 +08:00

354 lines
12 KiB
C#

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;
public class UIManager : MonoBehaviour
{
[Header("管理器引用")]
[SerializeField] private StepManager _stepManager;
[SerializeField] private InteractionSystem _interactionSystem;
[Header("=== 顶部提示栏 ===")]
[SerializeField] private GameObject _tipPanel;
[SerializeField] private Text _tipText;
[Header("=== 详细操作说明面板 ===")]
[SerializeField] private GameObject _detailPanel;
[SerializeField] private Text _detailText;
[Header("=== 对话气泡 ===")]
[SerializeField] private GameObject _dialogueBubble;
[SerializeField] private Text _dialogueText;
[Header("=== 画中画视频 ===")]
[SerializeField] private GameObject _videoPanel;
[Header("=== 仿真导航栏按钮 ===")]
[SerializeField] private Button _btnFullScreen;
[SerializeField] private Button _btnPrevious;
[SerializeField] private Button _btnNext;
[SerializeField] private Button _btnSwitchMode;
[SerializeField] private Button _btnReturn;
[SerializeField] private Text _btnSwitchModeLabel;
[Header("=== 底部进度条 ===")]
[SerializeField] private Slider _progressBar;
[SerializeField] private Text _progressText;
[Header("=== 弹窗 ===")]
[SerializeField] private ExamPopup _examPopup;
[SerializeField] private GameObject _endPanel;
private void Start()
{
Debug.Log("=== UIManager 初始化开始 ===");
AutoFindPanels();
HideVideo();
if (_endPanel != null) _endPanel.SetActive(false);
if (_stepManager == null)
_stepManager = FindObjectOfType<StepManager>();
if (_interactionSystem == null)
_interactionSystem = FindObjectOfType<InteractionSystem>();
BindEvents();
BindButtons();
BindNavbarButtons();
Debug.Log("=== UIManager 初始化完成 ===");
}
private void AutoFindPanels()
{
var canvas = GameObject.Find("Canvas")?.transform;
if (canvas == null) return;
if (_videoPanel == null)
{
var t = canvas.Find("VideoPanel");
if (t != null) _videoPanel = t.gameObject;
}
if (_endPanel == null)
{
var t = canvas.Find("EndPanel");
if (t != null) _endPanel = t.gameObject;
}
}
private void BindNavbarButtons()
{
var experimentPanel = GameObject.Find("ExperimentPanel");
if (experimentPanel == null) return;
var navbar = experimentPanel.transform.Find("Navbar");
if (navbar == null) return;
var btnFS = navbar.Find("FullScreen");
if (btnFS != null) { var btn = btnFS.GetComponent<Button>(); if (btn != null) { btn.onClick.RemoveListener(ToggleFullScreen); btn.onClick.AddListener(ToggleFullScreen); } }
var btnPrev = navbar.Find("Previous");
if (btnPrev != null) { var btn = btnPrev.GetComponent<Button>(); if (btn != null) { btn.onClick.RemoveListener(OnPreviousClicked); btn.onClick.AddListener(OnPreviousClicked); } }
var btnNext = navbar.Find("Next");
if (btnNext != null) { var btn = btnNext.GetComponent<Button>(); if (btn != null) { btn.onClick.RemoveListener(OnNextClicked); btn.onClick.AddListener(OnNextClicked); } }
var btnReturn = navbar.Find("BtnBack");
if (btnReturn != null) { var btn = btnReturn.GetComponent<Button>(); if (btn != null) { btn.onClick.RemoveListener(OnReturnClicked); btn.onClick.AddListener(OnReturnClicked); } }
}
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); }
}
private void BindEvents()
{
if (_stepManager == null) return;
_stepManager.OnStepChanged.AddListener(OnStepChanged);
_stepManager.OnTipChanged.AddListener(UpdateTipContent);
_stepManager.OnDialogueChanged.AddListener(UpdateDialogueContent);
_stepManager.OnDetailedContent.AddListener(UpdateDetailContent);
_stepManager.OnVideoToggle.AddListener(ToggleVideo);
_stepManager.OnExamPopup.AddListener(ShowExamPopup);
_stepManager.OnExperimentComplete.AddListener(OnExperimentComplete);
_stepManager.OnModeUIUpdate.AddListener(UpdateModeUI);
}
private void UpdateModeUI(bool isExamMode)
{
if (_btnSwitchModeLabel != null)
_btnSwitchModeLabel.text = isExamMode ? "切换到:练习模式" : "切换到:考核模式";
}
private void OnStepChanged(int stepIndex)
{
UpdateProgressBar();
UpdateNavigationButtons();
}
private void UpdateTipContent(string text)
{
if (_tipPanel != null) _tipPanel.SetActive(!string.IsNullOrEmpty(text));
if (_tipText != null) _tipText.text = text;
}
private void UpdateDialogueContent(string text)
{
if (_dialogueBubble == null)
{
var t = GameObject.Find("Canvas")?.transform.Find("DialogueBubble");
if (t != null) _dialogueBubble = t.gameObject;
}
if (_dialogueBubble != null)
{
bool hasText = !string.IsNullOrEmpty(text);
bool isExam = GameManager.Instance != null && GameManager.Instance.CurrentMode == ExperimentMode.Exam;
bool isExamBubble = _dialogueBubble.transform.Find("step1") != null;
if (!isExam && isExamBubble)
{
_dialogueBubble.SetActive(false);
return;
}
_dialogueBubble.SetActive(hasText);
var txt = _dialogueBubble.GetComponentInChildren<Text>();
if (txt != null) txt.text = text;
}
}
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)
{
if (active && !string.IsNullOrEmpty(fileName)) ShowVideo(fileName);
else HideVideo();
}
public void ShowVideo(string fileName)
{
AutoFindPanels();
if (_videoPanel != null)
{
_videoPanel.SetActive(true);
var controller = _videoPanel.GetComponent<VideoController>();
if (controller != null)
{
controller.PlayVideo(fileName);
return;
}
var vp = _videoPanel.GetComponentInChildren<VideoPlayer>(true);
if (vp != null)
{
ConfigureStreamingVideo(vp, fileName);
vp.Play();
}
Debug.Log("UIManager: 显示并播放 VideoPanel: " + fileName);
}
}
private void ConfigureStreamingVideo(VideoPlayer vp, string fileName)
{
vp.source = VideoSource.Url;
vp.url = BuildStreamingVideoUrl(fileName);
vp.playOnAwake = false;
vp.isLooping = true;
vp.renderMode = VideoRenderMode.RenderTexture;
vp.audioOutputMode = VideoAudioOutputMode.Direct;
}
private string BuildStreamingVideoUrl(string fileName)
{
string safeName = string.IsNullOrEmpty(fileName) ? "bandage_demo.mp4" : fileName;
string baseUrl = Application.streamingAssetsPath.TrimEnd('/');
return baseUrl + "/Videos/" + safeName;
}
public void HideVideo()
{
AutoFindPanels();
if (_videoPanel != null)
{
var vp = _videoPanel.GetComponentInChildren<UnityEngine.Video.VideoPlayer>(true);
if (vp != null) vp.Stop();
_videoPanel.SetActive(false);
Debug.Log("UIManager: 隐藏 VideoPanel");
}
}
public void HideEndPanel()
{
AutoFindPanels();
if (_endPanel == null)
{
var t = GameObject.Find("Canvas")?.transform.Find("EndPanel");
if (t != null) _endPanel = t.gameObject;
}
if (_endPanel != null) _endPanel.SetActive(false);
}
public void ShowEndPanel()
{
AutoFindPanels();
if (_endPanel == null)
{
var t = GameObject.Find("Canvas")?.transform.Find("EndPanel");
if (t != null) _endPanel = t.gameObject;
}
if (_endPanel != null)
{
_endPanel.SetActive(true);
// 绑定 BtnYes:结束后返回首页
var btnYes = _endPanel.transform.Find("BtnYes")?.GetComponent<Button>();
if (btnYes != null)
{
btnYes.onClick.RemoveAllListeners();
btnYes.onClick.AddListener(OnReturnClicked);
}
// 绑定 BtnBack:关闭 EndPanel(如果你希望点它也是单纯关面板而不是退回到首页的话)
var btnBack = _endPanel.transform.Find("BtnBack")?.GetComponent<Button>();
if (btnBack != null)
{
btnBack.onClick.RemoveAllListeners();
btnBack.onClick.AddListener(() => { _endPanel.SetActive(false); });
}
// (如果还需要之前的 BtnReturn 点击退回到主页,可以继续绑定)
var btnRet = _endPanel.transform.Find("BtnReturn")?.GetComponent<Button>();
if (btnRet != null)
{
btnRet.onClick.RemoveAllListeners();
btnRet.onClick.AddListener(OnReturnClicked);
}
}
}
private void UpdateProgressBar()
{
if (_stepManager == null) return;
int cur = _stepManager.CurrentStepIndex + 1;
int total = _stepManager.TotalSteps;
if (_progressBar != null) _progressBar.value = (float)cur / total;
if (_progressText != null) _progressText.text = cur + "/" + total;
}
private void UpdateNavigationButtons()
{
if (_stepManager == null) return;
if (_btnPrevious != null) _btnPrevious.interactable = true;
if (_btnNext != null)
{
var label = _btnNext.GetComponentInChildren<Text>();
if (label != null) label.text = "下一步";
}
}
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()
{
ShowEndPanel();
}
private void ToggleFullScreen() { Screen.fullScreen = !Screen.fullScreen; }
private void OnNextClicked()
{
if (_stepManager == null) _stepManager = FindObjectOfType<StepManager>();
if (_stepManager != null && _stepManager.Mode == ExperimentMode.Exam)
{
var step = _stepManager.GetCurrentStep();
if (step != null && step.CompleteType != StepCompleteType.MultipleChoice)
_stepManager.OnStepInteractionComplete(1f);
}
_stepManager?.NextStep();
}
private void OnPreviousClicked()
{
if (_stepManager == null) _stepManager = FindObjectOfType<StepManager>();
_stepManager?.PreviousStep();
}
private void OnSwitchModeClicked()
{
if (_stepManager == null) return;
var oldMode = _stepManager.Mode;
var newMode = oldMode == ExperimentMode.Learn ? ExperimentMode.Exam : ExperimentMode.Learn;
_stepManager.SwitchMode(newMode);
}
private void OnReturnClicked()
{
HideEndPanel();
var pageCtrl = FindObjectOfType<PageController>();
if (pageCtrl != null) pageCtrl.ReturnToHome();
}
}