using System.Collections; using UnityEngine; using System.Collections.Generic; using System.IO; using UnityEngine.EventSystems; using System.Xml; using System.Xml.Serialization; using UnityEngine.Networking; using System.Text; using UnityEngine.UI; using TMPro; using System.Runtime.InteropServices; [XmlRoot("Scenario")] public class Scenario { [XmlIgnore] public string name; [XmlElement("title")] public string title; [XmlElement("changeTime")] //XmlAttribute public string changeTime; [XmlElement("needExamCompleted")] public bool needExamCompleted; //[XmlIgnore] //public string fullFileName; [XmlIgnore] public bool isModifyed; [XmlIgnore] public int curMode; [XmlIgnore] public ScenarioMode curModeSc; [XmlElement("init")] public ScenarioMode init = new ScenarioMode(); [XmlElement("demonstration")] public ScenarioMode demo = new ScenarioMode(); [XmlElement("training")] public ScenarioMode train = new ScenarioMode(); [XmlElement("examination")] public ScenarioMode exam = new ScenarioMode(); } public class ScenarioMode { [XmlElement("action")] public List acts = new List(); } public class ScAction { [XmlAttribute("objectName")] public string objName; [XmlAttribute("type")] public string type; // setState, setStateInRange, openPanel, setTextField, setIntField, switchTo3D, highlightOn, highlightOff, // highlightTime, waitForClick, waitForTime, setCurCameraPos, showText, hideText, execScenario, playAudio // setSkyBox [XmlAttribute("title")] public string title; [XmlIgnore] public int actNumberToShow=-1; [XmlElement("setState")] public actSetState setState; [XmlElement("setStateInRange")] public actSetStateInRange setStateInRange; [XmlElement("setTextField")] public actSetTextField setTextField; [XmlElement("setIntField")] public actSetIntField setIntField; [XmlElement("highlightTime")] public actHighlightTime highlightTime; [XmlElement("waitForTime")] public actWaitForTime waitForTime; [XmlElement("setCurCameraPos")] public actSetCurCameraPos setCurCameraPos; [XmlElement("showText")] public actShowText showText; [XmlElement("execScenario")] public actExecScenario execScenario; [XmlElement("playAudio")] public actPlayAudio playAudio; [XmlElement("switchMFIScreen")] public actSwitchMFIScreen switchMFIScreen; [XmlElement("setSkybox")] public actSetSkybox setSkybox; [XmlElement("showRect")] public actShowRect showRect; public ScAction clone() { ScAction res; byte[] buf = new byte[1024]; XmlSerializer serializer = new XmlSerializer(this.GetType()); Stream fs; fs = new MemoryStream(buf); //utf8.GetBytes(scText) StreamWriter writer = new StreamWriter(fs); serializer.Serialize(writer.BaseStream, this); writer.Close(); fs = new MemoryStream(buf); StreamReader reader = new StreamReader(fs); res = (ScAction)serializer.Deserialize(reader.BaseStream); reader.Close(); if (res == null) Debug.Log("Error: act clone fail"); //else // Debug.Log("act clone: " + res.objName); res.actNumberToShow = -1; return res; } } //нет необходимости в доп. данных: // public class actOpenPanel { } // public class actSwitchTo3D { } // public class actHighlightOn { } // public class actHighlightOff { } // public class actWaitForClick { } // public class actHighlightOff { } // public class actHideText { } // actHideRects public class actSetState { [XmlAttribute("val")] public int val; [XmlAttribute("name")] public string name = ""; } public class actSetStateInRange { [XmlAttribute("val")] public int val; [XmlAttribute("sec")] public int sec = 0; [XmlIgnore] public string rangeStr = ""; } public class actHighlightTime { [XmlAttribute("sec")] public int sec; } public class actWaitForTime { [XmlAttribute("sec")] public int sec; } public class actShowText { [XmlAttribute("text")] public string text; } public class actSetTextField { [XmlAttribute("text")] public string text; [XmlAttribute("color")] public string color; } public class actSetIntField { [XmlAttribute("from")] public int valFrom; [XmlAttribute("to")] public int valTo; [XmlAttribute("sec")] public int sec; [XmlAttribute("color")] public string color; } public class actSetSkybox { [XmlAttribute("name")] public string name; } public class actShowRect { [XmlAttribute("x1")] public int x1; [XmlAttribute("y1")] public int y1; //[XmlAttribute("z1")] //public float z1; [XmlAttribute("x2")] public int x2; [XmlAttribute("y2")] public int y2; //[XmlAttribute("z2")] //public float z2; } public class actExecScenario { [XmlAttribute("name")] public string name; [XmlAttribute("fast")] public bool fastFlag; } public class actPlayAudio { [XmlAttribute("filename")] public string filename; [XmlIgnore] public AudioClip clip = null; } public class actSwitchMFIScreen { [XmlAttribute("scrName")] public string scrName; } public class actSetCurCameraPos { [XmlAttribute("camera")] public string camera; // "view" (обзор), "cabin" (кабина, салон) [XmlAttribute("fov")] // Field of view public int fov; [XmlAttribute("viewMode")] public int viewMode; [XmlElement("position")] public uVector3 position; [XmlElement("rotation")] public uVector3 rotation; [XmlElement("scale")] public uVector3 scale; [XmlElement("scriptOffset")] // для скрипта Макса public uVector3 scriptOffset; } public class uVector3 { [XmlAttribute("x")] public float x; [XmlAttribute("y")] public float y; [XmlAttribute("z")] public float z; public Vector3 toVector3() { Vector3 v3 = new Vector3(); v3.x = x; v3.y = y; v3.z = z; return v3; } public Quaternion toQuaternion() { return Quaternion.Euler(x, y, z); // rotation в сценарии записаны в градусах! } } //---------------------------------------------------------------------------- public class Player : MonoBehaviour { public string state= "empty"; // empty, ready, pause, play public string mode; // demo, train, exam public string playMode; // play, waitForTime, waitForClick, cameraIsMoving Manager man=null; GameObject btnPlay, btnPause, actCounterText, progressBar, btnDemoMode, btnTrainMode, btnExamMode; public GameObject playerText; public Scenario SC = null; ScEditor sce = null; public List acts; int nextAct; bool canProgressBarChangePos; bool buildInProgress; ScenarioMode curScMode; float playDelta = 0.25f; float playTimeToWait; // playMode = waitForTime float cameraMoveCurTime, cameraMoveMaxTime; string playCamera; GameObject curCamera; string waitForClickObjName; public List highlightList = new List(); float highlightTimeDelta = 0.25f; float setStateInTimeDelta = 0.05f; List setStateInTimeList = new List(); List buttonAutoUncheckList = new List(); List rectsList = new List(); public bool isRectsShowing = false; Texture2D lineTex; float rectAlpha = 1f; bool rectAlphaDir = false; float rectW = 1000f; float rectH = 1000f; [HideInInspector] public bool isFullscreen = false; public bool isScEditorCameraMoving = false; class setStateInTimeStruct { public UnityObject obj; public float runTime, runCurTime; public int fromState, toState; } public class highlightObj { public UnityObject obj; public float sec; public Renderer[] renderers; public List materials = new List(); public List greenMaterials = new List(); public SpriteRenderer[] spriteRenderers; public Image[] images; public List spriteColors = new List(); public List imageColors = new List(); } struct TransformStruct { public Vector3 position; public Quaternion rotation; public Vector3 scale; }; TransformStruct cameraIsMovingFromPos = new TransformStruct(); int cameraFromFOV, cameraToFOV; TransformStruct cameraIsMovingToPos = new TransformStruct(); public void Init() { man = GameObject.Find("Manager").GetComponent(); btnPlay = GameObject.Find("PlayButtons/grey/green/play"); btnPlay.SetActive(true); btnPause = GameObject.Find("PlayButtons/grey/green/pause"); btnPause.SetActive(false); actCounterText = GameObject.Find("PlayButtons/grey/actCounterText"); progressBar = GameObject.Find("PlayButtons/ProgressBar"); btnDemoMode = GameObject.Find("ModeMenu/DemoMenuButton"); btnTrainMode = GameObject.Find("ModeMenu/LearnMenuButton"); btnExamMode = GameObject.Find("ModeMenu/TestMenuButton"); sce = GameObject.Find("ScEditor").GetComponent(); state = "empty"; canProgressBarChangePos = true; buildInProgress = false; acts = new List(); lineTex = new Texture2D(1, 1); rectAlpha = 1f; //Debug.Log("Player.Init: InvokeRepeating HighliteRefresh"); CancelInvoke("HighliteRefresh"); InvokeRepeating("HighliteRefresh", 0, highlightTimeDelta); //if(state == "empty") // LoadScenario("qwe"); // debug //LoadScenario("System_2"); //debug } void Update() { if (Input.GetMouseButtonDown(0)) { GameObject curCamera; if (man.cabinCamera.activeInHierarchy) curCamera = man.cabinCamera; else curCamera = man.viewCamera; Ray ray = curCamera.GetComponent().ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) if (hit.transform.gameObject != null) ClickedGO(hit.transform.gameObject); } } void OnGUI() { if (isRectsShowing) { //Vector2 g1 = GUIUtility.ScreenToGUIPoint(p1); //Vector2 g2 = GUIUtility.ScreenToGUIPoint(p2); foreach (actShowRect r in rectsList) { DrawLine(r.x1, r.y1, r.x2, r.y1, rectAlpha); DrawLine(r.x2, r.y1, r.x2, r.y2, rectAlpha); DrawLine(r.x2, r.y2, r.x1, r.y2, rectAlpha); DrawLine(r.x1, r.y2, r.x1, r.y1, rectAlpha); //Vector3 g1 = man.cam.WorldToScreenPoint(new Vector3((float)r.x1, (float)r.y1, (float)r.z1)); //Vector3 g2 = man.cam.WorldToScreenPoint(new Vector3((float)r.x2, (float)r.y2, (float)r.z2)); //DrawLine(g1.x, g1.y, g2.x, g1.y, rectAlpha); //DrawLine(g2.x, g1.y, g2.x, g2.y, rectAlpha); //DrawLine(g2.x, g2.y, g1.x, g2.y, rectAlpha); //DrawLine(g1.x, g2.y, g1.x, g1.y, rectAlpha); } if (rectAlphaDir) rectAlpha += 0.004f; else rectAlpha -= 0.004f; if (rectAlphaDir && rectAlpha >= 1f) { rectAlpha = 1f; rectAlphaDir = false; } if (!rectAlphaDir && rectAlpha <= 0.3f) { rectAlpha = 0.3f; rectAlphaDir = true; } } } void DrawLine(float _x1, float _y1, float _x2, float _y2, float a = 1f) //(int _x1, int _y1, int _x2, int _y2, float a=1f) { /*Matrix4x4 matrixBackup = GUI.matrix; float width = 3.0f; GUI.color = new Color(0, 1, 0, a); float angle = Mathf.Atan2(y2 - y1, x2 - x1) * 180f / Mathf.PI; GUIUtility.RotateAroundPivot(angle, new Vector2(x1, y1)); GUI.DrawTexture(new Rect(x1 - width / 2f, y1 - width / 2f, Mathf.Max(Mathf.Abs(x1 - x2), Mathf.Abs(y1 - y2)), width), lineTex); GUI.matrix = matrixBackup;*/ //float scrCoef = ((float)Screen.width / (float)Screen.height) / (16f / 9f); float x1 = Screen.width * (0.5f + _x1/ rectW); //1920 float y1 = Screen.height * (0.5f + _y1 / rectH);// * scrCoef; //1080 float x2 = Screen.width * (0.5f + _x2 / rectW); float y2 = Screen.height * (0.5f + _y2 / rectH);// * scrCoef; Matrix4x4 matrixBackup = GUI.matrix; float width = 3.0f; GUI.color = new Color(0, 1, 0, a); float angle = Mathf.Atan2(y2 - y1, x2 - x1) * 180f / Mathf.PI; GUIUtility.RotateAroundPivot(angle, new Vector2(x1, y1)); GUI.DrawTexture(new Rect(x1 - width / 2f, y1 - width / 2f, Mathf.Max(Mathf.Abs(x1 - x2), Mathf.Abs(y1 - y2)), width), lineTex); GUI.matrix = matrixBackup; } void ClickedGO(GameObject go) { if (state != "play") return; if (playMode != "waitForClick") return; if (go == null) return; if (man.objects == null) { Debug.LogError("Player: objects not loaded"); return; } UnityObject handlerObj = man.objects.FindHandler(go.name); if (handlerObj == null) return; if (!handlerObj.enabled) return; // объект выключен - игнорируем if(handlerObj.name == waitForClickObjName) { playMode = "play"; man.mouseEnterUI(); PlayActs(); } else if(handlerObj.name != "Kreslo_KVS" && handlerObj.name != "Kreslo_2P") { // клик в другой объект, что делаем? AudioSource beeper = GameObject.Find("beeper").GetComponent(); beeper.Play(); if (mode == "exam") { playerText.transform.Find("PlayerTextTMP").gameObject.GetComponent().text = "Ошибка в действиях обучаемого. Режим \"Контроль\" не пройден.\n\nПерезагрузите страницу."; playerText.SetActive(true); // чем наказываем: SetMode("exam"); if (man.mode == "play") { GameObject.Find("PlayButtons").SetActive(false); } } } } public void Clicked2D(BaseEventData evData) { if (man.mode != "play" && man.mode != "scedit") return; if (playMode != "waitForClick") return; RaycastHit2D hit; Ray ray = GameObject.Find("Camera").GetComponent().ScreenPointToRay(Input.mousePosition); PointerEventData _pointer = evData as PointerEventData; hit = Physics2D.Raycast(ray.origin, Vector2.up); if (hit.transform != null && _pointer.button == PointerEventData.InputButton.Left) ClickedGO(hit.transform.gameObject); } private void LateUpdate() { if (playMode == "cameraIsMoving") { cameraMoveCurTime += Time.deltaTime; float d = cameraMoveCurTime / cameraMoveMaxTime; if (playCamera == "cabin") { curCamera.transform.position = Vector3.Lerp(cameraIsMovingFromPos.position, cameraIsMovingToPos.position, d); curCamera.transform.rotation = Quaternion.Slerp(cameraIsMovingFromPos.rotation, cameraIsMovingToPos.rotation, d); //curCamera.GetComponent().fieldOfView = (int)Mathf.Lerp((float)cameraFromFOV, (float)cameraToFOV, d); // дергается при плавном изменении :( } else { curCamera.transform.rotation = Quaternion.Slerp(cameraIsMovingFromPos.rotation, cameraIsMovingToPos.rotation, d); curCamera.transform.position = curCamera.transform.localRotation * curCamera.GetComponent().offset + curCamera.GetComponent().target.position; curCamera.GetComponent().offset = Vector3.Lerp(cameraIsMovingFromPos.scale, cameraIsMovingToPos.scale, d); } if (cameraMoveCurTime >= cameraMoveMaxTime) { if (playCamera == "cabin") curCamera.GetComponent().fieldOfView = (float)cameraToFOV; if(isScEditorCameraMoving) { isScEditorCameraMoving = false; //man.mouseEnterUI(); } else { playMode = "play"; PlayActs(); } } //curCamera.AddComponent(); //Debug.Log("time = " + cameraMoveCurTime + " / "+cameraMoveMaxTime + ", d = " + d + " camera cur: " + curCamera.transform.position.x + " " + curCamera.transform.position.y + " " + curCamera.transform.position.z); //Debug.Log(" from: " + cameraIsMovingFromPos.position.x + " " + cameraIsMovingFromPos.position.y + " " + cameraIsMovingFromPos.position.z); } } public void LoadScenario(string scName) { //Debug.LogError("Loading Scenario " + scName); if (man == null) Init(); if (scName == "") return; StartCoroutine(LoadCoroutine(scName)); } public IEnumerator LoadCoroutine(string scName) { //Debug.Log("Starting Player.LoadCoroutine."); while (!man.isInitiated) yield return null; if (scName.ToLower() == "freemode") { man.mode = "free"; man.viewmode = 1; man.menuPlayButtons.SetActive(false); man.switchModeFree(); man.ChangeLayerPilotCabineDefault(); man.ChangeLayerExternalPanelsIgnore(); man.ChangeLayerPassCabineIgnore(); GameObject.Find("Air/view1").GetComponent().Start(); GameObject.Find("Air/view1").GetComponent().OnPointerDown(null); GameObject.Find("Air/view1").GetComponent().OnPointerClick(null); man.mouseExitUI(); yield break; } if (scName.ToLower().StartsWith("system_")) { man.switchModeView(); man.menuPlayButtons.SetActive(false); GameObject.Find("Air").SetActive(false); GameObject.Find("Obzor").GetComponent().ChooseSys(scName); yield break; } SC = null; state = "empty"; btnPlay.SetActive(true); btnPause.SetActive(false); actCounterText.GetComponent().text = ""; canProgressBarChangePos = false; progressBar.GetComponent().value = 0; canProgressBarChangePos = true; //Debug.Log("Loading Scenario: StartCoroutine"); if (!scName.ToLower().EndsWith(".xml")) scName += ".xml"; string path = Path.Combine(Application.streamingAssetsPath, "Scenario", scName); //+".xml" bool isWeb; string scText = ""; if(man == null) man = GameObject.Find("Manager").GetComponent(); Transform[] allPanels2D = man.canvas.transform.GetChild(0).GetComponentsInChildren(); Transform[] allPanels3D = man.copter.GetComponentsInChildren(); //Debug.Log("Player: Trying Deserialize " + path); path = path.Replace("file:///", ""); if (path.Contains("http")) { UnityWebRequest www = UnityWebRequest.Get(path); www.downloadHandler = new DownloadHandlerBuffer(); yield return www.SendWebRequest(); if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) { Debug.LogError(www.error); yield break; } else { scText = www.downloadHandler.text; //Debug.LogError("Player Web Deserialize: downloaded bytes " + scText.Length); } isWeb = true; } else isWeb = false; if (!isWeb && Application.platform == RuntimePlatform.WebGLPlayer) { //Debug.LogError("Player: Cannot open local files in WebGL"); } else { var utf8 = Encoding.UTF8 as UTF8Encoding; XmlSerializer serializer = new XmlSerializer(typeof(Scenario)); Stream fs; if (isWeb) fs = new MemoryStream(utf8.GetBytes(scText)); else fs = new FileStream(path, FileMode.Open); XmlReader reader = new XmlTextReader(fs); bool res = serializer.CanDeserialize(reader); reader.Close(); fs.Close(); if (!res) yield break; if (isWeb) fs = new MemoryStream(utf8.GetBytes(scText)); else fs = new FileStream(path, FileMode.Open); SC = (Scenario)serializer.Deserialize(fs); //Debug.LogError("Player Deserialize: man.objects = " + man.objects.obj.Count); fs.Close(); } SC.name = scName; if (SC == null) { Debug.LogError("Player: Scenario loading error (" + path + ")"); yield break; } else Debug.Log("Player: Loaded " + SC.init.acts.Count + " init, " + SC.demo.acts.Count + " demo, " + SC.train.acts.Count + " train, " + SC.exam.acts.Count + " exam" + " action(s) from " + path); //Debug.LogError("Player: Loaded " + SC.init.acts.Count + " init, " + SC.demo.acts.Count + " demo, " + SC.train.acts.Count + " train, " + SC.exam.acts.Count + " exam" + " action(s) from " + path); if (SC == null) { state = "empty"; actCounterText.GetComponent().text = "Сценарий не загружен"; } else { if (btnDemoMode == null) btnDemoMode = GameObject.Find("DemoMenuButton"); if (btnTrainMode == null) btnTrainMode = GameObject.Find("LearnMenuButton"); if (btnExamMode == null) btnExamMode = GameObject.Find("TestMenuButton"); btnDemoMode.GetComponent().Start(); btnTrainMode.GetComponent().Start(); btnExamMode.GetComponent().Start(); btnDemoMode.GetComponent().enabled = (SC.demo.acts.Count > 0); Image[] img = btnDemoMode.GetComponentsInChildren(); for (var i = 0; i < img.Length; i++) img[i].color = (SC.demo.acts.Count > 0) ? Color.white : Color.gray; if(img.Length == 2 && SC.demo.acts.Count == 0) { img[0].gameObject.SetActive(true); img[1].gameObject.SetActive(false); } btnTrainMode.GetComponent().enabled = (SC.train.acts.Count > 0); img = btnTrainMode.GetComponentsInChildren(); for (int i = 0; i < img.Length; i++) img[i].color = (SC.train.acts.Count > 0) ? Color.white : Color.gray; if (img.Length == 2 && SC.train.acts.Count == 0) { img[0].gameObject.SetActive(true); img[1].gameObject.SetActive(false); } btnExamMode.GetComponent().enabled = (SC.exam.acts.Count > 0); img = btnExamMode.GetComponentsInChildren(); for (var i = 0; i < img.Length; i++) img[i].color = (SC.exam.acts.Count > 0) ? Color.white : Color.gray; if (img.Length == 2 && SC.exam.acts.Count == 0) { img[0].gameObject.SetActive(true); img[1].gameObject.SetActive(false); } if (SC.demo.acts.Count > 0) SetMode("demo"); else if (SC.train.acts.Count > 0) SetMode("train"); else if (SC.exam.acts.Count > 0) SetMode("exam"); if(man.mode == "play") { playerText.transform.Find("PlayerTextTMP").gameObject.GetComponent().text = "Загружен сценарий \""+SC.title+ "\".\n
Выберите режим Демонстрация, Обучение или Контроль и нажмите кнопку воспроизведения."; playerText.SetActive(true); } if (SC.needExamCompleted && SC.exam != null && SC.exam.acts != null && SC.exam.acts.Count > 0 && Application.platform == RuntimePlatform.WebGLPlayer) { //Application.ExternalCall("scLoaded", SC.name, SC.title); } else { if (Application.platform == RuntimePlatform.WebGLPlayer) Application.ExternalCall("scFinished", SC.name, SC.title); } } //Debug.Log("Done Player.LoadCoroutine."); } public void SetMode(string newmode) { //Debug.Log("Player: SetMode "+newmode); if (newmode == "demo" && SC.demo.acts.Count == 0) return; if (newmode == "train" && SC.train.acts.Count == 0) return; if (newmode == "exam" && SC.exam.acts.Count == 0) return; for (int i = 0; i < highlightList.Count; i++) { RemoveFromHighliteList(highlightList[i].obj.name); i--; } state = "ready"; mode = newmode; Build(); state = "pause"; nextAct = 0; btnDemoMode.GetComponent().isGreen = (newmode == "demo"); btnDemoMode.GetComponent().OnPointerUp(null); btnTrainMode.GetComponent().isGreen = (newmode == "train"); btnTrainMode.GetComponent().OnPointerUp(null); btnExamMode.GetComponent().isGreen = (newmode == "exam"); btnExamMode.GetComponent().OnPointerUp(null); if (newmode == "exam" && man.mode == "play") progressBar.GetComponent().enabled = false; else progressBar.GetComponent().enabled = true; //actCounterText.GetComponent().text = ""; btnPlay.SetActive(true); btnPause.SetActive(false); if (!man.is3D) man.SwitchTo3D(); man.objects.SetDefaultValues(); if(man.mode == "play") man.mouseEnterUI(); man.mfi1.ses = man.mfi2.ses = man.mfi3.ses = man.mfi4.ses = man.mfi5.ses = true; } public void Play() { //Debug.Log("Player: play"); btnPlay.SetActive(true); btnPause.SetActive(false); if (!man.is3D && state != "pause") man.SwitchTo3D(); if (state == "empty" || SC == null) { //Debug.Log("Scenario not loaded."); actCounterText.GetComponent().text = "Сценарий не загружен"; return; } if (state == "ready") { Build(); man.mfi1.ses = man.mfi2.ses = man.mfi3.ses = man.mfi4.ses = man.mfi5.ses = true; } state = "play"; playMode = "play"; btnPlay.SetActive(false); btnPause.SetActive(true); playerText.SetActive(false); if(sce != null && sce.isActiveAndEnabled) sce.SetDefaultMaterialsToCurrentObject(); //InvokeRepeating("HighliteRefresh", 0, highlightTimeDelta); //Debug.Log("Player.Play: InvokeRepeating setStateInTime"); CancelInvoke("setStateInTime"); InvokeRepeating("setStateInTime", 0, setStateInTimeDelta); //Debug.Log("Player.Play: InvokeRepeating PlayActs"); CancelInvoke("PlayActs"); InvokeRepeating("PlayActs", 0, playDelta); // CancelInvoke ("PlayActs") } public void Pause() { //Debug.Log("Player: pause"); if (playMode == "waitForClick") return; state = "pause"; btnPlay.SetActive(true); btnPause.SetActive(false); //Debug.Log("Player.Pause: CancelInvoke setStateInTime"); //Debug.Log("Player.Pause: CancelInvoke PlayActs"); CancelInvoke("PlayActs"); CancelInvoke("setStateInTime"); //CancelInvoke("HighliteRefresh"); } void PlayActs() { if (buildInProgress) return; // ждем окончания работы корутины if (state != "play") return; if (playMode == "waitForClick") return; if (playMode == "cameraIsMoving") return; if (playMode == "waitForTime") // play, waitForTime, waitForClick { playTimeToWait -= playDelta; if (playTimeToWait > 0) return; playMode = "play"; playTimeToWait = 0; } if (nextAct >= acts.Count) { ScenarioFinished(); return; } while (state == "play" && playMode == "play") { canProgressBarChangePos = false; progressBar.GetComponent().value = nextAct; canProgressBarChangePos = true; int actsDone = nextAct - 1; if (actsDone < 0) actsDone = 0; actCounterText.GetComponent().text = acts[actsDone].actNumberToShow + "/" + acts[acts.Count - 1].actNumberToShow; RunAction(acts[nextAct]); nextAct++; //последний плохо работает if (nextAct >= acts.Count && playMode != "waitForClick" && playMode != "waitForTime" && playMode != "cameraIsMoving") ScenarioFinished(); } } // setState, setStateInRange, openPanel, setTextField, setIntField, switchTo3D, highlightOn, highlightOff, // highlightTime, waitForClick, waitForTime, setCurCameraPos, showText, hideText, execScenario, playAudio public void RunAction(ScAction act, bool runFast=false) { //Debug.Log(" Play " + nextAct + ": " + act.type); if(act.type == "setState") { UnityObject obj = man.objects.Find(act.objName); if(obj == null) { ScenarioError("Ошибка setState: объект \"" + act.objName + "\" не найден в сцене."); state = "pause"; return; } SetObjectState(obj, act.setState.val); } if (act.type == "setStateInRange") { UnityObject obj = man.objects.Find(act.objName); if (obj == null) { ScenarioError("Ошибка setStateInRange: объект \"" + act.objName + "\" не найден в сцене."); state = "pause"; return; } if(!runFast) SetObjectState(obj, act.setStateInRange.val, act.setStateInRange.sec); else SetObjectState(obj, act.setStateInRange.val, 0); } if (act.type == "openPanel") { if (act.objName.Substring(act.objName.Length - 3) == "_3D") { string panel2D = act.objName.Substring(0, act.objName.Length - 3); UnityObject obj2D = man.objects.Find(panel2D); if (obj2D != null) man.SwitchTo2D(obj2D.name); else { ScenarioError("Ошибка сценария: соответствующая объекту \""+ act.objName + "\" 2D-панель не найдена."); state = "pause"; return; } } else { ScenarioError("Ошибка сценария: невозможно определить имя 2D-панели объекта \"" + act.objName + "\"."); state = "pause"; return; } } if (act.type == "switchTo3D") { if(man.is3D) { ScenarioError("Ошибка сценария: действие \"Закрыть панель\" невыполнимо - нет открытых панелей."); state = "pause"; return; } man.SwitchTo3D(); } if (act.type == "setTextField") { UnityObject obj = man.objects.Find(act.objName); if (obj == null) { ScenarioError("Ошибка setTextField: объект \"" + act.objName + "\" не найден в сцене."); state = "pause"; return; } obj.SetObjectText(act.setTextField.text, act.setTextField.color); } if (act.type == "setIntField" || act.type == "setFloatField") { UnityObject obj = man.objects.Find(act.objName); if (obj == null) { ScenarioError("Ошибка setIntField: объект \"" + act.objName + "\" не найден в сцене."); state = "pause"; return; } obj.textcolor = act.setIntField.color; obj.setTextFieldAsFloat = (act.type == "setFloatField"); if (!runFast) { SetObjectState(obj, act.setIntField.valFrom, 0); SetObjectState(obj, act.setIntField.valTo, act.setIntField.sec); } else SetObjectState(obj, act.setIntField.valTo, 0); } if (act.type == "highlightOn") { AddToHighliteList(act.objName); } if (act.type == "highlightOff") { RemoveFromHighliteList(act.objName); } if (act.type == "highlightTime") { AddToHighliteList(act.objName, act.highlightTime.sec); } if (act.type == "waitForClick" && !runFast) { waitForClickObjName = act.objName; playMode = "waitForClick"; if (man.mode == "play") man.mouseExitUI(); } if (act.type == "waitForTime") { if (!runFast) { playMode = "waitForTime"; playTimeToWait = act.waitForTime.sec; } else { for (int k = 0; k < highlightList.Count; k++) { highlightObj hObj = highlightList[k]; if (hObj.sec != 0f) { hObj.sec -= act.waitForTime.sec; if (hObj.sec <= 0) { RemoveFromHighliteList(hObj.obj.name); k--; continue; } } } } } if (act.type == "showText") { playerText.transform.Find("PlayerTextTMP").gameObject.GetComponent().text = act.showText.text; playerText.SetActive(true); } if (act.type == "hideText") { playerText.SetActive(false); } //if (act.type == "execScenario") не нужно if (act.type == "playAudio" && !runFast) { AudioSource aSrc = GameObject.Find("audioPlayer").GetComponent(); aSrc.clip = act.playAudio.clip; aSrc.Play(); } if (act.type == "switchMFIScreen") { man.objects.Find(act.objName).gameObject.GetComponent().SwitchScreen(act.switchMFIScreen.scrName); } if (act.type == "setSkybox") { GameObject.Find("skyBox").GetComponent().setSkybox(act.setSkybox.name); } if (act.type == "showRect") { rectsList.Add(act.showRect); isRectsShowing = true; } if (act.type == "hideRects") { rectsList.Clear(); isRectsShowing = false; } if (act.type == "setCurCameraPos" && !runFast) { if (!man.is3D && !isScEditorCameraMoving) { ScenarioError("Ошибка сценария: для перемещения камеры необходимо закрыть 2D-панель."); state = "pause"; return; //man.SwitchTo3D(); //man.ChangeLayerDefault(); !!! } playCamera = act.setCurCameraPos.camera; if (playCamera == "cabin") { curCamera = man.cabinCamera; man.switchModeFree(); if (act.setCurCameraPos.position.z > 6.15f) { // кабина man.viewmode = 1; curCamera.GetComponent().farClipPlane = 100f; curCamera.GetComponent().fieldOfView = 50f; //60f; man.ChangeLayerExternalPanelsIgnore(); man.ChangeLayerPilotCabineDefault(); man.ChangeLayerPassCabineIgnore(); } else { // грузовая man.viewmode = 2; curCamera.GetComponent().farClipPlane = 200f; curCamera.GetComponent().fieldOfView = 50f; man.ChangeLayerExternalPanelsIgnore(); man.ChangeLayerPassCabineDefault(); man.ChangeLayerPilotCabineIgnore(); } } else { man.viewmode = 3; curCamera = man.viewCamera; man.switchModeView(); } cameraIsMovingToPos.position = act.setCurCameraPos.position.toVector3(); cameraIsMovingToPos.rotation = act.setCurCameraPos.rotation.toQuaternion(); cameraIsMovingFromPos.position = curCamera.transform.position; cameraIsMovingFromPos.rotation = curCamera.transform.rotation; cameraMoveCurTime = 0; var heading = cameraIsMovingToPos.position - curCamera.transform.position; cameraMoveMaxTime = 1f; int dist = (int)((float)heading.magnitude * act.setCurCameraPos.scale.x); if (dist <= 1) cameraMoveMaxTime = 1f; if (dist > 1 && dist <= 3) cameraMoveMaxTime = 1.9f; if (dist > 3 && dist <= 8) cameraMoveMaxTime = 2.7f; if (dist > 8) cameraMoveMaxTime = 3.5f; if (playCamera == "cabin") { cameraFromFOV = (int)curCamera.GetComponent().fieldOfView; cameraToFOV = (int)act.setCurCameraPos.fov; if (cameraToFOV > cameraFromFOV) curCamera.GetComponent().fieldOfView = (float)cameraToFOV; } else { cameraIsMovingToPos.scale = act.setCurCameraPos.scriptOffset.toVector3(); // переменные скрипта внешней камеры, это не scale cameraIsMovingFromPos.scale = curCamera.GetComponent().offset; curCamera.GetComponent().offset = act.setCurCameraPos.scriptOffset.toVector3(); //curCamera.GetComponent().offset.y = act.setCurCameraPos.scriptOffset.y; //curCamera.GetComponent().offset.z = act.setCurCameraPos.scriptOffset.z; } man.viewmode = act.setCurCameraPos.viewMode; playMode = "cameraIsMoving"; } } void setStateInTime() { for(int i=0;i= setStateInTimeList[i].runTime) { setStateInTimeList[i].obj.SetObjectState(setStateInTimeList[i].toState); setStateInTimeList.RemoveAt(i); i--; } } } public void SetObjectState(UnityObject obj, int newState, float sec = 0) // функция для обработки изменений состояния за определенное время { // непосредственное изменение - в классе Mi38objects - obj.SetObjectState(newState); // (класс Mi38objects не является наследником MonoBehaviour и не позволяет вызывать корутины и т.п.) if (obj.dim == "2D" && obj.type == "buttonAutoUncheck") { obj.SetObjectState(newState); if(newState == 1) { buttonAutoUncheckList.Add(obj); Invoke("button2DAutoUncheckFunction", 0.5f); } return; } if(sec == 0) obj.SetObjectState(newState); // для всех остальных случаев else { setStateInTimeStruct sit = new setStateInTimeStruct(); sit.obj = obj; sit.runCurTime = 0; sit.runTime = sec; sit.fromState = obj.curState; sit.toState = newState; setStateInTimeList.Add(sit); } } void button2DAutoUncheckFunction() { foreach(UnityObject obj in buttonAutoUncheckList) obj.SetObjectState(0); buttonAutoUncheckList.Clear(); } void ScenarioFinished() { //Debug.Log("Player.ScenarioFinished: CancelInvoke setStateInTime"); Debug.Log("Player.ScenarioFinished: CancelInvoke PlayActs"); CancelInvoke("PlayActs"); CancelInvoke("setStateInTime"); //CancelInvoke("HighliteRefresh"); rectsList.Clear(); isRectsShowing = false; man.mfi1.ses = man.mfi2.ses = man.mfi3.ses = man.mfi4.ses = man.mfi5.ses = true; state = "pause"; nextAct = 0; int actsDone = nextAct - 1; if (actsDone < 0) actsDone = 0; actCounterText.GetComponent().text = acts[actsDone].actNumberToShow + "/" + acts[acts.Count-1].actNumberToShow; canProgressBarChangePos = false; progressBar.GetComponent().value = 0; canProgressBarChangePos = true; btnPlay.SetActive(true); btnPause.SetActive(false); AudioSource aSrc = GameObject.Find("audioPlayer").GetComponent(); aSrc.Stop(); man.objects.SetDefaultValues(); for(int i=0;i().text = acts[actsDone].actNumberToShow + "/" + acts[acts.Count - 1].actNumberToShow; if (acts.Count != 0) progressBar.GetComponent().maxValue = acts.Count-1; canProgressBarChangePos = false; progressBar.GetComponent().value = 0; canProgressBarChangePos = true; man.objects.SetDefaultValues(); buildInProgress = false; //Debug.Log("Player: builded " + acts.Count + " total actions"); IEnumerator buildScMode(ScenarioMode scMode, bool showActNumber=false) { for (int i = 0; i < scMode.acts.Count; i++) { if (scMode.acts[i].type != "execScenario" && scMode.acts[i].type != "playAudio") acts.Add(scMode.acts[i].clone()); if (scMode.acts[i].type == "execScenario") { actCounterText.GetComponent().text = "Загрузка сценария " + scMode.acts[i].execScenario.name; yield return StartCoroutine(BuildActExecScenario(scMode.acts[i])); } if (scMode.acts[i].type == "playAudio") { actCounterText.GetComponent().text = "Загрузка аудио " + scMode.acts[i].playAudio.filename; yield return StartCoroutine(BuildActPlayAudio(scMode.acts[i])); } if (showActNumber) acts[acts.Count - 1].actNumberToShow = i + 1; } } } public IEnumerator BuildActExecScenario(ScAction execAct) { string path = Path.Combine(Application.streamingAssetsPath, "Scenario", execAct.execScenario.name + ".xml"); string scText = ""; UnityWebRequest www = UnityWebRequest.Get(path); www.downloadHandler = new DownloadHandlerBuffer(); yield return www.SendWebRequest(); if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) { Debug.LogError("Player: error loading scenario ("+ path + ")" + www.error); yield break; } else scText = www.downloadHandler.text; var utf8 = Encoding.UTF8 as UTF8Encoding; XmlSerializer serializer = new XmlSerializer(typeof(Scenario)); Stream fs = new MemoryStream(utf8.GetBytes(scText)); XmlReader reader = new XmlTextReader(fs); bool res = serializer.CanDeserialize(reader); reader.Close(); fs.Close(); if (!res) yield break; fs = new MemoryStream(utf8.GetBytes(scText)); Scenario execSC = (Scenario)serializer.Deserialize(fs); //Debug.LogError("Player Deserialize: man.objects = " + man.objects.obj.Count); fs.Close(); if (execSC == null) Debug.LogError("Player exec scenario: Scenario loading error (" + path + ")"); //else // Debug.Log("Player exec scenario: Loaded " + execSC.init.acts.Count + " init, " + execSC.demo.acts.Count + " demo, " + execSC.train.acts.Count + " train, " + execSC.exam.acts.Count + " exam" + " action(s) from " + path); ScenarioMode execCurScMode = execSC.demo; if (mode == "train") execCurScMode = execSC.train; if (mode == "exam") execCurScMode = execSC.exam; yield return buildExecScMode(execSC.init); yield return buildExecScMode(execCurScMode); IEnumerator buildExecScMode(ScenarioMode scMode) { for (int i = 0; i < scMode.acts.Count; i++) { if (scMode.acts[i].type == "openPanel" || scMode.acts[i].type == "switchTo3D" || scMode.acts[i].type == "highlightOn" || scMode.acts[i].type == "highlightOff" || scMode.acts[i].type == "highlightTime" || scMode.acts[i].type == "waitForClick" || scMode.acts[i].type == "setCurCameraPos" || scMode.acts[i].type == "showText" || scMode.acts[i].type == "hideText" || scMode.acts[i].type == "playAudio") if (execAct.execScenario.fastFlag) continue; if (scMode.acts[i].type == "execScenario") { actCounterText.GetComponent().text = "Загрузка сценария " + scMode.acts[i].execScenario.name; if (execAct.execScenario.fastFlag) scMode.acts[i].execScenario.fastFlag = true; yield return StartCoroutine(BuildActExecScenario(scMode.acts[i])); continue; } if (scMode.acts[i].type == "playAudio") { actCounterText.GetComponent().text = "Загрузка аудио " + scMode.acts[i].playAudio.filename; yield return StartCoroutine(BuildActPlayAudio(scMode.acts[i])); continue; } if (scMode.acts[i].type == "setStateInRange") { if (execAct.execScenario.fastFlag) scMode.acts[i].setStateInRange.sec = 0; } if (scMode.acts[i].type == "setIntField" || scMode.acts[i].type == "setFloatField") { if (execAct.execScenario.fastFlag) scMode.acts[i].setIntField.sec = 0; } acts.Add(scMode.acts[i].clone()); } } } // setState, setStateInRange, openPanel, setTextField, setIntField, switchTo3D, highlightOn, highlightOff, // highlightTime, waitForClick, waitForTime, setCurCameraPos, showText, hideText, execScenario, playAudio public IEnumerator BuildActPlayAudio(ScAction playAct) { //Debug.Log("Player: build ActPlay " + playAct.playAudio.filename); string path = Path.Combine(Application.streamingAssetsPath, "Scenario", SC.name.Replace(".xml",""), playAct.playAudio.filename); UnityWebRequest www; if(playAct.playAudio.filename.EndsWith(".wav")) www = UnityWebRequestMultimedia.GetAudioClip(path, AudioType.WAV); else www = UnityWebRequestMultimedia.GetAudioClip(path, AudioType.MPEG); yield return www.SendWebRequest(); if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) { Debug.LogError("Player: error loading audio - "+ www.error+ " " + path); playAct.playAudio.clip = null; yield break; } else { playAct.playAudio.clip = DownloadHandlerAudioClip.GetContent(www); //Debug.Log("Player audio from Web: downloaded seconds " + playAct.playAudio.clip.length); } ScAction res = playAct.clone(); res.playAudio.clip = playAct.playAudio.clip; acts.Add(res); } public void onProgressBarChange() { if (state == "empty") // || state == "ready" return; if (!canProgressBarChangePos) return; if (man.isProgressBarChangingInProgress) return; //Debug.Log("Player: onProgressBarChange"); state = "pause"; btnPlay.SetActive(true); btnPause.SetActive(false); int toAct = (int)progressBar.GetComponent().value; if (progressBar.GetComponent().value == 0f) { man.objects.SetDefaultValues(); actCounterText.GetComponent().text = "0/" + acts[acts.Count - 1].actNumberToShow; } else actCounterText.GetComponent().text = acts[toAct].actNumberToShow + "/" + acts[acts.Count - 1].actNumberToShow; if (toAct == nextAct-1) return; //двигаем камеру к последней установленной позиции int lastCamAct = -1; for(int i = toAct; i >= 0;i--) if(acts[i].type == "setCurCameraPos") { lastCamAct = i; break; }; if (lastCamAct != -1) { playCamera = acts[lastCamAct].setCurCameraPos.camera; if (playCamera == "cabin") { curCamera = man.cabinCamera; if (man.fusel.activeInHierarchy) man.switchModeFree(); curCamera.transform.position = acts[lastCamAct].setCurCameraPos.position.toVector3(); curCamera.transform.rotation = acts[lastCamAct].setCurCameraPos.rotation.toQuaternion(); curCamera.GetComponent().fieldOfView = acts[lastCamAct].setCurCameraPos.fov; if(curCamera.transform.position.z > 6.15f) { // кабина man.viewmode = 1; curCamera.GetComponent().farClipPlane = 100f; curCamera.GetComponent().fieldOfView = 50f; man.ChangeLayerExternalPanelsIgnore(); man.ChangeLayerPilotCabineDefault(); man.ChangeLayerPassCabineIgnore(); } else { // грузовая man.viewmode = 2; curCamera.GetComponent().farClipPlane = 200f; curCamera.GetComponent().fieldOfView = 50f; man.ChangeLayerExternalPanelsIgnore(); man.ChangeLayerPassCabineDefault(); man.ChangeLayerPilotCabineIgnore(); } } else { // внешка man.viewmode = 3; curCamera = man.viewCamera; if (!man.fusel.activeInHierarchy) man.switchModeView(); curCamera.transform.position = acts[lastCamAct].setCurCameraPos.position.toVector3(); curCamera.transform.rotation = acts[lastCamAct].setCurCameraPos.rotation.toQuaternion(); curCamera.GetComponent().offset = acts[lastCamAct].setCurCameraPos.scriptOffset.toVector3(); } } man.isProgressBarChangingInProgress = true; rectsList.Clear(); isRectsShowing = false; if (!man.is3D) man.SwitchTo3D(); for (int i = 0; i <= toAct; i++) RunAction(acts[i], true); nextAct = toAct + 1; man.isProgressBarChangingInProgress = false; } void AddToHighliteList(string objName, float sec=0f) { UnityObject obj = man.objects.Find(objName); if (obj == null) return; for (int i = 0; i < highlightList.Count; i++) if (highlightList[i].obj.name == objName) return; highlightObj hObj = new highlightObj(); hObj.obj = obj; hObj.sec = sec; if (obj.dim == "3D") { hObj.renderers = obj.gameObject.transform.GetComponentsInChildren(); //parent. foreach (Renderer r in hObj.renderers) { MakeActive obj_ma = r.gameObject.GetComponent(); if (obj_ma != null) if (obj_ma.materialsReplaced) obj_ma.RestoreChildrenMaterials(); } hObj.materials.Clear(); hObj.greenMaterials.Clear(); for (int i = 0; i < hObj.renderers.Length; i++) { hObj.materials.Add(hObj.renderers[i].material); Material greenMat = new Material(hObj.renderers[i].material); greenMat.SetColor("_EmissionColor", new Color(0f / 255f, 50f / 255f, 0f / 255f)); hObj.greenMaterials.Add(greenMat); } } else { hObj.spriteRenderers = obj.gameObject.transform.GetComponentsInChildren(); //parent. hObj.images = obj.gameObject.transform.GetComponentsInChildren(); hObj.spriteColors.Clear(); hObj.imageColors.Clear(); for (int i = 0; i < hObj.spriteRenderers.Length; i++) hObj.spriteColors.Add(hObj.spriteRenderers[i].color); for (int i = 0; i < hObj.images.Length; i++) hObj.imageColors.Add(hObj.images[i].color); } highlightList.Add(hObj); } void RemoveFromHighliteList(string objName) { int ind = -1; for (int i = 0; i < highlightList.Count; i++) if (highlightList[i].obj.name == objName) ind = i; if (ind == -1) return; highlightObj hObj = highlightList[ind]; if (hObj.obj.dim == "3D") { if (hObj.renderers != null && hObj.materials.Count != 0) for (int i = 0; i < hObj.renderers.Length; i++) hObj.renderers[i].material = hObj.materials[i]; } else { for (int i = 0; i < hObj.spriteRenderers.Length; i++) hObj.spriteRenderers[i].color = hObj.spriteColors[i]; for (int i = 0; i < hObj.images.Length; i++) hObj.images[i].color = hObj.imageColors[i]; } highlightList.RemoveAt(ind); } void HighliteRefresh() { for(int k=0;k < highlightList.Count;k++) { highlightObj hObj = highlightList[k]; if(hObj.sec != 0f) { hObj.sec -= highlightTimeDelta; if(hObj.sec <= 0) { RemoveFromHighliteList(hObj.obj.name); k--; continue; } } if (hObj.obj.dim == "3D") for (int i = 0; i < hObj.renderers.Length; i++) hObj.renderers[i].material = hObj.greenMaterials[i]; else { for (int i = 0; i < hObj.spriteRenderers.Length; i++) hObj.spriteRenderers[i].color = Color.green; for (int i = 0; i < hObj.images.Length; i++) hObj.images[i].color = Color.green; } } } void ScenarioError(string msg) { playerText.transform.Find("PlayerTextTMP").gameObject.GetComponent().text = ""+msg+"
"; playerText.SetActive(true); if(!man.isProgressBarChangingInProgress) Invoke("delayHide", 5f); } void delayHide() { playerText.SetActive(false); } public void ScenarioMsg5sec(string msg) { playerText.transform.Find("PlayerTextTMP").gameObject.GetComponent().text = msg; playerText.SetActive(true); if (!man.isProgressBarChangingInProgress) Invoke("delayHide", 5f); } public void SetFullscreenButtonClick() { GameObject btnGO = GameObject.Find("maxmin"); if (btnGO == null) return; if(Application.platform == RuntimePlatform.WebGLPlayer) { isFullscreen = !isFullscreen; Screen.fullScreen = isFullscreen; } btnGO.GetComponent().isGreen = false; } } // setState, setStateInRange, openPanel, setTextField, setIntField, switchTo3D, highlightOn, highlightOff, // highlightTime, waitForClick, waitForTime, setCurCameraPos, showText, hideText, execScenario, playAudio, showRect