471 lines
17 KiB
C#
471 lines
17 KiB
C#
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
public class PageController : MonoBehaviour
|
||
{
|
||
[Header("=== 三个主页面 ===")]
|
||
[SerializeField] private GameObject _homePagePanel;
|
||
[SerializeField] private GameObject _modeSelectPanel;
|
||
[SerializeField] private GameObject _fixationPanel;
|
||
|
||
[Header("=== 实验页面 ===")]
|
||
[SerializeField] private GameObject _experimentPanel;
|
||
[SerializeField] private Button _btnExperimentBack;
|
||
|
||
[Header("=== 实验内 UI(由 UIManager 管理)===")]
|
||
[SerializeField] private UIManager _uiManager;
|
||
|
||
[Header("=== 首页控件 ===")]
|
||
[SerializeField] private Button _btnStart;
|
||
[SerializeField] private Button _btnExit;
|
||
|
||
[Header("=== 模式选择页控件 ===")]
|
||
[SerializeField] private Button _btnBack;
|
||
[SerializeField] private Button _btnPracticeMode;
|
||
[SerializeField] private Button _btnExamMode;
|
||
[SerializeField] private Text _modeDescText;
|
||
|
||
[Header("=== 固定方式选择页控件 ===")]
|
||
[SerializeField] private Button _btnFixationBack;
|
||
[SerializeField] private Button _btnLimbFixation;
|
||
[SerializeField] private Button _btnSplintFixation;
|
||
|
||
[Header("=== 模式说明文案 ===")]
|
||
[SerializeField] [TextArea(2, 4)] private string _practiceModeDesc =
|
||
"模拟练习模式:不限时长,可反复练习。系统不评分,帮助您熟悉实验流程和操作步骤。";
|
||
[SerializeField] [TextArea(2, 4)] private string _examModeDesc =
|
||
"考核评估模式:限定时间,完成后系统自动评分,并提供详细反馈报告。";
|
||
|
||
[Header("=== 编辑器预览(仅 Editor 模式有效)===")]
|
||
[SerializeField] private EditorPreviewPage _editorPreview = EditorPreviewPage.None;
|
||
|
||
public enum Page { Home, ModeSelect, Fixation, Experiment }
|
||
public enum EditorPreviewPage { None, Home, ModeSelect, Fixation, Experiment }
|
||
|
||
private Page _currentPage = Page.Home;
|
||
private ExperimentMode _selectedMode = ExperimentMode.Learn;
|
||
private int _lastReturnHomeFrame = -1;
|
||
|
||
private void Start()
|
||
{
|
||
Debug.Log("=== PageController 初始化开始 ===");
|
||
|
||
// 一开始就隐藏鞋子,以免在主页或开场动画时穿帮
|
||
HideShose();
|
||
|
||
// 关掉多余AudioListener(只留Main Camera的)
|
||
var cam2 = GameObject.Find("camera2"); if (cam2 != null) { var al = cam2.GetComponent<AudioListener>(); if (al != null) al.enabled = false; }
|
||
var cam3 = GameObject.Find("camera3"); if (cam3 != null) { var al = cam3.GetComponent<AudioListener>(); if (al != null) al.enabled = false; }
|
||
|
||
// 绑定首页按钮
|
||
if (_btnStart != null) { _btnStart.onClick.AddListener(OnStartClicked); Debug.Log("PageController: _btnStart 绑定成功"); }
|
||
else Debug.LogError("PageController: _btnStart 未赋值!");
|
||
|
||
if (_btnExit != null) { _btnExit.onClick.AddListener(OnExitClicked); Debug.Log("PageController: _btnExit 绑定成功"); }
|
||
else Debug.LogError("PageController: _btnExit 未赋值!");
|
||
|
||
if (_btnBack != null) { _btnBack.onClick.AddListener(OnModeBackClicked); Debug.Log("PageController: _btnBack 绑定成功"); }
|
||
else Debug.LogError("PageController: _btnBack 未赋值!");
|
||
|
||
if (_btnPracticeMode != null) { _btnPracticeMode.onClick.AddListener(() => OnModeSelected(ExperimentMode.Learn)); Debug.Log("PageController: _btnPracticeMode 绑定成功"); }
|
||
else Debug.LogError("PageController: _btnPracticeMode 未赋值!");
|
||
|
||
if (_btnExamMode != null) { _btnExamMode.onClick.AddListener(() => OnModeSelected(ExperimentMode.Exam)); Debug.Log("PageController: _btnExamMode 绑定成功"); }
|
||
else Debug.LogError("PageController: _btnExamMode 未赋值!");
|
||
|
||
if (_btnFixationBack == null && _fixationPanel != null) { var fb = _fixationPanel.transform.Find("BtnBack"); if (fb != null) { _btnFixationBack = fb.GetComponent<Button>(); Debug.Log("PageController: 自动绑定 FixationPanel/BtnBack"); } }
|
||
if (_btnFixationBack != null) { _btnFixationBack.onClick.AddListener(OnFixationBackClicked); Debug.Log("PageController: _btnFixationBack 绑定成功"); }
|
||
else Debug.LogError("PageController: _btnFixationBack 未找到!");
|
||
|
||
if (_btnLimbFixation != null) { _btnLimbFixation.onClick.AddListener(() => OnFixationSelected(FixationMethod.LimbFixation)); Debug.Log("PageController: _btnLimbFixation 绑定成功"); }
|
||
else Debug.LogError("PageController: _btnLimbFixation 未赋值!");
|
||
|
||
if (_btnSplintFixation != null) { _btnSplintFixation.onClick.AddListener(() => OnFixationSelected(FixationMethod.SplintFixation)); Debug.Log("PageController: _btnSplintFixation 绑定成功"); }
|
||
else Debug.LogError("PageController: _btnSplintFixation 未赋值!");
|
||
|
||
if (_btnExperimentBack == null && _experimentPanel != null) { var eb = _experimentPanel.transform.Find("Navbar/BtnBack"); if (eb != null) { _btnExperimentBack = eb.GetComponent<Button>(); Debug.Log("PageController: 自动绑定 ExperimentPanel/Navbar/BtnBack"); } }
|
||
if (_btnExperimentBack != null) { _btnExperimentBack.onClick.AddListener(OnExperimentBackClicked); Debug.Log("PageController: _btnExperimentBack 绑定成功"); }
|
||
else Debug.LogError("PageController: _btnExperimentBack 未找到!");
|
||
|
||
ShowPage(Page.Home);
|
||
Debug.Log("=== PageController 初始化完成 ===");
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
#if UNITY_EDITOR
|
||
if (!Application.isPlaying)
|
||
{
|
||
if (_editorPreview != EditorPreviewPage.None)
|
||
{
|
||
Page targetPage = (Page)((int)_editorPreview - 1);
|
||
ShowPage(targetPage);
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
private void ShowPage(Page page)
|
||
{
|
||
_currentPage = page;
|
||
if (_homePagePanel != null) _homePagePanel.SetActive(page == Page.Home);
|
||
if (_modeSelectPanel != null) _modeSelectPanel.SetActive(page == Page.ModeSelect);
|
||
if (_fixationPanel != null) _fixationPanel.SetActive(page == Page.Fixation);
|
||
if (_experimentPanel != null) _experimentPanel.SetActive(page == Page.Experiment);
|
||
|
||
if (page == Page.ModeSelect && _modeDescText != null)
|
||
_modeDescText.text = "";
|
||
|
||
var audioManager = FindObjectOfType<AudioManager>();
|
||
if (audioManager != null)
|
||
{
|
||
if (page == Page.Experiment) audioManager.PlayExperimentBg();
|
||
else audioManager.PlayHomeBg();
|
||
}
|
||
|
||
Debug.Log($"PageController: 页面切换 -> [{page}]");
|
||
}
|
||
|
||
#region 按钮回调
|
||
|
||
private void OnStartClicked()
|
||
{
|
||
ShowPage(Page.ModeSelect);
|
||
}
|
||
|
||
private void OnExitClicked()
|
||
{
|
||
#if UNITY_EDITOR
|
||
UnityEditor.EditorApplication.isPlaying = false;
|
||
#else
|
||
Application.Quit();
|
||
#endif
|
||
}
|
||
|
||
private void OnModeBackClicked()
|
||
{
|
||
ShowPage(Page.Home);
|
||
}
|
||
|
||
private void OnModeSelected(ExperimentMode mode)
|
||
{
|
||
_selectedMode = mode;
|
||
if (_modeDescText != null)
|
||
_modeDescText.text = (mode == ExperimentMode.Learn) ? _practiceModeDesc : _examModeDesc;
|
||
|
||
GameManager.Instance.CurrentMode = mode;
|
||
GameManager.Instance.CurrentExperimentType = ExperimentType.FractureFixation;
|
||
|
||
ShowPage(Page.Fixation);
|
||
}
|
||
|
||
private void OnFixationBackClicked()
|
||
{
|
||
ShowPage(Page.ModeSelect);
|
||
}
|
||
|
||
private void OnFixationSelected(FixationMethod method)
|
||
{
|
||
GameManager.Instance.CurrentFixationMethod = method;
|
||
|
||
var openingFlow = FindObjectOfType<OpeningFlowController>();
|
||
if (openingFlow != null)
|
||
{
|
||
ShowPage(Page.Experiment);
|
||
openingFlow.PlayOpeningFlow(() =>
|
||
{
|
||
if (_uiManager != null)
|
||
{
|
||
_uiManager.gameObject.SetActive(true);
|
||
}
|
||
|
||
var stepManager = FindObjectOfType<StepManager>();
|
||
if (stepManager != null)
|
||
{
|
||
stepManager.InitializeFromGameManager();
|
||
}
|
||
|
||
StartCoroutine(StartInitialVoiceAndCameraRoutine());
|
||
});
|
||
}
|
||
else
|
||
{
|
||
ShowPage(Page.Experiment);
|
||
if (_uiManager != null) _uiManager.gameObject.SetActive(true);
|
||
|
||
var stepManager = FindObjectOfType<StepManager>();
|
||
if (stepManager != null) stepManager.InitializeFromGameManager();
|
||
StartCoroutine(StartInitialVoiceAndCameraRoutine());
|
||
}
|
||
}
|
||
|
||
private void OnExperimentBackClicked()
|
||
{
|
||
ReturnToHome();
|
||
}
|
||
|
||
public void ReturnToHome()
|
||
{
|
||
if (_lastReturnHomeFrame == Time.frameCount)
|
||
{
|
||
Debug.Log("PageController: 返回首页已在本帧执行,跳过重复调用");
|
||
return;
|
||
}
|
||
|
||
_lastReturnHomeFrame = Time.frameCount;
|
||
Debug.Log("PageController: 返回首页,开始完整复位流程");
|
||
|
||
StopAllCoroutines();
|
||
ActionHistory.Clear();
|
||
|
||
if (_uiManager != null)
|
||
{
|
||
_uiManager.HideVideo();
|
||
_uiManager.HideEndPanel();
|
||
}
|
||
|
||
HideCanvasPanel("VideoPanel");
|
||
HideCanvasPanel("EndPanel");
|
||
HideCanvasPanel("DialogueBubble");
|
||
HideCanvasPanel("GradeResult");
|
||
HideCanvasPanel("TipPanel");
|
||
|
||
// --- 核心修复:退出时彻底清理并隐藏所有交互物体 ---
|
||
foreach (var handler in GetSceneObjectsOfType<PingClickHandler>())
|
||
{
|
||
handler.ResetState(false);
|
||
handler.ForceHideOutline();
|
||
handler.gameObject.SetActive(false);
|
||
Debug.Log($"PageController: 已隐藏 Ping {handler.name}");
|
||
}
|
||
|
||
foreach (var handler in GetSceneObjectsOfType<ChanraoTuibuHandler>())
|
||
{
|
||
handler.ResetState(false);
|
||
handler.ForceHideOutline();
|
||
handler.gameObject.SetActive(false);
|
||
Debug.Log($"PageController: 已隐藏 ChanraoTuibu {handler.name}");
|
||
}
|
||
|
||
HideSceneObjectsByNamePrefix("chanrao");
|
||
|
||
// 找到 Shose 重置并彻底隐藏
|
||
var shose = FindSceneObject("Shose");
|
||
if (shose != null)
|
||
{
|
||
var h = shose.GetComponent<ShoseClickHandler>();
|
||
if (h != null)
|
||
{
|
||
h.ResetState(false);
|
||
h.ForceHideOutline();
|
||
}
|
||
|
||
// 关键:返回主页时,必须禁用点击组件,并隐藏物体
|
||
if (h != null) h.enabled = false;
|
||
shose.SetActive(false);
|
||
Debug.Log("PageController: 已隐藏 Shose");
|
||
}
|
||
|
||
// 把 touchArray 里的点也关掉
|
||
var touchArray = GameObject.Find("touchArray");
|
||
if (touchArray != null)
|
||
{
|
||
foreach (Transform t in touchArray.transform)
|
||
{
|
||
var point2Handler = t.GetComponent<Point2ClickHandler>();
|
||
if (point2Handler != null) point2Handler.ResetState(false);
|
||
t.gameObject.SetActive(false);
|
||
}
|
||
}
|
||
|
||
var woman = GameObject.Find("woman");
|
||
if (woman != null)
|
||
{
|
||
var anim = woman.GetComponent<Animator>();
|
||
if (anim != null)
|
||
{
|
||
anim.SetBool("IsCheck", false);
|
||
anim.SetBool("isCrouch", false);
|
||
}
|
||
}
|
||
|
||
var manInjury = GameObject.Find("manInjury");
|
||
if (manInjury != null)
|
||
{
|
||
var anim = manInjury.GetComponent<Animator>();
|
||
if (anim != null) anim.SetBool("CheckFoot", false);
|
||
}
|
||
|
||
var audioManager = FindObjectOfType<AudioManager>();
|
||
if (audioManager != null)
|
||
{
|
||
audioManager.StopVoice();
|
||
audioManager.StopSfx();
|
||
audioManager.ResetCamerasToHome();
|
||
}
|
||
// ------------------------------------------------
|
||
|
||
ShowPage(Page.Home);
|
||
Debug.Log("PageController: 返回首页复位完成");
|
||
}
|
||
|
||
private void HideCanvasPanel(string panelName)
|
||
{
|
||
var panel = FindSceneObject(panelName);
|
||
if (panel != null) panel.SetActive(false);
|
||
}
|
||
|
||
private GameObject FindSceneObject(string objectName)
|
||
{
|
||
var found = GameObject.Find(objectName);
|
||
if (found != null) return found;
|
||
|
||
foreach (var t in Resources.FindObjectsOfTypeAll<Transform>())
|
||
{
|
||
if (t == null || !t.gameObject.scene.IsValid()) continue;
|
||
if (t.name == objectName) return t.gameObject;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
private T[] GetSceneObjectsOfType<T>() where T : Component
|
||
{
|
||
var all = Resources.FindObjectsOfTypeAll<T>();
|
||
var list = new System.Collections.Generic.List<T>();
|
||
foreach (var item in all)
|
||
{
|
||
if (item == null || !item.gameObject.scene.IsValid()) continue;
|
||
list.Add(item);
|
||
}
|
||
return list.ToArray();
|
||
}
|
||
|
||
private void HideSceneObjectsByNamePrefix(string prefix)
|
||
{
|
||
foreach (var t in Resources.FindObjectsOfTypeAll<Transform>())
|
||
{
|
||
if (t == null || !t.gameObject.scene.IsValid()) continue;
|
||
if (!t.name.StartsWith(prefix, System.StringComparison.OrdinalIgnoreCase)) continue;
|
||
t.gameObject.SetActive(false);
|
||
Debug.Log($"PageController: 已隐藏残留对象 {t.name}");
|
||
}
|
||
}
|
||
|
||
private System.Collections.IEnumerator StartInitialVoiceAndCameraRoutine()
|
||
{
|
||
float waitTime = 1f; // 默认等1秒
|
||
var am = FindObjectOfType<AudioManager>();
|
||
|
||
// 隐藏视频面板
|
||
var allT = Resources.FindObjectsOfTypeAll<Transform>();
|
||
foreach (var t in allT)
|
||
{
|
||
if (t.name == "VideoPanel" && t.parent != null && t.parent.name == "Canvas")
|
||
{
|
||
t.gameObject.SetActive(false);
|
||
}
|
||
}
|
||
|
||
// 找鞋子
|
||
var shose = FindSceneObject("Shose");
|
||
|
||
var point2 = GameObject.Find("touchArray/point2");
|
||
if (point2 == null)
|
||
{
|
||
var touchArray = GameObject.Find("touchArray");
|
||
if (touchArray != null)
|
||
{
|
||
var p2 = touchArray.transform.Find("point2");
|
||
if (p2 != null) point2 = p2.gameObject;
|
||
}
|
||
}
|
||
|
||
if (shose != null)
|
||
{
|
||
var h = shose.GetComponent<ShoseClickHandler>();
|
||
if (h == null) h = shose.AddComponent<ShoseClickHandler>();
|
||
h.targetPoint = GameObject.Find("ShosePoint")?.transform;
|
||
|
||
var ping004 = FindFirstPingStepObject();
|
||
h.nextObject = ping004;
|
||
|
||
// 鞋子出现,但默认不开组件(不可点击)
|
||
h.enabled = false;
|
||
shose.SetActive(true);
|
||
}
|
||
|
||
if (point2 != null)
|
||
{
|
||
var oldHandler = point2.GetComponent<TouchPositionHandler>();
|
||
if (oldHandler != null) Destroy(oldHandler);
|
||
|
||
var h2 = point2.GetComponent<Point2ClickHandler>();
|
||
if (h2 == null) h2 = point2.AddComponent<Point2ClickHandler>();
|
||
if (h2.nextObject == null) h2.nextObject = shose;
|
||
|
||
point2.SetActive(false);
|
||
}
|
||
|
||
// 1. 强制播放第一句语音
|
||
if (am != null)
|
||
{
|
||
#if UNITY_EDITOR
|
||
var autoClip = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>("Assets/Audio/people/周围环境安全,我是救护志愿者,我可以帮助您吗.mp3");
|
||
if (autoClip != null)
|
||
{
|
||
am.PlayVoice(autoClip);
|
||
waitTime = autoClip.length + 1f;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
Debug.Log($"PageController: 开始等待 {waitTime} 秒以切换摄像机并激活鞋子");
|
||
|
||
var tipPanel = GameObject.Find("TipPanel");
|
||
if (tipPanel == null)
|
||
{
|
||
foreach(var t in allT) { if (t.name == "TipPanel") { tipPanel = t.gameObject; break; } }
|
||
}
|
||
if (tipPanel != null) tipPanel.SetActive(true);
|
||
|
||
yield return new WaitForSeconds(waitTime);
|
||
|
||
if (tipPanel != null) tipPanel.SetActive(false);
|
||
if (am != null) am.SwitchToCamera3();
|
||
|
||
if (point2 != null)
|
||
{
|
||
point2.SetActive(true);
|
||
Debug.Log("PageController: 镜头切换到camera3,point2 已显示");
|
||
}
|
||
}
|
||
|
||
private void HideShose()
|
||
{
|
||
var shose = FindSceneObject("Shose");
|
||
if (shose != null)
|
||
{
|
||
shose.SetActive(false);
|
||
}
|
||
}
|
||
|
||
private GameObject FindFirstPingStepObject()
|
||
{
|
||
foreach (var ping in GetSceneObjectsOfType<PingClickHandler>())
|
||
{
|
||
if (ping != null && ping.name == "ping.004") return ping.gameObject;
|
||
}
|
||
|
||
foreach (var ping in GetSceneObjectsOfType<PingClickHandler>())
|
||
{
|
||
if (ping != null && ping.pingIndex == 0) return ping.gameObject;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
#endregion
|
||
|
||
}
|