2025-01-02 14:13:47 +08:00

696 lines
27 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<Transform> _curModuleToolArray = new List<Transform>();//当前步骤需要用到的所有工具
//动画交互
public NiuData _CurSceneStep;//为了方便做对比,临时保存当前步骤
private Dictionary<bool, List<GameObject>> _curStepUseBTDic;//当前步骤要点击的所有物体true表示正确选项false表示错误选项
private List<OutLineRender> _currentHighlights = new List<OutLineRender>();
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<PlayableDirector>();
_curTimeLineCtrl = GetComponent<TimelineDirectorCtrl>();
GameManager.Instance._EventManager.AddListener<ClickToolArgs>(OnClickToolEvent);
}
private void Start()
{
GetCurModuleTools();
UseToolsActive(true);
InitPlayAnmState(null,null);
StartCoroutine("InitScene");
}
private IEnumerator InitScene()
{
yield return new WaitForSeconds(0.1f);
List<NiuData> 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<VideoShowPanel>().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<ClickToolArgs>(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);
}
}
/// <summary>
/// 播放动画前场景物体状态
/// </summary>
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);
}
}
/// <summary>
/// 根据不同任务名称切换动画控制器
/// </summary>
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();
}
/// <summary>
/// 获取当前模块需要用到的工具
/// </summary>
/// <returns></returns>
private void GetCurModuleTools()
{
List<string> toolArray = new List<string>();
List<NiuData> 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);
}
}
}
}
/// <summary>
/// 该模块用到的所有工具显示状态
/// </summary>
/// <param name="showAble"></param>
public void UseToolsActive(bool showAble)
{
for (int i = 0; i < _curModuleToolArray.Count; i++)
{
_curModuleToolArray[i].gameObject.SetActive(showAble);
}
}
/// <summary>
/// 获取此步骤需要点击的工具
/// </summary>
/// <param name="step"></param>
public List<GameObject> GetNeedClickTools(NiuData step)
{
_curStepUseBTDic = new Dictionary<bool, List<GameObject>>();
List<GameObject> toolTemp = new List<GameObject>();
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<GameObject> tempList = new List<GameObject>();
tempList.Add(tempGeo);
_curStepUseBTDic.Add(j == 0, tempList);
}
}
}
return toolTemp;
}
/// <summary>
/// 让此步骤需要点击的物体高亮显示
/// </summary>
/// <param name="model">需要点击物体名字</param>
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>();
}
// 设置泛光强度和默认禁用泛光效果
outlineRender.OutLineStrength = 1;
outlineRender.enabled = true;
// 将泛光效果组件添加到高亮列表中
_currentHighlights.Add(outlineRender);
}
}
}
/// <summary>
/// 训练模式下点击物体触发下一步
/// </summary>
/// <param name="triGeo"></param>
/// <param name="clickFinishCall"></param>
private void ClickToolCallInTrainState(GameObject triGeo,Action clickFinishCall)
{
if (GameManager.Instance._StateContext.GetState().Name.Equals("TrainState"))
{
List<GameObject> useBts = _curStepUseBTDic[true];
if (useBts.Contains(triGeo))
{
if (triGeo.GetComponent<OutLineRender>())
{
triGeo.GetComponent<OutLineRender>().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();
}
}
}
/// <summary>
/// 考核模式下点击物体触发下一步
/// </summary>
/// <param name="triGeo"></param>
/// <param name="clickFinishCall"></param>
private void ClickToolCallInExamState(GameObject triGeo, Action clickFinishCall)
{
if (GameManager.Instance._StateContext.GetState().Name.Equals("ExamState"))
{
bool addScoreTemp = true;
List<GameObject> useBts = _curStepUseBTDic[true];
if (useBts.Contains(triGeo))
{
if (triGeo.GetComponent<OutLineRender>())
{
triGeo.GetComponent<OutLineRender>().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();
}
}
}
/// <summary>
/// 步骤是答题系统类型的处理方式
/// </summary>
/// <param name="step"></param>
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);
});
}
/// <summary>
/// 步骤是过渡类型的处理方式
/// </summary>
/// <param name="step"></param>
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;
});
}
/// <summary>
/// 步骤是过渡动画类型的处理方式
/// </summary>
/// <param name="step"></param>
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);
}
/// <summary>
/// 图片选择类题型
/// 目前只有胚胎选择最后一步需要
/// </summary>
/// <param name="temp"></param>
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<Toggle>().isOn = false;
tempGeo.GetComponent<Toggle>().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<GameObject> togs = new List<GameObject>();
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<Toggle>().isOn = false;
tempGeo.GetComponent<Toggle>().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);
}
});
}
}
}
/// <summary>
/// 跳转动画步骤
/// </summary>
/// <param name="partData"></param>
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);
}
}
}
}
/// <summary>
/// 正向跳转步骤
/// </summary>
/// <param name="partData"></param>
private void PositiveJumpStep(NiuData partData)
{
_IsPlayAnm = false;
_CurSceneStep = partData;
GameManager.Instance._DataNiuHandler.CurNiuHandler.Value = partData;
}
/// <summary>
/// 反向跳转步骤
/// </summary>
/// <param name="partData"></param>
private void NegativeJumpStep(NiuData partData)
{
_IsPlayAnm = false;
_CurSceneStep = partData;
GameManager.Instance._DataNiuHandler.CurNiuHandler.Value = partData;
}
/// <summary>
/// 获取当前要播放的动画片段的开始时间
/// </summary>
/// <param name="step"></param>
/// <returns></returns>
private float GetPlayTime(NiuData step, bool jumpStepAble)
{
int allFrame = 0;
List<NiuData> 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;
}
}
}
}