private void HandleKeyPress(ScummInputState kbd, StringBuilder textBuf) { if (kbd.IsKeyDown(KeyCode.Backspace)) { // backspace if (textBuf.Length > 0) textBuf.Remove(textBuf.Length - 1, 1); } else { // TODO: do this in ScummInputState ? var key = (char?)kbd.GetKeys().Where(k => k >= (KeyCode)32 && k <= (KeyCode)126).Select(k => (KeyCode?)k).FirstOrDefault(); if (!key.HasValue) return; // Cannot enter text wider than the save/load panel if (_enteredTextWidth >= PanLineWidth - 10) return; // Cannot enter text longer than MaxTextLen-1 chars, since // the storage is only so big. Note: The code used to incorrectly // allow up to MaxTextLen, which caused an out of bounds access, // overwriting the next entry in the list of savegames partially. // This could be triggered by e.g. entering lots of periods ".". if (textBuf.Length >= MaxTextLen - 1) return; // Allow the key only if is a letter, a digit, or one of a selected // list of extra characters if (char.IsLetterOrDigit(key.Value) || " ,().='-&+!?\"".Contains(key.Value.ToString())) { textBuf.Append(key); } } }
private ushort SaveRestorePanel(bool allowSave) { _keyPressed = new ScummInputState(); _system.InputManager.ResetKeys(); _mouseWheel = 0; ButtonControl(null); _text.DrawToScreen(WithMask); // flush text restore buffer ConResource[] lookList; ushort cnt; byte lookListLen; if (allowSave) { lookList = _savePanLookList; lookListLen = 6; _system.InputManager.ShowVirtualKeyboard(); } else { lookList = _restorePanLookList; if (AutoSaveExists()) lookListLen = 7; else lookListLen = 6; } bool withAutoSave = lookListLen == 7; var textSprites = new byte[MaxOnScreen + 1][]; _firstText = 0; var saveGameTexts = LoadDescriptions().Select(s => new StringBuilder(s)).ToArray(); _selectedGame = 0; bool quitPanel = false; bool refreshNames = true; bool refreshAll = true; ushort clickRes = 0; while (!quitPanel && !SkyEngine.ShouldQuit) { clickRes = 0; if (refreshNames || refreshAll) { if (refreshAll) { _text.FlushForRedraw(); _savePanel.DrawToScreen(NoMask); _quitButton.DrawToScreen(NoMask); if (withAutoSave) _autoSaveButton.DrawToScreen(NoMask); refreshAll = false; } for (cnt = 0; cnt < MaxOnScreen; cnt++) if (textSprites[cnt] != null) textSprites[cnt] = null; SetUpGameSprites(saveGameTexts, textSprites, _firstText, _selectedGame); ShowSprites(textSprites, allowSave); refreshNames = false; } _text.DrawToScreen(WithMask); _system.GraphicsManager.UpdateScreen(); _mouseClicked = false; Delay(50); if (_controlPanel == null) return clickRes; if (_keyPressed.IsKeyDown(KeyCode.Escape)) { // escape pressed _mouseClicked = false; clickRes = CancelPressed; quitPanel = true; } else if (_keyPressed.IsKeyDown(KeyCode.Return)) // TODO: || _keyPressed.IsKeyDown(KeyCode.Enter) { clickRes = HandleClick(lookList[0]); if (_controlPanel == null) //game state was destroyed return clickRes; if (clickRes == GameSaved) SaveDescriptions(saveGameTexts); else if (clickRes == NoDiskSpace) { // TODO: DisplayMessage(0, "Could not save the game. (%s)", _saveFileMan.popErrorDesc().c_str()); } quitPanel = true; _mouseClicked = false; _keyPressed = new ScummInputState(); _system.InputManager.ResetKeys(); } if (allowSave && _keyPressed.GetKeys().Count > 0) { HandleKeyPress(_keyPressed, saveGameTexts[_selectedGame]); refreshNames = true; _keyPressed = new ScummInputState(); _system.InputManager.ResetKeys(); } if (_mouseWheel != 0) { if (_mouseWheel < 0) clickRes = ShiftUp(Slow); else if (_mouseWheel > 0) clickRes = ShiftDown(Slow); _mouseWheel = 0; if (clickRes == Shifted) { _selectedGame = _firstText; refreshNames = true; } } bool haveButton = false; var mouse = _system.InputManager.GetMousePosition(); for (cnt = 0; cnt < lookListLen; cnt++) if (lookList[cnt].IsMouseOver((uint)mouse.X, (uint)mouse.Y)) { ButtonControl(lookList[cnt]); haveButton = true; if (_mouseClicked && lookList[cnt].OnClick != 0) { _mouseClicked = false; clickRes = HandleClick(lookList[cnt]); if (_controlPanel == null) //game state was destroyed return clickRes; if (clickRes == Shifted) { _selectedGame = _firstText; refreshNames = true; } if (clickRes == NoDiskSpace) { // TODO: DisplayMessage(0, "Could not save the game. (%s)", _saveFileMan.popErrorDesc().c_str()); quitPanel = true; } if ((clickRes == CancelPressed) || (clickRes == GameRestored)) quitPanel = true; if (clickRes == GameSaved) { SaveDescriptions(saveGameTexts); quitPanel = true; } if (clickRes == RestoreFailed) refreshAll = true; } } if (_mouseClicked) { if ((mouse.X >= GameNameX) && (mouse.X <= GameNameX + PanLineWidth) && (mouse.Y >= GameNameY) && (mouse.Y <= GameNameY + PanCharHeight * MaxOnScreen)) { _selectedGame = (ushort)((mouse.Y - GameNameY) / PanCharHeight + _firstText); refreshNames = true; } } if (!haveButton) ButtonControl(null); } for (cnt = 0; cnt < MaxOnScreen + 1; cnt++) textSprites[cnt] = null; if (allowSave) { _system.InputManager.HideVirtualKeyboard(); } return clickRes; }
internal protected virtual void ProcessInput() { // // Determine the mouse button state. // mouseAndKeyboardStat = 0; if (_leftBtnPressed.HasFlag(MouseButtonStatus.Clicked) && _rightBtnPressed.HasFlag(MouseButtonStatus.Clicked)) { // Pressing both mouse buttons is treated as if you pressed // the cutscene exit key (ESC) in V4+ games. That mimicks // the behavior of the original engine where pressing both // mouse buttons also skips the current cutscene. mouseAndKeyboardStat = 0; // lastKeyHit = Common::KeyState(Common::KEYCODE_ESCAPE); } else if (_rightBtnPressed.HasFlag(MouseButtonStatus.Clicked) && (Game.Version <= 3 && Game.GameId != GameId.Loom)) { // Pressing right mouse button is treated as if you pressed // the cutscene exit key (ESC) in V0-V3 games. That mimicks // the behavior of the original engine where pressing right // mouse button also skips the current cutscene. mouseAndKeyboardStat = 0; // lastKeyHit = Common::KeyState(Common::KEYCODE_ESCAPE); } else if (_leftBtnPressed.HasFlag(MouseButtonStatus.Clicked)) { mouseAndKeyboardStat = (KeyCode)ScummMouseButtonState.LeftClick; } else if (_rightBtnPressed.HasFlag(MouseButtonStatus.Clicked)) { mouseAndKeyboardStat = (KeyCode)ScummMouseButtonState.RightClick; } if (Game.Version >= 6) { Variables[VariableLeftButtonHold.Value] = _leftBtnPressed.HasFlag(MouseButtonStatus.Down) ? 1 : 0; Variables[VariableRightButtonHold.Value] = _rightBtnPressed.HasFlag(MouseButtonStatus.Down) ? 1 : 0; // scumm7: left/right button down if (Game.Version >= 7) { Variables[VariableLeftButtonDown.Value] = _leftBtnPressed.HasFlag(MouseButtonStatus.Clicked) ? 1 : 0; Variables[VariableRightButtonDown.Value] = _rightBtnPressed.HasFlag(MouseButtonStatus.Clicked) ? 1 : 0; } } _leftBtnPressed &= ~MouseButtonStatus.Clicked; _rightBtnPressed &= ~MouseButtonStatus.Clicked; var cutsceneExitKeyEnabled = (!VariableCutSceneExitKey.HasValue || Variables[VariableCutSceneExitKey.Value] != 0); var mainmenuKeyEnabled = !VariableMainMenu.HasValue || _variables[VariableMainMenu.Value] != 0; // For games which use VAR_MAINMENU_KEY, disable the mainmenu key if // requested by the scripts. We make an exception for COMI (i.e. // forcefully always enable it there), as that always disables it. if (Game.GameId == GameId.CurseOfMonkeyIsland) { mainmenuKeyEnabled = true; } if (cutsceneExitKeyEnabled && _inputState.IsKeyDown(KeyCode.Escape)) { AbortCutscene(); // VAR_CUTSCENEEXIT_KEY doesn't exist in SCUMM0 if (VariableCutSceneExitKey.HasValue) { mouseAndKeyboardStat = (KeyCode)Variables[VariableCutSceneExitKey.Value]; } } if (mainmenuKeyEnabled && _inputState.IsKeyDown(KeyCode.F5)) { if (VariableSaveLoadScript.HasValue && _currentRoom != 0) { RunScript(Variables[VariableSaveLoadScript.Value], false, false, new int[0]); } ShowMenu(); if (VariableSaveLoadScript2.HasValue && _currentRoom != 0) { RunScript(Variables[VariableSaveLoadScript2.Value], false, false, new int[0]); } } for (var i = KeyCode.A; i <= KeyCode.Z; i++) { if (_inputState.IsKeyDown(i)) { mouseAndKeyboardStat = i; } } for (var i = KeyCode.F1; i <= KeyCode.F9; i++) { if (_inputState.IsKeyDown(i)) { mouseAndKeyboardStat = i; } } if (_inputState.IsKeyDown(KeyCode.Return)) { mouseAndKeyboardStat = KeyCode.Return; } if (_inputState.IsKeyDown(KeyCode.Backspace)) { mouseAndKeyboardStat = KeyCode.Backspace; } if (_inputState.IsKeyDown(KeyCode.Tab)) { mouseAndKeyboardStat = KeyCode.Tab; } if (_inputState.IsKeyDown(KeyCode.Space)) { mouseAndKeyboardStat = KeyCode.Space; } if ((Game.GameId == Scumm.IO.GameId.Indy4 || Game.GameId == Scumm.IO.GameId.Pass)) { var numpad = new int[] { '0', 335, 336, 337, 331, 332, 333, 327, 328, 329 }; for (var i = KeyCode.D0; i <= KeyCode.D9; i++) { if (_inputState.IsKeyDown(i)) { mouseAndKeyboardStat = (KeyCode)numpad[i - KeyCode.D0]; } } } else { for (var i = KeyCode.D0; i <= KeyCode.D9; i++) { if (_inputState.IsKeyDown(i)) { mouseAndKeyboardStat = i - (int)KeyCode.D0 + '0'; } } } _mousePos = _inputManager.GetMousePosition(); if (_mousePos.X < 0) { _mousePos.X = 0; } if (_mousePos.X > ScreenWidth - 1) { _mousePos.X = (short)(ScreenWidth - 1); } if (_mousePos.Y < 0) { _mousePos.Y = 0; } if (_mousePos.Y > ScreenHeight - 1) { _mousePos.Y = (short)(ScreenHeight - 1); } var mouseX = (ScreenStartStrip * 8) + _mousePos.X; var mouseY = _mousePos.Y - MainVirtScreen.TopLine + ((_game.Version >= 7) ? ScreenTop : 0); if (Game.Version >= 3) { Variables[VariableMouseX.Value] = _mousePos.X; Variables[VariableMouseY.Value] = _mousePos.Y; Variables[VariableVirtualMouseX.Value] = mouseX; Variables[VariableVirtualMouseY.Value] = mouseY; } else if (Game.Version >= 1) { // We use shifts below instead of dividing by V12_X_MULTIPLIER resp. // V12_Y_MULTIPLIER to handle negative coordinates correctly. // This fixes e.g. bugs #1328131 and #1537595. Variables[VariableVirtualMouseX.Value] = mouseX >> V12_X_SHIFT; Variables[VariableVirtualMouseY.Value] = mouseY >> V12_Y_SHIFT; // Adjust mouse coordinates as narrow rooms in NES are centered // if (_game.platform == Common::kPlatformNES && _NESStartStrip > 0) // { // VAR(VAR_VIRT_MOUSE_X) -= 2; // if (VAR(VAR_VIRT_MOUSE_X) < 0) // VAR(VAR_VIRT_MOUSE_X) = 0; // } } }
private byte MainLoop() { byte retCode = 0; System.InputManager.ResetKeys(); while ((retCode == 0) && !ShouldQuit) { // do we need the section45-hack from sword.c here? CheckCd(); _screen.NewScreen(Logic.ScriptVars[(int)ScriptVariableNames.NEW_SCREEN]); _logic.NewScreen(Logic.ScriptVars[(int)ScriptVariableNames.NEW_SCREEN]); _sound.NewScreen(Logic.ScriptVars[(int)ScriptVariableNames.NEW_SCREEN]); Logic.ScriptVars[(int)ScriptVariableNames.SCREEN] = Logic.ScriptVars[(int)ScriptVariableNames.NEW_SCREEN]; do { int newTime; bool scrollFrameShown = false; int frameTime = Environment.TickCount; _logic.Engine(); _logic.UpdateScreenParams(); // sets scrolling _screen.Draw(); _mouse.Animate(); _sound.Engine(); _menu.Refresh(Menu.MENU_TOP); _menu.Refresh(Menu.MENU_BOT); newTime = Environment.TickCount; if (newTime - frameTime < 1000 / FRAME_RATE) { scrollFrameShown = _screen.ShowScrollFrame(); Delay(1000 / (FRAME_RATE * 2) - (Environment.TickCount - frameTime)); } newTime = Environment.TickCount; if ((newTime - frameTime < 1000 / FRAME_RATE) || !scrollFrameShown) { _screen.UpdateScreen(); } Delay(1000 / FRAME_RATE - (Environment.TickCount - frameTime)); _mouse.Engine((ushort)_mouseCoord.X, (ushort)_mouseCoord.Y, _mouseState); if (SystemVars.ForceRestart) { retCode = Control.CONTROL_RESTART_GAME; } // The control panel is triggered by F5 or ESC. else if (((_keyPressed.IsKeyDown(KeyCode.F5) || _keyPressed.IsKeyDown(KeyCode.Escape)) && (Logic.ScriptVars[(int)ScriptVariableNames.MOUSE_STATUS] & 1) != 0) || (SystemVars.ControlPanelMode != 0)) { retCode = _control.RunPanel(); if (retCode == Control.CONTROL_NOTHING_DONE) { _screen.FullRefresh(); } } // TODO: Check for Debugger Activation //if (_keyPressed.hasFlags(Common::KBD_CTRL) && _keyPressed.keycode == Common::KEYCODE_d) //{ // this.getDebugger().attach(); // this.getDebugger().onFrame(); //} _mouseState = 0; _keyPressed = new ScummInputState(); } while ((Logic.ScriptVars[(int)ScriptVariableNames.SCREEN] == Logic.ScriptVars[(int)ScriptVariableNames.NEW_SCREEN]) && (retCode == 0) && !ShouldQuit); if ((retCode == 0) && (Logic.ScriptVars[(int)ScriptVariableNames.SCREEN] != 53) && SystemVars.WantFade && !ShouldQuit) { _screen.FadeDownPalette(); int relDelay = Environment.TickCount; while (_screen.StillFading()) { relDelay += 1000 / FRAME_RATE; _screen.UpdateScreen(); Delay(relDelay - Environment.TickCount); } } _sound.QuitScreen(); _screen.QuitScreen(); // close graphic resources _objectMan.CloseSection(Logic.ScriptVars[(int)ScriptVariableNames.SCREEN]); // close the section that PLAYER has just left, if it's empty now } return(retCode); }
private void HandleSaveKey(ScummInputState kbd) { if (_selectedSavegame < 255) { var saveName = new StringBuilder(_saveNames[_selectedSavegame]); byte len = (byte)_saveNames[_selectedSavegame].Length; if (kbd.IsKeyDown(KeyCode.Backspace) && len != 0) // backspace saveName.Remove(saveName.Length - 1, 1); else { var key = kbd.GetKeys().Select(k => (char?)k).LastOrDefault(); if (key.HasValue && keyAccepted(key.Value) && (len < 31)) { saveName.Append(key.Value); } } _saveNames[_selectedSavegame] = saveName.ToString(); ShowSavegameNames(); } }