diff options
-rw-r--r-- | engines/titanic/detection.cpp | 5 | ||||
-rw-r--r-- | engines/titanic/events.cpp | 143 | ||||
-rw-r--r-- | engines/titanic/events.h | 79 | ||||
-rw-r--r-- | engines/titanic/game_state.cpp | 2 | ||||
-rw-r--r-- | engines/titanic/main_game_window.cpp | 147 | ||||
-rw-r--r-- | engines/titanic/main_game_window.h | 42 | ||||
-rw-r--r-- | engines/titanic/pet_control/pet_rooms_glyphs.cpp | 4 | ||||
-rw-r--r-- | engines/titanic/titanic.cpp | 27 | ||||
-rw-r--r-- | engines/titanic/titanic.h | 8 | ||||
-rw-r--r-- | engines/titanic/true_talk/tt_npc_script.cpp | 2 |
10 files changed, 282 insertions, 177 deletions
diff --git a/engines/titanic/detection.cpp b/engines/titanic/detection.cpp index ca4db961b2..a9878d9da7 100644 --- a/engines/titanic/detection.cpp +++ b/engines/titanic/detection.cpp @@ -127,8 +127,9 @@ SaveStateList TitanicMetaEngine::listSaves(const char *target) const { if (in) { Titanic::CompressedFile file; file.open(in); - Titanic::CProjectItem::readSavegameHeader(&file, header); - saveList.push_back(SaveStateDescriptor(slot, header._saveName)); + + if (Titanic::CProjectItem::readSavegameHeader(&file, header)) + saveList.push_back(SaveStateDescriptor(slot, header._saveName)); if (header._thumbnail) { header._thumbnail->free(); diff --git a/engines/titanic/events.cpp b/engines/titanic/events.cpp index ff425abcde..381d371a68 100644 --- a/engines/titanic/events.cpp +++ b/engines/titanic/events.cpp @@ -30,9 +30,8 @@ namespace Titanic { -Events::Events(TitanicEngine *vm): _vm(vm), _specialButtons(0), - _frameCounter(1), _priorFrameTime(0), _priorLeftDownTime(0), - _priorMiddleDownTime(0), _priorRightDownTime(0) { +Events::Events(TitanicEngine *vm): _vm(vm), _frameCounter(1), + _priorFrameTime(0) { } void Events::pollEvents() { @@ -45,29 +44,29 @@ void Events::pollEvents() { switch (event.type) { case Common::EVENT_MOUSEMOVE: _mousePos = event.mouse; - mouseMove(); + eventTarget()->mouseMove(_mousePos); break; case Common::EVENT_LBUTTONDOWN: _mousePos = event.mouse; - leftButtonDown(); + eventTarget()->leftButtonDown(_mousePos); break; case Common::EVENT_LBUTTONUP: _mousePos = event.mouse; - leftButtonUp(); + eventTarget()->leftButtonUp(_mousePos); break; case Common::EVENT_MBUTTONDOWN: _mousePos = event.mouse; - middleButtonDown(); + eventTarget()->middleButtonDown(_mousePos); break; case Common::EVENT_MBUTTONUP: _mousePos = event.mouse; - middleButtonUp(); + eventTarget()->middleButtonUp(_mousePos); break; case Common::EVENT_KEYDOWN: - keyDown(event.kbd); + eventTarget()->keyDown(event.kbd); break; case Common::EVENT_KEYUP: - keyUp(event.kbd); + eventTarget()->keyUp(event.kbd); break; default: break; @@ -87,7 +86,7 @@ bool Events::checkForNextFrameCounter() { _priorFrameTime = milli; // Handle any idle updates - onIdle(); + eventTarget()->onIdle(); // Give time to the debugger _vm->_debugger->onFrame(); @@ -105,128 +104,6 @@ uint32 Events::getTicksCount() const { return g_system->getMillis(); } -void Events::onIdle() { - if (!_vm->_window->_inputAllowed) - return; - CGameManager *gameManager = _vm->_window->_gameManager; - if (!gameManager) - return; - - // Let the game manager perform any game updates - gameManager->update(); - - if (gameManager->_gameState._quitGame) { - // Game needs to shut down - _vm->quitGame(); - } -} - -#define HANDLE_MESSAGE(METHOD) if (_vm->_window->_inputAllowed) { \ - _vm->_window->_gameManager->_inputTranslator.METHOD(_specialButtons, Point(_mousePos.x, _mousePos.y)); \ - _vm->_window->mouseChanged(); \ - } - - -void Events::mouseMove() { - HANDLE_MESSAGE(mouseMove) -} - -void Events::leftButtonDown() { - _specialButtons |= MK_LBUTTON; - - if ((getTicksCount() - _priorLeftDownTime) < DOUBLE_CLICK_TIME) { - _priorLeftDownTime = 0; - leftButtonDoubleClick(); - } else { - _priorLeftDownTime = getTicksCount(); - HANDLE_MESSAGE(leftButtonDown) - } -} - -void Events::leftButtonUp() { - _specialButtons &= ~MK_LBUTTON; - HANDLE_MESSAGE(leftButtonUp) -} - -void Events::leftButtonDoubleClick() { - HANDLE_MESSAGE(leftButtonDoubleClick) -} - -void Events::middleButtonDown() { - _specialButtons |= MK_MBUTTON; - - if ((getTicksCount() - _priorMiddleDownTime) < DOUBLE_CLICK_TIME) { - _priorMiddleDownTime = 0; - middleButtonDoubleClick(); - } else { - _priorMiddleDownTime = getTicksCount(); - HANDLE_MESSAGE(middleButtonDown) - } -} - -void Events::middleButtonUp() { - _specialButtons &= ~MK_MBUTTON; - HANDLE_MESSAGE(middleButtonUp) -} - -void Events::middleButtonDoubleClick() { - HANDLE_MESSAGE(middleButtonDoubleClick) -} - -void Events::rightButtonDown() { - _specialButtons |= MK_RBUTTON; - - if ((getTicksCount() - _priorRightDownTime) < DOUBLE_CLICK_TIME) { - _priorRightDownTime = 0; - rightButtonDoubleClick(); - } else { - _priorRightDownTime = getTicksCount(); - HANDLE_MESSAGE(rightButtonDown) - } -} - -void Events::rightButtonUp() { - _specialButtons &= ~MK_RBUTTON; - HANDLE_MESSAGE(rightButtonUp) -} - -void Events::rightButtonDoubleClick() { - HANDLE_MESSAGE(rightButtonDoubleClick) -} - -void Events::charPress(char c) { - -} - -void Events::keyDown(Common::KeyState keyState) { - handleKbdSpecial(keyState); - - if (keyState.keycode == Common::KEYCODE_d && (keyState.flags & Common::KBD_CTRL)) { - // Attach to the debugger - _vm->_debugger->attach(); - _vm->_debugger->onFrame(); - } - - if (_vm->_window->_inputAllowed) - _vm->_window->_gameManager->_inputTranslator.keyDown(keyState); -} - -void Events::keyUp(Common::KeyState keyState) { - handleKbdSpecial(keyState); -} - -void Events::handleKbdSpecial(Common::KeyState keyState) { - if (keyState.flags & Common::KBD_CTRL) - _specialButtons |= MK_CONTROL; - else - _specialButtons &= ~MK_CONTROL; - - if (keyState.flags & Common::KBD_SHIFT) - _specialButtons |= MK_SHIFT; - else - _specialButtons &= ~MK_SHIFT; -} - void Events::sleep(uint time) { uint32 delayEnd = g_system->getMillis() + time; diff --git a/engines/titanic/events.h b/engines/titanic/events.h index ab3d755535..68666c7c46 100644 --- a/engines/titanic/events.h +++ b/engines/titanic/events.h @@ -25,6 +25,8 @@ #include "common/scummsys.h" #include "common/events.h" +#include "common/stack.h" +#include "support/rect.h" namespace Titanic { @@ -39,16 +41,41 @@ enum SpecialButtons { class TitanicEngine; +/** + * A base class for windows that can receive event messages + */ +class CEventTarget { +public: + virtual ~CEventTarget() {} + + /** + * Called to handle any regular updates the game requires + */ + virtual void onIdle() {} + + /** + * Mouse/key event handlers + */ + virtual void mouseMove(const Point &mousePos) {} + virtual void leftButtonDown(const Point &mousePos) {} + virtual void leftButtonUp(const Point &mousePos) {} + virtual void leftButtonDoubleClick(const Point &mousePos) {} + virtual void middleButtonDown(const Point &mousePos) {} + virtual void middleButtonUp(const Point &mousePos) {} + virtual void middleButtonDoubleClick(const Point &mousePos) {} + virtual void rightButtonDown(const Point &mousePos) {} + virtual void rightButtonUp(const Point &mousePos) {} + virtual void keyDown(Common::KeyState keyState) {} + virtual void keyUp(Common::KeyState keyState) {} +}; + class Events { private: TitanicEngine *_vm; + Common::Stack<CEventTarget *> _eventTargets; uint32 _frameCounter; uint32 _priorFrameTime; - uint32 _priorLeftDownTime; - uint32 _priorMiddleDownTime; - uint32 _priorRightDownTime; Common::Point _mousePos; - uint _specialButtons; /** * Check whether it's time to display the next screen frame @@ -56,29 +83,32 @@ private: bool checkForNextFrameCounter(); /** - * Called to handle any regular updates the game requires + * Return the currently active event target */ - void onIdle(); - - void mouseMove(); - void leftButtonDown(); - void leftButtonUp(); - void leftButtonDoubleClick(); - void middleButtonDown(); - void middleButtonUp(); - void middleButtonDoubleClick(); - void rightButtonDown(); - void rightButtonUp(); - void rightButtonDoubleClick(); - void charPress(char c); - void keyDown(Common::KeyState keyState); - void keyUp(Common::KeyState keyState); - void handleKbdSpecial(Common::KeyState keyState); + CEventTarget *eventTarget() const { + return _eventTargets.top(); + } public: Events(TitanicEngine *vm); ~Events() {} /** + * Adds a new event target to the top of the list. It will get + * all events generated until such time as another is pushed on + * top of it, or the removeTarget method is called + */ + void addTarget(CEventTarget *target) { + _eventTargets.push(target); + } + + /** + * Removes the currently active event target + */ + void removeTarget() { + _eventTargets.pop(); + } + + /** * Check for any pending events */ void pollEvents(); @@ -100,13 +130,6 @@ public: uint32 getTicksCount() const; /** - * Return whether a given special key is currently pressed - */ - bool isSpecialPressed(SpecialButtons btn) const { return _specialButtons; } - - uint getSpecialButtons() const { return _specialButtons; } - - /** * Sleep for a specified period of time */ void sleep(uint time); diff --git a/engines/titanic/game_state.cpp b/engines/titanic/game_state.cpp index 6c81bc8699..f7ae304b29 100644 --- a/engines/titanic/game_state.cpp +++ b/engines/titanic/game_state.cpp @@ -120,7 +120,7 @@ void CGameState::changeView(CViewItem *newView, CMovieClip *clip) { oldView->leaveView(newView); // If Shift key is pressed, skip showing the transition clip - if (g_vm->_events->isSpecialPressed(MK_SHIFT)) + if (g_vm->_window->isSpecialPressed(MK_SHIFT)) clip = nullptr; if (_mode == GSMODE_2) { diff --git a/engines/titanic/main_game_window.cpp b/engines/titanic/main_game_window.cpp index 3c549c4e89..736154a502 100644 --- a/engines/titanic/main_game_window.cpp +++ b/engines/titanic/main_game_window.cpp @@ -20,16 +20,19 @@ * */ +#include "common/config-manager.h" #include "titanic/titanic.h" -#include "titanic/main_game_window.h" #include "titanic/game_manager.h" #include "titanic/game_view.h" +#include "titanic/main_game_window.h" #include "titanic/messages/messages.h" #include "titanic/pet_control/pet_control.h" namespace Titanic { -CMainGameWindow::CMainGameWindow(TitanicEngine *vm): _vm(vm) { +CMainGameWindow::CMainGameWindow(TitanicEngine *vm): _vm(vm), + _specialButtons(0), _priorLeftDownTime(0), + _priorMiddleDownTime(0), _priorRightDownTime(0) { _gameView = nullptr; _gameManager = nullptr; _project = nullptr; @@ -37,6 +40,12 @@ CMainGameWindow::CMainGameWindow(TitanicEngine *vm): _vm(vm) { _image = nullptr; _cursor = nullptr; _pendingLoadSlot = -1; + + // Set the window as an event target + vm->_events->addTarget(this); +} + +CMainGameWindow::~CMainGameWindow() { } bool CMainGameWindow::Create() { @@ -53,14 +62,11 @@ void CMainGameWindow::applicationStarting() { // Set up the game project, and get game slot int saveSlot = loadGame(); assert(_project); - + // Set the video mode CScreenManager *screenManager = CScreenManager::setCurrent(); screenManager->setMode(640, 480, 16, 0, true); - // TODO: Remove initial background and palette - - // Create game view and manager _gameView = new CSTGameView(this); _gameManager = new CGameManager(_project, _gameView); @@ -98,7 +104,10 @@ int CMainGameWindow::loadGame() { } int CMainGameWindow::selectSavegame() { - // TODO: For now, hardcoded to -1 for new saves + // If the user selected a savegame from the launcher, return it + if (ConfMan.hasKey("save_slot")) + return ConfMan.getInt("save_slot"); + return -1; } @@ -111,7 +120,7 @@ void CMainGameWindow::setActiveView(CViewItem *viewItem) { _gameView->createSurface(key); } } - + void CMainGameWindow::draw() { if (_gameManager) { if (!_gameView->_surface) { @@ -202,4 +211,126 @@ void CMainGameWindow::loadGame(int slotId) { _gameManager->_gameState.setMode(GSMODE_PENDING_LOAD); } +void CMainGameWindow::onIdle() { + if (!_inputAllowed) + return; + CGameManager *gameManager = _gameManager; + if (!gameManager) + return; + + // Let the game manager perform any game updates + gameManager->update(); + + if (gameManager->_gameState._quitGame) { + // Game needs to shut down + _vm->quitGame(); + } +} + +#define HANDLE_MESSAGE(METHOD) if (_inputAllowed) { \ + _gameManager->_inputTranslator.METHOD(_specialButtons, mousePos); \ + mouseChanged(); \ + } + + +void CMainGameWindow::mouseMove(const Point &mousePos) { + HANDLE_MESSAGE(mouseMove) +} + +void CMainGameWindow::leftButtonDown(const Point &mousePos) { + _specialButtons |= MK_LBUTTON; + + if ((_vm->_events->getTicksCount() - _priorLeftDownTime) < DOUBLE_CLICK_TIME) { + _priorLeftDownTime = 0; + leftButtonDoubleClick(mousePos); + } else { + _priorLeftDownTime = _vm->_events->getTicksCount(); + HANDLE_MESSAGE(leftButtonDown) + } +} + +void CMainGameWindow::leftButtonUp(const Point &mousePos) { + _specialButtons &= ~MK_LBUTTON; + HANDLE_MESSAGE(leftButtonUp) +} + +void CMainGameWindow::leftButtonDoubleClick(const Point &mousePos) { + HANDLE_MESSAGE(leftButtonDoubleClick) +} + +void CMainGameWindow::middleButtonDown(const Point &mousePos) { + _specialButtons |= MK_MBUTTON; + + if ((_vm->_events->getTicksCount() - _priorMiddleDownTime) < DOUBLE_CLICK_TIME) { + _priorMiddleDownTime = 0; + middleButtonDoubleClick(mousePos); + } else { + _priorMiddleDownTime = _vm->_events->getTicksCount(); + HANDLE_MESSAGE(middleButtonDown) + } +} + +void CMainGameWindow::middleButtonUp(const Point &mousePos) { + _specialButtons &= ~MK_MBUTTON; + HANDLE_MESSAGE(middleButtonUp) +} + +void CMainGameWindow::middleButtonDoubleClick(const Point &mousePos) { + HANDLE_MESSAGE(middleButtonDoubleClick) +} + +void CMainGameWindow::rightButtonDown(const Point &mousePos) { + _specialButtons |= MK_RBUTTON; + + if ((_vm->_events->getTicksCount() - _priorRightDownTime) < DOUBLE_CLICK_TIME) { + _priorRightDownTime = 0; + rightButtonDoubleClick(mousePos); + } else { + _priorRightDownTime = _vm->_events->getTicksCount(); + HANDLE_MESSAGE(rightButtonDown) + } +} + +void CMainGameWindow::rightButtonUp(const Point &mousePos) { + _specialButtons &= ~MK_RBUTTON; + HANDLE_MESSAGE(rightButtonUp) +} + +void CMainGameWindow::rightButtonDoubleClick(const Point &mousePos) { + HANDLE_MESSAGE(rightButtonDoubleClick) +} + +void CMainGameWindow::charPress(char c) { + +} + +void CMainGameWindow::keyDown(Common::KeyState keyState) { + handleKbdSpecial(keyState); + + if (keyState.keycode == Common::KEYCODE_d && (keyState.flags & Common::KBD_CTRL)) { + // Attach to the debugger + _vm->_debugger->attach(); + _vm->_debugger->onFrame(); + } + + if (_inputAllowed) + _gameManager->_inputTranslator.keyDown(keyState); +} + +void CMainGameWindow::keyUp(Common::KeyState keyState) { + handleKbdSpecial(keyState); +} + +void CMainGameWindow::handleKbdSpecial(Common::KeyState keyState) { + if (keyState.flags & Common::KBD_CTRL) + _specialButtons |= MK_CONTROL; + else + _specialButtons &= ~MK_CONTROL; + + if (keyState.flags & Common::KBD_SHIFT) + _specialButtons |= MK_SHIFT; + else + _specialButtons &= ~MK_SHIFT; +} + } // End of namespace Titanic diff --git a/engines/titanic/main_game_window.h b/engines/titanic/main_game_window.h index 18c03942ce..7a651ec970 100644 --- a/engines/titanic/main_game_window.h +++ b/engines/titanic/main_game_window.h @@ -29,16 +29,22 @@ #include "titanic/game_view.h" #include "titanic/support/image.h" #include "titanic/core/project_item.h" +#include "titanic/events.h" namespace Titanic { class TitanicEngine; -class CMainGameWindow { +class CMainGameWindow : public CEventTarget { private: TitanicEngine *_vm; int _pendingLoadSlot; - + uint _specialButtons; + uint32 _priorFrameTime; + uint32 _priorLeftDownTime; + uint32 _priorMiddleDownTime; + uint32 _priorRightDownTime; +private: /** * Checks for the presence of any savegames and, if present, * lets the user pick one to resume @@ -65,6 +71,12 @@ private: * Draws all the items within the view */ void drawViewContents(CScreenManager *screenManager); + + void leftButtonDoubleClick(const Point &mousePos); + void middleButtonDoubleClick(const Point &mousePos); + void rightButtonDoubleClick(const Point &mousePos); + void charPress(char c); + void handleKbdSpecial(Common::KeyState keyState); public: CGameView *_gameView; CGameManager *_gameManager; @@ -74,6 +86,22 @@ public: void *_cursor; public: CMainGameWindow(TitanicEngine *vm); + virtual ~CMainGameWindow(); + + /** + * Called to handle any regular updates the game requires + */ + void onIdle(); + + virtual void mouseMove(const Point &mousePos); + virtual void leftButtonDown(const Point &mousePos); + virtual void leftButtonUp(const Point &mousePos); + virtual void middleButtonDown(const Point &mousePos); + virtual void middleButtonUp(const Point &mousePos); + virtual void rightButtonDown(const Point &mousePos); + virtual void rightButtonUp(const Point &mousePos); + virtual void keyDown(Common::KeyState keyState); + virtual void keyUp(Common::KeyState keyState); /** * Creates the window @@ -104,6 +132,16 @@ public: * Schedules a savegame to be loaded */ void loadGame(int slotId); + + /* + * Return whether a given special key is currently pressed + */ + bool isSpecialPressed(SpecialButtons btn) const { return _specialButtons; } + + /** + * Returns the bitset of the currently pressed special buttons + */ + uint getSpecialButtons() const { return _specialButtons; } }; } // End of namespace Titanic diff --git a/engines/titanic/pet_control/pet_rooms_glyphs.cpp b/engines/titanic/pet_control/pet_rooms_glyphs.cpp index 5de814af24..810342a23e 100644 --- a/engines/titanic/pet_control/pet_rooms_glyphs.cpp +++ b/engines/titanic/pet_control/pet_rooms_glyphs.cpp @@ -103,7 +103,7 @@ void CPetRoomsGlyph::drawAt(CScreenManager *screenManager, const Point &pt, bool void CPetRoomsGlyph::selectGlyph(const Point &topLeft, const Point &pt) { if (isAssigned()) { - bool isShiftPressed = g_vm->_events->getSpecialButtons() & MK_SHIFT; + bool isShiftPressed = g_vm->_window->getSpecialButtons() & MK_SHIFT; if (isShiftPressed) { int selection = getSelection(topLeft, pt); @@ -116,7 +116,7 @@ void CPetRoomsGlyph::selectGlyph(const Point &topLeft, const Point &pt) { } bool CPetRoomsGlyph::dragGlyph(const Point &topLeft, CMouseDragStartMsg *msg) { - bool isShiftPressed = g_vm->_events->getSpecialButtons() & MK_SHIFT; + bool isShiftPressed = g_vm->_window->getSpecialButtons() & MK_SHIFT; CPetControl *petControl = getPetControl(); if (!isShiftPressed && petControl) { diff --git a/engines/titanic/titanic.cpp b/engines/titanic/titanic.cpp index 7b91a1a630..dfb68fd9d5 100644 --- a/engines/titanic/titanic.cpp +++ b/engines/titanic/titanic.cpp @@ -181,4 +181,31 @@ CString TitanicEngine::generateSaveName(int slot) { return CString::format("%s.%03d", _targetName.c_str(), slot); } +CString TitanicEngine::getSavegameName(int slot) { + // Try and open up the savegame for access + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading( + generateSaveName(slot)); + + if (in) { + // Read in the savegame header data + CompressedFile file; + file.open(in); + + TitanicSavegameHeader header; + bool isValid = CProjectItem::readSavegameHeader(&file, header); + if (header._thumbnail) { + header._thumbnail->free(); + delete header._thumbnail; + } + + file.close(); + + if (isValid) + // Set the name text + return header._saveName; + } + + return CString(); +} + } // End of namespace Titanic diff --git a/engines/titanic/titanic.h b/engines/titanic/titanic.h index dd289714c9..ec015551b8 100644 --- a/engines/titanic/titanic.h +++ b/engines/titanic/titanic.h @@ -70,6 +70,8 @@ enum TitanicDebugChannels { #define TOTAL_ITEMS 46 #define TOTAL_ROOMS 34 +#define MAX_SAVES 99 + struct TitanicGameDescription; class TitanicEngine; @@ -159,6 +161,12 @@ public: * @param slot Slot number */ CString generateSaveName(int slot); + + /** + * Checks whether a savegame exists for the given slot, + * and if it exists, returns it's description + */ + CString getSavegameName(int slot); }; extern TitanicEngine *g_vm; diff --git a/engines/titanic/true_talk/tt_npc_script.cpp b/engines/titanic/true_talk/tt_npc_script.cpp index 70953914fa..8cce90ebff 100644 --- a/engines/titanic/true_talk/tt_npc_script.cpp +++ b/engines/titanic/true_talk/tt_npc_script.cpp @@ -416,7 +416,7 @@ void TTnpcScript::loadBody(SimpleFile *file) { for (uint idx = 0; idx < _ranges.size(); ++idx) { TTscriptRange &item = _ranges[idx]; - if (item._id == id) { + if (item._id == (uint)id) { item._priorIndex = val; break; } |