diff options
author | Johannes Schickel | 2010-10-13 03:57:44 +0000 |
---|---|---|
committer | Johannes Schickel | 2010-10-13 03:57:44 +0000 |
commit | 75e8452b6e6a2bf4fb2f588aa00b428a60d873b5 (patch) | |
tree | f29541d55309487a94bd1d38e8b53bb3dde9aec6 /engines/hugo/mouse.cpp | |
parent | 48ee83b88957dab86bc763e9ef21a70179fa8679 (diff) | |
parent | e9f50882ea5b6beeefa994040be9d3bab6a1f107 (diff) | |
download | scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.tar.gz scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.tar.bz2 scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.zip |
OPENGL: Merged from trunk, from rev 52105 to 53396.
This includes an rather hacky attempt to merge all the recent gp2x backend
changes into the branch. I suppose the gp2x backend and probably all new
backends, i.e. gph, dingux etc., might not compile anymore.
Since I have no way of testing those it would be nice if porters could look
into getting those up to speed in this branch.
svn-id: r53399
Diffstat (limited to 'engines/hugo/mouse.cpp')
-rw-r--r-- | engines/hugo/mouse.cpp | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/engines/hugo/mouse.cpp b/engines/hugo/mouse.cpp new file mode 100644 index 0000000000..b305489568 --- /dev/null +++ b/engines/hugo/mouse.cpp @@ -0,0 +1,303 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +// mouse.cpp : Handle all mouse activity + +#include "common/system.h" + +#include "hugo/game.h" +#include "hugo/hugo.h" +#include "hugo/mouse.h" +#include "hugo/global.h" +#include "hugo/schedule.h" +#include "hugo/display.h" +#include "hugo/inventory.h" +#include "hugo/route.h" +#include "hugo/util.h" + +namespace Hugo { + +#define EXIT_HOTSPOT -4 // Cursor over Exit hotspot +#define CURSOR_NAME 2 // Index of name used under cursor +#define CURSOR_NOCHAR '~' // Don't show name of object under cursor +#define SX_OFF 10 // Cursor offset to name string +#define SY_OFF -2 // Cursor offset to name string +#define IX_OFF 8 // Cursor to icon image (dib coords) +#define IY_OFF 10 // Cursor to icon image (dib coords) + +enum seqTextMouse { + kMsNoWayText = 0, + kMsExit = 1 +}; + +MouseHandler::MouseHandler(HugoEngine &vm) : _vm(vm) { +} + +// Shadow-blit supplied string into dib_a at cx,cy and add to display list +void MouseHandler::cursorText(char *buffer, int16 cx, int16 cy, uif_t fontId, int16 color) { + debugC(1, kDebugMouse, "cursorText(%s, %d, %d, %d, %d)", buffer, cx, cy, fontId, color); + + _vm.screen().loadFont(fontId); + + // Find bounding rect for string + int16 sdx = _vm.screen().stringLength(buffer); + int16 sdy = _vm.screen().fontHeight() + 1; // + 1 for shadow + int16 sx = (cx < XPIX / 2) ? cx + SX_OFF : cx - sdx - SX_OFF / 2; + int16 sy = cy + SY_OFF; + + // Display the string and add rect to display list + _vm.screen().shadowStr(sx, sy, buffer, _TBRIGHTWHITE); + _vm.screen().displayList(D_ADD, sx, sy, sdx, sdy); +} + +// Find the exit hotspot containing cx, cy. +// Return hotspot index or -1 if not found. +int16 MouseHandler::findExit(int16 cx, int16 cy) { + debugC(2, kDebugMouse, "findExit(%d, %d)", cx, cy); + + int i = 0; + for (hotspot_t *hotspot = _vm._hotspots; hotspot->screenIndex >= 0; i++, hotspot++) { + if (hotspot->screenIndex == *_vm._screen_p) { + if (cx >= hotspot->x1 && cx <= hotspot->x2 && cy >= hotspot->y1 && cy <= hotspot->y2) + return i; + } + } + return -1; +} + +// Process a mouse right click at coord cx, cy over object objid +void MouseHandler::processRightClick(int16 objId, int16 cx, int16 cy) { + debugC(1, kDebugMouse, "Process_rclick(%d, %d, %d)", objId, cx, cy); + + status_t &gameStatus = _vm.getGameStatus(); + + if (gameStatus.storyModeFl || _vm._hero->pathType == QUIET) // Make sure user has control + return; + + bool foundFl = false; // TRUE if route found to object + // Check if this was over iconbar + if (gameStatus.inventoryState == I_ACTIVE && cy < INV_DY + DIBOFF_Y) { // Clicked over iconbar object + if (gameStatus.inventoryObjId == -1) + gameStatus.inventoryObjId = objId; // Not using so select new object + else if (gameStatus.inventoryObjId == objId) + gameStatus.inventoryObjId = -1; // Same icon - deselect it + else + _vm.useObject(objId); // Use status.objid on object + } else { // Clicked over viewport object + object_t *obj = &_vm._objects[objId]; + int16 x, y; + switch (obj->viewx) { // Where to walk to + case -1: // Walk to object position + if (_vm.findObjectSpace(obj, &x, &y)) + foundFl = _vm.route().startRoute(GO_GET, objId, x, y); + if (!foundFl) // Can't get there, try to use from here + _vm.useObject(objId); + break; + case 0: // Immediate use + _vm.useObject(objId); // Pick up or use object + break; + default: // Walk to view point if possible + if (!_vm.route().startRoute(GO_GET, objId, obj->viewx, obj->viewy)) { + if (_vm._hero->cycling == INVISIBLE)// If invisible do + _vm.useObject(objId); // immediate use + else + Utils::Box(BOX_ANY, "%s", _vm._textMouse[kMsNoWayText]); // Can't get there + } + break; + } + } +} + +// Process a left mouse click over: +// 1. An icon - show description +// 2. An object - walk to and show description +// 3. An icon scroll arrow - scroll the iconbar +// 4. Nothing - attempt to walk there +// 5. Exit - walk to exit hotspot +void MouseHandler::processLeftClick(int16 objId, int16 cx, int16 cy) { + debugC(1, kDebugMouse, "Process_lclick(%d, %d, %d)", objId, cx, cy); + + int16 i, x, y; + object_t *obj; + + status_t &gameStatus = _vm.getGameStatus(); + + if (gameStatus.storyModeFl || _vm._hero->pathType == QUIET) // Make sure user has control + return; + + switch (objId) { + case -1: // Empty space - attempt to walk there + _vm.route().startRoute(GO_SPACE, 0, cx, cy); + break; + case LEFT_ARROW: // A scroll arrow - scroll the iconbar + case RIGHT_ARROW: + // Scroll the iconbar and display results + _vm.inventory().processInventory((objId == LEFT_ARROW) ? INV_LEFT : INV_RIGHT); + _vm.screen().moveImage(_vm.screen().getIconBuffer(), 0, 0, XPIX, INV_DY, XPIX, _vm.screen().getFrontBuffer(), 0, DIBOFF_Y, XPIX); + _vm.screen().moveImage(_vm.screen().getIconBuffer(), 0, 0, XPIX, INV_DY, XPIX, _vm.screen().getBackBuffer(), 0, DIBOFF_Y, XPIX); + _vm.screen().displayList(D_ADD, 0, DIBOFF_Y, XPIX, INV_DY); + break; + case EXIT_HOTSPOT: // Walk to exit hotspot + i = findExit(cx, cy); + x = _vm._hotspots[i].viewx; + y = _vm._hotspots[i].viewy; + if (x >= 0) { // Hotspot refers to an exit + // Special case of immediate exit + if (gameStatus.jumpExitFl) { + // Get rid of iconbar if necessary + if (gameStatus.inventoryState != I_OFF) + gameStatus.inventoryState = I_UP; + _vm.scheduler().insertActionList(_vm._hotspots[i].actIndex); + } else { // Set up route to exit spot + if (_vm._hotspots[i].direction == Common::KEYCODE_RIGHT) + x -= HERO_MAX_WIDTH; + else if (_vm._hotspots[i].direction == Common::KEYCODE_LEFT) + x += HERO_MAX_WIDTH; + if (!_vm.route().startRoute(GO_EXIT, i, x, y)) + Utils::Box(BOX_ANY, "%s", _vm._textMouse[kMsNoWayText]); // Can't get there + } + + // Get rid of any attached icon + gameStatus.inventoryObjId = -1; + } + break; + default: // Look at an icon or object + obj = &_vm._objects[objId]; + + // Over iconbar - immediate description + if (gameStatus.inventoryState == I_ACTIVE && cy < INV_DY + DIBOFF_Y) + _vm.lookObject(obj); + else { + bool foundFl = false; // TRUE if route found to object + switch (obj->viewx) { // Clicked over viewport object + case -1: // Walk to object position + if (_vm.findObjectSpace(obj, &x, &y)) + foundFl = _vm.route().startRoute(GO_LOOK, objId, x, y); + if (!foundFl) // Can't get there, immediate description + _vm.lookObject(obj); + break; + case 0: // Immediate description + _vm.lookObject(obj); + break; + default: // Walk to view point if possible + if (!_vm.route().startRoute(GO_LOOK, objId, obj->viewx, obj->viewy)) { + if (_vm._hero->cycling == INVISIBLE) // If invisible do + _vm.lookObject(obj); // immediate decription + else + Utils::Box(BOX_ANY, "%s", _vm._textMouse[kMsNoWayText]); // Can't get there + } + break; + } + } + break; + } +} + +// Process mouse activity +void MouseHandler::mouseHandler() { + debugC(2, kDebugMouse, "mouseHandler"); + + int16 cx = _vm.getMouseX(); + int16 cy = _vm.getMouseY(); + + status_t &gameStatus = _vm.getGameStatus(); + + gameStatus.cx = cx; // Save cursor coords + gameStatus.cy = cy; + + // Don't process if outside client area + if (cx < 0 || cx > XPIX || cy < DIBOFF_Y || cy > VIEW_DY + DIBOFF_Y) + return; + + // Display dragged inventory icon if one currently selected + if (gameStatus.inventoryObjId != -1) { + // Find index of icon + int16 iconId; // Find index of dragged icon + for (iconId = 0; iconId < _vm._maxInvent; iconId++) { + if (gameStatus.inventoryObjId == _vm._invent[iconId]) + break; + } + + // Compute source coordinates in dib_u + int16 ux = (iconId + NUM_ARROWS) * INV_DX % XPIX; + int16 uy = (iconId + NUM_ARROWS) * INV_DX / XPIX * INV_DY; + + // Compute destination coordinates in dib_a + int iconx = cx + IX_OFF; + int icony = cy + IY_OFF; + iconx = MAX(iconx, 0); // Keep within dib_a bounds + iconx = MIN(iconx, XPIX - INV_DX); + icony = MAX(icony, 0); + icony = MIN(icony, YPIX - INV_DY); + + // Copy the icon and add to display list + _vm.screen().moveImage(_vm.screen().getGUIBuffer(), ux, uy, INV_DX, INV_DY, XPIX, _vm.screen().getFrontBuffer(), iconx, icony, XPIX); + _vm.screen().displayList(D_ADD, iconx, icony, INV_DX, INV_DY); + } + + int16 objId = -1; // Current source object + // Process cursor over an object or icon + if (gameStatus.inventoryState == I_ACTIVE) // Check inventory icon bar first + objId = _vm.inventory().processInventory(INV_GET, cx, cy); + if (objId == -1) // No match, check rest of view + objId = _vm.findObject(cx, cy); + if (objId >= 0) { // Got a match + // Display object name next to cursor (unless CURSOR_NOCHAR) + // Note test for swapped hero name + char *name = _vm._arrayNouns[_vm._objects[(objId == HERO) ? _vm._heroImage : objId].nounIndex][CURSOR_NAME]; + if (name[0] != CURSOR_NOCHAR) + cursorText(name, cx, cy, U_FONT8, _TBRIGHTWHITE); + + // Process right click over object in view or iconbar + if (gameStatus.rightButtonFl) + processRightClick(objId, cx, cy); + } + + // Process cursor over an exit hotspot + if (objId == -1) { + int i = findExit(cx, cy); + if (i != -1 && _vm._hotspots[i].viewx >= 0) { + objId = EXIT_HOTSPOT; + cursorText(_vm._textMouse[kMsExit], cx, cy, U_FONT8, _TBRIGHTWHITE); + } + } + + // Left click over icon, object or to move somewhere + if (gameStatus.leftButtonFl) + processLeftClick(objId, cx, cy); + + // Clear mouse click states + gameStatus.leftButtonFl = false; + gameStatus.rightButtonFl = false; +} + +} // End of namespace Hugo |