void TSpit::xtakeit(const ArgumentArray &args) { // Pick up and move a marble // First, let's figure out what marble we're now holding uint32 &marble = _vm->_vars["themarble"]; marble = 0; for (uint32 i = 0; i < kMarbleCount; i++) { RivenHotspot *marbleHotspot = _vm->getCard()->getHotspotByName(s_marbleNames[i]); if (marbleHotspot->containsPoint(getMousePosition())) { marble = i + 1; break; } } // xtakeit() shouldn't be called if we're not on a marble hotspot assert(marble != 0); // Redraw the background _vm->getCard()->drawPicture(1); // Loop until the player lets go (or quits) while (mouseIsDown() && !_vm->hasGameEnded()) { _vm->doFrame(); } // Check if we landed in a valid location and no other marble has that location uint32 &marblePos = _vm->_vars[s_marbleNames[marble - 1]]; bool foundMatch = false; for (int y = 0; y < 25 && !foundMatch; y++) { for (int x = 0; x < 25 && !foundMatch; x++) { Common::Rect testHotspot = generateMarbleGridRect(x, y); // Let's try to place the marble! if (testHotspot.contains(getMousePosition())) { // Set this as the position setMarbleX(marblePos, x); setMarbleY(marblePos, y); // Let's make sure no other marble is in this spot... for (uint16 i = 0; i < kMarbleCount; i++) if (i != marble - 1 && _vm->_vars[s_marbleNames[i]] == marblePos) marblePos = 0; // We have a match foundMatch = true; } } } // If we still don't have a match, reset it to the original location if (!foundMatch) marblePos = 0; // Check the new hotspots and refresh everything marble = 0; setMarbleHotspots(); drawMarbles(); }
void Render::addDirtyRect(Common::Rect r) { if (_fullRefresh) return; // Clip rectangle r.clip(_backGroundSurface.w, _backGroundSurface.h); // If it is empty after clipping, we are done if (r.isEmpty()) return; // Check if the new rectangle is contained within another in the list Common::List<Common::Rect>::iterator it; for (it = _dirtyRects.begin(); it != _dirtyRects.end(); ) { // If we find a rectangle which fully contains the new one, // we can abort the search. if (it->contains(r)) return; // Conversely, if we find rectangles which are contained in // the new one, we can remove them if (r.contains(*it)) it = _dirtyRects.erase(it); else ++it; } // If we got here, we can safely add r to the list of dirty rects. if (_vm->_interface->getFadeMode() != kFadeOut) _dirtyRects.push_back(r); }
void CSTimeHelp::mouseMove(Common::Point &pos) { bool mouseIsDown = _vm->getEventManager()->getButtonState() & 1; for (uint i = 0; i < _qars.size(); i++) { Common::Rect thisRect = _vm->getInterface()->_dialogTextRect; thisRect.top += 1 + i*15; thisRect.bottom = thisRect.top + 15; if (!thisRect.contains(pos)) continue; if (mouseIsDown) { if (i != _currEntry) break; highlightLine(i); } _vm->getInterface()->cursorOverHotspot(); _currHover = i; return; } if (_currHover != 0xffff) { if (_vm->getInterface()->cursorGetShape() != 3) { unhighlightLine(_currHover); _vm->getInterface()->cursorSetShape(1); } _currHover = 0xffff; } }
void ThemeEngine::addDirtyRect(Common::Rect r) { // Clip the rect to screen coords r.clip(_screen.w, _screen.h); // If it is empty after clipping, we are done if (r.isEmpty()) return; // Check if the new rectangle is contained within another in the list Common::List<Common::Rect>::iterator it; for (it = _dirtyScreen.begin(); it != _dirtyScreen.end();) { // If we find a rectangle which fully contains the new one, // we can abort the search. if (it->contains(r)) return; // Conversely, if we find rectangles which are contained in // the new one, we can remove them if (r.contains(*it)) it = _dirtyScreen.erase(it); else ++it; } // If we got here, we can safely add r to the list of dirty rects. _dirtyScreen.push_back(r); }
bool Script::hotspot(Common::Rect rect, uint16 address, uint8 cursor) { // Test if the current mouse position is contained in the specified rectangle Common::Point mousepos = _vm->_system->getEventManager()->getMousePos(); bool contained = rect.contains(mousepos); // Show hotspots when debugging if (Common::isDebugChannelEnabled(kGroovieDebugHotspots) || Common::isDebugChannelEnabled(kGroovieDebugAll)) { rect.translate(0, -80); _vm->_graphicsMan->_foreground.frameRect(rect, 250); _vm->_system->copyRectToScreen((byte*)_vm->_graphicsMan->_foreground.getBasePtr(0, 0), 640, 0, 80, 640, 320); _vm->_system->updateScreen(); } // If there's an already planned action, do nothing if (_inputAction != -1) { return false; } if (contained) { // Change the mouse cursor if (_newCursorStyle == 5) { _newCursorStyle = cursor; } // If clicked with the mouse, jump to the specified address if (_mouseClicked) { _inputAction = address; } } return contained; }
MenuInputState *run() { if (_vm->_input->getLastButtonEvent() != kMouseLeftUp) { return this; } int cell = -1; Common::Point p; _vm->_input->getCursorPos(p); if (_menuRect.contains(p)) { cell = (p.x - _menuRect.left) / _cellW + 3 * ((p.y - _menuRect.top) / _cellH); } bool close = false; switch (cell) { case 4: // resume case -1: // invalid cell close = true; break; case 0: // toggle music if (_mscStatus != -1) { _vm->enableMusic(!_mscStatus); _mscStatus = _vm->getMusicStatus(); _vm->_gfx->setItemFrame(_mscMenuObjId, frameFromStatus(_mscStatus)); } break; case 1: // toggle sfx if (_sfxStatus != -1) { _vm->enableSfx(!_sfxStatus); _sfxStatus = _vm->getSfxStatus(); _vm->_gfx->setItemFrame(_sfxMenuObjId, frameFromStatus(_sfxStatus)); } break; case 2: // save warning("Saving is not supported yet"); _vm->_saveLoad->saveGame(); break; case 3: // load warning("Loading is not supported yet"); close = _vm->_saveLoad->loadGame(); break; case 5: // quit return _helper->getState("quitdialog"); } if (close) { _vm->_gfx->freeDialogueObjects(); return 0; } _vm->_input->setArrowCursor(); return this; }
ItemPosition InventoryRenderer::hitTest(const Common::Point &p) const { Common::Rect r; getRect(r); if (!r.contains(p)) return -1; return ((p.x - _pos.x) / _props->_itemWidth) + (_props->_itemsPerLine * ((p.y - _pos.y) / _props->_itemHeight)); }
bool Animation::hitFrameRect(int x, int y) const { if (!gfxobj) { return false; } Common::Rect r; getFrameRect(r); return r.contains(x, y); }
void CSTimeHelp::mouseDown(Common::Point &pos) { for (uint i = 0; i < _qars.size(); i++) { Common::Rect thisRect = _vm->getInterface()->_dialogTextRect; thisRect.top += 1 + i*15; thisRect.bottom = thisRect.top + 15; if (!thisRect.contains(pos)) continue; _currEntry = i; highlightLine(i); _vm->getInterface()->cursorSetShape(5); } }
void CSTimeHelp::mouseUp(Common::Point &pos) { if (_currEntry == 0xffff || _qars[_currEntry].speech == 0) { _vm->getInterface()->cursorSetShape(1); end(); return; } Common::Rect thisRect = _vm->getInterface()->_dialogTextRect; thisRect.top += 1 + _currEntry*15; thisRect.bottom = thisRect.top + 15; if (!thisRect.contains(pos)) return; _vm->addEvent(CSTimeEvent(kCSTimeEventCharStartFlapping, _vm->getCase()->getCurrScene()->getHelperId(), 5900 + _qars[_currEntry].speech)); _nextToProcess = _currEntry; _askedAlready.push_back(_qars[_currEntry].text); }
const CloseData *LabEngine::getObject(Common::Point pos, const CloseData *closePtr) { const CloseDataList *list; if (!closePtr) list = &(getViewData(_roomNum, _direction)->_closeUps); else list = &(closePtr->_subCloseUps); CloseDataList::const_iterator wrkClosePtr; for (wrkClosePtr = list->begin(); wrkClosePtr != list->end(); ++wrkClosePtr) { Common::Rect objRect; objRect = _utils->rectScale(wrkClosePtr->_x1, wrkClosePtr->_y1, wrkClosePtr->_x2, wrkClosePtr->_y2); if (objRect.contains(pos)) return &(*wrkClosePtr); } return nullptr; }
int32 HotSpot::isPointInRectsCube(const Common::Point &p) { for (uint j = 0; j < rects.size(); j++) { Common::Rect rect = Common::Rect( rects[j].centerHeading - rects[j].width / 2, rects[j].centerPitch - rects[j].height / 2, rects[j].centerHeading + rects[j].width / 2, rects[j].centerPitch + rects[j].height / 2); // Make sure heading is in the correct range Common::Point lookAt = p; if (rect.right > 360 && lookAt.x <= rect.right - 360) lookAt.x += 360; if (rect.contains(lookAt)) return j; } return -1; }
/** * @brief Marks a dirty rectangle on the surface * @param r The rectangle to be marked dirty */ void Surface::markDirtyRect(Common::Rect r) { Common::List<Common::Rect>::iterator it; r.clip(w, h); if (r.isEmpty()) return; it = _dirtyRects.begin(); while (it != _dirtyRects.end()) { if (it->contains(r)) return; if (r.contains(*it)) it = _dirtyRects.erase(it); else ++it; } _dirtyRects.push_back(r); }
int32 HotSpot::isPointInRectsFrame(GameState *state, const Common::Point &p) { for (uint j = 0; j < rects.size(); j++) { int16 x = rects[j].centerPitch; int16 y = rects[j].centerHeading; int16 w = rects[j].width; int16 h = rects[j].height; if (y < 0) { x = state->getVar(x); y = state->getVar(-y); h = -h; } Common::Rect rect = Common::Rect(w, h); rect.translate(x, y); if (rect.contains(p)) return j; } return -1; }
bool LabEngine::takeItem(Common::Point pos) { const CloseDataList *list; if (!_closeDataPtr) { list = &(getViewData(_roomNum, _direction)->_closeUps); } else if (_closeDataPtr->_closeUpType < 0) { _conditions->inclElement(abs(_closeDataPtr->_closeUpType)); return true; } else list = &(_closeDataPtr->_subCloseUps); CloseDataList::const_iterator closePtr; for (closePtr = list->begin(); closePtr != list->end(); ++closePtr) { Common::Rect objRect; objRect = _utils->rectScale(closePtr->_x1, closePtr->_y1, closePtr->_x2, closePtr->_y2); if (objRect.contains(pos) && (closePtr->_closeUpType < 0)) { _conditions->inclElement(abs(closePtr->_closeUpType)); return true; } } return false; }
void LabEngine::setCurrentClose(Common::Point pos, const CloseData **closePtrList, bool useAbsoluteCoords, bool next) { const CloseDataList *list; if (!*closePtrList) list = &(getViewData(_roomNum, _direction)->_closeUps); else list = &((*closePtrList)->_subCloseUps); CloseDataList::const_iterator closePtr; for (closePtr = list->begin(); closePtr != list->end(); ++closePtr) { Common::Rect target; if (!useAbsoluteCoords) target = Common::Rect(closePtr->_x1, closePtr->_y1, closePtr->_x2, closePtr->_y2); else target = _utils->rectScale(closePtr->_x1, closePtr->_y1, closePtr->_x2, closePtr->_y2); if (target.contains(pos) && (next || !closePtr->_graphicName.empty())) { if (next) { // cycle to the next one ++closePtr; if (closePtr == list->end()) closePtr = list->begin(); } *closePtrList = &(*closePtr); return; } } // If we got here, no match was found. If we want the "next" close-up, // return the first one in the list, if any. if (next) { if (!list->empty()) *closePtrList = &(*list->begin()); } }
void WidgetVerbs::highlightVerbControls() { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; Common::Point mousePos = events.mousePos(); // Get highlighted verb _selector = -1; Common::Rect bounds = _bounds; bounds.grow(-3); if (bounds.contains(mousePos)) _selector = (mousePos.y - bounds.top) / (screen.fontHeight() + 7); // See if a new verb is being pointed at if (_selector != _oldSelector) { // Redraw the verb list for (int idx = 0; idx < (int)_verbCommands.size(); ++idx) { byte color = (idx == _selector) ? (byte)COMMAND_HIGHLIGHTED : (byte)INFO_TOP; _surface.writeString(_verbCommands[idx], Common::Point((_bounds.width() - screen.stringWidth(_verbCommands[idx])) / 2, (screen.fontHeight() + 7) * idx + 5), color); } _oldSelector = _selector; } }
void OSpit::xbookclick(const ArgumentArray &args) { // Let's hook onto our video RivenVideo *video = _vm->_video->getSlot(args[0]); // Convert from the standard QuickTime base time to milliseconds // The values are in terms of 1/600 of a second. // Have I said how much I just *love* QuickTime? </sarcasm> uint32 startTime = args[1] * 1000 / 600; uint32 endTime = args[2] * 1000 / 600; // Track down our hotspot Common::String hotspotName = Common::String::format("touchBook%d", args[3]); RivenHotspot *hotspot = _vm->getCard()->getHotspotByName(hotspotName); Common::Rect hotspotRect = hotspot->getRect(); debug(0, "xbookclick:"); debug(0, "\tVideo Code = %d", args[0]); debug(0, "\tStart Time = %dms", startTime); debug(0, "\tEnd Time = %dms", endTime); debug(0, "\tHotspot = %d -> %s", args[3], hotspotName.c_str()); // Just let the video play while we wait until Gehn opens the trap book for us while (video->getTime() < startTime && !_vm->hasGameEnded()) { _vm->doFrame(); } // Break out if we're quitting if (_vm->hasGameEnded()) return; // OK, Gehn has opened the trap book and has asked us to go in. Let's watch // and see what the player will do... while (video->getTime() < endTime && !_vm->hasGameEnded()) { if (hotspotRect.contains(getMousePosition())) _vm->_cursor->setCursor(kRivenOpenHandCursor); else _vm->_cursor->setCursor(kRivenMainCursor); if (mouseIsDown()) { if (hotspotRect.contains(getMousePosition())) { // OK, we've used the trap book! We go for ride lady! _vm->_video->closeVideos(); // Stop all videos _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor _vm->_gfx->scheduleTransition(kRivenTransitionBlend); _vm->getCard()->drawPicture(3); // Black out the screen _vm->_sound->playSound(0); // Play the link sound _vm->delay(12000); _vm->getCard()->playMovie(7); // Activate Gehn Link Video RivenVideo *linkVideo = _vm->_video->openSlot(1); // Play Gehn Link Video linkVideo->playBlocking(); _vm->_vars["ocage"] = 1; _vm->_vars["agehn"] = 4; // Set Gehn to the trapped state _vm->_vars["atrapbook"] = 1; // We've got the trap book again _vm->_sound->playSound(0); // Play the link sound again _vm->_gfx->scheduleTransition(kRivenTransitionBlend); _vm->changeToCard(_vm->getStack()->getCardStackId(0x2885)); // Link out! _vm->_inventory->forceVisible(true); _vm->delay(2000); _vm->_inventory->forceVisible(false); _vm->_scriptMan->stopAllScripts(); // Stop all running scripts (so we don't remain in the cage) return; } } _vm->doFrame(); } // Break out if we're quitting if (_vm->hasGameEnded()) return; // If there was no click and this is the third time Gehn asks us to // use the trap book, he will shoot the player. Dead on arrival. // Run the credits from here. if (_vm->_vars["agehn"] == 3) { runCredits(args[0], 5000, 995); return; } // There was no click, so just play the rest of the video. video->playBlocking(); }
TestExitStatus EventTests::mouseEvents() { Testsuite::clearScreen(); Common::String info = "Testing Mouse events.\n " "Any movement/click generated by L/R/M mouse buttons or the mouse wheel should be detected.\n" "Press X to exit"; if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) { Testsuite::logPrintf("Info! Skipping test : keyboard events\n"); return kTestSkipped; } Common::EventManager *eventMan = g_system->getEventManager(); Common::Point pt(0, 30); Common::Rect rectInfo = Testsuite::writeOnScreen("Generate mouse events make L/R/M button clicks, move wheel", pt); pt.y += 15; Testsuite::writeOnScreen("Press X to exit", pt); pt.y = 70; Common::Rect rectLB = Testsuite::writeOnScreen("Left-button click : Not tested", pt); pt.y += 15; Common::Rect rectRB = Testsuite::writeOnScreen("Right-button click : Not tested", pt); pt.y += 15; Common::Rect rectMB = Testsuite::writeOnScreen("Middle-button click : Not tested", pt); pt.y += 15; Common::Rect rectWheel = Testsuite::writeOnScreen("Wheel Movements : Not tested", pt); // Init Mouse Palette GFXtests::initMousePalette(); Common::Rect finishZone = drawFinishZone(); bool quitLoop = false; TestExitStatus passed = kTestPassed; // handle all mouse events Common::Event event; while (!quitLoop) { // Show mouse CursorMan.showMouse(true); g_system->updateScreen(); while (eventMan->pollEvent(event)) { // Quit if explicitly requested if (Engine::shouldQuit()) { return passed; } switch (event.type) { case Common::EVENT_MOUSEMOVE: // Movements havee already been tested in GFX break; case Common::EVENT_LBUTTONDOWN: Testsuite::clearScreen(rectInfo); Testsuite::writeOnScreen("Mouse left-button pressed", Common::Point(rectInfo.left, rectInfo.top)); break; case Common::EVENT_RBUTTONDOWN: Testsuite::clearScreen(rectInfo); Testsuite::writeOnScreen("Mouse right-button pressed", Common::Point(rectInfo.left, rectInfo.top)); break; case Common::EVENT_WHEELDOWN: Testsuite::clearScreen(rectInfo); Testsuite::writeOnScreen("Mouse wheel moved down", Common::Point(rectInfo.left, rectInfo.top)); Testsuite::writeOnScreen("Wheel Movements : Done!", Common::Point(rectWheel.left, rectWheel.top)); break; case Common::EVENT_MBUTTONDOWN: Testsuite::clearScreen(rectInfo); Testsuite::writeOnScreen("Mouse middle-button pressed ", Common::Point(rectInfo.left, rectInfo.top)); break; case Common::EVENT_LBUTTONUP: Testsuite::clearScreen(rectInfo); if (finishZone.contains(eventMan->getMousePos())) { quitLoop = true; } Testsuite::writeOnScreen("Mouse left-button released", Common::Point(rectInfo.left, rectInfo.top)); Testsuite::writeOnScreen("Left-button clicks : Done!", Common::Point(rectLB.left, rectLB.top)); break; case Common::EVENT_RBUTTONUP: Testsuite::clearScreen(rectInfo); Testsuite::writeOnScreen("Mouse right-button released", Common::Point(rectInfo.left, rectInfo.top)); Testsuite::writeOnScreen("Right-button clicks : Done!", Common::Point(rectRB.left, rectRB.top)); break; case Common::EVENT_WHEELUP: Testsuite::clearScreen(rectInfo); Testsuite::writeOnScreen("Mouse wheel moved up", Common::Point(rectInfo.left, rectInfo.top)); Testsuite::writeOnScreen("Wheel Movements : Done!", Common::Point(rectWheel.left, rectWheel.top)); break; case Common::EVENT_MBUTTONUP: Testsuite::clearScreen(rectInfo); Testsuite::writeOnScreen("Mouse middle-button released ", Common::Point(rectInfo.left, rectInfo.top)); Testsuite::writeOnScreen("Middle-button clicks : Done!", Common::Point(rectMB.left, rectMB.top)); break; case Common::EVENT_KEYDOWN: if (event.kbd.keycode == Common::KEYCODE_x) { Testsuite::clearScreen(rectInfo); Testsuite::writeOnScreen("Exit requested", Common::Point(rectInfo.left, rectInfo.top)); quitLoop = true; } break; default: break; } } } CursorMan.showMouse(false); // Verify results now! if (Testsuite::handleInteractiveInput("Were mouse clicks (L/R/M buttons) and wheel movements identfied ?", "Yes", "No", kOptionRight)) { Testsuite::logDetailedPrintf("Mouse clicks (L/R/M buttons) and wheel movements failed"); passed = kTestFailed; } return passed; }
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; }
void LabEngine::processMap(uint16 curRoom) { byte place = 1; uint16 curMsg = curRoom; uint16 curFloor = _maps[curRoom]._pageNumber; while (1) { IntuiMessage *msg = _event->getMsg(); if (shouldQuit()) { _quitLab = true; return; } updateEvents(); _graphics->screenUpdate(); _system->delayMillis(10); if (!msg) { updateEvents(); byte newcolor[3]; if (place <= 14) { newcolor[0] = 14 << 2; newcolor[1] = place << 2; newcolor[2] = newcolor[1]; } else { newcolor[0] = 14 << 2; newcolor[1] = (28 - place) << 2; newcolor[2] = newcolor[1]; } waitTOF(); _graphics->writeColorRegs(newcolor, 1, 1); _interface->handlePressedButton(); waitTOF(); place++; if (place >= 28) place = 1; } else { uint32 msgClass = msg->_msgClass; uint16 msgCode = msg->_code; uint16 mouseX = msg->_mouse.x; uint16 mouseY = msg->_mouse.y; if ((msgClass == kMessageRightClick) || ((msgClass == kMessageRawKey) && (msgCode == Common::KEYCODE_ESCAPE))) return; if (msgClass == kMessageButtonUp) { if (msgCode == 0) { // Quit menu button return; } else if (msgCode == 1) { // Up arrow uint16 upperFloor = getUpperFloor(curFloor); if (upperFloor != kFloorNone) { curFloor = upperFloor; _graphics->fade(false); drawMap(curRoom, curMsg, curFloor, false); _graphics->fade(true); } } else if (msgCode == 2) { // Down arrow uint16 lowerFloor = getLowerFloor(curFloor); if (lowerFloor != kFloorNone) { curFloor = lowerFloor; _graphics->fade(false); drawMap(curRoom, curMsg, curFloor, false); _graphics->fade(true); } } } else if (msgClass == kMessageLeftClick) { if ((curFloor == kFloorLower) && _utils->mapRectScale(538, 277, 633, 352).contains(mouseX, mouseY) && floorVisited(kFloorSurMaze)) { curFloor = kFloorSurMaze; _graphics->fade(false); drawMap(curRoom, curMsg, curFloor, false); _graphics->fade(true); } else if ((curFloor == kFloorMiddle) && _utils->mapRectScale(358, 71, 452, 147).contains(mouseX, mouseY) && floorVisited(kFloorCarnival)) { curFloor = kFloorCarnival; _graphics->fade(false); drawMap(curRoom, curMsg, curFloor, false); _graphics->fade(true); } else if ((curFloor == kFloorMiddle) && _utils->mapRectScale(557, 325, 653, 401).contains(mouseX, mouseY) && floorVisited(kFloorMedMaze)) { curFloor = kFloorMedMaze; _graphics->fade(false); drawMap(curRoom, curMsg, curFloor, false); _graphics->fade(true); } else if ((curFloor == kFloorUpper) && _utils->mapRectScale(524, 97, 645, 207).contains(mouseX, mouseY) && floorVisited(kFloorHedgeMaze)) { curFloor = kFloorHedgeMaze; _graphics->fade(false); drawMap(curRoom, curMsg, curFloor, false); _graphics->fade(true); } else if (mouseX > _utils->mapScaleX(314)) { uint16 oldMsg = curMsg; Common::Rect curCoords; for (int i = 1; i <= _maxRooms; i++) { curCoords = roomCoords(i); if ((_maps[i]._pageNumber == curFloor) && _roomsFound->in(i) && curCoords.contains(Common::Point(mouseX, mouseY))) { curMsg = i; } } if (oldMsg != curMsg) { if (!_rooms[curMsg]._roomMsg.empty()) _resource->readViews(curMsg); const char *sptr; if ((sptr = _rooms[curMsg]._roomMsg.c_str())) { _graphics->rectFillScaled(13, 148, 135, 186, 3); _graphics->flowText(_msgFont, 0, 5, 3, true, true, true, true, _utils->vgaRectScale(14, 148, 134, 186), sptr); if (_maps[oldMsg]._pageNumber == curFloor) drawRoomMap(oldMsg, (bool)(oldMsg == curRoom)); curCoords = roomCoords(curMsg); int right = (curCoords.left + curCoords.right) / 2; int left = right - 1; int top, bottom; top = bottom = (curCoords.top + curCoords.bottom) / 2; if ((curMsg != curRoom) && (_maps[curMsg]._pageNumber == curFloor)) _graphics->rectFill(left, top, right, bottom, 1); } } } } _graphics->screenUpdate(); } } // while }
uint16 PopupMenu::Show(int numEntries, const char *actions[]) { if (numEntries == 0) return 0xffff; LureEngine &engine = LureEngine::getReference(); Events &e = Events::getReference(); Mouse &mouse = Mouse::getReference(); OSystem &system = *g_system; Screen &screen = Screen::getReference(); Common::Rect r; bool isEGA = LureEngine::getReference().isEGA(); byte bgColour = isEGA ? EGA_DIALOG_BG_COLOUR : 0; byte textColour = isEGA ? EGA_DIALOG_TEXT_COLOUR : VGA_DIALOG_TEXT_COLOUR; byte whiteColour = isEGA ? EGA_DIALOG_WHITE_COLOUR : VGA_DIALOG_WHITE_COLOUR; const uint16 yMiddle = FULL_SCREEN_HEIGHT / 2; #ifndef LURE_CLICKABLE_MENUS uint16 oldX = mouse.x(); uint16 oldY = mouse.y(); mouse.cursorOff(); mouse.setPosition(FULL_SCREEN_WIDTH / 2, yMiddle); // Round up number of lines in dialog to next odd number uint16 numLines = (numEntries / 2) * 2 + 1; if (numLines > 5) numLines = 5; #else mouse.pushCursorNum(CURSOR_ARROW); // In WinCE, the whole menu is shown and the items are click-selectable uint16 numLines = numEntries; #endif // Figure out the character width uint16 numCols = 0; for (int ctr = 0; ctr < numEntries; ++ctr) { int len = strlen(actions[ctr]); if (len > numCols) numCols = len; } // Create the dialog surface Common::Point size; Surface::getDialogBounds(size, numCols, numLines, false); Surface *s = new Surface(size.x, size.y); s->createDialog(true); int selectedIndex = 0; bool refreshFlag = true; r.left = Surface::textX(); r.right = s->width() - Surface::textX() + 1; r.top = Surface::textY(); r.bottom = s->height() - Surface::textY() + 1; for (;;) { if (refreshFlag) { // Set up the contents of the menu s->fillRect(r, bgColour); for (int index = 0; index < numLines; ++index) { #ifndef LURE_CLICKABLE_MENUS int actionIndex = selectedIndex - (numLines / 2) + index; #else int actionIndex = index; #endif if ((actionIndex >= 0) && (actionIndex < numEntries)) { s->writeString(Surface::textX(), Surface::textY() + index * FONT_HEIGHT, actions[actionIndex], true, #ifndef LURE_CLICKABLE_MENUS (index == (numLines / 2)) ? whiteColour : textColour, #else (index == selectedIndex) ? whiteColour : textColour, #endif false); } } s->copyToScreen(0, yMiddle-(s->height() / 2)); system.updateScreen(); refreshFlag = false; } while (e.pollEvent()) { if (engine.shouldQuit()) { selectedIndex = 0xffff; goto bail_out; } else if (e.type() == Common::EVENT_WHEELUP) { // Scroll upwards if (selectedIndex > 0) { --selectedIndex; refreshFlag = true; } } else if (e.type() == Common::EVENT_WHEELDOWN) { // Scroll downwards if (selectedIndex < numEntries - 1) { ++selectedIndex; refreshFlag = true; } } else if (e.type() == Common::EVENT_KEYDOWN) { uint16 keycode = e.event().kbd.keycode; if (((keycode == Common::KEYCODE_KP8) || (keycode == Common::KEYCODE_UP)) && (selectedIndex > 0)) { --selectedIndex; refreshFlag = true; } else if (((keycode == Common::KEYCODE_KP2) || (keycode == Common::KEYCODE_DOWN)) && (selectedIndex < numEntries-1)) { ++selectedIndex; refreshFlag = true; } else if ((keycode == Common::KEYCODE_RETURN) || (keycode == Common::KEYCODE_KP_ENTER)) { goto bail_out; } else if (keycode == Common::KEYCODE_ESCAPE) { selectedIndex = 0xffff; goto bail_out; } #ifdef LURE_CLICKABLE_MENUS } else if (e.type() == Common::EVENT_LBUTTONDOWN || e.type() == Common::EVENT_MOUSEMOVE) { int16 x = mouse.x(); int16 y = mouse.y() - yMiddle + (s->height() / 2); refreshFlag = true; if (r.contains(x, y)) { selectedIndex = (y - r.top) / FONT_HEIGHT; if (e.type() == Common::EVENT_LBUTTONDOWN) goto bail_out; } #else } else if ((e.type() == Common::EVENT_LBUTTONDOWN) || (e.type() == Common::EVENT_MBUTTONDOWN)) { //mouse.waitForRelease(); goto bail_out; #endif } else if (e.type() == Common::EVENT_RBUTTONDOWN) { mouse.waitForRelease(); selectedIndex = 0xffff; goto bail_out; } } #ifndef LURE_CLICKABLE_MENUS // Warping the mouse to "neutral" even if the top/bottom menu // entry has been reached has both pros and cons. It makes the // menu behave a bit more sensibly, but it also makes it harder // to move the mouse pointer out of the ScummVM window. if (mouse.y() < yMiddle - POPMENU_CHANGE_SENSITIVITY) { if (selectedIndex > 0) { --selectedIndex; refreshFlag = true; } mouse.setPosition(FULL_SCREEN_WIDTH / 2, yMiddle); } else if (mouse.y() > yMiddle + POPMENU_CHANGE_SENSITIVITY) { if (selectedIndex < numEntries - 1) { ++selectedIndex; refreshFlag = true; } mouse.setPosition(FULL_SCREEN_WIDTH / 2, yMiddle); } #endif system.delayMillis(20); } bail_out: delete s; #ifndef LURE_CLICKABLE_MENUS mouse.setPosition(oldX, oldY); mouse.cursorOn(); #else mouse.popCursor(); #endif screen.update(); return selectedIndex; }
bool ClickText::containsPoint(const Common::Point &point) const { Common::Rect r = _bbox; r.translate(_position.x, _position.y); return r.contains(point); }