/// <summary> /// 事件:键盘即将按下按钮 /// </summary> private void window_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.SystemKey == Key.LeftAlt || e.SystemKey == Key.RightAlt) { MainWindow.altDown = true; } else if (e.SystemKey == Key.F4 && MainWindow.altDown) { this.world.GetMainRender().Shutdown(); } else if (e.SystemKey == Key.Enter && MainWindow.altDown && this.IsKeyAltWindowSizeEnabled) { if (Director.IsFullScreen) { Director.IsFullScreen = !Director.IsFullScreen; this.WindowScreenTransform(); } else { Director.IsFullScreen = !Director.IsFullScreen; this.FullScreenTransform(); } } SemaphoreDispatcher.Activate($"System_Key_{e.Key}"); }
/// <summary> /// 事件:键盘即将松开按钮 /// </summary> private void window_PreviewKeyUp(object sender, KeyEventArgs e) { if (e.SystemKey == Key.LeftAlt || e.SystemKey == Key.RightAlt) { MainWindow.altDown = false; } SemaphoreDispatcher.Deactivate($"System_Key_{e.Key}"); }
/// <summary> /// 初始化运行时环境,并指定脚本的入口 /// </summary> private void InitRuntime() { var mainScene = this.resMana.GetScene(GlobalConfigContext.Script_Main); if (mainScene == null) { LogUtils.LogLine(String.Format("No Entry Point Scene: {0}, Program will exit.", GlobalConfigContext.Script_Main), "Director", LogLevel.Error); this.updateRender.Shutdown(); } this.resMana.GetAllScene().ForEach(t => Director.RunMana.Symbols.AddSceneSymbolContext(t)); Director.RunMana.CallScene(mainScene); SemaphoreDispatcher.InitSystemSemaphore(); }
/// <summary> /// 立即结束本次调用 /// </summary> /// <param name="svm">要作用的调用堆栈</param> public void ExitCall(StackMachine svm) { // 弹调用堆栈 var consumed = svm.Consume(); // 弹出的是主堆栈上的场景 if (svm == this.CallStack && consumed.State == StackMachineState.Interpreting) { // 恢复到上一个并行栈帧的状态 this.BackTraceParallel(); // 关闭当前的信号量订阅者 SemaphoreDispatcher.UnregisterSemaphoreService(); } }
/// <summary> /// 提供精灵按钮鼠标离开时的处理函数 /// </summary> /// <param name="sender">触发者</param> /// <param name="e">鼠标参数</param> public void MouseLeaveHandler(object sender, MouseEventArgs e) { if (this.Enable) { this.IsMouseOver = this.IsMouseOn = false; SemaphoreDispatcher.Deactivate($"System_Button_Over_{this.Id}"); if (this.DisplayBinding != null && (this.ImageMouseOver != null || this.ImageMouseOn != null)) { BitmapImage myBitmapImage = this.ImageNormal.SpriteBitmapImage; //this.ImageNormal.DisplayBinding = this.DisplayBinding; this.DisplayBinding.Width = myBitmapImage.PixelWidth; this.DisplayBinding.Height = myBitmapImage.PixelHeight; this.DisplayBinding.Source = myBitmapImage; } } }
/// <summary> /// 事件:窗体关闭 /// </summary> private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { if (!ViewPageManager.IsAtMainStage()) { SplashPage.LoadingExitFlag = true; Director.CollapseWorld(); return; } if (SemaphoreDispatcher.CountBinding("System_PreviewShutdown") > 0) { e.Cancel = true; SemaphoreDispatcher.Activate("System_PreviewShutdown"); } else { Director.CollapseWorld(); } }
/// <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(); } }
/// <summary> /// 设置运行时环境管理器,用于读取保存的信息 /// </summary> /// <param name="rm">反序列化后的RM实例</param> public static void ResumeFromSaveData(RuntimeManager rm) { // 停止消息循环 Director.PauseUpdateContext(); // 清空回滚器 RollbackManager.Clear(); // 清空画面 ViewManager.GetInstance().RemoveView(ResourceType.Unknown); // 检查是否需要回滚当前的并行处理 Director.RunMana.StopAllParallel(); // 变更运行时环境 Director.RunMana = rm; Director.RunMana.ParallelHandler = Director.GetInstance().ParallelUpdateContext; SymbolTable.ResetSynObject(Director.RunMana.Symbols); LogUtils.LogLine("RuntimeManager is replaced", "Director", LogLevel.Important); // 缓存指令指针 var irname = rm.CallStack.ESP.IR; var isname = rm.CallStack.ESP.BindingSceneName; rm.CallStack.ESP.MircoStep(Director.GetInstance().resMana.GetScene(isname).YuriDict[irname]); // 变更屏幕管理器 ScreenManager.ResetSynObject(Director.RunMana.Screen); LogUtils.LogLine("ScreenManager is replaced", "Director", LogLevel.Important); // 重绘整个画面 ViewManager.GetInstance().ReDraw(); // 重新绑定渲染器的作用堆栈 UpdateRender render = Director.GetInstance().updateRender; render.VsmReference = Director.RunMana.CallStack; // 恢复背景音乐 if (GlobalConfigContext.UseBassEngine) { MusicianBass.GetInstance().RePerform(Director.RunMana.Musics); } else { Musician.GetInstance().RePerform(Director.RunMana.Musics); } // 清空字符串缓冲 render.dialogPreStr = String.Empty; render.pendingDialogQueue.Clear(); // 关闭自动播放 Director.RunMana.IsAutoplaying = false; // 弹空全部等待,复现保存最后一个动作 Director.RunMana.ExitUserWait(); Interrupt reactionNtr = new Interrupt() { Type = InterruptType.LoadReaction, Detail = "Reaction for load data", InterruptSA = Director.RunMana.DashingPureSa, InterruptFuncSign = String.Empty, ReturnTarget = null, PureInterrupt = true }; // 提交中断 Director.RunMana.CallStack.Submit(reactionNtr); // 重启并行调度系统 var sc = ResourceManager.GetInstance().GetScene(Director.RunMana.CallStack.EBP.BindingSceneName); Director.RunMana.ParallelExecutorStack = new Stack <List <ParallelExecutor> >(); Director.RunMana.ConstructParallel(sc); Director.RunMana.RestartParallel(); Director.RunMana.LastScenario = sc.Scenario; // 重启信号分发系统 SemaphoreDispatcher.ReBinding(sc, Director.RunMana.SemaphoreBindings); // 重启主调用堆栈上的消息循环 Director.ResumeUpdateContext(); }
/// <summary> /// 将系统跳转到指定的稳定状态 /// </summary> /// <param name="ssp">要演绎的状态包装</param> public static void GotoSteadyState(RollbackableSnapshot ssp) { // 停止消息循环 Director.PauseUpdateContext(); // 结束全部动画 SpriteAnimation.ClearAnimateWaitingDict(); // 检查是否需要回滚当前的并行处理和信号绑定 bool needRepara = false; if (ssp.VMRef.ESP.BindingSceneName != Director.RunMana.CallStack.SAVEP.BindingSceneName) { Director.RunMana.PauseParallel(); needRepara = true; } // 退到SSP所描述的状态 SymbolTable.GetInstance().SetDAO(ssp.sceneDao.Fork() as SceneContextDAO, ssp.globalDao.Fork() as GlobalContextDAO); ScreenManager.ResetSynObject(ssp.ScreenStateRef.Fork() as ScreenManager); Director.RunMana.ResetCallstackObject(ssp.VMRef.Fork() as StackMachine); Director.RunMana.Backlogs = ForkableState.DeepCopyBySerialization(ssp.BacklogRef); Director.RunMana.Musics = ForkableState.DeepCopyBySerialization(ssp.MusicRef); Director.RunMana.DashingPureSa = ssp.ReactionRef.Clone(true); Director.RunMana.SemaphoreBindings = ForkableState.DeepCopyBySerialization(ssp.SemaphoreDict); Director.RunMana.EnableRClick = ssp.EnableRClickRef; Director.RunMana.PerformingChapter = ssp.PerformingChapterRef; Director.ScrMana = ScreenManager.GetInstance(); // 刷新主渲染器上的堆栈绑定 Director.GetInstance().RefreshMainRenderVMReference(); Director.GetInstance().GetMainRender().IsBranching = ssp.IsBranchingRefer; // 重绘整个画面 ViewManager.GetInstance().ReDraw(true); // 恢复音效 UpdateRender render = Director.GetInstance().GetMainRender(); if (GlobalConfigContext.UseBassEngine) { MusicianBass.GetInstance().RePerform(Director.RunMana.Musics); } else { Musician.GetInstance().RePerform(Director.RunMana.Musics); } // 清空字符串缓冲 render.dialogPreStr = String.Empty; render.pendingDialogQueue.Clear(); // 关闭自动播放 Director.RunMana.IsAutoplaying = false; // 弹空全部等待,复现保存最后一个动作 Director.RunMana.ExitUserWait(); Interrupt reactionNtr = new Interrupt() { Type = InterruptType.LoadReaction, Detail = "Reaction for rollback", InterruptSA = ssp.ReactionRef, InterruptFuncSign = String.Empty, ReturnTarget = null, PureInterrupt = true }; // 提交中断到主调用堆栈 Director.RunMana.CallStack.Submit(reactionNtr); // 重启并行处理和信号系统 if (needRepara) { var sc = ResourceManager.GetInstance().GetScene(ssp.VMRef.EBP.BindingSceneName); Director.RunMana.ConstructParallelForRollingBack(sc); Director.RunMana.BackTraceParallel(); Director.RunMana.LastSceneName = sc.Scenario; SemaphoreDispatcher.ReBinding(sc, Director.RunMana.SemaphoreBindings); } // 重启消息循环 Director.ResumeUpdateContext(); }