using CG.UTility; using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; using UnityEngine.Playables; using CG.Framework; using System; using UnityEngine.UI; /******************************************************************************* *Create By CG *Function *******************************************************************************/ namespace ZXK.LouDiXvMuNiu { public class NiuSceneMng : MonoBehaviour { public static NiuSceneMng _Instance = null; //物品展示 [SerializeField] private Transform _toolContain = null; private List _curModuleToolArray = new List();//当前步骤需要用到的所有工具 //动画交互 public NiuData _CurSceneStep;//为了方便做对比,临时保存当前步骤 private Dictionary> _curStepUseBTDic;//当前步骤要点击的所有物体,true表示正确选项,false表示错误选项 private List _currentHighlights = new List(); private PlayableDirector _curTimeLine = null; private TimelineDirectorCtrl _curTimeLineCtrl = null; [SerializeField] private PlayableAsset _peoplePlanTimeLineClip = null; [SerializeField] private PlayableAsset _CSPLCLTimeLineClip = null; [SerializeField] private PlayableAsset _TQFQCLTimeLineClip = null; [SerializeField] private PlayableAsset _JZLVJCTimeLineClip = null; [SerializeField] private PlayableAsset _RGSJTimeLineClip = null; [SerializeField] private PlayableAsset _CPTimeLineClip = null; [SerializeField] private PlayableAsset _PTXZTimeLineClip = null; [SerializeField] private PlayableAsset _PTYZTimeLineClip = null; [SerializeField] private PlayableAsset _YYZDTimeLineClip = null; [SerializeField] private Transform _TQFQTran = null; [SerializeField] private Transform _CSPLTran = null; [SerializeField] private Transform _RGSJTran = null; [ReadOnly]//是否正在播放动画 public bool _IsPlayAnm = false; private void Awake() { if (_Instance == null) { _Instance = this; } _curTimeLine = GetComponent(); _curTimeLineCtrl = GetComponent(); GameManager.Instance._EventManager.AddListener(OnClickToolEvent); } private void Start() { GetCurModuleTools(); UseToolsActive(true); InitPlayAnmState(null,null); StartCoroutine("InitScene"); } private IEnumerator InitScene() { yield return new WaitForSeconds(0.1f); List tempData = GameManager.Instance._DataNiuHandler.NiuStepTypeDic[GameManager.Instance._CurModelType]; if (GameManager.Instance._StateContext.GetState().Name.Equals("ExamState")) { for (int i = 0; i < tempData.Count; i++) { if (tempData[i].TaskType == ConstCtrl.TASKTYPE_ShowGeo) { _CurSceneStep = tempData[i]; break; } } } else { _CurSceneStep = tempData[0]; } GameManager.Instance._DataNiuHandler.CurNiuHandler.Value = _CurSceneStep; } private void Update() { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit rayHit; if (PopUpMng._TriAble&& _CurSceneStep != null) { if (_CurSceneStep.TaskType.Equals(ConstCtrl.TASKTYPE_ShowGeo)) {//工具物品展示 UI_Manage.Instance.HidePanel("TooltipBoxTip"); if (Physics.Raycast(ray, out rayHit, Mathf.Infinity)) { if (_curModuleToolArray.Contains(rayHit.transform)) { Vector3 worldPos = rayHit.point; PopUpMng.ShowToolInfoTip(rayHit.transform.name, worldPos + Vector3.up * 0.05f, -1); } } } else if (_CurSceneStep.TaskType.Equals(ConstCtrl.TASKTYPE_Anim)) {//timeline动画 if (Input.GetMouseButtonUp(0) && Physics.Raycast(ray, out rayHit, Mathf.Infinity)) { ClickToolCallInTrainState(rayHit.transform.gameObject, () => { JumpTimeline(GameManager.Instance._DataNiuHandler.GetNextStep(), false); }); ClickToolCallInExamState(rayHit.transform.gameObject, () => { JumpTimeline(GameManager.Instance._DataNiuHandler.GetNextStep(_CurSceneStep.QNextNum), false); }); } } else if (_CurSceneStep.TaskType.Equals(ConstCtrl.TASKTYPE_Video)) { if (Input.GetMouseButtonUp(0) && Physics.Raycast(ray, out rayHit, Mathf.Infinity)) { ClickToolCallInTrainState(rayHit.transform.gameObject, () => { GameObject videoGeo = UI_Manage.Instance.ShowPanel("VideoShowPanel", Type.GetType("ZXK.LouDiXvMuNiu.VideoShowPanel"), UIGroup.Tip); videoGeo.GetComponent().PlayVideoClip(_CurSceneStep.VideoPath, () => { GameManager.Instance._DataNiuHandler.CurNiuHandler.Value = GameManager.Instance._DataNiuHandler.GetNextStep(); }); }); if (GameManager.Instance._StateContext.GetState().Name.Equals("ExamState")) { } } } } } private void OnDestroy() { _curTimeLineCtrl?.Stop(); GameManager.Instance._EventManager.RemoveListener(OnClickToolEvent); } private void OnClickToolEvent(ClickToolArgs e) { if (GameManager.Instance._StateContext.GetState().Name.Equals("ExamState")) { GameObject toolGeo = UtilitiesMng.GetGeoByName(new Transform[1] { _toolContain }, e.SelectTool, true); toolGeo.SetActive(true); } } /// /// 播放动画前场景物体状态 /// public void InitPlayAnmState(NiuData curObj, NiuData previousObj) { foreach (Transform t in _TQFQTran) { t.gameObject.SetActive(false); } foreach (Transform t in _CSPLTran) { t.gameObject.SetActive(false); } foreach (Transform t in _RGSJTran) { t.gameObject.SetActive(false); } if (GameManager.Instance._CurModelType.Equals(ConstCtrl.ModuleName_TQFAQCL)) { _TQFQTran.Find("SM_Niu_CaShi_an01").gameObject.SetActive(true); SetTimeLineCtrl(curObj, previousObj, _TQFQCLTimeLineClip); } else if (GameManager.Instance._CurModelType.Equals(ConstCtrl.ModuleName_CSPLCL)) { _CSPLTran.Find("SM_Niu_ZhusheB_Bozi_an02renG").gameObject.SetActive(true); SetTimeLineCtrl(curObj, previousObj, _CSPLCLTimeLineClip); } else if (GameManager.Instance._CurModelType.Equals(ConstCtrl.ModuleName_JZLVJC)) { SetTimeLineCtrl(curObj, previousObj, _JZLVJCTimeLineClip); } else if (GameManager.Instance._CurModelType.Equals(ConstCtrl.ModuleName_RGSJ)) { _RGSJTran.Find("SM_Niu_RenGongSouJing01").gameObject.SetActive(true); GameObject ytgGeo = UtilitiesMng.GetGeoByName(new Transform[1] { _toolContain }, "液氮罐", true); GameObject gjj2Geo = UtilitiesMng.GetGeoByName(new Transform[1] { _toolContain }, "工具架2", true); ytgGeo.gameObject.SetActive(true); gjj2Geo.gameObject.SetActive(true); SetTimeLineCtrl(curObj, previousObj, _RGSJTimeLineClip); } else if (GameManager.Instance._CurModelType.Equals(ConstCtrl.ModuleName_CP)) { SetTimeLineCtrl(curObj, previousObj, _CPTimeLineClip); } else if (GameManager.Instance._CurModelType.Equals(ConstCtrl.ModuleName_PTXZ)) { SetTimeLineCtrl(curObj, previousObj, _PTXZTimeLineClip); } else if (GameManager.Instance._CurModelType.Equals(ConstCtrl.ModuleName_PTYZ)) { _RGSJTran.Find("SM_Niu_RenGongSouJing01").gameObject.SetActive(true); SetTimeLineCtrl(curObj, previousObj, _PTYZTimeLineClip); } else if (GameManager.Instance._CurModelType.Equals(ConstCtrl.ModuleName_YYZD)) { SetTimeLineCtrl(curObj, previousObj, _YYZDTimeLineClip); } } /// /// 根据不同任务名称切换动画控制器 /// private void SetTimeLineCtrl(NiuData curObj, NiuData previousObj, PlayableAsset timeAsset) { if (curObj!=null&& previousObj!=null&&!curObj.TaskName.Equals(previousObj.TaskName)) { if (curObj.TaskName.Equals(ConstCtrl.TaskName_ActualOperation)) { _curTimeLine.playableAsset = timeAsset; _curTimeLineCtrl.SetDuration(); } else if (curObj.TaskName.Equals(ConstCtrl.TaskName_OperationPlan)) { if (_curTimeLine.playableAsset != _peoplePlanTimeLineClip) { _curTimeLine.playableAsset = _peoplePlanTimeLineClip; _curTimeLineCtrl.SetDuration(); } } } _curTimeLineCtrl.Stop(); } /// /// 获取当前模块需要用到的工具 /// /// private void GetCurModuleTools() { List toolArray = new List(); List tempData = GameManager.Instance._DataNiuHandler.NiuStepTypeDic[GameManager.Instance._CurModelType]; for (int i = 0; i < tempData.Count; i++) { if (string.IsNullOrEmpty(tempData[i].ToolsName)) continue; string[] tools = tempData[i].ToolsName.Split("|"); for (int j = 0; j < tools.Length; j++) { GameObject toolGeo = UtilitiesMng.GetGeoByName(new Transform[1] { _toolContain }, tools[j], true); if (toolGeo&&!toolArray.Contains(tools[j])) { toolArray.Add(tools[j]); _curModuleToolArray.Add(toolGeo.transform); } } } } /// /// 该模块用到的所有工具显示状态 /// /// public void UseToolsActive(bool showAble) { for (int i = 0; i < _curModuleToolArray.Count; i++) { _curModuleToolArray[i].gameObject.SetActive(showAble); } } /// /// 获取此步骤需要点击的工具 /// /// public List GetNeedClickTools(NiuData step) { _curStepUseBTDic = new Dictionary>(); List toolTemp = new List(); string[] tempBtArray = step.ModelBT.Split("+"); if (GameManager.Instance._StateContext.GetState().Name.Equals("ExamState") &&!string.IsNullOrEmpty(step.ExamModelBT)) { tempBtArray = step.ExamModelBT.Split("+"); } for (int i = 0; i < tempBtArray.Length; i++) { string[] tempBts = tempBtArray[i].Split("|"); int count = 0; if (GameManager.Instance._StateContext.GetState().Name.Equals("ExamState")) { count = tempBts.Length; } else { count = 1; } for (int j = 0; j < count; j++) { GameObject tempGeo = UtilitiesMng.GetGeoByName(new Transform[1] { transform }, tempBts[j], true); if (tempGeo == null) continue; tempGeo.SetActive(true); toolTemp.Add(tempGeo); if (_curStepUseBTDic.ContainsKey(j == 0)) { _curStepUseBTDic[j == 0].Add(tempGeo); } else { List tempList = new List(); tempList.Add(tempGeo); _curStepUseBTDic.Add(j == 0, tempList); } } } return toolTemp; } /// /// 让此步骤需要点击的物体高亮显示 /// /// 需要点击物体名字 public void OnlyShowBTGeo(GameObject[] modelBTsName) { for (int i = 0; i < _currentHighlights.Count; i++) { _currentHighlights[i].enabled = false; } for (int i = 0; i < modelBTsName.Length; i++) { string modelBTName = modelBTsName[i].name; if (!modelBTName.Contains("_sign")) { OutLineRender outlineRender; // 如果模型上没有泛光效果组件,则添加一个新的 if (!modelBTsName[i].TryGetComponent(out outlineRender)) { outlineRender = modelBTsName[i].AddComponent(); } // 设置泛光强度和默认禁用泛光效果 outlineRender.OutLineStrength = 1; outlineRender.enabled = true; // 将泛光效果组件添加到高亮列表中 _currentHighlights.Add(outlineRender); } } } /// /// 训练模式下点击物体触发下一步 /// /// /// private void ClickToolCallInTrainState(GameObject triGeo,Action clickFinishCall) { if (GameManager.Instance._StateContext.GetState().Name.Equals("TrainState")) { List useBts = _curStepUseBTDic[true]; if (useBts.Contains(triGeo)) { if (triGeo.GetComponent()) { triGeo.GetComponent().enabled = false; } else { triGeo.SetActive(false); } useBts.Remove(triGeo); } if (useBts.Count == 0) { foreach (var item in _curStepUseBTDic) { for (int i = 0; i < item.Value.Count; i++) { item.Value[i].SetActive(false); } } _curStepUseBTDic.Clear(); clickFinishCall?.Invoke(); } } } /// /// 考核模式下点击物体触发下一步 /// /// /// private void ClickToolCallInExamState(GameObject triGeo, Action clickFinishCall) { if (GameManager.Instance._StateContext.GetState().Name.Equals("ExamState")) { bool addScoreTemp = true; List useBts = _curStepUseBTDic[true]; if (useBts.Contains(triGeo)) { if (triGeo.GetComponent()) { triGeo.GetComponent().enabled = false; } else { triGeo.SetActive(false); } useBts.Remove(triGeo); } else { PopUpMng.PopChoseErrowToast(_CurSceneStep.ExamEvvr, 2.0f); addScoreTemp = false; } if (useBts.Count == 0) { foreach (var item in _curStepUseBTDic) { for (int i = 0; i < item.Value.Count; i++) { item.Value[i].SetActive(false); } } _curStepUseBTDic.Clear(); if (addScoreTemp) { GameManager.Instance._DataNiuHandler.AddScore(_CurSceneStep.ModuleName, _CurSceneStep.ThreeTaskName, _CurSceneStep.Score); } clickFinishCall?.Invoke(); } } } /// /// 步骤是答题系统类型的处理方式 /// /// public void AnswerSystemInStep(NiuData step) { string[] answers = step.OptionsAll.Split("|"); PopUpMng.PopAnswerQuestions(step.Question, answers, GetOptionIndex(step.OptionRight), () => { JumpTimeline(GameManager.Instance._DataNiuHandler.GetNextStep(_CurSceneStep.QNextNum), false); }); } /// /// 步骤是过渡类型的处理方式 /// /// public void TimeTranInStep(NiuData step) { _IsPlayAnm = true; string[] msg = step.ModelBT.Split("|"); string timeFixMsg = msg[0]; string[] timepoints = msg[1].Split("-"); int startTime = int.Parse(timepoints[0]); int endTime = int.Parse(timepoints[1]); PopUpMng.PopTimeIntCount(timeFixMsg, startTime, endTime, 3.0f, endTime >= startTime, () => { if (GameManager.Instance._StateContext.GetState().Name.Equals("TrainState")) { GameManager.Instance._DataNiuHandler.CurNiuHandler.Value = GameManager.Instance._DataNiuHandler.GetNextStep(); } else if (GameManager.Instance._StateContext.GetState().Name.Equals("ExamState")) { GameManager.Instance._DataNiuHandler.CurNiuHandler.Value = GameManager.Instance._DataNiuHandler.GetNextStep(_CurSceneStep.QNextNum); } _IsPlayAnm = true; }); } /// /// 步骤是过渡动画类型的处理方式 /// /// public void TimeTranAnmInStep(NiuData step) { _IsPlayAnm = true; string[] msg = step.ModelBT.Split("|"); string timeFixMsg = msg[0]; string[] timepoints = msg[1].Split("-"); int startTime = int.Parse(timepoints[0]); int endTime = int.Parse(timepoints[1]); if (GameManager.Instance._StateContext.GetState().Name.Equals("TrainState")) { JumpTimeline(GameManager.Instance._DataNiuHandler.GetNextStep(), false); } else if (GameManager.Instance._StateContext.GetState().Name.Equals("ExamState")) { JumpTimeline(GameManager.Instance._DataNiuHandler.GetNextStep(_CurSceneStep.QNextNum), false); } float durTime = step.TimelineLength / 60.0f; PopUpMng.PopTimeIntCount(timeFixMsg, startTime, endTime, durTime, endTime >= startTime, null); } /// /// 图片选择类题型 /// 目前只有胚胎选择最后一步需要 /// /// public void ChoiceImgInStep(string[] temp) { if (GameManager.Instance._StateContext.GetState().Name.Equals("TrainState")) { GameObject tempGeo = UtilitiesMng.GetGeoByName(new Transform[1] { transform }, temp[0], true); tempGeo.SetActive(true); tempGeo.GetComponent().isOn = false; tempGeo.GetComponent().onValueChanged.AddListener((isOn) => { if (isOn) { tempGeo.transform.GetChild(0).gameObject.SetActive(true); float a = 0.0f; DOTween.To(() => a, x => x = a, 1.0f, 2.0f).OnComplete(() => { tempGeo.SetActive(false); }); JumpTimeline(GameManager.Instance._DataNiuHandler.GetNextStep(), false); } }); } else if (GameManager.Instance._StateContext.GetState().Name.Equals("ExamState")) { List togs = new List(); for (int i = 0; i < temp.Length; i++) { GameObject tempGeo = UtilitiesMng.GetGeoByName(new Transform[1] { transform }, temp[i], true); tempGeo.transform.GetChild(0).gameObject.SetActive(false); togs.Add(tempGeo); tempGeo.SetActive(true); tempGeo.GetComponent().isOn = false; tempGeo.GetComponent().onValueChanged.AddListener((isOn) => { if (isOn) { for (int i = 0; i < togs.Count; i++) { togs[i].transform.GetChild(0).gameObject.SetActive(true); } float a = 0.0f; DOTween.To(() => a, x => x = a, 1.0f, 2.0f).OnComplete(() => { for (int i = 0; i < togs.Count; i++) { togs[i].SetActive(false); } }); JumpTimeline(GameManager.Instance._DataNiuHandler.GetNextStep(), false); } }); } } } /// /// 跳转动画步骤 /// /// public void JumpTimeline(NiuData partData,bool jumpStepAble) { if (_CurSceneStep == null) _CurSceneStep = partData; if (_CurSceneStep.id == partData.id) {//相同步骤不跳转 } else {//跳转不同步骤,可能是点击上下步产生的,每次点击上下步对应的跳转是上下步里面的第一个小步骤 _IsPlayAnm = true; if (_CurSceneStep.id > partData.id) {//逆序跳转,倒播 if (!jumpStepAble) { _curTimeLineCtrl.ContinuePlayBackwardByPausePoint(GetPlayTime(partData, jumpStepAble), () => { NegativeJumpStep(partData); }); } else { _curTimeLineCtrl.StopInTime(GetPlayTime(partData, jumpStepAble)); NegativeJumpStep(partData); } } else if (_CurSceneStep.id < partData.id) {//顺序跳转,正播 if (!jumpStepAble) { _curTimeLineCtrl.ContinuePlayForwardByPausePoint(GetPlayTime(partData, jumpStepAble), () => { PositiveJumpStep(partData); }); } else { _curTimeLineCtrl.StopInTime(GetPlayTime(partData, jumpStepAble)); PositiveJumpStep(partData); } } } } /// /// 正向跳转步骤 /// /// private void PositiveJumpStep(NiuData partData) { _IsPlayAnm = false; _CurSceneStep = partData; GameManager.Instance._DataNiuHandler.CurNiuHandler.Value = partData; } /// /// 反向跳转步骤 /// /// private void NegativeJumpStep(NiuData partData) { _IsPlayAnm = false; _CurSceneStep = partData; GameManager.Instance._DataNiuHandler.CurNiuHandler.Value = partData; } /// /// 获取当前要播放的动画片段的开始时间 /// /// /// private float GetPlayTime(NiuData step, bool jumpStepAble) { int allFrame = 0; List modelInfos = GameManager.Instance._DataNiuHandler.NiuStepTypeDic[GameManager.Instance._CurModelType]; string addAbleTaskName = null; if (jumpStepAble) { addAbleTaskName = step.TaskName; } else { for (int a = 0; a < modelInfos.Count; a++) { if (step.id == modelInfos[a].id) { if (step.TaskName != modelInfos[a - 1].TaskName) { addAbleTaskName = modelInfos[a - 1].TaskName; } else { addAbleTaskName = step.TaskName; } } } } for (int a = 0; a < modelInfos.Count; a++) { if (modelInfos[a].TaskName.Equals(addAbleTaskName) && modelInfos[a].id < step.id) { allFrame += modelInfos[a].TimelineLength; } } return allFrame / 60.0f; } public int GetOptionIndex(string OptionMsg) { switch (OptionMsg) { case "A": return 0; case "B": return 1; case "C": return 2; case "D": return 3; default: return 0; } } } }