diff options
Diffstat (limited to 'engines/titanic/main_game_window.cpp')
-rw-r--r-- | engines/titanic/main_game_window.cpp | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/engines/titanic/main_game_window.cpp b/engines/titanic/main_game_window.cpp new file mode 100644 index 0000000000..486bc417d7 --- /dev/null +++ b/engines/titanic/main_game_window.cpp @@ -0,0 +1,350 @@ +/* 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. + * + */ + +#include "common/config-manager.h" +#include "titanic/titanic.h" +#include "titanic/continue_save_dialog.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), + _specialButtons(0), _priorLeftDownTime(0), + _priorMiddleDownTime(0), _priorRightDownTime(0) { + _gameView = nullptr; + _gameManager = nullptr; + _project = nullptr; + _inputAllowed = false; + _image = nullptr; + _cursor = nullptr; + _pendingLoadSlot = -1; + + // Set the window as an event target + vm->_events->addTarget(this); +} + +CMainGameWindow::~CMainGameWindow() { +} + +bool CMainGameWindow::Create() { + Image image; + image.load("TITANIC"); + + // TODO: Stuff + return true; +} + +void CMainGameWindow::applicationStarting() { + // Set the video mode + CScreenManager *screenManager = CScreenManager::setCurrent(); + screenManager->setMode(640, 480, 16, 0, true); + + // Set up the game project, and get game slot + int saveSlot = getSavegameSlot(); + if (saveSlot == -2) + return; + + // Create game view and manager + _gameView = new CSTGameView(this); + _gameManager = new CGameManager(_project, _gameView, g_vm->_mixer); + _gameView->setGameManager(_gameManager); + + // Load either a new game or selected existing save + _project->loadGame(saveSlot); + _inputAllowed = true; + _gameManager->_gameState.setMode(GSMODE_INTERACTIVE); + + // TODO: Cursor/image + + // Generate starting messages for entering the view, node, and room. + // Note the old fields are nullptr, since there's no previous view/node/room + CViewItem *view = _gameManager->_gameState._gameLocation.getView(); + CEnterViewMsg enterViewMsg(nullptr, view); + enterViewMsg.execute(view, nullptr, MSGFLAG_SCAN); + + CNodeItem *node = view->findNode(); + CEnterNodeMsg enterNodeMsg(nullptr, node); + enterNodeMsg.execute(node, nullptr, MSGFLAG_SCAN); + + CRoomItem *room = view->findRoom(); + CEnterRoomMsg enterRoomMsg(nullptr, room); + enterRoomMsg.execute(room, nullptr, MSGFLAG_SCAN); + + _gameManager->initBounds(); +} + +int CMainGameWindow::getSavegameSlot() { + _project = new CProjectItem(); + _project->setFilename("starship.prj"); + + return selectSavegame(); +} + +int CMainGameWindow::selectSavegame() { + // If the user selected a savegame from the launcher, return it + if (ConfMan.hasKey("save_slot")) + return ConfMan.getInt("save_slot"); + + CContinueSaveDialog dialog; + bool hasSavegames = false; + + // Loop through save slots to find any existing save slots + for (int idx = 0; idx < MAX_SAVES; ++idx) { + CString saveName = g_vm->getSavegameName(idx); + if (!saveName.empty()) { + dialog.addSavegame(idx, saveName); + hasSavegames = true; + } + } + + // If there are savegames, show the select dialog and get a choice. + // If there aren't, return -1 to indicate starting a new game + return hasSavegames ? dialog.show() : -1; +} + +void CMainGameWindow::setActiveView(CViewItem *viewItem) { + _gameManager->_gameState._gameLocation.setView(viewItem); + + CResourceKey key; + if (viewItem->getResourceKey(&key)) { + // Create a surface based on the key + _gameView->createSurface(key); + } +} + +void CMainGameWindow::draw() { + if (_gameManager) { + if (!_gameView->_surface) { + CViewItem *view = _gameManager->getView(); + if (view) + setActiveView(view); + } + + CScreenManager *scrManager = CScreenManager::setCurrent(); + scrManager->clearSurface(SURFACE_BACKBUFFER, &_gameManager->_bounds); + + switch (_gameManager->_gameState._mode) { + case GSMODE_INTERACTIVE: + case GSMODE_CUTSCENE: + if (_gameManager->_gameState._petActive) + drawPet(scrManager); + + drawView(); + drawViewContents(scrManager); + scrManager->drawCursors(); + break; + + case GSMODE_5: + g_vm->_filesManager->debug(scrManager); + break; + + case GSMODE_PENDING_LOAD: + // Pending savegame to load + _gameManager->_gameState.setMode(GSMODE_INTERACTIVE); + _vm->_window->_project->loadGame(_pendingLoadSlot); + break; + + default: + break; + } + } +} + +void CMainGameWindow::drawPet(CScreenManager *screenManager) { + if (_gameView && _gameView->_surface) { + CPetControl *petControl = _gameManager->_project->getPetControl(); + if (petControl) + petControl->draw(screenManager); + } +} + +void CMainGameWindow::drawView() { + if (_gameView->_surface) + _gameView->drawView(); +} + +void CMainGameWindow::drawViewContents(CScreenManager *screenManager) { + // Get a reference to the reference, validating that it's present + if (!screenManager) + return; + CViewItem *view = _gameManager->getView(); + if (!view) + return; + CNodeItem *node = view->findNode(); + if (!node) + return; + CRoomItem *room = node->findRoom(); + if (!room) + return; + + double xVal = 0.0, yVal = 0.0; + room->calcNodePosition(node->_nodePos, xVal, yVal); + + // Iterate through drawing all the items in the scene except any item + // that's currently being dragged + for (CTreeItem *treeItem = view; treeItem; treeItem = treeItem->scan(view)) { + if (treeItem != _gameManager->_dragItem) + treeItem->draw(screenManager); + } + + // Finally draw the drag item if there is one + if (_gameManager->_dragItem) + _gameManager->_dragItem->draw(screenManager); +} + +void CMainGameWindow::mouseChanged() { + if (_gameManager->_gameState._mode != GSMODE_5) + _gameManager->update(); +} + +void CMainGameWindow::loadGame(int slotId) { + _pendingLoadSlot = 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 |