diff options
Diffstat (limited to 'engines/m4')
-rw-r--r-- | engines/m4/actor.cpp | 4 | ||||
-rw-r--r-- | engines/m4/converse.cpp | 6 | ||||
-rw-r--r-- | engines/m4/globals.cpp | 4 | ||||
-rw-r--r-- | engines/m4/gui.h | 10 | ||||
-rw-r--r-- | engines/m4/m4.cpp | 23 | ||||
-rw-r--r-- | engines/m4/m4.h | 5 | ||||
-rw-r--r-- | engines/m4/m4_menus.cpp | 14 | ||||
-rw-r--r-- | engines/m4/m4_views.cpp | 16 | ||||
-rw-r--r-- | engines/m4/m4_views.h | 6 | ||||
-rw-r--r-- | engines/m4/mads_views.cpp | 378 | ||||
-rw-r--r-- | engines/m4/mads_views.h | 84 | ||||
-rw-r--r-- | engines/m4/module.mk | 1 | ||||
-rw-r--r-- | engines/m4/scene.cpp | 420 | ||||
-rw-r--r-- | engines/m4/scene.h | 79 |
14 files changed, 581 insertions, 469 deletions
diff --git a/engines/m4/actor.cpp b/engines/m4/actor.cpp index e80bcac6ca..102001713f 100644 --- a/engines/m4/actor.cpp +++ b/engines/m4/actor.cpp @@ -149,11 +149,11 @@ void Inventory::moveObject(char* name, int32 scene) { } void Inventory::addToBackpack(uint32 objectIndex) { - _vm->_interfaceView->inventoryAdd(_inventory[objectIndex]->name, "", _inventory[objectIndex]->icon); + _m4Vm->scene()->getInterface()->inventoryAdd(_inventory[objectIndex]->name, "", _inventory[objectIndex]->icon); } void Inventory::removeFromBackpack(uint32 objectIndex) { - _vm->_interfaceView->inventoryRemove(_inventory[objectIndex]->name); + _m4Vm->scene()->getInterface()->inventoryRemove(_inventory[objectIndex]->name); } bool Inventory::isInCurrentScene(char* name) { diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp index 7bdc289742..18d61ef7ce 100644 --- a/engines/m4/converse.cpp +++ b/engines/m4/converse.cpp @@ -343,7 +343,7 @@ void Converse::startConversation(const char *convName, bool showConverseBox, Con _playerCommandsAllowed = _vm->_player->commandsAllowed; if (_vm->isM4()) // TODO: remove (interface not implemented yet in MADS games) - _interfaceWasVisible = _vm->_interfaceView->isVisible(); + _interfaceWasVisible = _m4Vm->scene()->getInterface()->isVisible(); _vm->_player->setCommandsAllowed(false); _style = style; @@ -352,7 +352,7 @@ void Converse::startConversation(const char *convName, bool showConverseBox, Con _vm->_mouse->lockCursor(CURSOR_ARROW); if (_interfaceWasVisible) - _vm->_interfaceView->hide(); + _m4Vm->scene()->getInterface()->hide(); _vm->_conversationView->setNode(0); _vm->_conversationView->show(); @@ -368,7 +368,7 @@ void Converse::endConversation() { _offsetMap.clear(); _vm->_player->setCommandsAllowed(_playerCommandsAllowed); if (_interfaceWasVisible) - _vm->_interfaceView->show(); + _m4Vm->scene()->getInterface()->show(); } void Converse::loadConversation(const char *convName) { diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp index 06bbcec9c1..39226f0ebc 100644 --- a/engines/m4/globals.cpp +++ b/engines/m4/globals.cpp @@ -271,7 +271,7 @@ Globals::Globals(MadsM4Engine *vm): _vm(vm) { } bool Globals::isInterfaceVisible() { - return _vm->_interfaceView->isVisible(); + return _m4Vm->scene()->getInterface()->isVisible(); } /*--------------------------------------------------------------------------*/ @@ -434,7 +434,7 @@ void Player::setCommandsAllowed(bool value) { if (value) { // Player commands are enabled again _vm->_mouse->lockCursor(CURSOR_ARROW); - //_vm->_interfaceView->cancelSentence(); + //_m4Vm->scene()->getInterface()->cancelSentence(); } else { // Player commands are disabled, so show hourglass cursor _vm->_mouse->lockCursor(CURSOR_HOURGLASS); diff --git a/engines/m4/gui.h b/engines/m4/gui.h index d03c092602..9d0f3e3f17 100644 --- a/engines/m4/gui.h +++ b/engines/m4/gui.h @@ -441,6 +441,16 @@ public: void keyMouseCollision() {} }; +class GameInterfaceView: public View { +public: + GameInterfaceView(MadsM4Engine *vm, const Common::Rect &rect): View(vm, rect) {}; + ~GameInterfaceView() {}; + + virtual void initialise() {}; + virtual void setSelectedObject(int objectNumber) {}; + virtual void addObjectToInventory(int objectNumber) {}; +}; + } #endif diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index fef646325c..7b3a84e98d 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -169,7 +169,6 @@ Common::Error MadsM4Engine::run() { _font = new Font(this); if (getGameType() == GType_Burger) { _actor = new Actor(this); - _interfaceView = new GameInterfaceView(this); _conversationView = new ConversationView(this); } else { _actor = NULL; @@ -352,8 +351,6 @@ Common::Error M4Engine::run() { burger_inventory[i].icon); _inventory->addToBackpack(i); // debug: this adds ALL objects to the player's backpack } - - _viewManager->addView(_interfaceView); } // Show intro @@ -420,6 +417,8 @@ Common::Error M4Engine::run() { _kernel->roomInit(); + _scene->show(); + #ifdef INTRO_TEST if (_kernel->currentRoom == 951) { curPart = 0; @@ -516,17 +515,17 @@ Common::Error MadsEngine::run() { _mouse->setCursorNum(0); // Load MADS data files - MadsGlobals *globals = (MadsGlobals *)_globals; - globals->loadMadsVocab(); // vocab.dat - globals->loadMadsQuotes(); // quotes.dat - globals->loadMadsMessagesInfo(); // messages.dat - globals->loadMadsObjects(); + MadsGlobals *globs = (MadsGlobals *)_globals; + globs->loadMadsVocab(); // vocab.dat + globs->loadMadsQuotes(); // quotes.dat + globs->loadMadsMessagesInfo(); // messages.dat + globs->loadMadsObjects(); // Setup globals - globals->easyMouse = true; - globals->invObjectsStill = false; - globals->textWindowStill = false; - globals->storyMode = 0; + globs->easyMouse = true; + globs->invObjectsStill = false; + globs->textWindowStill = false; + globs->storyMode = 0; // Test code to dump all messages to the console //for (int i = 0; i < _globals->getMessagesSize(); i++) diff --git a/engines/m4/m4.h b/engines/m4/m4.h index 29f3acce34..80aba64188 100644 --- a/engines/m4/m4.h +++ b/engines/m4/m4.h @@ -80,7 +80,7 @@ class Scene; class ViewManager; class View; class Inventory; -class GameInterfaceView; +class M4InterfaceView; class ConversationView; class Actor; class Converse; @@ -190,7 +190,6 @@ public: Dialogs *_dialogs; M4Surface *_screen; Inventory *_inventory; - GameInterfaceView *_interfaceView; ConversationView *_conversationView; Sound *_sound; Rails *_rails; @@ -199,6 +198,8 @@ public: WoodScript *_ws; Animation *_animation; Common::RandomSource *_random; + + Scene *scene() { return _scene; }; }; class MadsEngine: public MadsM4Engine { diff --git a/engines/m4/m4_menus.cpp b/engines/m4/m4_menus.cpp index e48e076066..118b09f50b 100644 --- a/engines/m4/m4_menus.cpp +++ b/engines/m4/m4_menus.cpp @@ -328,9 +328,9 @@ OrionMenuView::OrionMenuView(MadsM4Engine *Vm, int x, int y, MenuType menuType, _calledFromMainMenu = calledFromMainMenu; _loadSaveFromHotkey = loadSaveFromHotkey; - _interfaceWasVisible = _vm->_interfaceView->isVisible(); + _interfaceWasVisible = _m4Vm->scene()->getInterface()->isVisible(); if (_interfaceWasVisible) - _vm->_interfaceView->hide(); + _m4Vm->scene()->getInterface()->hide(); _vm->_mouse->setCursorNum(CURSOR_ARROW); @@ -496,11 +496,11 @@ M4Surface *OrionMenuView::createThumbnail() { // Translate the game interface view - since it's using standard colors that can't be // averaged, simply take the top left pixel of every 3x3 pixel block - _vm->_interfaceView->onRefresh(NULL, &srcSurface); - destP = result->getBasePtr(0, 0) + (_vm->_screen->width() / 3) * (_vm->_interfaceView->bounds().top / 3); + _m4Vm->scene()->getInterface()->onRefresh(NULL, &srcSurface); + destP = result->getBasePtr(0, 0) + (_vm->_screen->width() / 3) * (_m4Vm->scene()->getInterface()->bounds().top / 3); - int yStart = _vm->_interfaceView->bounds().top; - int yEnd = MIN(_vm->_screen->height() - 1, (int) _vm->_interfaceView->bounds().bottom - 1); + int yStart = _m4Vm->scene()->getInterface()->bounds().top; + int yEnd = MIN(_vm->_screen->height() - 1, (int) _m4Vm->scene()->getInterface()->bounds().bottom - 1); for (int yCtr = yStart; yCtr <= yEnd; yCtr += 3) { srcP = (byte *)srcSurface.getBasePtr(0, yCtr) + (yCtr * _vm->_screen->width()); @@ -526,7 +526,7 @@ void OrionMenuView::destroyView() { engine->_palette->fadeFromGreen(M4_DIALOG_FADE_STEPS, M4_DIALOG_FADE_DELAY, fadeToBlack); if (interfaceVisible) - engine->_interfaceView->show(); + engine->scene()->showInterface(); } } diff --git a/engines/m4/m4_views.cpp b/engines/m4/m4_views.cpp index 93ff74b879..3d633cef0d 100644 --- a/engines/m4/m4_views.cpp +++ b/engines/m4/m4_views.cpp @@ -127,7 +127,7 @@ bool GUIInventory::onEvent(M4EventType eventType, int32 param, int x, int y, GUI if (result) { for (int i = 0; i < overIndex + _scrollPosition; i++) ++curItem; - _vm->_interfaceView->setStatusText(curItem->get()->name); + _m4Vm->scene()->getInterface()->setStatusText(curItem->get()->name); } } @@ -218,8 +218,8 @@ const char *INTERFACE_SERIES = "999intr"; #define SPR(x) _sprites->getFrame(x) -GameInterfaceView::GameInterfaceView(MadsM4Engine *vm): - View(vm, Common::Rect(0, vm->_screen->height() - INTERFACE_HEIGHT, +M4InterfaceView::M4InterfaceView(MadsM4Engine *vm): + GameInterfaceView(vm, Common::Rect(0, vm->_screen->height() - INTERFACE_HEIGHT, vm->_screen->width(), vm->_screen->height())), _statusText(GUITextField(this, Common::Rect(200, 1, 450, 21))), _inventory(GUIInventory(this, vm, Common::Rect(188, 22, 539, 97), 9, 1, 39, 75, 3)) { @@ -256,11 +256,11 @@ GameInterfaceView::GameInterfaceView(MadsM4Engine *vm): #undef SPR -GameInterfaceView::~GameInterfaceView() { +M4InterfaceView::~M4InterfaceView() { delete _sprites; } -void GameInterfaceView::setHighlightedButton(int index) { +void M4InterfaceView::setHighlightedButton(int index) { if (index == _highlightedIndex) return; @@ -268,7 +268,7 @@ void GameInterfaceView::setHighlightedButton(int index) { _highlightedIndex = index; } -bool GameInterfaceView::onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents) { +bool M4InterfaceView::onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents) { static bool selectionFlag = false; if (eventType == MEVENT_LEFT_RELEASE) selectionFlag = false; @@ -287,7 +287,7 @@ bool GameInterfaceView::onEvent(M4EventType eventType, int32 param, int x, int y if (_vm->_mouse->getCursorNum() != CURSOR_LOOK && _vm->_mouse->getCursorNum() != CURSOR_TAKE && _vm->_mouse->getCursorNum() != CURSOR_USE && - _vm->_interfaceView->_inventory.getSelectedIndex() == -1) { + _m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) { if (_vm->_mouse->getCursorNum() != 0) _vm->_mouse->setCursorNum(0); } @@ -330,7 +330,7 @@ bool GameInterfaceView::onEvent(M4EventType eventType, int32 param, int x, int y return true; } -void GameInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) { +void M4InterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) { clear(); _statusText.onRefresh(); diff --git a/engines/m4/m4_views.h b/engines/m4/m4_views.h index 02e34fead0..0cf8ceac5d 100644 --- a/engines/m4/m4_views.h +++ b/engines/m4/m4_views.h @@ -87,7 +87,7 @@ public: void setVisible(bool value) { _visible = value; } }; -class GameInterfaceView: public View { +class M4InterfaceView: public GameInterfaceView { typedef Common::List<Common::SharedPtr<GUIButton> > ButtonList; typedef ButtonList::iterator ButtonsIterator; public: @@ -100,8 +100,8 @@ public: private: void setHighlightedButton(int index); public: - GameInterfaceView(MadsM4Engine *vm); - ~GameInterfaceView(); + M4InterfaceView(MadsM4Engine *vm); + ~M4InterfaceView(); void onRefresh(RectList *rects, M4Surface *destSurface); bool onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents); diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp new file mode 100644 index 0000000000..d4d3bc53cb --- /dev/null +++ b/engines/m4/mads_views.cpp @@ -0,0 +1,378 @@ +/* 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$ + * + */ + +#include "m4/m4_views.h" +#include "m4/dialogs.h" +#include "m4/events.h" +#include "m4/font.h" +#include "m4/globals.h" +#include "m4/m4.h" +#include "m4/staticres.h" + +namespace M4 { + +static const int INV_ANIM_FRAME_SPEED = 8; +static const int INVENTORY_X = 160; +static const int INVENTORY_Y = 159; +static const int SCROLLER_DELAY = 200; + +/*-------------------------------------------------------------------------- + * MadsInterfaceView handles the user interface section at the bottom of + * game screens in MADS games + *-------------------------------------------------------------------------- + */ + +MadsInterfaceView::MadsInterfaceView(MadsM4Engine *vm): GameInterfaceView(vm, + Common::Rect(0, MADS_SURFACE_HEIGHT, vm->_screen->width(), vm->_screen->height())) { + _screenType = VIEWID_INTERFACE; + _highlightedElement = -1; + _topIndex = 0; + _selectedObject = -1; + _cheatKeyCtr = 0; + + _objectSprites = NULL; + _objectPalData = NULL; + + /* Set up the rect list for screen elements */ + // Actions + for (int i = 0; i < 10; ++i) + _screenObjects.addRect((i / 5) * 32 + 1, (i % 5) * 8 + MADS_SURFACE_HEIGHT + 2, + ((i / 5) + 1) * 32 + 3, ((i % 5) + 1) * 8 + MADS_SURFACE_HEIGHT + 2); + + // Scroller elements (up arrow, scroller, down arrow) + _screenObjects.addRect(73, 160, 82, 167); + _screenObjects.addRect(73, 168, 82, 190); + _screenObjects.addRect(73, 191, 82, 198); + + // Inventory object names + for (int i = 0; i < 5; ++i) + _screenObjects.addRect(89, 158 + i * 8, 160, 166 + i * 8); + + // Full rectangle area for all vocab actions + for (int i = 0; i < 5; ++i) + _screenObjects.addRect(239, 158 + i * 8, 320, 166 + i * 8); +} + +MadsInterfaceView::~MadsInterfaceView() { + delete _objectSprites; +} + +void MadsInterfaceView::setFontMode(InterfaceFontMode newMode) { + switch (newMode) { + case ITEM_NORMAL: + _vm->_font->setColors(4, 4, 0xff); + break; + case ITEM_HIGHLIGHTED: + _vm->_font->setColors(5, 5, 0xff); + break; + case ITEM_SELECTED: + _vm->_font->setColors(6, 6, 0xff); + break; + } +} + +void MadsInterfaceView::initialise() { + // Build up the inventory list + _inventoryList.clear(); + + for (uint i = 0; i < _madsVm->globals()->getObjectsSize(); ++i) { + MadsObject *obj = _madsVm->globals()->getObject(i); + if (obj->roomNumber == PLAYER_INVENTORY) + _inventoryList.push_back(i); + } + + // If the inventory has at least one object, select it + if (_inventoryList.size() > 0) + setSelectedObject(_inventoryList[0]); +} + +void MadsInterfaceView::setSelectedObject(int objectNumber) { + char resName[80]; + + // Load inventory resource + if (_objectSprites) { + _vm->_palette->deleteRange(_objectPalData); + delete _objectSprites; + } + + // Check to make sure the object is in the inventory, and also visible on-screen + int idx = _inventoryList.indexOf(objectNumber); + if (idx == -1) { + // Object wasn't found, so return + _selectedObject = -1; + return; + } + + // Found the object + if (idx < _topIndex) + _topIndex = idx; + else if (idx >= (_topIndex + 5)) + _topIndex = MAX(0, idx - 4); + + _selectedObject = objectNumber; + sprintf(resName, "*OB%.3dI.SS", objectNumber); + + Common::SeekableReadStream *data = _vm->res()->get(resName); + _objectSprites = new SpriteAsset(_vm, data, data->size(), resName); + _vm->res()->toss(resName); + + // Slot it into available palette space + _objectPalData = _objectSprites->getRgbList(); + _vm->_palette->addRange(_objectPalData); + _objectSprites->translate(_objectPalData, true); + + _objectFrameNumber = 0; +} + +void MadsInterfaceView::addObjectToInventory(int objectNumber) { + if (_inventoryList.indexOf(objectNumber) == -1) { + _madsVm->globals()->getObject(objectNumber)->roomNumber = PLAYER_INVENTORY; + _inventoryList.push_back(objectNumber); + } + + setSelectedObject(objectNumber); +} + +void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) { + _vm->_font->setFont(FONT_INTERFACE_MADS); + char buffer[100]; + + // Check to see if any dialog is currently active + bool dialogVisible = _vm->_viewManager->getView(LAYER_DIALOG) != NULL; + + // Highlighting logic for action list + int actionIndex = 0; + for (int x = 0; x < 2; ++x) { + for (int y = 0; y < 5; ++y, ++actionIndex) { + // Determine the font colour depending on whether an item is selected. Note that the first action, + // 'Look', is always 'selected', even when another action is clicked on + setFontMode((_highlightedElement == actionIndex) ? ITEM_HIGHLIGHTED : + ((actionIndex == 0) ? ITEM_SELECTED : ITEM_NORMAL)); + + // Get the verb action and capitalise it + const char *verbStr = _madsVm->globals()->getVocab(kVerbLook + actionIndex); + strcpy(buffer, verbStr); + if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; + + // Display the verb + const Common::Rect r(_screenObjects[actionIndex]); + _vm->_font->writeString(destSurface, buffer, r.left, r.top, r.width(), 0); + } + } + + // Check for highlighting of the scrollbar controls + if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_SCROLLER) || (_highlightedElement == SCROLL_DOWN)) { + // Highlight the control's borders + const Common::Rect r(_screenObjects[_highlightedElement]); + destSurface->frameRect(r, 5); + } + + // Draw the horizontal line in the scroller representing the current top selected + const Common::Rect scroller(_screenObjects[SCROLL_SCROLLER]); + int yP = (_inventoryList.size() < 2) ? 0 : (scroller.height() - 5) * _topIndex / (_inventoryList.size() - 1); + destSurface->setColor(4); + destSurface->hLine(scroller.left + 2, scroller.right - 3, scroller.top + 2 + yP); + + // List inventory items + for (uint i = 0; i < 5; ++i) { + if ((_topIndex + i) >= _inventoryList.size()) + break; + + const char *descStr = _madsVm->globals()->getVocab(_madsVm->globals()->getObject( + _inventoryList[_topIndex + i])->descId); + strcpy(buffer, descStr); + if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; + + const Common::Rect r(_screenObjects[INVLIST_START + i]); + + // Set the highlighting of the inventory item + if (_highlightedElement == (int)(INVLIST_START + i)) setFontMode(ITEM_HIGHLIGHTED); + else if (_selectedObject == _inventoryList[_topIndex + i]) setFontMode(ITEM_SELECTED); + else setFontMode(ITEM_NORMAL); + + // Write out it's description + _vm->_font->writeString(destSurface, buffer, r.left, r.top, r.width(), 0); + } + + // Handle the display of any currently selected object + if (_objectSprites) { + // Display object sprite. Note that the frame number isn't used directly, because it would result + // in too fast an animation + M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED); + spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, 0); + + if (!_madsVm->globals()->invObjectsStill && !dialogVisible) { + // If objetcs are to animated, move to the next frame + if (++_objectFrameNumber >= (_objectSprites->getCount() * INV_ANIM_FRAME_SPEED)) + _objectFrameNumber = 0; + } + + // List the vocab actions for the currently selected object + MadsObject *obj = _madsVm->globals()->getObject(_selectedObject); + int yIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1); + + for (int i = 0; i < obj->vocabCount; ++i) { + const Common::Rect r(_screenObjects[VOCAB_START + i]); + + // Get the vocab description and capitalise it + const char *descStr = _madsVm->globals()->getVocab(obj->vocabList[i].vocabId); + strcpy(buffer, descStr); + if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; + + // Set the highlighting and display the entry + setFontMode((i == yIndex) ? ITEM_HIGHLIGHTED : ITEM_NORMAL); + _vm->_font->writeString(destSurface, buffer, r.left, r.top, r.width(), 0); + } + } +} + +bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) { + // If the mouse isn't being held down, then reset the repeated scroll timer + if (eventType != MEVENT_LEFT_HOLD) + _nextScrollerTicks = 0; + + // Handle various event types + switch (eventType) { + case MEVENT_MOVE: + // If the cursor isn't in "wait mode", don't do any processing + if (_vm->_mouse->getCursorNum() == CURSOR_WAIT) + return true; + + // Ensure the cursor is the standard arrow + _vm->_mouse->setCursorNum(CURSOR_ARROW); + + // Check if any interface element is currently highlighted + _highlightedElement = _screenObjects.find(Common::Point(x, y)); + + return true; + + case MEVENT_LEFT_CLICK: + // Left mouse click + // Check if an inventory object was selected + if ((_highlightedElement >= INVLIST_START) && (_highlightedElement < (INVLIST_START + 5))) { + // Ensure there is an inventory item listed in that cell + uint idx = _highlightedElement - INVLIST_START; + if ((_topIndex + idx) < _inventoryList.size()) { + // Set the selected object + setSelectedObject(_inventoryList[_topIndex + idx]); + } + } else if ((_highlightedElement >= ACTIONS_START) && (_highlightedElement < (ACTIONS_START + 10))) { + // A standard action was selected + _vm->_scene->setAction(kVerbLook + (_highlightedElement - ACTIONS_START)); + } else if ((_highlightedElement >= VOCAB_START) && (_highlightedElement < (VOCAB_START + 5))) { + // A vocab action was selected + MadsObject *obj = _madsVm->globals()->getObject(_selectedObject); + int vocabIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1); + if (vocabIndex >= 0) + _vm->_scene->setAction(obj->vocabList[vocabIndex].vocabId, _selectedObject); + } + + return true; + + case MEVENT_LEFT_HOLD: + // Left mouse hold + // Handle the scroller - the up/down buttons allow for multiple actions whilst the mouse is held down + if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_DOWN)) { + if ((_nextScrollerTicks == 0) || (g_system->getMillis() >= _nextScrollerTicks)) { + // Handle scroll up/down action + _nextScrollerTicks = g_system->getMillis() + SCROLLER_DELAY; + + if ((_highlightedElement == SCROLL_UP) && (_topIndex > 0)) + --_topIndex; + if ((_highlightedElement == SCROLL_DOWN) && (_topIndex < (int)(_inventoryList.size() - 1))) + ++_topIndex; + } + } + return true; + + case MEVENT_LEFT_DRAG: + // Left mouse drag + // Handle the the the scroller area that can be dragged to adjust the top displayed index + if (_highlightedElement == SCROLL_SCROLLER) { + // Calculate the new top index based on the Y position + const Common::Rect r(_screenObjects[SCROLL_SCROLLER]); + _topIndex = CLIP((int)(_inventoryList.size() - 1) * (y - r.top - 2) / (r.height() - 5), + 0, (int)_inventoryList.size() - 1); + } + return true; + + case KEVENT_KEY: + if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX) + handleCheatKey(param1); + handleKeypress(param1); + return true; + + default: + break; + } + + return false; +} + +bool MadsInterfaceView::handleCheatKey(int32 keycode) { + switch (keycode) { + case Common::KEYCODE_SPACE: + // TODO: Move player to current destination + return true; + + case Common::KEYCODE_t | (Common::KEYCODE_LALT): + case Common::KEYCODE_t | (Common::KEYCODE_RALT): + { + // Teleport to room + //Scene *sceneView = (Scene *)vm->_viewManager->getView(VIEWID_SCENE); + + + return true; + } + + default: + break; + } + + return false; +} + +const char *CHEAT_SEQUENCE = "widepipe"; + +bool MadsInterfaceView::handleKeypress(int32 keycode) { + int flags = keycode >> 24; + int kc = keycode & 0xffff; + + // Capitalise the letter if necessary + if (_cheatKeyCtr < CHEAT_SEQUENCE_MAX) { + if ((flags == Common::KBD_CTRL) && (kc == CHEAT_SEQUENCE[_cheatKeyCtr])) { + ++_cheatKeyCtr; + if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX) + Dialog::display(_vm, 22, cheatingEnabledDesc); + return true; + } else { + _cheatKeyCtr = 0; + } + } + + return false; +} + +} // End of namespace M4 diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h new file mode 100644 index 0000000000..3fbd20c2b1 --- /dev/null +++ b/engines/m4/mads_views.h @@ -0,0 +1,84 @@ +/* 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$ + * + */ + +#ifndef M4_MADS_VIEWS_H +#define M4_MADS_VIEWS_H + +#include "m4/gui.h" +#include "m4/viewmgr.h" +#include "common/rect.h" +#include "common/list.h" +#include "common/ptr.h" + +namespace M4 { + +class IntegerList: public Common::Array<int> { +public: + int indexOf(int v) { + for (uint i = 0; i < size(); ++i) + if (operator [](i) == v) + return i; + return -1; + } +}; + +enum InterfaceFontMode {ITEM_NORMAL, ITEM_HIGHLIGHTED, ITEM_SELECTED}; + +enum InterfaceObjects {ACTIONS_START = 0, SCROLL_UP = 10, SCROLL_SCROLLER = 11, SCROLL_DOWN = 12, + INVLIST_START = 13, VOCAB_START = 18}; + +class MadsInterfaceView: public GameInterfaceView { +private: + IntegerList _inventoryList; + RectList _screenObjects; + int _highlightedElement; + int _topIndex; + uint32 _nextScrollerTicks; + int _cheatKeyCtr; + + // Object display fields + int _selectedObject; + SpriteAsset *_objectSprites; + RGBList *_objectPalData; + int _objectFrameNumber; + + void setFontMode(InterfaceFontMode newMode); + bool handleCheatKey(int32 keycode); + bool handleKeypress(int32 keycode); +public: + MadsInterfaceView(MadsM4Engine *vm); + ~MadsInterfaceView(); + + virtual void initialise(); + virtual void setSelectedObject(int objectNumber); + virtual void addObjectToInventory(int objectNumber); + + void onRefresh(RectList *rects, M4Surface *destSurface); + bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); +}; + +} + +#endif diff --git a/engines/m4/module.mk b/engines/m4/module.mk index 31746be5af..f6b9fa01cc 100644 --- a/engines/m4/module.mk +++ b/engines/m4/module.mk @@ -20,6 +20,7 @@ MODULE_OBJS = \ m4_views.o \ mads_anim.o \ mads_menus.o \ + mads_views.o \ midi.o \ rails.o \ resource.o \ diff --git a/engines/m4/scene.cpp b/engines/m4/scene.cpp index ca4ba732ee..6d4c4ae64d 100644 --- a/engines/m4/scene.cpp +++ b/engines/m4/scene.cpp @@ -33,17 +33,12 @@ #include "m4/rails.h" #include "m4/font.h" #include "m4/m4_views.h" +#include "m4/mads_views.h" #include "m4/compression.h" #include "m4/staticres.h" namespace M4 { -static const int INV_ANIM_FRAME_SPEED = 8; -static const int INVENTORY_X = 160; -static const int INVENTORY_Y = 159; -static const int SCROLLER_DELAY = 200; - - Scene::Scene(MadsM4Engine *vm): View(vm, Common::Rect(0, 0, vm->_screen->width(), vm->_screen->height())) { _screenType = VIEWID_SCENE; @@ -56,7 +51,6 @@ Scene::Scene(MadsM4Engine *vm): View(vm, Common::Rect(0, 0, vm->_screen->width() _interfacePal = NULL; _interfaceSurface = NULL; _inverseColorTable = NULL; - strcpy(_statusText, ""); _vm->_rails->setCodeSurface(_codeSurface); } @@ -98,6 +92,14 @@ void Scene::show() { _vm->_viewManager->addView(this); } +void Scene::showInterface() { + _vm->_viewManager->addView(_interfaceSurface); +} + +void Scene::hideInterface() { + _vm->_viewManager->deleteView(_interfaceSurface); +} + void Scene::loadSceneResources(int sceneNumber) { char filename[kM4MaxFilenameSize]; int i = 0, x = 0, y = 0; @@ -280,28 +282,6 @@ void Scene::playIntro() { } -void Scene::update() { - // TODO: Needs a proper implementation - // NOTE: Don't copy the background when in M4 mode or WoodScript anims won't be shown - if (!_vm->isM4()) { - _backgroundSurface->copyTo(this); - - // Handle display of any status text - if (_statusText[0]) { - // Text colors are inverted in Dragonsphere - if (_vm->getGameType() == GType_DragonSphere) - _vm->_font->setColors(_vm->_palette->BLACK, _vm->_palette->WHITE, _vm->_palette->BLACK); - else - _vm->_font->setColors(_vm->_palette->WHITE, _vm->_palette->BLACK, _vm->_palette->BLACK); - - _vm->_font->setFont(FONT_MAIN_MADS); - _vm->_font->writeString(this, _statusText, (width() - _vm->_font->getWidth(_statusText)) / 2, 142, 0); - } - - _interfaceSurface->copyTo(this, 0, this->height() - _interfaceSurface->height()); - } -} - void Scene::onRefresh(RectList *rects, M4Surface *destSurface) { update(); View::onRefresh(rects, destSurface); @@ -435,6 +415,7 @@ void Scene::showMADSV2TextBox(char *text, int x, int y, char *faceName) { M4Scene::M4Scene(M4Engine *vm): Scene(vm) { _vm = vm; _sceneSprites = NULL; + _interfaceSurface = new M4InterfaceView(vm); } M4Scene::~M4Scene() { @@ -460,7 +441,7 @@ void M4Scene::loadScene(int sceneNumber) { if (_vm->getGameType() == GType_Burger && sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER) - _vm->_interfaceView->setStatusText(""); + setStatusText(""); // Load scene def file (*.CHK) loadSceneResources(sceneNumber); @@ -485,7 +466,7 @@ void M4Scene::loadScene(int sceneNumber) { if (sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER) { - _vm->_interfaceView->show(); + _m4Vm->scene()->getInterface()->show(); showSprites(); } @@ -503,6 +484,11 @@ void M4Scene::loadSceneCodes(int sceneNumber, int index) { _vm->res()->toss(filename); } +void M4Scene::show() { + Scene::show(); + _vm->_viewManager->addView(_interfaceSurface); +} + void M4Scene::checkHotspotAtMousePos(int x, int y) { if (_vm->getGameType() == GType_Riddle) return; @@ -517,15 +503,15 @@ void M4Scene::checkHotspotAtMousePos(int x, int y) { if (_vm->_mouse->getCursorNum() != CURSOR_LOOK && _vm->_mouse->getCursorNum() != CURSOR_TAKE && _vm->_mouse->getCursorNum() != CURSOR_USE && - _vm->_interfaceView->_inventory.getSelectedIndex() == -1) { + _m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) { _vm->_mouse->setCursorNum(currentHotSpot->getCursor()); } - _vm->_interfaceView->setStatusText(currentHotSpot->getPrep()); + _m4Vm->scene()->getInterface()->setStatusText(currentHotSpot->getPrep()); } else { if (_vm->_mouse->getCursorNum() != CURSOR_LOOK && _vm->_mouse->getCursorNum() != CURSOR_TAKE && _vm->_mouse->getCursorNum() != CURSOR_USE && - _vm->_interfaceView->_inventory.getSelectedIndex() == -1) { + _m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) { _vm->_mouse->setCursorNum(0); } else { @@ -551,14 +537,14 @@ void M4Scene::leftClick(int x, int y) { printf("Player said: %s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab()); // FIXME: This should be moved somewhere else, and is incomplete - if (_vm->_interfaceView->_inventory.getSelectedIndex() == -1) { + if (_m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) { if (_vm->_mouse->getVerb() == NULL) { strcpy(_vm->_player->verb, currentHotSpot->getVerb()); } else { strcpy(_vm->_player->verb, _vm->_mouse->getVerb()); } } else { - strcpy(_vm->_player->verb, _vm->_interfaceView->_inventory.getSelectedObjectName()); + strcpy(_vm->_player->verb, _m4Vm->scene()->getInterface()->_inventory.getSelectedObjectName()); } strcpy(_vm->_player->noun, currentHotSpot->getVocab()); strcpy(_vm->_player->object, ""); @@ -573,13 +559,21 @@ void M4Scene::leftClick(int x, int y) { void M4Scene::rightClick(int x, int y) { if (_vm->getGameType() == GType_Burger) { nextCommonCursor(); - _vm->_interfaceView->_inventory.clearSelected(); + _m4Vm->scene()->getInterface()->_inventory.clearSelected(); } } void M4Scene::setAction(int action, int objectId) { } +void M4Scene::setStatusText(const char *text) { + getInterface()->setStatusText(text); +} + +void M4Scene::update() { + +} + void M4Scene::nextCommonCursor() { int cursorIndex = _vm->_mouse->getCursorNum(); @@ -608,6 +602,7 @@ void M4Scene::nextCommonCursor() { MadsScene::MadsScene(MadsEngine *vm): Scene(vm) { _vm = vm; + strcpy(_statusText, ""); _interfaceSurface = new MadsInterfaceView(vm); _currentAction = kVerbNone; } @@ -705,10 +700,10 @@ void MadsScene::checkHotspotAtMousePos(int x, int y) { sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(verbId), currentHotSpot->getVocab()); statusText[0] = toupper(statusText[0]); // capitalize first letter - setMADSStatusText(statusText); + setStatusText(statusText); } else { _vm->_mouse->setCursorNum(0); - setMADSStatusText(""); + setStatusText(""); } } @@ -723,7 +718,7 @@ void MadsScene::leftClick(int x, int y) { } statusText[0] = toupper(statusText[0]); // capitalize first letter - setMADSStatusText(statusText); + setStatusText(statusText); } } @@ -754,344 +749,29 @@ void MadsScene::setAction(int action, int objectId) { _currentAction = action; } - setMADSStatusText(statusText); + setStatusText(statusText); } -/*-------------------------------------------------------------------------- - * MadsInterfaceView handles the user interface section at the bottom of - * game screens in MADS games - *-------------------------------------------------------------------------- - */ - -MadsInterfaceView::MadsInterfaceView(MadsM4Engine *vm): InterfaceView(vm, Common::Rect(0, MADS_SURFACE_HEIGHT, - vm->_screen->width(), vm->_screen->height())) { - _screenType = VIEWID_INTERFACE; - _highlightedElement = -1; - _topIndex = 0; - _selectedObject = -1; - _cheatKeyCtr = 0; - - _objectSprites = NULL; - _objectPalData = NULL; - - /* Set up the rect list for screen elements */ - // Actions - for (int i = 0; i < 10; ++i) - _screenObjects.addRect((i / 5) * 32 + 1, (i % 5) * 8 + MADS_SURFACE_HEIGHT + 2, - ((i / 5) + 1) * 32 + 3, ((i % 5) + 1) * 8 + MADS_SURFACE_HEIGHT + 2); - - // Scroller elements (up arrow, scroller, down arrow) - _screenObjects.addRect(73, 160, 82, 167); - _screenObjects.addRect(73, 168, 82, 190); - _screenObjects.addRect(73, 191, 82, 198); - - // Inventory object names - for (int i = 0; i < 5; ++i) - _screenObjects.addRect(89, 158 + i * 8, 160, 166 + i * 8); - - // Full rectangle area for all vocab actions - for (int i = 0; i < 5; ++i) - _screenObjects.addRect(239, 158 + i * 8, 320, 166 + i * 8); +void MadsScene::setStatusText(const char *text) { + strcpy(_statusText, text); } -MadsInterfaceView::~MadsInterfaceView() { - delete _objectSprites; -} +void MadsScene::update() { + _backgroundSurface->copyTo(this); -void MadsInterfaceView::setFontMode(InterfaceFontMode newMode) { - switch (newMode) { - case ITEM_NORMAL: - _vm->_font->setColors(4, 4, 0xff); - break; - case ITEM_HIGHLIGHTED: - _vm->_font->setColors(5, 5, 0xff); - break; - case ITEM_SELECTED: - _vm->_font->setColors(6, 6, 0xff); - break; - } -} - -void MadsInterfaceView::initialise() { - // Build up the inventory list - _inventoryList.clear(); - - for (uint i = 0; i < _madsVm->globals()->getObjectsSize(); ++i) { - MadsObject *obj = _madsVm->globals()->getObject(i); - if (obj->roomNumber == PLAYER_INVENTORY) - _inventoryList.push_back(i); - } - - // If the inventory has at least one object, select it - if (_inventoryList.size() > 0) - setSelectedObject(_inventoryList[0]); -} - -void MadsInterfaceView::setSelectedObject(int objectNumber) { - char resName[80]; - - // Load inventory resource - if (_objectSprites) { - _vm->_palette->deleteRange(_objectPalData); - delete _objectSprites; - } - - // Check to make sure the object is in the inventory, and also visible on-screen - int idx = _inventoryList.indexOf(objectNumber); - if (idx == -1) { - // Object wasn't found, so return - _selectedObject = -1; - return; - } - - // Found the object - if (idx < _topIndex) - _topIndex = idx; - else if (idx >= (_topIndex + 5)) - _topIndex = MAX(0, idx - 4); - - _selectedObject = objectNumber; - sprintf(resName, "*OB%.3dI.SS", objectNumber); - - Common::SeekableReadStream *data = _vm->res()->get(resName); - _objectSprites = new SpriteAsset(_vm, data, data->size(), resName); - _vm->res()->toss(resName); - - // Slot it into available palette space - _objectPalData = _objectSprites->getRgbList(); - _vm->_palette->addRange(_objectPalData); - _objectSprites->translate(_objectPalData, true); - - _objectFrameNumber = 0; -} - -void MadsInterfaceView::addObjectToInventory(int objectNumber) { - if (_inventoryList.indexOf(objectNumber) == -1) { - _madsVm->globals()->getObject(objectNumber)->roomNumber = PLAYER_INVENTORY; - _inventoryList.push_back(objectNumber); - } - - setSelectedObject(objectNumber); -} - -void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) { - _vm->_font->setFont(FONT_INTERFACE_MADS); - char buffer[100]; - - // Check to see if any dialog is currently active - bool dialogVisible = _vm->_viewManager->getView(LAYER_DIALOG) != NULL; - - // Highlighting logic for action list - int actionIndex = 0; - for (int x = 0; x < 2; ++x) { - for (int y = 0; y < 5; ++y, ++actionIndex) { - // Determine the font colour depending on whether an item is selected. Note that the first action, - // 'Look', is always 'selected', even when another action is clicked on - setFontMode((_highlightedElement == actionIndex) ? ITEM_HIGHLIGHTED : - ((actionIndex == 0) ? ITEM_SELECTED : ITEM_NORMAL)); - - // Get the verb action and capitalise it - const char *verbStr = _madsVm->globals()->getVocab(kVerbLook + actionIndex); - strcpy(buffer, verbStr); - if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; - - // Display the verb - const Common::Rect r(_screenObjects[actionIndex]); - _vm->_font->writeString(destSurface, buffer, r.left, r.top, r.width(), 0); - } - } - - // Check for highlighting of the scrollbar controls - if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_SCROLLER) || (_highlightedElement == SCROLL_DOWN)) { - // Highlight the control's borders - const Common::Rect r(_screenObjects[_highlightedElement]); - destSurface->frameRect(r, 5); - } - - // Draw the horizontal line in the scroller representing the current top selected - const Common::Rect scroller(_screenObjects[SCROLL_SCROLLER]); - int yP = (_inventoryList.size() < 2) ? 0 : (scroller.height() - 5) * _topIndex / (_inventoryList.size() - 1); - destSurface->setColor(4); - destSurface->hLine(scroller.left + 2, scroller.right - 3, scroller.top + 2 + yP); - - // List inventory items - for (uint i = 0; i < 5; ++i) { - if ((_topIndex + i) >= _inventoryList.size()) - break; - - const char *descStr = _madsVm->globals()->getVocab(_madsVm->globals()->getObject( - _inventoryList[_topIndex + i])->descId); - strcpy(buffer, descStr); - if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; - - const Common::Rect r(_screenObjects[INVLIST_START + i]); - - // Set the highlighting of the inventory item - if (_highlightedElement == (int)(INVLIST_START + i)) setFontMode(ITEM_HIGHLIGHTED); - else if (_selectedObject == _inventoryList[_topIndex + i]) setFontMode(ITEM_SELECTED); - else setFontMode(ITEM_NORMAL); - - // Write out it's description - _vm->_font->writeString(destSurface, buffer, r.left, r.top, r.width(), 0); - } - - // Handle the display of any currently selected object - if (_objectSprites) { - // Display object sprite. Note that the frame number isn't used directly, because it would result - // in too fast an animation - M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED); - spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, 0); - - if (!_madsVm->globals()->invObjectsStill && !dialogVisible) { - // If objetcs are to animated, move to the next frame - if (++_objectFrameNumber >= (_objectSprites->getCount() * INV_ANIM_FRAME_SPEED)) - _objectFrameNumber = 0; - } - - // List the vocab actions for the currently selected object - MadsObject *obj = _madsVm->globals()->getObject(_selectedObject); - int yIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1); - - for (int i = 0; i < obj->vocabCount; ++i) { - const Common::Rect r(_screenObjects[VOCAB_START + i]); - - // Get the vocab description and capitalise it - const char *descStr = _madsVm->globals()->getVocab(obj->vocabList[i].vocabId); - strcpy(buffer, descStr); - if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A'; - - // Set the highlighting and display the entry - setFontMode((i == yIndex) ? ITEM_HIGHLIGHTED : ITEM_NORMAL); - _vm->_font->writeString(destSurface, buffer, r.left, r.top, r.width(), 0); - } - } -} - -bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) { - // If the mouse isn't being held down, then reset the repeated scroll timer - if (eventType != MEVENT_LEFT_HOLD) - _nextScrollerTicks = 0; - - // Handle various event types - switch (eventType) { - case MEVENT_MOVE: - // If the cursor isn't in "wait mode", don't do any processing - if (_vm->_mouse->getCursorNum() == CURSOR_WAIT) - return true; - - // Ensure the cursor is the standard arrow - _vm->_mouse->setCursorNum(CURSOR_ARROW); - - // Check if any interface element is currently highlighted - _highlightedElement = _screenObjects.find(Common::Point(x, y)); - - return true; - - case MEVENT_LEFT_CLICK: - // Left mouse click - // Check if an inventory object was selected - if ((_highlightedElement >= INVLIST_START) && (_highlightedElement < (INVLIST_START + 5))) { - // Ensure there is an inventory item listed in that cell - uint idx = _highlightedElement - INVLIST_START; - if ((_topIndex + idx) < _inventoryList.size()) { - // Set the selected object - setSelectedObject(_inventoryList[_topIndex + idx]); - } - } else if ((_highlightedElement >= ACTIONS_START) && (_highlightedElement < (ACTIONS_START + 10))) { - // A standard action was selected - _vm->_scene->setAction(kVerbLook + (_highlightedElement - ACTIONS_START)); - } else if ((_highlightedElement >= VOCAB_START) && (_highlightedElement < (VOCAB_START + 5))) { - // A vocab action was selected - MadsObject *obj = _madsVm->globals()->getObject(_selectedObject); - int vocabIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1); - if (vocabIndex >= 0) - _vm->_scene->setAction(obj->vocabList[vocabIndex].vocabId, _selectedObject); - } - - return true; - - case MEVENT_LEFT_HOLD: - // Left mouse hold - // Handle the scroller - the up/down buttons allow for multiple actions whilst the mouse is held down - if ((_highlightedElement == SCROLL_UP) || (_highlightedElement == SCROLL_DOWN)) { - if ((_nextScrollerTicks == 0) || (g_system->getMillis() >= _nextScrollerTicks)) { - // Handle scroll up/down action - _nextScrollerTicks = g_system->getMillis() + SCROLLER_DELAY; - - if ((_highlightedElement == SCROLL_UP) && (_topIndex > 0)) - --_topIndex; - if ((_highlightedElement == SCROLL_DOWN) && (_topIndex < (int)(_inventoryList.size() - 1))) - ++_topIndex; - } - } - return true; - - case MEVENT_LEFT_DRAG: - // Left mouse drag - // Handle the the the scroller area that can be dragged to adjust the top displayed index - if (_highlightedElement == SCROLL_SCROLLER) { - // Calculate the new top index based on the Y position - const Common::Rect r(_screenObjects[SCROLL_SCROLLER]); - _topIndex = CLIP((int)(_inventoryList.size() - 1) * (y - r.top - 2) / (r.height() - 5), - 0, (int)_inventoryList.size() - 1); - } - return true; - - case KEVENT_KEY: - if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX) - handleCheatKey(param1); - handleKeypress(param1); - return true; - - default: - break; - } - - return false; -} - -bool MadsInterfaceView::handleCheatKey(int32 keycode) { - switch (keycode) { - case Common::KEYCODE_SPACE: - // TODO: Move player to current destination - return true; - - case Common::KEYCODE_t | (Common::KEYCODE_LALT): - case Common::KEYCODE_t | (Common::KEYCODE_RALT): - { - // Teleport to room - //Scene *sceneView = (Scene *)vm->_viewManager->getView(VIEWID_SCENE); - - - return true; - } - - default: - break; - } - - return false; -} - -const char *CHEAT_SEQUENCE = "widepipe"; - -bool MadsInterfaceView::handleKeypress(int32 keycode) { - int flags = keycode >> 24; - int kc = keycode & 0xffff; + // Handle display of any status text + if (_statusText[0]) { + // Text colors are inverted in Dragonsphere + if (_vm->getGameType() == GType_DragonSphere) + _vm->_font->setColors(_vm->_palette->BLACK, _vm->_palette->WHITE, _vm->_palette->BLACK); + else + _vm->_font->setColors(_vm->_palette->WHITE, _vm->_palette->BLACK, _vm->_palette->BLACK); - // Capitalise the letter if necessary - if (_cheatKeyCtr < CHEAT_SEQUENCE_MAX) { - if ((flags == Common::KBD_CTRL) && (kc == CHEAT_SEQUENCE[_cheatKeyCtr])) { - ++_cheatKeyCtr; - if (_cheatKeyCtr == CHEAT_SEQUENCE_MAX) - Dialog::display(_vm, 22, cheatingEnabledDesc); - return true; - } else { - _cheatKeyCtr = 0; - } + _vm->_font->setFont(FONT_MAIN_MADS); + _vm->_font->writeString(this, _statusText, (width() - _vm->_font->getWidth(_statusText)) / 2, 142, 0); } - return false; + _interfaceSurface->copyTo(this, 0, this->height() - _interfaceSurface->height()); } } // End of namespace M4 diff --git a/engines/m4/scene.h b/engines/m4/scene.h index c5abcbe201..a5ea10ac00 100644 --- a/engines/m4/scene.h +++ b/engines/m4/scene.h @@ -32,6 +32,9 @@ class View; #include "m4/hotspot.h" #include "m4/graphics.h" #include "m4/viewmgr.h" +#include "m4/gui.h" +#include "m4/m4_views.h" +#include "m4/mads_views.h" namespace M4 { @@ -83,10 +86,9 @@ class Scene: public View { private: byte *_inverseColorTable; HotSpotList _sceneHotspots; - char _statusText[100]; protected: int _currentScene; - InterfaceView *_interfaceSurface; + GameInterfaceView *_interfaceSurface; M4Surface *_backgroundSurface; M4Surface *_codeSurface; RGBList *_palData; @@ -104,6 +106,8 @@ public: virtual void leftClick(int x, int y) = 0; virtual void rightClick(int x, int y) = 0; virtual void setAction(int action, int objectId = -1) = 0; + virtual void setStatusText(const char *text) = 0; + virtual void update() = 0; // TODO: perhaps move playIntro() someplace else? void playIntro(); @@ -117,11 +121,11 @@ public: int getCurrentScene() { return _currentScene; } M4Surface *getBackgroundSurface() const { return _backgroundSurface; } byte *getInverseColorTable() const { return _inverseColorTable; } - void update(); - void setMADSStatusText(const char *text) { strcpy(_statusText, text); } + void showInterface(); + void hideInterface(); void showMADSV2TextBox(char *text, int x, int y, char *faceName); - InterfaceView *getInterface() { return _interfaceSurface; } - SceneResources getSceneResources() { return _sceneResources; } + GameInterfaceView *getInterface() { return _interfaceSurface; }; + SceneResources getSceneResources() { return _sceneResources; }; void onRefresh(RectList *rects, M4Surface *destSurface); bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); @@ -142,10 +146,15 @@ public: // Methods that differ between engines virtual void loadScene(int sceneNumber); virtual void loadSceneCodes(int sceneNumber, int index = 0); + virtual void show(); virtual void checkHotspotAtMousePos(int x, int y); virtual void leftClick(int x, int y); virtual void rightClick(int x, int y); virtual void setAction(int action, int objectId = -1); + virtual void setStatusText(const char *text); + virtual void update(); + + M4InterfaceView *getInterface() { return (M4InterfaceView *)_interfaceSurface; }; }; class MadsScene: public Scene { @@ -153,6 +162,7 @@ private: MadsEngine *_vm; int _currentAction; + char _statusText[100]; public: MadsScene(MadsEngine *vm); virtual ~MadsScene() {}; @@ -165,61 +175,10 @@ public: virtual void leftClick(int x, int y); virtual void rightClick(int x, int y); virtual void setAction(int action, int objectId = -1); -}; - -enum InterfaceFontMode {ITEM_NORMAL, ITEM_HIGHLIGHTED, ITEM_SELECTED}; - -enum InterfaceObjects {ACTIONS_START = 0, SCROLL_UP = 10, SCROLL_SCROLLER = 11, SCROLL_DOWN = 12, - INVLIST_START = 13, VOCAB_START = 18}; - -class IntegerList: public Common::Array<int> { -public: - int indexOf(int v) { - for (uint i = 0; i < size(); ++i) - if (operator [](i) == v) - return i; - return -1; - } -}; + virtual void setStatusText(const char *text); + virtual void update(); -class InterfaceView: public View { -public: - InterfaceView(MadsM4Engine *vm, const Common::Rect &bounds): View(vm, bounds) {}; - ~InterfaceView() {}; - - virtual void initialise() {}; - virtual void setSelectedObject(int objectNumber) {}; - virtual void addObjectToInventory(int objectNumber) {}; -}; - -class MadsInterfaceView: public InterfaceView { -private: - IntegerList _inventoryList; - RectList _screenObjects; - int _highlightedElement; - int _topIndex; - uint32 _nextScrollerTicks; - int _cheatKeyCtr; - - // Object display fields - int _selectedObject; - SpriteAsset *_objectSprites; - RGBList *_objectPalData; - int _objectFrameNumber; - - void setFontMode(InterfaceFontMode newMode); - bool handleCheatKey(int32 keycode); - bool handleKeypress(int32 keycode); -public: - MadsInterfaceView(MadsM4Engine *vm); - ~MadsInterfaceView(); - - virtual void initialise(); - virtual void setSelectedObject(int objectNumber); - virtual void addObjectToInventory(int objectNumber); - - void onRefresh(RectList *rects, M4Surface *destSurface); - bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); + MadsInterfaceView *getInterface() { return (MadsInterfaceView *)_interfaceSurface; }; }; } // End of namespace M4 |