using QFramework; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using XMLTool; public class OperationController : MonoSingleton { public struct OnOperationChanged { } public struct StepExecute { public int index; } public struct OnNextStep { } public struct StepStatusOnChange { public int curIndex; public StepStatus status; } public enum StepStatus { NoStart, Start, Finished, } OperationController() { } public Operation operation; Dictionary curOperations = new Dictionary(); List steps = new List(); int index = -1; bool isStepRun = false; IAction curAction; public override void OnSingletonInit() { base.OnSingletonInit(); TypeEventSystem.Global.Register((arg) => { Refresh(); }).UnRegisterWhenGameObjectDestroyed(gameObject); } public void Refresh() { Global.AppType operationType = Global.AppType.All; int index = 0; foreach (var operation in Global.Instance.curModule.Operations) { if (string.IsNullOrEmpty(operation.moduleType) == false) { Enum.TryParse(operation.moduleType, out operationType); } if (Global.appTpe == operationType || operationType == Global.AppType.All) { if (string.IsNullOrEmpty(operation.name)) { curOperations.Add(index.ToString(), operation); } else { curOperations.Add(operation.name, operation); } index++; } } foreach (var operation in curOperations) { this.operation = operation.Value; foreach (var item in operation.Value.Steps) { AddStep(item); } TypeEventSystem.Global.Register(OnExecute); TypeEventSystem.Global.Register(OnNext); TypeEventSystem.Global.Register(OnModuleQuitHandler); break; } } public void ChangeOperation(string name) { if (curOperations.ContainsKey(name)) { index = -1; curAction?.Deinit(); steps.Clear(); this.operation = curOperations[name]; foreach (var item in this.operation.Steps) { AddStep(item); } TypeEventSystem.Global.Send(); OnNext(default); } } private void OnModuleQuitHandler(OnModuleQuit quit) { Clear(); } public void Clear() { index = -1; curAction?.Deinit(); operation = null; steps.Clear(); curOperations.Clear(); TypeEventSystem.Global.UnRegister(OnModuleQuitHandler); TypeEventSystem.Global.UnRegister(OnExecute); TypeEventSystem.Global.UnRegister(OnNext); } private void OnNext(OnNextStep step) { Execute(this.index + 1); } private void OnExecute(StepExecute execute) { Execute(execute.index); } public void Begin() { index = 0; Execute(index); } public void AddStep(Step step) { steps.Add(step); if (step.SubSteps != null && step.SubSteps.Count > 0) { foreach (var subStep in step.SubSteps) { AddStep(subStep); } } } public void Execute(int targetIndex) { if (this.index == targetIndex) { return; } if (isStepRun) { curAction?.Deinit(); } if (targetIndex < steps.Count && targetIndex >= 0) { if (this.index < targetIndex) { var seq = ActionKit.Sequence(); if (this.index >= 0) { int startIndex = this.index; // 当前这步 已经做完了 不需要finished if (curAction != null && curAction.Status == ActionStatus.Finished) { startIndex += 1; } for (int i = startIndex; i < targetIndex; i++) { // 完成动作 直接执行 IAction finishAction = ActionHelper.GetActionAndSub(steps[i].Finished); TypeEventSystem.Global.Send(new StepStatusOnChange() { curIndex = i, status = StepStatus.Finished }); if (finishAction != null) { seq.Append(finishAction); } } } TypeEventSystem.Global.Send(); seq.Start(this, () => { curAction = ActionHelper.GetActionAndSub(steps[targetIndex].Start); RunCurAction(curAction, targetIndex); }); } else if (this.index > targetIndex) { var seq = ActionKit.Sequence(); for (int i = this.index; i >= targetIndex; i--) { // 重置动作 直接重置 IAction resetAction = ActionHelper.GetActionAndSub(steps[i].Reset); if (resetAction != null) { seq.Append(resetAction); } TypeEventSystem.Global.Send(new StepStatusOnChange() { curIndex = i, status = StepStatus.NoStart }); } TypeEventSystem.Global.Send(); seq.Start(this, () => { curAction = ActionHelper.GetActionAndSub(steps[targetIndex].Start); RunCurAction(curAction, targetIndex); }); } else { curAction = ActionHelper.GetActionAndSub(steps[targetIndex].Start); RunCurAction(curAction, targetIndex); } } } public void RunCurAction(IAction curAction, int targetIndex) { TypeEventSystem.Global.Send(); if (curAction != null) { this.index = targetIndex; isStepRun = true; TypeEventSystem.Global.Send(new StepStatusOnChange() { curIndex = targetIndex, status = StepStatus.Start }); curAction.Start(this, () => { isStepRun = false; TypeEventSystem.Global.Send(new StepStatusOnChange() { curIndex = targetIndex, status = StepStatus.Finished }); }); } else { this.index = targetIndex; TypeEventSystem.Global.Send(new StepStatusOnChange() { curIndex = targetIndex, status = StepStatus.Finished }); Execute(this.index + 1); } } }