/// <summary> /// 处理并行调用和信号函数的消息循环 /// </summary> private void ParallelUpdateContext(object sender, EventArgs e) { // 如果主消息循环暂停那么就直接迭代掉 if (Director.IsContextUpdatePaused) { return; } // 获取绑定的调用堆栈 var dispatcher = sender as DispatcherTimer; dispatcher.Stop(); ParallelDispatcherArgsPackage pdap; try { pdap = dispatcher.Tag as ParallelDispatcherArgsPackage; } catch (Exception ex) { LogUtils.LogLine("Parallel Failed " + ex, "Director", LogLevel.Warning); dispatcher.Start(); return; } if (pdap == null) { LogUtils.LogLine("Parallel Failed.", "Director", LogLevel.Warning); dispatcher.Start(); return; } var paraVM = pdap.IsSemaphore ? pdap.SemaphoreStack : Director.RunMana.ParallelExecutorStack.Peek()[pdap.Index].Executor; bool resumeFlag = true; while (true) { // 取得调用堆栈顶部状态 StackMachineState stackState = Director.RunMana.GameState(paraVM); GameState paraGameState = GameState.Exit; switch (stackState) { case StackMachineState.Interpreting: case StackMachineState.FunctionCalling: resumeFlag = false; paraGameState = GameState.Performing; break; case StackMachineState.WaitUser: dispatcher.Start(); return; case StackMachineState.WaitAnimation: // 并行器里不应该出现等待动画结束,立即结束本次迭代 return; case StackMachineState.Await: paraGameState = GameState.Waiting; resumeFlag = true; break; case StackMachineState.Interrupt: LogUtils.LogLine( "There is a interrupt in parallel function, which may cause system pause", "Director", LogLevel.Warning); paraGameState = GameState.Interrupt; resumeFlag = false; break; case StackMachineState.NOP: paraGameState = GameState.Exit; resumeFlag = true; break; } // 根据调用堆栈顶部更新系统 switch (paraGameState) { // 等待状态 case GameState.Waiting: // 计算已经等待的时间 if (DateTime.Now - paraVM.ESP.TimeStamp > paraVM.ESP.Delay) { paraVM.Consume(); } break; // 等待动画 case GameState.WaitAni: if (SpriteAnimation.IsAnyAnimation == false) { paraVM.Consume(); } break; // 演绎脚本 case GameState.Performing: // 取下一动作 var nextInstruct = Director.RunMana.MoveNext(paraVM); // 如果指令空了就立即迭代本次消息循环 if (nextInstruct == null) { dispatcher.Start(); return; } // 处理影响调用堆栈的动作 if (nextInstruct.Type == SActionType.act_wait) { double waitMs = nextInstruct.ArgsDict.ContainsKey("time") ? (double)PolishEvaluator.Evaluate(nextInstruct.ArgsDict["time"], paraVM) : 0; paraVM.Submit("Parallel Time Waiting", DateTime.Now, TimeSpan.FromMilliseconds(waitMs)); break; } else if (nextInstruct.Type == SActionType.act_waitani) { // 并行器里不应该出现等待动画结束,立即结束本次迭代 LogUtils.LogLine( "There is a animation wait in parallel function, which may cause system pause", "Director", LogLevel.Warning); break; } else if (nextInstruct.Type == SActionType.act_waituser) { LogUtils.LogLine( "There is a user wait in parallel function, which may cause system pause", "Director", LogLevel.Warning); paraVM.Submit("Director", nextInstruct.NodeName); break; } else if (nextInstruct.Type == SActionType.act_jump) { var jumpToScene = nextInstruct.ArgsDict["filename"]; var jumpToTarget = nextInstruct.ArgsDict["target"]; // 场景内跳转 if (jumpToScene == String.Empty) { if (stackState == StackMachineState.Interpreting) { var currentScene = this.resMana.GetScene(paraVM.ESP.BindingSceneName); if (!currentScene.LabelDictionary.ContainsKey(jumpToTarget)) { LogUtils.LogLine( String.Format("Ignored Jump Instruction (target not exist): {0}", jumpToTarget), "Director", LogLevel.Error); break; } paraVM.ESP.MircoStep(currentScene.LabelDictionary[jumpToTarget]); } else if (stackState == StackMachineState.FunctionCalling) { var currentFunc = paraVM.ESP.BindingFunction; if (!currentFunc.LabelDictionary.ContainsKey(jumpToTarget)) { LogUtils.LogLine( String.Format("Ignored Jump Instruction (target not exist): {0}", jumpToTarget), "Director", LogLevel.Error); break; } paraVM.ESP.MircoStep(currentFunc.LabelDictionary[jumpToTarget]); } } // 跨场景跳转 else { LogUtils.LogLine( "There is a jump across scene in parallel function, it will be ignored", "Director", LogLevel.Warning); } break; } else if (nextInstruct.Type == SActionType.act_call) { var callFunc = nextInstruct.ArgsDict["name"]; var signFunc = nextInstruct.ArgsDict["sign"]; this.FunctionCalling(callFunc, signFunc, paraVM); break; } // 处理常规动作 pdap.Render.Execute(nextInstruct); break; // 系统中断 case GameState.Interrupt: var interruptSa = paraVM.ESP.IP; var interruptExitPoint = paraVM.ESP.Tag; // 退出中断 var pureInt = paraVM.ESP.BindingInterrupt.PureInterrupt; var interruptFuncCalling = paraVM.ESP.BindingInterrupt.InterruptFuncSign; var needExitWait = paraVM.ESP.BindingInterrupt.ExitWait; Director.RunMana.ExitCall(paraVM); // 处理中断优先动作 if (interruptSa != null) { if (interruptSa.Type == SActionType.act_waituser) { LogUtils.LogLine( "There is a user wait in parallel function, which may cause system pause", "Director", LogLevel.Warning); paraVM.Submit("Director", interruptSa.NodeName); break; } else { var iterSa = interruptSa; while (iterSa != null) { pdap.Render.Execute(interruptSa); iterSa = iterSa.Next; } } } // 判断中断是否需要处理后续动作 if (pureInt) { break; } // 跳出所有用户等待 if (needExitWait || interruptExitPoint != String.Empty) { while (paraVM.Count() > 0 && paraVM.ESP.State == StackMachineState.WaitUser) { Director.RunMana.ExitCall(paraVM); } } // 处理跳转(与中断调用互斥) if (interruptExitPoint != String.Empty) { RunnableYuriri curRunnable; if (paraVM.EBP.BindingFunction == null) { curRunnable = this.resMana.GetScene(paraVM.EBP.BindingSceneName); } else { curRunnable = paraVM.EBP.BindingFunction; } if (!curRunnable.LabelDictionary.ContainsKey(interruptExitPoint)) { LogUtils.LogLine(String.Format("Ignored parallel Interrupt jump Instruction (target not exist): {0}", interruptExitPoint), "Director", LogLevel.Error); break; } paraVM.EBP.MircoStep(curRunnable.LabelDictionary[interruptExitPoint]); } // 处理中断函数调用 else if (interruptFuncCalling != String.Empty) { var ifcItems = interruptFuncCalling.Split('('); var funPureName = ifcItems[0]; var funParas = "(" + ifcItems[1]; this.FunctionCalling(funPureName, funParas, paraVM); } break; // 退出(其实就是执行完毕了一轮,应该重新开始) case GameState.Exit: if (pdap.IsSemaphore == false) { paraVM.Submit(pdap.BindingSF, new List <object>()); } else { switch (pdap.SemaphoreType) { case SemaphoreHandlerType.ScheduleOnce: return; case SemaphoreHandlerType.ScheduleForever: paraVM.Submit(pdap.BindingSF, new List <object>()); break; case SemaphoreHandlerType.ScheduleWhenActivated: throw new NotImplementedException(); } } break; } if (resumeFlag) { break; } } if (resumeFlag) { dispatcher.Start(); } }
/// <summary> /// 处理消息循环 /// </summary> private void UpdateContext(object sender, EventArgs e) { bool resumeFlag = true; this.timer.Stop(); while (true) { // 取得调用堆栈顶部状态 StackMachineState stackState = Director.RunMana.GameState(Director.RunMana.CallStack); switch (stackState) { case StackMachineState.Interpreting: case StackMachineState.FunctionCalling: this.curState = GameState.Performing; resumeFlag = false; break; case StackMachineState.WaitUser: this.curState = GameState.WaitForUserInput; resumeFlag = true; break; case StackMachineState.WaitAnimation: this.curState = GameState.WaitAni; resumeFlag = true; break; case StackMachineState.Await: this.curState = GameState.Waiting; resumeFlag = true; break; case StackMachineState.Interrupt: this.curState = GameState.Interrupt; resumeFlag = false; break; case StackMachineState.AutoWait: this.curState = GameState.AutoPlay; resumeFlag = true; break; case StackMachineState.NOP: this.curState = GameState.Exit; resumeFlag = true; break; } // 根据调用堆栈顶部更新系统 switch (this.curState) { // 等待状态 case GameState.Waiting: // 计算已经等待的时间 if (DateTime.Now - Director.RunMana.CallStack.ESP.TimeStamp > Director.RunMana.CallStack.ESP.Delay) { Director.RunMana.ExitCall(Director.RunMana.CallStack); } break; // 等待动画 case GameState.WaitAni: if (SpriteAnimation.IsAnyAnimation == false && SCamera2D.IsAnyAnimation == false && SCamera3D.IsAnyAnimation == false) { Director.RunMana.ExitCall(Director.RunMana.CallStack); } break; // 自动播放 case GameState.AutoPlay: // 等待动画和延时 if (DateTime.Now - Director.RunMana.CallStack.ESP.TimeStamp > Director.RunMana.CallStack.ESP.Delay && SpriteAnimation.IsAnyAnimation == false && SCamera2D.IsAnyAnimation == false && SCamera3D.IsAnyAnimation == false && Director.IsRClicking == false && Musician.IsVoicePlaying == false && SemaphoreDispatcher.GetSemaphoreState("System_PreviewShutdown") == false && ViewPageManager.IsAtMainStage() == true) { this.updateRender.IsShowingDialog = false; this.updateRender.dialogPreStr = String.Empty; if (this.updateRender.IsContinousDialog == false) { ViewManager.GetInstance().GetMessageLayer(0).Visibility = Visibility.Hidden; this.updateRender.HideMessageTria(); } Director.RunMana.ExitCall(Director.RunMana.CallStack); } break; // 等待用户操作 case GameState.WaitForUserInput: break; // 中断 case GameState.Interrupt: var interruptSa = Director.RunMana.CallStack.ESP.IP; var interruptExitPoint = Director.RunMana.CallStack.ESP.Tag; // 退出中断 var pureInt = Director.RunMana.CallStack.ESP.BindingInterrupt.PureInterrupt; var interruptFuncCalling = Director.RunMana.CallStack.ESP.BindingInterrupt.InterruptFuncSign; var needExitWait = Director.RunMana.CallStack.ESP.BindingInterrupt.ExitWait; Director.RunMana.ExitCall(Director.RunMana.CallStack); // 处理中断优先动作 if (interruptSa != null) { if (interruptSa.Type == SActionType.act_waituser) { Director.RunMana.UserWait("Director", interruptSa.NodeName); } else { var iterSa = interruptSa; while (iterSa != null) { this.updateRender.Execute(interruptSa); iterSa = iterSa.Next; } } } // 判断中断是否需要处理后续动作 if (pureInt) { break; } // 跳出所有用户等待 if (needExitWait || interruptExitPoint != String.Empty) { Director.RunMana.ExitUserWait(); } // 处理跳转(与中断调用互斥) if (interruptExitPoint != String.Empty) { RunnableYuriri curRunnable; if (Director.RunMana.CallStack.EBP.BindingFunction == null) { curRunnable = this.resMana.GetScene(Director.RunMana.CallStack.EBP.BindingSceneName); } else { curRunnable = Director.RunMana.CallStack.EBP.BindingFunction; } if (!curRunnable.LabelDictionary.ContainsKey(interruptExitPoint)) { LogUtils.LogLine(String.Format("Ignored Interrupt jump Instruction (target not exist): {0}", interruptExitPoint), "Director", LogLevel.Error); break; } Director.RunMana.CallStack.EBP.MircoStep(curRunnable.LabelDictionary[interruptExitPoint]); } // 处理中断函数调用 else if (interruptFuncCalling != String.Empty) { var ifcItems = interruptFuncCalling.Split('('); var funPureName = ifcItems[0]; var funParas = "(" + ifcItems[1]; this.FunctionCalling(funPureName, funParas, Director.RunMana.CallStack); } break; // 演绎脚本 case GameState.Performing: // 取下一动作 var nextInstruct = Director.RunMana.MoveNext(Director.RunMana.CallStack); // 如果指令空了就立即迭代本次消息循环 if (nextInstruct == null) { this.timer.Start(); return; } // 处理影响调用堆栈的动作 if (nextInstruct.Type == SActionType.act_wait) { double waitMs = nextInstruct.ArgsDict.ContainsKey("time") ? (double)PolishEvaluator.Evaluate(nextInstruct.ArgsDict["time"], Director.RunMana.CallStack) : 0; Director.RunMana.Delay(nextInstruct.NodeName, DateTime.Now, TimeSpan.FromMilliseconds(waitMs)); break; } else if (nextInstruct.Type == SActionType.act_waitani) { Director.RunMana.AnimateWait(nextInstruct.NodeName); break; } else if (nextInstruct.Type == SActionType.act_waituser) { Director.RunMana.UserWait("Director", nextInstruct.NodeName); break; } else if (nextInstruct.Type == SActionType.act_jump) { var jumpToScene = nextInstruct.ArgsDict["filename"]; var jumpToTarget = nextInstruct.ArgsDict["target"]; // 场景内跳转 if (jumpToScene == String.Empty) { if (stackState == StackMachineState.Interpreting) { var currentScene = this.resMana.GetScene(Director.RunMana.CallStack.ESP.BindingSceneName); if (!currentScene.LabelDictionary.ContainsKey(jumpToTarget)) { LogUtils.LogLine( String.Format("Ignored Jump Instruction (target not exist): {0}", jumpToTarget), "Director", LogLevel.Error); break; } Director.RunMana.CallStack.ESP.MircoStep(currentScene.LabelDictionary[jumpToTarget]); } else if (stackState == StackMachineState.FunctionCalling) { var currentFunc = Director.RunMana.CallStack.ESP.BindingFunction; if (!currentFunc.LabelDictionary.ContainsKey(jumpToTarget)) { LogUtils.LogLine( String.Format("Ignored Jump Instruction (target not exist): {0}", jumpToTarget), "Director", LogLevel.Error); break; } Director.RunMana.CallStack.ESP.MircoStep(currentFunc.LabelDictionary[jumpToTarget]); } } // 跨场景跳转 else { var jumpScene = this.resMana.GetScene(jumpToScene); if (jumpScene == null) { LogUtils.LogLine( String.Format("Ignored Jump Instruction (scene not exist): {0}", jumpToScene), "Director", LogLevel.Error); break; } if (jumpToTarget != String.Empty && !jumpScene.LabelDictionary.ContainsKey(jumpToTarget)) { LogUtils.LogLine( String.Format("Ignored Jump Instruction (target not exist): {0} -> {1}", jumpToScene, jumpToTarget), "Director", LogLevel.Error); break; } Director.RunMana.ExitCall(Director.RunMana.CallStack); Director.RunMana.CallScene(jumpScene, jumpToTarget == String.Empty ? jumpScene.Ctor : jumpScene.LabelDictionary[jumpToTarget]); } break; } else if (nextInstruct.Type == SActionType.act_call) { var callFunc = nextInstruct.ArgsDict["name"]; var signFunc = nextInstruct.ArgsDict["sign"]; this.FunctionCalling(callFunc, signFunc, Director.RunMana.CallStack); break; } // 处理常规动作 this.updateRender.Execute(nextInstruct); break; // 退出 case GameState.Exit: this.updateRender.Shutdown(); break; } // 处理IO this.updateRender.UpdateForMouseState(); // 是否恢复消息循环 if (resumeFlag) { break; } } if (resumeFlag) { this.timer.Start(); } }