bool AgiEngine::showPredictiveDialog() { GUI::PredictiveDialog predictiveDialog; inGameTimerPause(); predictiveDialog.runModal(); inGameTimerResume(); Common::String predictiveResult(predictiveDialog.getResult()); uint16 predictiveResultLen = predictiveResult.size(); if (predictiveResult.size()) { // User actually entered something for (int16 resultPos = 0; resultPos < predictiveResultLen; resultPos++) { keyEnqueue(predictiveResult[resultPos]); } if (!cycleInnerLoopIsActive()) { if (_text->promptIsEnabled()) { // add ENTER, when the input is probably meant for the prompt keyEnqueue(AGI_KEY_ENTER); } } else { switch (_game.cycleInnerLoopType) { case CYCLE_INNERLOOP_GETSTRING: case CYCLE_INNERLOOP_GETNUMBER: // add ENTER, when the input is probably meant for GetString/GetNumber keyEnqueue(AGI_KEY_ENTER); break; default: break; } } return true; } return false; }
bool AgiEngine::handleMouseClicks(uint16 &key) { // No mouse click? -> exit if (key != AGI_MOUSE_BUTTON_LEFT) return false; if (!cycleInnerLoopIsActive()) { // Only do this, when no inner loop is currently active Common::Rect displayLineRect = _gfx->getFontRectForDisplayScreen(0, 0, FONT_COLUMN_CHARACTERS, 1); // Common::Rect displayLineRect(_gfx->getDisplayScreenWidth(), _gfx->getDisplayFontHeight()); if (displayLineRect.contains(_mouse.pos)) { // Mouse is inside first line of the screen if (getFlag(VM_FLAG_MENUS_ACCESSIBLE) && _menu->isAvailable()) { _menu->delayedExecuteViaMouse(); key = 0; // eat event return true; } } if (_text->promptIsEnabled()) { // Prompt is currently enabled int16 promptRow = _text->promptRow_Get(); displayLineRect.moveTo(0, promptRow * _gfx->getDisplayFontHeight()); if (displayLineRect.contains(_mouse.pos)) { // and user clicked within the line of the prompt showPredictiveDialog(); key = 0; // eat event return true; } } } if (cycleInnerLoopIsActive()) { // inner loop active, check what kind of loop it is. Then process / forward it switch (_game.cycleInnerLoopType) { case CYCLE_INNERLOOP_GETSTRING: case CYCLE_INNERLOOP_GETNUMBER: { // process in here int16 stringRow, stringColumn, stringMaxLen; _text->stringPos_Get(stringRow, stringColumn); stringMaxLen = _text->stringGetMaxLen(); Common::Rect displayRect = _gfx->getFontRectForDisplayScreen(stringColumn, stringRow, stringMaxLen, 1); if (displayRect.contains(_mouse.pos)) { // user clicked inside the input space showPredictiveDialog(); key = 0; // eat event return true; } break; } case CYCLE_INNERLOOP_INVENTORY: // TODO: forward break; case CYCLE_INNERLOOP_MENU_VIA_KEYBOARD: _menu->mouseEvent(key); key = 0; // eat event break; case CYCLE_INNERLOOP_SYSTEMUI_SELECTSAVEDGAMESLOT: // TODO: forward break; default: break; } } return false; }
// We return the current key, or 0 if no key was pressed uint16 AgiEngine::processAGIEvents() { uint16 key; ScreenObjEntry *screenObjEgo = &_game.screenObjTable[SCREENOBJECTS_EGO_ENTRY]; wait(10); key = doPollKeyboard(); // In AGI Mouse emulation mode we must update the mouse-related // vars in every interpreter cycle. // // We run AGIMOUSE always as a side effect setVar(VM_VAR_MOUSE_X, _mouse.pos.x / 2); setVar(VM_VAR_MOUSE_Y, _mouse.pos.y); if (!cycleInnerLoopIsActive()) { // Click-to-walk mouse interface if (_game.playerControl && (screenObjEgo->flags & fAdjEgoXY)) { int toX = screenObjEgo->move_x; int toY = screenObjEgo->move_y; // AGI Mouse games use ego's sprite's bottom left corner for mouse walking target. // Amiga games use ego's sprite's bottom center for mouse walking target. // Atari ST and Apple II GS seem to use the bottom left if (getPlatform() == Common::kPlatformAmiga) toX -= (screenObjEgo->xSize / 2); // Center ego's sprite horizontally // Adjust ego's sprite's mouse walking target position (These parameters are // controlled with the adj.ego.move.to.x.y-command). Note that these values rely // on the horizontal centering of the ego's sprite at least on the Amiga platform. toX += _game.adjMouseX; toY += _game.adjMouseY; screenObjEgo->direction = getDirection(screenObjEgo->xPos, screenObjEgo->yPos, toX, toY, screenObjEgo->stepSize); if (screenObjEgo->direction == 0) inDestination(screenObjEgo); } } handleMouseClicks(key); if (!cycleInnerLoopIsActive()) { // no inner loop active at the moment, regular processing if (key) { if (!handleController(key)) { if (key) { // Only set VAR_KEY, when no controller/direction was detected setVar(VM_VAR_KEY, key & 0xFF); if (_text->promptIsEnabled()) { _text->promptKeyPress(key); } } } } if (_menu->delayedExecuteActive()) { _menu->execute(); } } else { // inner loop active // call specific workers switch (_game.cycleInnerLoopType) { case CYCLE_INNERLOOP_GETSTRING: // loop called from TextMgr::stringEdit() case CYCLE_INNERLOOP_GETNUMBER: if (key) { _text->stringKeyPress(key); } break; case CYCLE_INNERLOOP_INVENTORY: // loop called from InventoryMgr::show() if (key) { _inventory->keyPress(key); } break; case CYCLE_INNERLOOP_MENU_VIA_KEYBOARD: if (key) { _menu->keyPress(key); } break; case CYCLE_INNERLOOP_MENU_VIA_MOUSE: _menu->mouseEvent(key); break; case CYCLE_INNERLOOP_SYSTEMUI_SELECTSAVEDGAMESLOT: if (key) { _systemUI->savedGameSlot_KeyPress(key); } break; case CYCLE_INNERLOOP_SYSTEMUI_VERIFICATION: _systemUI->askForVerificationKeyPress(key); break; case CYCLE_INNERLOOP_MESSAGEBOX: if (key) { _text->messageBox_KeyPress(key); } break; default: break; } } _gfx->updateScreen(); return key; }