diff options
Diffstat (limited to 'engines/bladerunner/ui/spinner.cpp')
-rw-r--r-- | engines/bladerunner/ui/spinner.cpp | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/engines/bladerunner/ui/spinner.cpp b/engines/bladerunner/ui/spinner.cpp new file mode 100644 index 0000000000..9018de15e6 --- /dev/null +++ b/engines/bladerunner/ui/spinner.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. + * + */ + +#include "bladerunner/ui/spinner.h" + +#include "bladerunner/bladerunner.h" +#include "bladerunner/mouse.h" +#include "bladerunner/scene.h" +#include "bladerunner/shape.h" +#include "bladerunner/text_resource.h" +#include "bladerunner/vqa_player.h" +#include "bladerunner/ui/ui_image_picker.h" + +#include "common/rect.h" +#include "common/system.h" + +namespace BladeRunner { + +Spinner::Spinner(BladeRunnerEngine *vm) { + _vm = vm; + reset(); + _imagePicker = new UIImagePicker(vm, kSpinnerDestinations); + _vqaPlayer = nullptr; +} + +Spinner::~Spinner() { + delete _imagePicker; + + reset(); + + if (_vqaPlayer != nullptr) { + _vqaPlayer->close(); + delete _vqaPlayer; + } +} + +void Spinner::setSelectableDestinationFlag(int destination, bool selectable) { + _isDestinationSelectable[destination] = selectable; +} + +bool Spinner::querySelectableDestinationFlag(int destination) const { + return _isDestinationSelectable[destination]; +} + +const Spinner::Destination Spinner::kSpinnerDestinationsNear[] = { + { 0, Common::Rect(210, 263, 263, 332) }, + { 1, Common::Rect(307, 330, 361, 381) }, + { 2, Common::Rect(338, 137, 362, 169) }, + { 3, Common::Rect(248, 135, 289, 168) }, + { 4, Common::Rect(352, 222, 379, 238) }, + { -1, Common::Rect(-1,-1,-1,-1) } +}; + +const Spinner::Destination Spinner::kSpinnerDestinationsMedium[] = { + { 0, Common::Rect(252, 242, 279, 283) }, + { 1, Common::Rect(301, 273, 328, 304) }, + { 2, Common::Rect(319, 182, 336, 200) }, + { 3, Common::Rect(269, 181, 293, 200) }, + { 4, Common::Rect(325, 227, 345, 240) }, + { 5, Common::Rect(259, 74, 380, 119) }, + { 6, Common::Rect(203, 124, 224, 136) }, + { 7, Common::Rect(200, 147, 222, 170) }, + { -1, Common::Rect(-1,-1,-1,-1) } +}; + +const Spinner::Destination Spinner::kSpinnerDestinationsFar[] = { + { 0, Common::Rect(220, 227, 246, 262) }, + { 1, Common::Rect(260, 252, 286, 279) }, + { 2, Common::Rect(286, 178, 302, 196) }, + { 3, Common::Rect(244, 178, 263, 195) }, + { 4, Common::Rect(288, 216, 306, 228) }, + { 5, Common::Rect(249, 77, 353, 124) }, + { 6, Common::Rect(190, 127, 208, 138) }, + { 7, Common::Rect(185, 149, 206, 170) }, + { 8, Common::Rect(398, 249, 419, 268) }, + { 9, Common::Rect(390, 218, 419, 236) }, + { -1, Common::Rect(-1, -1, -1, -1) } +}; + +int Spinner::chooseDestination(int loopId, bool immediately) { + _selectedDestination = 0; + if (!_vm->openArchive("MODE.MIX")) { + return 0; + } + + if (loopId < 0) { + _isOpen = true; + } else { + _vm->playerLosesControl(); + _vm->_scene->loopStartSpecial(kSceneLoopModeSpinner, loopId, immediately); + while (!_isOpen) { + _vm->gameTick(); + } + _vm->playerGainsControl(); + } + + _vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack); + if (!_vqaPlayer->open("SPINNER.VQA")) { + return 0; + } + + _vm->_mouse->setCursor(0); + + // Determine which map we need to show to include the active destinations + uint8 mapmask = 0; + uint8 mapmaskv[kSpinnerDestinations] = { 1, 1, 1, 1, 1, 3, 3, 3, 7, 7 }; + for (int i = 0; i != kSpinnerDestinations; ++i) { + if (_isDestinationSelectable[i]) { + mapmask |= mapmaskv[i]; + } + } + + _destinations = nullptr; + int firstShapeId = 0; + int shapeCount = 0; + int spinnerLoopId = 4; + + mapmask = 1; + + if (mapmask & 4) { + _destinations = kSpinnerDestinationsFar; + firstShapeId = 26; + shapeCount = 20; + spinnerLoopId = 4; + } else if (mapmask & 2) { + _destinations = kSpinnerDestinationsMedium; + firstShapeId = 10; + shapeCount = 16; + spinnerLoopId = 2; + } else if (mapmask & 1) { + _destinations = kSpinnerDestinationsNear; + firstShapeId = 0; + shapeCount = 10; + spinnerLoopId = 0; + } else { + return -1; + } + + _vqaPlayer->setLoop(spinnerLoopId, -1, kLoopSetModeImmediate, nullptr, nullptr); + _vqaPlayer->setLoop(spinnerLoopId + 1, -1, kLoopSetModeJustStart, nullptr, nullptr); + + for (int j = 0; j != shapeCount; ++j) { + _shapes.push_back(new Shape(_vm)); + _shapes[j]->readFromContainer("SPINNER.SHP", firstShapeId + j); + } + + _imagePicker->resetImages(); + + for (const Destination *dest = _destinations; dest->id != -1; ++dest) { + if (!_isDestinationSelectable[dest->id]) { + continue; + } + + const char *tooltip = _vm->_textSpinnerDestinations->getText(dest->id); + + _imagePicker->defineImage( + dest->id, + dest->rect, + _shapes[dest->id], + _shapes[dest->id + _shapes.size() / 2], + _shapes[dest->id + _shapes.size() / 2], + tooltip + ); + } + + _imagePicker->activate( + nullptr, + nullptr, + nullptr, + mouseUpCallback, + this + ); + + // TODO: Freeze game time + _selectedDestination = -1; + do { + _vm->gameTick(); + } while (_selectedDestination == -1); + + _imagePicker->deactivate(); + + for (int i = 0; i != (int)_shapes.size(); ++i) { + delete _shapes[i]; + } + _shapes.clear(); + + if (_vqaPlayer != nullptr) { + _vqaPlayer->close(); + delete _vqaPlayer; + _vqaPlayer = nullptr; + } + + _vm->closeArchive("MODE.MIX"); + + _isOpen = false; + + // TODO: Unfreeze game time + // TODO: _vm->_scene->resume(); + + return _selectedDestination; +} + +void Spinner::mouseUpCallback(int image, void *self) { + if (image >= 0 && image < 10) { + ((Spinner *)self)->setSelectedDestination(image); + } +} + +void Spinner::open() { + _isOpen = true; +} + +bool Spinner::isOpen() const { + return _isOpen; +} + +int Spinner::handleMouseUp(int x, int y) { + _imagePicker->handleMouseAction(x, y, false, true, false); + return false; +} + +int Spinner::handleMouseDown(int x, int y) { + _imagePicker->handleMouseAction(x, y, true, false, false); + return false; +} + +void Spinner::tick() { + if (!_vm->_gameIsRunning) { + return; + } + + int frame = _vqaPlayer->update(); + assert(frame >= -1); + + // vqaPlayer renders to _surfaceBack + blit(_vm->_surfaceBack, _vm->_surfaceFront); + + Common::Point p = _vm->getMousePos(); + _imagePicker->handleMouseAction(p.x, p.y, false, false, false); + if (_imagePicker->hasHoveredImage()) { + _vm->_mouse->setCursor(1); + } else { + _vm->_mouse->setCursor(0); + } + _imagePicker->draw(_vm->_surfaceFront); + _vm->_mouse->draw(_vm->_surfaceFront, p.x, p.y); + _imagePicker->drawTooltip(_vm->_surfaceFront, p.x, p.y); + + _vm->blitToScreen(_vm->_surfaceFront); + _vm->_system->delayMillis(10); +} + +void Spinner::setSelectedDestination(int destination) { + _selectedDestination = destination; +} + +void Spinner::reset() { + for (int i = 0; i != kSpinnerDestinations; ++i) { + _isDestinationSelectable[i] = false; + } + + _isOpen = false; + _destinations = nullptr; + _selectedDestination = -1; + _imagePicker = nullptr; + + for (int i = 0; i != (int)_shapes.size(); ++i) { + delete _shapes[i]; + } + _shapes.clear(); +} + +void Spinner::resume() { + if(_vqaPlayer == nullptr) { + return; + } + + //_vqa->clear(); + _vqaPlayer->setLoop(0, -1, kLoopSetModeImmediate, nullptr, nullptr); + tick(); + _vqaPlayer->setLoop(1, -1, kLoopSetModeJustStart, nullptr, nullptr); +} + +} // End of namespace BladeRunner |