aboutsummaryrefslogtreecommitdiff
path: root/engines/bladerunner/ui
diff options
context:
space:
mode:
authorPeter Kohaut2018-01-14 12:12:06 +0100
committerPeter Kohaut2018-01-28 10:57:16 +0100
commit1e5f9d3078f236f306b5d868bcd52f4e47f7b512 (patch)
tree0d402af27d75064d60e4674ab3bd4c9ad08759f1 /engines/bladerunner/ui
parent3a937f19c0a5e347c801c62d345475be082f9e41 (diff)
downloadscummvm-rg350-1e5f9d3078f236f306b5d868bcd52f4e47f7b512.tar.gz
scummvm-rg350-1e5f9d3078f236f306b5d868bcd52f4e47f7b512.tar.bz2
scummvm-rg350-1e5f9d3078f236f306b5d868bcd52f4e47f7b512.zip
BLADERUNNER: Added basic KIA interface
Settings works Help works Clue database works Fixed code for inserting objects into scene Reorganization of few files Unification & code formatting of few older files
Diffstat (limited to 'engines/bladerunner/ui')
-rw-r--r--engines/bladerunner/ui/elevator.cpp325
-rw-r--r--engines/bladerunner/ui/elevator.h73
-rw-r--r--engines/bladerunner/ui/kia.cpp1229
-rw-r--r--engines/bladerunner/ui/kia.h155
-rw-r--r--engines/bladerunner/ui/kia_log.cpp128
-rw-r--r--engines/bladerunner/ui/kia_log.h65
-rw-r--r--engines/bladerunner/ui/kia_section_base.cpp35
-rw-r--r--engines/bladerunner/ui/kia_section_base.h67
-rw-r--r--engines/bladerunner/ui/kia_section_clues.cpp422
-rw-r--r--engines/bladerunner/ui/kia_section_clues.h95
-rw-r--r--engines/bladerunner/ui/kia_section_crimes.cpp37
-rw-r--r--engines/bladerunner/ui/kia_section_crimes.h82
-rw-r--r--engines/bladerunner/ui/kia_section_diagnostic.h39
-rw-r--r--engines/bladerunner/ui/kia_section_help.cpp90
-rw-r--r--engines/bladerunner/ui/kia_section_help.h54
-rw-r--r--engines/bladerunner/ui/kia_section_load.h39
-rw-r--r--engines/bladerunner/ui/kia_section_pogo.h39
-rw-r--r--engines/bladerunner/ui/kia_section_save.h39
-rw-r--r--engines/bladerunner/ui/kia_section_settings.cpp301
-rw-r--r--engines/bladerunner/ui/kia_section_settings.h80
-rw-r--r--engines/bladerunner/ui/kia_section_suspects.h41
-rw-r--r--engines/bladerunner/ui/kia_shapes.cpp69
-rw-r--r--engines/bladerunner/ui/kia_shapes.h54
-rw-r--r--engines/bladerunner/ui/spinner.cpp303
-rw-r--r--engines/bladerunner/ui/spinner.h84
-rw-r--r--engines/bladerunner/ui/ui_check_box.cpp140
-rw-r--r--engines/bladerunner/ui/ui_check_box.h64
-rw-r--r--engines/bladerunner/ui/ui_component.h62
-rw-r--r--engines/bladerunner/ui/ui_container.cpp67
-rw-r--r--engines/bladerunner/ui/ui_container.h56
-rw-r--r--engines/bladerunner/ui/ui_image_picker.cpp331
-rw-r--r--engines/bladerunner/ui/ui_image_picker.h104
-rw-r--r--engines/bladerunner/ui/ui_input_box.cpp115
-rw-r--r--engines/bladerunner/ui/ui_input_box.h69
-rw-r--r--engines/bladerunner/ui/ui_scroll_box.cpp662
-rw-r--r--engines/bladerunner/ui/ui_scroll_box.h137
-rw-r--r--engines/bladerunner/ui/ui_slider.cpp153
-rw-r--r--engines/bladerunner/ui/ui_slider.h63
38 files changed, 5968 insertions, 0 deletions
diff --git a/engines/bladerunner/ui/elevator.cpp b/engines/bladerunner/ui/elevator.cpp
new file mode 100644
index 0000000000..f0c8d7d921
--- /dev/null
+++ b/engines/bladerunner/ui/elevator.cpp
@@ -0,0 +1,325 @@
+/* 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/elevator.h"
+
+#include "bladerunner/actor.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/audio_player.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/mouse.h"
+#include "bladerunner/shape.h"
+#include "bladerunner/script/script.h"
+#include "bladerunner/ui/ui_image_picker.h"
+#include "bladerunner/vqa_player.h"
+
+#include "common/rect.h"
+#include "common/str.h"
+#include "common/system.h"
+
+namespace BladeRunner {
+
+Elevator::Elevator(BladeRunnerEngine *vm) {
+ _vm = vm;
+ reset();
+ _imagePicker = new UIImagePicker(vm, 8);
+}
+
+Elevator::~Elevator() {
+ delete _imagePicker;
+ reset();
+}
+
+int Elevator::activate(int elevatorId) {
+ const char *vqaName;
+
+ if (elevatorId == 1) {
+ _buttonClicked = 3;
+ vqaName = "MA06ELEV.VQA";
+ } else if (elevatorId == 2) {
+ _buttonClicked = 1;
+ vqaName = "PS02ELEV.VQA";
+ } else {
+ error("Invalid elevator id");
+ }
+
+ if (!_vm->openArchive("MODE.MIX")) {
+ return 0;
+ }
+
+ _vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack);
+ if (!_vqaPlayer->open(vqaName)) {
+ return 0;
+ }
+
+ _vqaPlayer->setLoop(1, -1, kLoopSetModeJustStart, nullptr, nullptr);
+ _vm->_mouse->setCursor(0);
+
+ for (int i = 0; i != 16; ++i) {
+ _shapes.push_back(new Shape(_vm));
+ _shapes[i]->readFromContainer("ELEVATOR.SHP", i);
+ }
+
+ _imagePicker->resetImages();
+
+ if (elevatorId == 1) {
+ _imagePicker->defineImage(
+ 0,
+ Common::Rect(220, 298, 308, 392),
+ nullptr,
+ _shapes[11],
+ _shapes[14],
+ nullptr);
+ _imagePicker->defineImage(
+ 1,
+ Common::Rect(259, 259, 302, 292),
+ nullptr,
+ _shapes[10],
+ _shapes[13],
+ nullptr);
+ _imagePicker->defineImage(
+ 2,
+ Common::Rect(227, 398, 301, 434),
+ nullptr,
+ _shapes[12],
+ _shapes[15],
+ nullptr);
+ } else {
+ _imagePicker->defineImage(
+ 4,
+ Common::Rect(395, 131, 448, 164),
+ nullptr,
+ _shapes[0],
+ _shapes[5],
+ nullptr
+ );
+ _imagePicker->defineImage(
+ 3,
+ Common::Rect(395, 165, 448, 198),
+ nullptr,
+ _shapes[1],
+ _shapes[6],
+ nullptr
+ );
+ _imagePicker->defineImage(
+ 5,
+ Common::Rect(395, 199, 448, 232),
+ nullptr,
+ _shapes[2],
+ _shapes[7],
+ nullptr
+ );
+ _imagePicker->defineImage(
+ 6,
+ Common::Rect(395, 233, 448, 264),
+ nullptr,
+ _shapes[3],
+ _shapes[8],
+ nullptr
+ );
+ _imagePicker->defineImage(
+ 7,
+ Common::Rect(395, 265, 448, 295),
+ nullptr,
+ _shapes[4],
+ _shapes[9],
+ nullptr
+ );
+ }
+
+ _imagePicker->activate(
+ mouseInCallback,
+ mouseOutCallback,
+ mouseDownCallback,
+ mouseUpCallback,
+ this
+ );
+
+ open();
+
+ // TODO: time->lock();
+
+ _buttonClicked = -1;
+ do {
+ _vm->gameTick();
+ } while (_buttonClicked == -1);
+
+ _imagePicker->deactivate();
+
+ _vqaPlayer->close();
+ delete _vqaPlayer;
+
+ for (int i = 0; i != (int)_shapes.size(); ++i) {
+ delete _shapes[i];
+ }
+ _shapes.clear();
+
+ _vm->closeArchive("MODE.MIX");
+
+ _isOpen = false;
+
+ // TODO: time->unlock();
+
+ return _buttonClicked;
+}
+
+void Elevator::open() {
+ resetDescription();
+ _isOpen = true;
+}
+
+bool Elevator::isOpen() const {
+ return _isOpen;
+}
+
+int Elevator::handleMouseUp(int x, int y) {
+ _imagePicker->handleMouseAction(x, y, false, true, false);
+ return false;
+}
+
+int Elevator::handleMouseDown(int x, int y) {
+ _imagePicker->handleMouseAction(x, y, true, false, false);
+ return false;
+}
+
+void Elevator::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();
+
+ // TODO(madmoose): BLADE.EXE has hasHoveredImage before handleMouseAction?
+ _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);
+
+ _vm->blitToScreen(_vm->_surfaceFront);
+ tickDescription();
+ _vm->_system->delayMillis(10);
+}
+
+void Elevator::buttonClick(int buttonId) {
+ _buttonClicked = buttonId;
+}
+
+void Elevator::reset() {
+ _isOpen = false;
+ _vqaPlayer = nullptr;
+ _imagePicker = nullptr;
+ _actorId = -1;
+ _sentenceId = -1;
+ _timeSpeakDescription = 0;
+}
+
+void Elevator::buttonFocus(int buttonId) {
+ switch (buttonId) {
+ case 7:
+ setupDescription(kActorAnsweringMachine, 140);
+ break;
+ case 6:
+ setupDescription(kActorAnsweringMachine, 130);
+ break;
+ case 5:
+ setupDescription(kActorAnsweringMachine, 120);
+ break;
+ case 4:
+ setupDescription(kActorAnsweringMachine, 100);
+ break;
+ case 3:
+ setupDescription(kActorAnsweringMachine, 110);
+ break;
+ case 2:
+ setupDescription(kActorAnsweringMachine, 130);
+ break;
+ case 1:
+ setupDescription(kActorAnsweringMachine, 100);
+ break;
+ case 0:
+ setupDescription(kActorAnsweringMachine, 150);
+ break;
+ default:
+ resetDescription();
+ break;
+ }
+}
+
+void Elevator::setupDescription(int actorId, int sentenceId) {
+ _actorId = actorId;
+ _sentenceId = sentenceId;
+
+ // TODO: Use proper timer
+ _timeSpeakDescription = _vm->getTotalPlayTime() + 600;
+}
+
+void Elevator::resetDescription() {
+ _actorId = -1;
+ _sentenceId = -1;
+ _timeSpeakDescription = 0;
+}
+
+void Elevator::tickDescription() {
+ int now = _vm->getTotalPlayTime();
+ if (_actorId <= 0 || now < _timeSpeakDescription) {
+ return;
+ }
+
+ _vm->_actors[_actorId]->speechPlay(_sentenceId, false);
+ _actorId = -1;
+ _sentenceId = -1;
+}
+
+void Elevator::resume() {
+ // TODO
+}
+
+void Elevator::mouseInCallback(int buttonId, void *self) {
+ ((Elevator *)self)->buttonFocus(buttonId);
+}
+
+void Elevator::mouseOutCallback(int, void *self) {
+ ((Elevator *)self)->buttonFocus(-1);
+}
+
+void Elevator::mouseDownCallback(int, void *self) {
+ Elevator *elevator = ((Elevator *)self);
+ const char *name = elevator->_vm->_gameInfo->getSfxTrack(515);
+ elevator->_vm->_audioPlayer->playAud(name, 100, 0, 0, 50, 0);
+}
+
+void Elevator::mouseUpCallback(int buttonId, void *self) {
+ ((Elevator *)self)->buttonClick(buttonId);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/elevator.h b/engines/bladerunner/ui/elevator.h
new file mode 100644
index 0000000000..f2e1443929
--- /dev/null
+++ b/engines/bladerunner/ui/elevator.h
@@ -0,0 +1,73 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_ELEVATOR_H
+#define BLADERUNNER_ELEVATOR_H
+
+#include "common/array.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class Shape;
+class VQAPlayer;
+class UIImagePicker;
+
+class Elevator {
+ BladeRunnerEngine *_vm;
+ bool _isOpen;
+ VQAPlayer *_vqaPlayer;
+ int _buttonClicked;
+ Common::Array<Shape *> _shapes;
+ UIImagePicker *_imagePicker;
+ int _actorId;
+ int _sentenceId;
+ int _timeSpeakDescription;
+
+public:
+ Elevator(BladeRunnerEngine *vm);
+ ~Elevator();
+
+ int activate(int elevatorId);
+ void open();
+ bool isOpen() const;
+ int handleMouseUp(int x, int y);
+ int handleMouseDown(int x, int y);
+ void tick();
+ void buttonClick(int buttonId);
+ void reset();
+ void buttonFocus(int buttonId);
+ void setupDescription(int actorId, int sentenceId);
+ void resetDescription();
+ void tickDescription();
+ void resume();
+
+private:
+ static void mouseInCallback(int, void *);
+ static void mouseOutCallback(int, void *);
+ static void mouseDownCallback(int, void *);
+ static void mouseUpCallback(int, void *);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/kia.cpp b/engines/bladerunner/ui/kia.cpp
new file mode 100644
index 0000000000..09c5918872
--- /dev/null
+++ b/engines/bladerunner/ui/kia.cpp
@@ -0,0 +1,1229 @@
+/* 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/kia.h"
+
+#include "bladerunner/actor.h"
+#include "bladerunner/audio_player.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/combat.h"
+#include "bladerunner/font.h"
+#include "bladerunner/game_constants.h"
+#include "bladerunner/game_flags.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/mouse.h"
+#include "bladerunner/scene.h"
+#include "bladerunner/shape.h"
+#include "bladerunner/script/kia.h"
+#include "bladerunner/settings.h"
+#include "bladerunner/slice_renderer.h"
+#include "bladerunner/text_resource.h"
+#include "bladerunner/ui/kia_log.h"
+#include "bladerunner/ui/kia_section_base.h"
+#include "bladerunner/ui/kia_section_clues.h"
+#include "bladerunner/ui/kia_section_crimes.h"
+#include "bladerunner/ui/kia_section_diagnostic.h"
+#include "bladerunner/ui/kia_section_help.h"
+#include "bladerunner/ui/kia_section_load.h"
+#include "bladerunner/ui/kia_section_settings.h"
+#include "bladerunner/ui/kia_section_pogo.h"
+#include "bladerunner/ui/kia_section_save.h"
+#include "bladerunner/ui/kia_section_suspects.h"
+#include "bladerunner/ui/kia_shapes.h"
+#include "bladerunner/ui/ui_image_picker.h"
+#include "bladerunner/vqa_player.h"
+
+#include "common/str.h"
+#include "common/keyboard.h"
+
+namespace BladeRunner {
+
+const char *KIA::kPogo = "POGO";
+
+enum KIASections {
+ kKIASectionNone = 0,
+ kKIASectionCrimes = 1,
+ kKIASectionSuspects = 2,
+ kKIASectionClues = 3,
+ kKIASectionSettings = 4,
+ kKIASectionHelp = 5,
+ kKIASectionSave = 6,
+ kKIASectionLoad = 7,
+ kKIASectionQuit = 8,
+ kKIASectionDiagnostic = 9,
+ kKIASectionPogo = 10
+};
+
+KIA::KIA(BladeRunnerEngine *vm) {
+ _vm = vm;
+
+ _script = new KIAScript(_vm);
+ _log = new KIALog(_vm);
+ _shapes = new KIAShapes(_vm);
+
+ _forceOpen = 0;
+ _currentSectionId = kKIASectionNone;
+ _lastSectionIdKIA = kKIASectionCrimes;
+ _lastSectionIdOptions = kKIASectionSettings;
+ _playerVqaTimeLast = _vm->getTotalPlayTime();
+ _playerVqaFrame = 0;
+ _playerVisualizerState = 0;
+ _playerPhotographId = -1;
+ _playerPhotograph = nullptr;
+ _playerSliceModelId = -1;
+ _playerSliceModelAngle = 0.0f;
+ // _playerImage = nullptr;
+ _timeLast = _vm->getTotalPlayTime();
+ _playerActorDialogueQueueCapacity = 31;
+ _playerActorDialogueQueuePosition = 0;
+ _playerActorDialogueQueueSize = 0;
+ _playerActorDialogueQueue = new ActorDialogueQueueEntry[_playerActorDialogueQueueCapacity];
+ _playerActorDialogueState = 0;
+ _currentSection = nullptr;
+ _mainVqaPlayer = nullptr;
+ _playerVqaPlayer = nullptr;
+ // _thumbnail = nullptr;
+
+ _pogoPos = 0;
+
+ _buttons = new UIImagePicker(_vm, 22);
+
+ _crimesSection = new KIASectionCrimes(_vm); // PlayerActor->_clues
+ _suspectsSection = new KIASectionSuspects(_vm); // PlayerActor->_clues
+ _cluesSection = new KIASectionClues(_vm, _vm->_playerActor->_clues);
+ _settingsSection = new KIASectionSettings(_vm);
+ _helpSection = new KIASectionHelp(_vm);
+ _saveSection = new KIASectionSave(_vm);
+ _loadSection = new KIASectionLoad(_vm);
+ _diagnosticSection = new KIASectionDiagnostic(_vm);
+ _pogoSection = new KIASectionPogo(_vm);
+}
+
+KIA::~KIA() {
+ delete _playerPhotograph;
+ // delete _playerImage;
+ // delete _thumbnail;
+ delete _settingsSection;
+ delete _buttons;
+ delete _shapes;
+ delete _log;
+ delete _script;
+}
+
+void KIA::openLastOpened() {
+ open(_lastSectionIdKIA);
+}
+
+void KIA::openOptions() {
+ open(kKIASectionSettings);
+}
+
+void KIA::tick() {
+ if (!_currentSectionId) {
+ return;
+ }
+
+ int timeNow = _vm->getTotalPlayTime();
+ int timeDiff = timeNow - _timeLast;
+
+ if (_playerActorDialogueQueueSize == _playerActorDialogueQueuePosition) {
+ _playerActorDialogueState = 0;
+ } else if (_playerActorDialogueState == 0) {
+ if (_playerSliceModelId == -1 && _playerPhotographId == -1) { //&& !this->_playerImage
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(495), 70, 0, 0, 50, 0);
+ }
+ _playerActorDialogueState = 1;
+ } else if (_playerActorDialogueState == 200) {
+ if (!_vm->_actors[_playerActorDialogueQueue[_playerActorDialogueQueuePosition].actorId]->isSpeeching()) {
+ if (_playerActorDialogueQueueSize != _playerActorDialogueQueuePosition) {
+ _playerActorDialogueQueuePosition = (_playerActorDialogueQueuePosition + 1) % _playerActorDialogueQueueCapacity;
+ }
+ if (_playerActorDialogueQueueSize != _playerActorDialogueQueuePosition) {
+ _vm->_actors[_playerActorDialogueQueue[_playerActorDialogueQueuePosition].actorId]->speechPlay(_playerActorDialogueQueue[_playerActorDialogueQueuePosition].sentenceId, true);
+ }
+ }
+ } else {
+ _playerActorDialogueState += timeDiff;
+
+ if (_playerActorDialogueState >= 200) {
+ _playerActorDialogueState = 200;
+ _vm->_actors[_playerActorDialogueQueue[_playerActorDialogueQueuePosition].actorId]->speechPlay(_playerActorDialogueQueue[_playerActorDialogueQueuePosition].sentenceId, true);
+ }
+ }
+
+ int timeDiffDiv48 = (timeNow - _playerVqaTimeLast) / 48;
+ if (timeDiffDiv48 > 0) {
+ _playerVqaTimeLast = timeNow;
+ if (_playerActorDialogueQueueSize == _playerActorDialogueQueuePosition || _playerSliceModelId != -1 || _playerPhotographId != -1) { // || this->_viewerImage
+ if (_playerVisualizerState > 0) {
+ _playerVisualizerState = MAX(_playerVisualizerState - timeDiffDiv48, 0);
+ }
+ } else {
+ if (_playerVisualizerState < 2) {
+ _playerVisualizerState = MIN(_playerVisualizerState + timeDiffDiv48, 2);
+
+ }
+ }
+
+ if ( _playerSliceModelId != -1 || _playerPhotographId != -1 ) { // || _playerImage
+ if (_playerVqaFrame < 8) {
+ int newVqaFrame = MIN(timeDiffDiv48 + _playerVqaFrame, 8);
+ if (_playerVqaFrame <= 0 && newVqaFrame > 0) {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(497), 100, 70, 70, 50, 0);
+ }
+ _playerVqaFrame = newVqaFrame;
+ }
+ } else {
+ if (_playerVqaFrame > 0) {
+ int newVqaFrame = MAX(_playerVqaFrame - timeDiffDiv48, 0);
+ if (_playerVqaFrame >= 8 && newVqaFrame < 8)
+ {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(496), 100, 70, 70, 50, 0);
+ }
+ _playerVqaFrame = newVqaFrame;
+ }
+ }
+ }
+
+ _mainVqaPlayer->update(false);
+ blit(_vm->_surfaceBack, _vm->_surfaceFront);
+
+ Common::Point mouse = _vm->getMousePos();
+
+ if (!_transitionId) {
+ _buttons->handleMouseAction(mouse.x, mouse.y, false, false, false);
+ if (_buttons->hasHoveredImage()) {
+ _vm->_mouse->setCursor(1);
+ } else {
+ _vm->_mouse->setCursor(0);
+ }
+ if (_currentSection) {
+ _currentSection->handleMouseMove(mouse.x, mouse.y);
+ }
+ }
+
+ if (_vm->_gameFlags->query(kFlagKIAPrivacyAddon)) {
+ _shapes->get(40)->draw(_vm->_surfaceFront, 0, 0);
+ _shapes->get(41)->draw(_vm->_surfaceFront, 211, 447);
+ }
+ if (_currentSectionId != kKIASectionQuit && _transitionId != 14) {
+ if (_vm->_settings->getDifficulty() > 0) {
+ _vm->_mainFont->drawColor(Common::String::format("%04d", _vm->_gameVars[2]), _vm->_surfaceFront, 580, 341, 0x2991);
+ } else {
+ _shapes->get(39)->draw(_vm->_surfaceFront, 583, 342);
+ }
+ }
+ _playerVqaPlayer->seekToFrame(_playerVqaFrame);
+ _playerVqaPlayer->update(true); //_vm->_surfaceFront, 3
+
+ _playerSliceModelAngle += (float)(timeDiff) * 1.0f/400.0f;
+ while (_playerSliceModelAngle >= 2 * M_PI) {
+ _playerSliceModelAngle -= (float)(2 * M_PI);
+ }
+
+ if (_playerVqaFrame == 8) {
+ if (_playerSliceModelId != -1) {
+ _vm->_sliceRenderer->drawOnScreen(_playerSliceModelId, 0, 585, 80, _playerSliceModelAngle, 100.0, _vm->_surfaceFront);
+ } else if (_playerPhotographId != -1) {
+ int width = _playerPhotograph->getWidth();
+ int height = _playerPhotograph->getHeight();
+ _playerPhotograph->draw(_vm->_surfaceFront, 590 - width / 2, 80 - height / 2);
+ }
+ // else if (_playerImage) {
+ // ...
+ // }
+ }
+
+ if (_playerVisualizerState == 1) {
+ _shapes->get(51)->draw(_vm->_surfaceFront, 576, 174);
+ } else if (_playerVisualizerState == 2) {
+ _shapes->get(50)->draw(_vm->_surfaceFront, 576, 174);
+ _shapes->get(_vm->_rnd.getRandomNumberRng(90, 105))->draw(_vm->_surfaceFront, 576, 174);
+ }
+ if (!_transitionId) {
+ _buttons->draw(_vm->_surfaceFront);
+ if (_currentSection) {
+ _currentSection->draw(_vm->_surfaceFront);
+ }
+ }
+ if (_vm->_settings->getAmmoAmount(0) > 0) {
+ if (_vm->_settings->getAmmoType() == 0) {
+ _shapes->get(42)->draw(_vm->_surfaceFront, 147, 405);
+ } else {
+ _shapes->get(45)->draw(_vm->_surfaceFront, 140, 446);
+ }
+ }
+ if (_vm->_settings->getAmmoAmount(1) > 0) {
+ if (_vm->_settings->getAmmoType() == 1) {
+ _shapes->get(43)->draw(_vm->_surfaceFront, 167, 394);
+ } else {
+ _shapes->get(46)->draw(_vm->_surfaceFront, 160, 446);
+ }
+ }
+ if (_vm->_settings->getAmmoAmount(2) > 0) {
+ if (_vm->_settings->getAmmoType() == 2) {
+ _shapes->get(44)->draw(_vm->_surfaceFront, 189, 385);
+ } else {
+ _shapes->get(47)->draw(_vm->_surfaceFront, 182, 446);
+ }
+ }
+ _vm->_mainFont->drawColor("1.00", _vm->_surfaceFront, 438, 471, 0x1CE7);
+ if (!_transitionId) {
+ _buttons->drawTooltip(_vm->_surfaceFront, mouse.x, mouse.y);
+ }
+ _vm->_mouse->draw(_vm->_surfaceFront, mouse.x, mouse.y);
+ _vm->blitToScreen(_vm->_surfaceFront);
+
+ _timeLast = timeNow;
+}
+
+void KIA::handleMouseDown(int mouseX, int mouseY, bool mainButton) {
+ if (!_currentSectionId) {
+ return;
+ }
+ if (mainButton) {
+ _buttons->handleMouseAction(mouseX, mouseY, true, false, false);
+ }
+ if (_currentSection) {
+ _currentSection->handleMouseDown(mainButton);
+ }
+}
+
+void KIA::handleMouseUp(int mouseX, int mouseY, bool mainButton) {
+ if (!_currentSectionId) {
+ return;
+ }
+ if (mainButton) {
+ _buttons->handleMouseAction(mouseX, mouseY, false, true, false);
+ }
+ if (_currentSection) {
+ _currentSection->handleMouseUp(mainButton);
+ }
+ if (_currentSection && _currentSection->_field0) {
+ if (_currentSectionId == kKIASectionCrimes) {
+ open(kKIASectionSuspects);
+ // kiaSuspects::sub_45290C(_suspectsMenu, _crimesMenu->selectedSuspectId);
+ _log->next();
+ _log->clearFuture();
+ } else if (_currentSectionId == kKIASectionSuspects) {
+ open(kKIASectionCrimes);
+ // kiaCrimes::updateCrime(_crimesMenu, *&_suspectsMenu->data[8052]);
+ _log->next();
+ _log->clearFuture();
+ } else {
+ open(kKIASectionNone);
+ }
+ }
+}
+
+void KIA::handleKeyUp(const Common::KeyState &kbd) {
+ if (!_currentSectionId) {
+ return;
+ }
+
+ if (toupper(kbd.ascii) != kPogo[_pogoPos]) {
+ _pogoPos = 0;
+ }
+ if (_currentSectionId != kKIASectionSave) {
+ if (toupper(kbd.ascii) == kPogo[_pogoPos]) {
+ ++_pogoPos;
+ if (!kPogo[_pogoPos]) {
+ open(kKIASectionPogo);
+ _pogoPos = 0;
+ }
+ }
+ }
+ if (kbd.keycode == Common::KEYCODE_ESCAPE) {
+ if (!_forceOpen) {
+ open(kKIASectionNone);
+ }
+ } else {
+ if (_currentSection) {
+ _currentSection->handleKeyUp(kbd);
+ }
+ }
+ if (_currentSection && _currentSection->_field0) {
+ open(kKIASectionNone);
+ }
+}
+
+void KIA::handleKeyDown(const Common::KeyState &kbd) {
+ if (!_currentSectionId) {
+ return;
+ }
+ switch (kbd.keycode) {
+ case Common::KEYCODE_F1:
+ open(kKIASectionHelp);
+ break;
+ case Common::KEYCODE_F2:
+ if (!_forceOpen) {
+ open(kKIASectionSave);
+ }
+ break;
+ case Common::KEYCODE_F3:
+ open(kKIASectionLoad);
+ break;
+ case Common::KEYCODE_F10:
+ open(kKIASectionQuit);
+ break;
+ case Common::KEYCODE_F4:
+ if (_currentSectionId != kKIASectionCrimes) {
+ if (!_forceOpen) {
+ open(kKIASectionCrimes);
+ _log->next();
+ _log->clearFuture();
+ }
+ }
+ break;
+ case Common::KEYCODE_F5:
+ if (_currentSectionId != kKIASectionSuspects) {
+ if (_forceOpen) {
+ open(kKIASectionSuspects);
+ _log->next();
+ _log->clearFuture();
+ }
+ }
+ break;
+ case Common::KEYCODE_F6:
+ if (_currentSectionId != kKIASectionClues) {
+ if (!_forceOpen) {
+ open(kKIASectionClues);
+ _log->next();
+ _log->clearFuture();
+ }
+ }
+ break;
+ default:
+ if (_currentSection) {
+ _currentSection->handleKeyDown(kbd);
+ }
+ break;
+ }
+ if (_currentSection && _currentSection->_field0) {
+ open(kKIASectionNone);
+ }
+}
+
+void KIA::playerReset() {
+ if (_playerActorDialogueQueueSize != _playerActorDialogueQueuePosition) {
+ if (_playerActorDialogueQueueSize != _playerActorDialogueQueuePosition) {
+ int actorId = _playerActorDialogueQueue[_playerActorDialogueQueuePosition].actorId;
+ if (_vm->_actors[actorId]->isSpeeching()) {
+ _vm->_actors[actorId]->speechStop();
+ }
+ }
+ }
+ _playerActorDialogueQueueSize = _playerActorDialogueQueuePosition;
+ _playerSliceModelId = -1;
+ if (_playerPhotographId != -1) {
+ delete _playerPhotograph;
+ _playerPhotograph = nullptr;
+ }
+ _playerPhotographId = -1;
+ // delete _playerImage;
+ // _playerImage = nullptr;
+ _playerActorDialogueState = 0;
+}
+
+void KIA::playActorDialogue(int actorId, int sentenceId) {
+ int newQueueSize = (_playerActorDialogueQueueSize + 1) % _playerActorDialogueQueueCapacity;
+ if (newQueueSize != _playerActorDialogueQueuePosition) {
+ _playerActorDialogueQueue[_playerActorDialogueQueueSize].actorId = actorId;
+ _playerActorDialogueQueue[_playerActorDialogueQueueSize].sentenceId = sentenceId;
+ _playerActorDialogueQueueSize = newQueueSize;
+ }
+}
+
+void KIA::playSliceModel(int sliceModelId) {
+ if (_playerVqaFrame == 8) {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(502), 70, 0, 0, 50, 0);
+ }
+ _playerSliceModelId = sliceModelId;
+}
+
+void KIA::playPhotograph(int photographId) {
+ if (_playerPhotographId != -1) {
+ delete _playerPhotograph;
+ _playerPhotograph = nullptr;
+ }
+ if (_playerVqaFrame == 8) {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(502), 70, 0, 0, 50, 0);
+ }
+ _playerPhotographId = photographId;
+ _playerPhotograph = new Shape(_vm);
+ _playerPhotograph->readFromContainer("photos.shp", photographId);
+}
+
+void KIA::mouseDownCallback(int buttonId, void *callbackData) {
+ KIA *self = (KIA *)callbackData;
+ switch (buttonId) {
+ case 0:
+ case 6:
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(503), 100, -65, -65, 50, 0);
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(505), 70, 0, 0, 50, 0);
+ if (buttonId == 12){
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(596), 70, 0, 0, 50, 0);
+ }
+ break;
+ case 15:
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(503), 70, 0, 0, 50, 0);
+ break;
+ }
+}
+
+void KIA::mouseUpCallback(int buttonId, void *callbackData) {
+ KIA *self = (KIA *)callbackData;
+ switch (buttonId) {
+ case 0:
+ case 6:
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(504), 100, -65, -65, 50, 0);
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(506), 70, 0, 0, 50, 0);
+ break;
+ case 15:
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(504), 100, 0, 0, 50, 0);
+ break;
+ default:
+ break;
+ }
+ self->buttonClicked(buttonId);
+}
+
+void KIA::loopEnded(void *callbackData, int frame, int loopId) {
+ KIA *self = (KIA *)callbackData;
+ self->_mainVqaPlayer->setLoop(self->getVqaLoopMain(self->_currentSectionId) + 1, -1, kLoopSetModeJustStart, nullptr, nullptr);
+ self->_transitionId = 0;
+}
+
+void KIA::open(int sectionId) {
+ if (_currentSectionId == sectionId) {
+ return;
+ }
+
+ if (!sectionId) {
+ unload();
+ return;
+ }
+
+ if (!_currentSectionId) {
+ init();
+ }
+
+ switch (_currentSectionId) {
+ case kKIASectionCrimes:
+ _crimesSection->saveToLog();
+ break;
+ case kKIASectionSuspects:
+ _suspectsSection->saveToLog();
+ break;
+ case kKIASectionClues:
+ _cluesSection->saveToLog();
+ break;
+ }
+
+ if (sectionId != kKIASectionCrimes && sectionId != kKIASectionSuspects && sectionId != kKIASectionClues) {
+ playerReset();
+ }
+
+ _transitionId = getTransitionId(_currentSectionId, sectionId);
+ const char *name = getSectionVqaName(sectionId);
+ if (getSectionVqaName(_currentSectionId) != name) {
+ if (_mainVqaPlayer) {
+ _mainVqaPlayer->close();
+ delete _mainVqaPlayer;
+ _mainVqaPlayer = nullptr;
+ }
+
+ _mainVqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack);
+ _mainVqaPlayer->open(name);
+ }
+
+ if (_transitionId) {
+ playTransitionSound(_transitionId);
+ _mainVqaPlayer->setLoop(getVqaLoopTransition(_transitionId), -1, kLoopSetModeImmediate, nullptr, nullptr);
+ _mainVqaPlayer->setLoop(getVqaLoopMain(sectionId), -1, kLoopSetModeEnqueue, loopEnded, this);
+ } else {
+ int loopId = getVqaLoopMain(sectionId);
+ _mainVqaPlayer->setLoop(loopId, -1, kLoopSetModeImmediate, nullptr, nullptr);
+ _mainVqaPlayer->setLoop(loopId + 1, -1, kLoopSetModeJustStart, nullptr, nullptr);
+ }
+
+ _buttons->resetImages();
+ createButtons(sectionId);
+ switchSection(sectionId);
+ _currentSectionId = sectionId;
+
+ if (sectionId == kKIASectionCrimes || sectionId == kKIASectionSuspects || sectionId == kKIASectionClues) {
+ _lastSectionIdKIA = _currentSectionId;
+ }
+
+ if (sectionId == kKIASectionSettings || sectionId == kKIASectionHelp || sectionId == kKIASectionSave || sectionId == kKIASectionLoad) {
+ _lastSectionIdOptions = _currentSectionId;
+ }
+}
+
+void KIA::init() {
+ if (!_vm->openArchive("MODE.MIX")) {
+ return;
+ }
+
+ playerReset();
+ _playerVqaFrame = 0;
+ _playerVqaTimeLast = _vm->getTotalPlayTime();
+ _timeLast = _vm->getTotalPlayTime();
+
+ if (_vm->_gameFlags->query(kFlagKIAPrivacyAddon) && !_vm->_gameFlags->query(kFlagKIAPrivacyAddonIntro)) {
+ _vm->_gameFlags->set(kFlagKIAPrivacyAddonIntro);
+ playPrivateAddon();
+ }
+
+ _shapes->load();
+ _buttons->activate(nullptr, nullptr, mouseDownCallback, mouseUpCallback, this);
+ _vm->_mouse->setCursor(0);
+ if (_playerVqaPlayer == nullptr) {
+
+ _playerVqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront);
+ _playerVqaPlayer->open("kiaover.vqa");
+ _playerVqaPlayer->setLoop(0, -1, kLoopSetModeJustStart, nullptr, nullptr);
+ }
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(501), 70, 0, 0, 50, 0);
+
+ // TODO: time->lock();
+}
+
+void KIA::unload() {
+ if (!_currentSectionId) {
+ return;
+ }
+
+ _forceOpen = false;
+
+ if (_currentSection) {
+ _currentSection->close();
+ _currentSection = nullptr;
+ }
+
+ _buttons->resetImages();
+ _buttons->deactivate();
+
+ _shapes->unload();
+
+ if (_mainVqaPlayer) {
+ _mainVqaPlayer->close();
+ delete _mainVqaPlayer;
+ _mainVqaPlayer = nullptr;
+ }
+
+ if (_playerVqaPlayer) {
+ _playerVqaPlayer->close();
+ delete _playerVqaPlayer;
+ _playerVqaPlayer = nullptr;
+ }
+
+ _vm->closeArchive("MODE.MIX");
+
+ _currentSectionId = 0;
+
+ // TODO: Unfreeze game time
+
+ //if (!_vm->_settings->isLoadingGame(&Settings) && GameRunning)
+ // if (_vm->_gameIsRunning) {
+ // _vm->_scene->resume(false);
+ // }
+}
+
+void KIA::createButtons(int sectionId) {
+ Common::Rect kiaButton6( 66, 00, 122, 44);
+ Common::Rect kiaButton7( 191, 29, 233, 70);
+ Common::Rect kiaButton8( 234, 29, 278, 70);
+ Common::Rect kiaButton9( 278, 29, 321, 70);
+ Common::Rect kiaButton10(322, 29, 365, 70);
+ Common::Rect kiaButton11(366, 29, 410, 70);
+ Common::Rect kiaButton12(420, 286, 472, 328);
+ Common::Rect kiaButton13(334, 286, 386, 328);
+ Common::Rect kiaButton14(411, 29, 453, 70);
+ Common::Rect kiaButton15(264, 9, 304, 26);
+ Common::Rect kiaButton16(140, 406, 160, 479);
+ Common::Rect kiaButton17(161, 406, 180, 479);
+ Common::Rect kiaButton18(181, 406, 202, 479);
+ Common::Rect kiaButton19(575, 307, 606, 350);
+ Common::Rect kiaButton21(211, 443, 291, 479);
+
+ const Shape *shapeUp = nullptr;
+ const Shape *shapeHovered = nullptr;
+ const Shape *shapeDown = nullptr;
+
+ switch (sectionId) {
+ case kKIASectionCrimes:
+ case kKIASectionSuspects:
+ case kKIASectionClues:
+ _buttons->defineImage(0, kiaButton6, nullptr, nullptr, _shapes->get(1), _vm->_textKIA->getText(23));
+
+ if (sectionId == kKIASectionCrimes) {
+ shapeUp = _shapes->get(2);
+ shapeHovered = _shapes->get(2);
+ shapeDown = _shapes->get(10);
+ } else {
+ shapeUp = nullptr;
+ shapeHovered = nullptr;
+ shapeDown = _shapes->get(18);
+ }
+ _buttons->defineImage(1, kiaButton7, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(24));
+
+ if (sectionId == kKIASectionSuspects) {
+ shapeUp = _shapes->get(3);
+ shapeHovered = _shapes->get(3);
+ shapeDown = _shapes->get(11);
+ } else {
+ shapeUp = nullptr;
+ shapeHovered = nullptr;
+ shapeDown = _shapes->get(19);
+ }
+ _buttons->defineImage(2, kiaButton8, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(25));
+
+ if (sectionId == kKIASectionClues) {
+ shapeUp = _shapes->get(4);
+ shapeHovered = _shapes->get(4);
+ shapeDown = _shapes->get(12);
+ } else {
+ shapeUp = nullptr;
+ shapeHovered = nullptr;
+ shapeDown = _shapes->get(20);
+ }
+ _buttons->defineImage(3, kiaButton9, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(26));
+
+ _buttons->defineImage(4, kiaButton10, nullptr, nullptr, _shapes->get(21), _vm->_textKIA->getText(27));
+
+ _buttons->defineImage(5, kiaButton11, nullptr, nullptr, _shapes->get(22), _vm->_textKIA->getText(28));
+
+ _buttons->defineImage(14, kiaButton14, nullptr, nullptr, _shapes->get(23), _vm->_textKIA->getText(29));
+
+ break;
+ case kKIASectionSettings:
+ case kKIASectionHelp:
+ case kKIASectionSave:
+ case kKIASectionLoad:
+ case kKIASectionDiagnostic:
+ case kKIASectionPogo:
+ _buttons->defineImage(6, kiaButton6, nullptr, nullptr, _shapes->get(0), _vm->_textKIA->getText(37));
+
+ if (sectionId == kKIASectionSettings) {
+ shapeUp = _shapes->get(5);
+ shapeHovered = _shapes->get(5);
+ shapeDown = _shapes->get(13);
+ } else {
+ shapeUp = nullptr;
+ shapeHovered = nullptr;
+ shapeDown = _shapes->get(24);
+ }
+ _buttons->defineImage(7, kiaButton7, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(38));
+
+ if (sectionId == kKIASectionHelp) {
+ shapeUp = _shapes->get(6);
+ shapeHovered = _shapes->get(6);
+ shapeDown = _shapes->get(14);
+ } else {
+ shapeUp = nullptr;
+ shapeHovered = nullptr;
+ shapeDown = _shapes->get(25);
+ }
+ _buttons->defineImage(8, kiaButton8, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(41));
+
+ if (sectionId == kKIASectionSave) {
+ shapeUp = _shapes->get(7);
+ shapeHovered = _shapes->get(7);
+ shapeDown = _shapes->get(15);
+ } else {
+ shapeUp = nullptr;
+ shapeHovered = nullptr;
+ shapeDown = _shapes->get(26);
+ }
+ _buttons->defineImage(9, kiaButton9, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(39));
+
+ if (sectionId == kKIASectionLoad) {
+ shapeUp = _shapes->get(8);
+ shapeHovered = _shapes->get(8);
+ shapeDown = _shapes->get(16);
+ } else {
+ shapeUp = nullptr;
+ shapeHovered = nullptr;
+ shapeDown = _shapes->get(27);
+ }
+ _buttons->defineImage(10, kiaButton10, shapeUp, shapeHovered, shapeDown, _vm->_textKIA->getText(40));
+
+ _buttons->defineImage(11, kiaButton11, nullptr, nullptr, _shapes->get(28), _vm->_textKIA->getText(42));
+
+ _buttons->defineImage(14, kiaButton14, nullptr, nullptr, _shapes->get(29), _vm->_textKIA->getText(29));
+
+ break;
+ case 8:
+ _buttons->defineImage(12, kiaButton12, _shapes->get(124), _shapes->get(124), _shapes->get(48), _vm->_textKIA->getText(42));
+
+ _buttons->defineImage(13, kiaButton13, _shapes->get(125), _shapes->get(125), _shapes->get(49), _vm->_textKIA->getText(29));
+ break;
+ }
+
+ if (sectionId != kKIASectionQuit) {
+ _buttons->defineImage(15, kiaButton15, nullptr, nullptr, _shapes->get(38), _vm->_textKIA->getText(43));
+
+ _buttons->defineImage(19, kiaButton19, nullptr, nullptr, nullptr, _vm->_textKIA->getText(44));
+
+ if (_vm->_settings->getAmmoAmount(0) > 0) {
+ _buttons->defineImage(16, kiaButton16, nullptr, nullptr, nullptr, _vm->_textKIA->getText(50));
+ }
+ Common::String tooltip;
+ if (_vm->_settings->getAmmoAmount(1) > 0) {
+ if (_vm->_settings->getDifficulty() > 0) {
+ tooltip = Common::String::format("%d", _vm->_settings->getAmmoAmount(1));
+ } else {
+ tooltip = _vm->_textKIA->getText(50);
+ }
+ _buttons->defineImage(17, kiaButton17, nullptr, nullptr, nullptr, tooltip.c_str());
+ }
+ if (_vm->_settings->getAmmoAmount(2) > 0) {
+ if (_vm->_settings->getDifficulty() > 0) {
+ tooltip = Common::String::format("%d", _vm->_settings->getAmmoAmount(2));
+ } else {
+ tooltip = _vm->_textKIA->getText(50);
+ }
+ _buttons->defineImage(18, kiaButton18, nullptr, nullptr, nullptr, tooltip.c_str());
+ }
+ if (_vm->_gameFlags->query(kFlagKIAPrivacyAddon)) {
+ _buttons->defineImage(21, kiaButton21, nullptr, nullptr, nullptr, nullptr);
+ }
+ }
+}
+
+void KIA::buttonClicked(int buttonId) {
+ int soundId = 0;
+
+ if (!_currentSectionId) {
+ return;
+ }
+ switch (buttonId) {
+ case 0:
+ open(kKIASectionSettings);
+ break;
+ case 1:
+ if (_currentSectionId != kKIASectionCrimes) {
+ open(kKIASectionCrimes);
+ _log->next();
+ _log->clearFuture();
+ }
+ break;
+ case 2:
+ if (_currentSectionId != kKIASectionSuspects) {
+ open(kKIASectionSuspects);
+ _log->next();
+ _log->clearFuture();
+ }
+ break;
+ case 3:
+ if (_currentSectionId != kKIASectionClues) {
+ open(kKIASectionClues);
+ _log->next();
+ _log->clearFuture();
+ }
+ break;
+ case 4:
+ if (_log->hasPrev()) {
+ int kiaLogPrevType = _log->getPrevType();
+ switch (kiaLogPrevType) {
+ case 2:
+ open(kKIASectionCrimes);
+ _log->prev();
+ _crimesSection->loadFromLog();
+ break;
+ case 1:
+ open(kKIASectionSuspects);
+ _log->prev();
+ _suspectsSection->loadFromLog();
+ break;
+ case 0:
+ open(kKIASectionClues);
+ _log->prev();
+ _cluesSection->loadFromLog();
+ break;
+ }
+ }
+ break;
+ case 5:
+ if (_log->hasNext()) {
+ int kiaLogNextType = _log->getNextType();
+ switch (kiaLogNextType) {
+ case 2:
+ open(kKIASectionCrimes);
+ _log->next();
+ _crimesSection->loadFromLog();
+ break;
+ case 1:
+ open(kKIASectionSuspects);
+ _log->next();
+ _suspectsSection->loadFromLog();
+ break;
+ case 0:
+ open(kKIASectionClues);
+ _log->next();
+ _cluesSection->loadFromLog();
+ break;
+ }
+ }
+ break;
+ case 6:
+ if (!_forceOpen) {
+ open(_lastSectionIdKIA);
+ }
+ break;
+ case 7:
+ open(kKIASectionSettings);
+ break;
+ case 8:
+ open(kKIASectionHelp);
+ break;
+ case 9:
+ if (!_forceOpen) {
+ open(kKIASectionSave);
+ }
+ break;
+ case 10:
+ open(kKIASectionLoad);
+ break;
+ case 11:
+ open(kKIASectionQuit);
+ break;
+ case 12:
+ _vm->_gameIsRunning = false;
+ open(kKIASectionNone);
+ break;
+ case 13:
+ open(_lastSectionIdOptions);
+ break;
+ case 14:
+ if (!_forceOpen) {
+ open(kKIASectionNone);
+ }
+ break;
+ case 15:
+ open(kKIASectionDiagnostic);
+ break;
+ case 16:
+ _vm->_settings->setAmmoType(0);
+ if (_vm->_rnd.getRandomNumber(1)) {
+ soundId = _vm->_combat->getHitSound();
+ } else {
+ soundId = _vm->_combat->getMissSound();
+ }
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(soundId), 70, 0, 0, 50, 0);
+ break;
+ case 17:
+ _vm->_settings->setAmmoType(1);
+ if (_vm->_rnd.getRandomNumber(1)) {
+ soundId = _vm->_combat->getHitSound();
+ } else {
+ soundId = _vm->_combat->getMissSound();
+ }
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(soundId), 70, 0, 0, 50, 0);
+ break;
+ case 18:
+ _vm->_settings->setAmmoType(2);
+ if (_vm->_rnd.getRandomNumber(1)) {
+ soundId = _vm->_combat->getHitSound();
+ } else {
+ soundId = _vm->_combat->getMissSound();
+ }
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(soundId), 70, 0, 0, 50, 0);
+ break;
+ case 19:
+ return;
+ case 20:
+ playerReset();
+ break;
+ case 21:
+ playPrivateAddon();
+ break;
+ }
+}
+
+void KIA::switchSection(int sectionId) {
+ if (_currentSection) {
+ _currentSection->close();
+ }
+ switch (sectionId) {
+ case kKIASectionCrimes:
+ _currentSection = _crimesSection;
+ break;
+ case kKIASectionSuspects:
+ _currentSection = _suspectsSection;
+ break;
+ case kKIASectionClues:
+ _currentSection = _cluesSection;
+ break;
+ case kKIASectionSettings:
+ _currentSection = _settingsSection;
+ break;
+ case kKIASectionHelp:
+ _currentSection = _helpSection;
+ break;
+ case kKIASectionSave:
+ _currentSection = _saveSection;
+ break;
+ case kKIASectionLoad:
+ _currentSection = _loadSection;
+ break;
+ case kKIASectionQuit:
+ _currentSection = nullptr;
+ break;
+ case kKIASectionDiagnostic:
+ _currentSection = _diagnosticSection;
+ break;
+ case kKIASectionPogo:
+ _currentSection = _pogoSection;
+ break;
+ default:
+ _currentSection = nullptr;
+ break;
+ }
+ if (_currentSection) {
+ _currentSection->open();
+ }
+}
+
+const char *KIA::getSectionVqaName(int sectionId) {
+ switch (sectionId) {
+ case kKIASectionCrimes:
+ return "kia_crim.vqa";
+ case kKIASectionSuspects:
+ return "kia_susp.vqa";
+ case kKIASectionClues:
+ return "kia_clue.vqa";
+ case kKIASectionSettings:
+ case kKIASectionHelp:
+ case kKIASectionSave:
+ case kKIASectionLoad:
+ case kKIASectionQuit:
+ case kKIASectionDiagnostic:
+ case kKIASectionPogo:
+ return "kia_ingm.vqa";
+ default:
+ return nullptr;
+ }
+}
+
+int KIA::getVqaLoopMain(int sectionId) {
+ switch (sectionId) {
+ case kKIASectionCrimes:
+ case kKIASectionSuspects:
+ case kKIASectionClues:
+ return 3;
+ case kKIASectionSettings:
+ case kKIASectionHelp:
+ case kKIASectionSave:
+ case kKIASectionLoad:
+ case kKIASectionDiagnostic:
+ case kKIASectionPogo:
+ return 4;
+ case kKIASectionQuit:
+ return 7;
+ default:
+ return 0;
+ }
+}
+
+int KIA::getVqaLoopTransition(int transitionId) {
+ switch (transitionId) {
+ case 0:
+ case 2:
+ case 7:
+ case 8:
+ return 0;
+ case 1:
+ case 4:
+ case 5:
+ case 9:
+ return 1;
+ case 3:
+ case 10:
+ case 11:
+ case 12:
+ return 2;
+ case 6:
+ return 3;
+ case 13:
+ return 6;
+ default:
+ return 0;
+ }
+}
+
+int KIA::getTransitionId(int oldSectionId, int newSectionId) {
+ switch (oldSectionId) {
+ case kKIASectionNone:
+ return 0;
+ case kKIASectionCrimes:
+ switch (newSectionId) {
+ case kKIASectionCrimes:
+ return 0;
+ case kKIASectionSuspects:
+ return 1;
+ case kKIASectionClues:
+ return 2;
+ case kKIASectionSettings:
+ case kKIASectionHelp:
+ case kKIASectionSave:
+ case kKIASectionLoad:
+ case kKIASectionDiagnostic:
+ case kKIASectionPogo:
+ return 3;
+ case kKIASectionQuit:
+ return 13;
+ }
+ return 0;
+ case kKIASectionSuspects:
+ switch (newSectionId) {
+ case kKIASectionCrimes:
+ return 4;
+ case kKIASectionSuspects:
+ return 0;
+ case kKIASectionClues:
+ return 5;
+ case kKIASectionSettings:
+ case kKIASectionHelp:
+ case kKIASectionSave:
+ case kKIASectionLoad:
+ case kKIASectionDiagnostic:
+ case kKIASectionPogo:
+ return 6;
+ case kKIASectionQuit:
+ return 13;
+ }
+ return 0;
+ case kKIASectionClues:
+ switch (newSectionId) {
+ case kKIASectionCrimes:
+ return 7;
+ case kKIASectionSuspects:
+ return 8;
+ case kKIASectionClues:
+ return 0;
+ case kKIASectionSettings:
+ case kKIASectionHelp:
+ case kKIASectionSave:
+ case kKIASectionLoad:
+ case kKIASectionDiagnostic:
+ case kKIASectionPogo:
+ return 9;
+ case kKIASectionQuit:
+ return 13;
+ }
+ return 0;
+ case kKIASectionSettings:
+ case kKIASectionHelp:
+ case kKIASectionSave:
+ case kKIASectionLoad:
+ case kKIASectionDiagnostic:
+ case kKIASectionPogo:
+ switch (newSectionId) {
+ case kKIASectionCrimes:
+ return 10;
+ case kKIASectionSuspects:
+ return 11;
+ case kKIASectionClues:
+ return 12;
+ case kKIASectionSettings:
+ case kKIASectionHelp:
+ case kKIASectionSave:
+ case kKIASectionLoad:
+ case kKIASectionDiagnostic:
+ case kKIASectionPogo:
+ return 0;
+ case kKIASectionQuit:
+ return 13;
+ }
+ return 0;
+ case kKIASectionQuit:
+ if (newSectionId != kKIASectionQuit) {
+ return 14;
+ }
+ }
+ return 0;
+}
+
+void KIA::playTransitionSound(int transitionId) {
+ switch (transitionId) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(498), 100, 0, 0, 50, 0);
+ break;
+ case 13:
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(499), 100, 0, 0, 50, 0);
+ break;
+ case 14:
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(500), 100, 0, 0, 50, 0);
+ break;
+ }
+}
+
+void KIA::playPrivateAddon() {
+ playerReset();
+ playSliceModel(524);
+ playActorDialogue(14, 2060);
+ playActorDialogue(14, 2070);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia.h b/engines/bladerunner/ui/kia.h
new file mode 100644
index 0000000000..c979f9ff8b
--- /dev/null
+++ b/engines/bladerunner/ui/kia.h
@@ -0,0 +1,155 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_KIA_H
+#define BLADERUNNER_KIA_H
+
+#include "common/str.h"
+
+
+namespace Common {
+struct KeyState;
+}
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class KIALog;
+class KIAScript;
+class KIASectionBase;
+class KIASectionClues;
+class KIASectionDiagnostic;
+class KIASectionCrimes;
+class KIASectionHelp;
+class KIASectionLoad;
+class KIASectionSettings;
+class KIASectionPogo;
+class KIASectionSave;
+class KIASectionSuspects;
+class KIAShapes;
+class Shape;
+class UIImagePicker;
+class VQAPlayer;
+
+class KIA {
+ static const char *kPogo;
+
+ struct ActorDialogueQueueEntry {
+ int actorId;
+ int sentenceId;
+ };
+
+ BladeRunnerEngine *_vm;
+
+ int _forceOpen;
+ int _transitionId;
+
+ int _lastSectionIdKIA;
+ int _lastSectionIdOptions;
+
+ int _playerVqaTimeLast;
+ VQAPlayer *_playerVqaPlayer;
+ int _playerVqaFrame;
+ int _playerVisualizerState;
+ int _playerPhotographId;
+ Shape *_playerPhotograph;
+ int _playerSliceModelId;
+ float _playerSliceModelAngle;
+ int _timeLast;
+
+ ActorDialogueQueueEntry *_playerActorDialogueQueue;
+ int _playerActorDialogueQueueCapacity;
+ int _playerActorDialogueQueuePosition;
+ int _playerActorDialogueQueueSize;
+ int _playerActorDialogueState;
+
+ KIASectionBase *_currentSection;
+ KIASectionClues *_cluesSection;
+ KIASectionCrimes *_crimesSection;
+ KIASectionDiagnostic *_diagnosticSection;
+ KIASectionHelp *_helpSection;
+ KIASectionLoad *_loadSection;
+ KIASectionSettings *_settingsSection;
+ KIASectionPogo *_pogoSection;
+ KIASectionSave *_saveSection;
+ KIASectionSuspects *_suspectsSection;
+
+ UIImagePicker *_buttons;
+
+ VQAPlayer *_mainVqaPlayer;
+
+ int _pogoPos;
+
+public:
+ int _currentSectionId;
+ KIALog *_log;
+ KIAScript *_script;
+ KIAShapes *_shapes;
+
+public:
+ KIA(BladeRunnerEngine *vm);
+ ~KIA();
+
+ void openLastOpened();
+ void openOptions();
+
+ void tick();
+
+ void handleMouseDown(int mouseX, int mouseY, bool mainButton);
+ void handleMouseUp(int mouseX, int mouseY, bool mainButton);
+ void handleKeyUp(const Common::KeyState &kbd);
+ void handleKeyDown(const Common::KeyState &kbd);
+
+ void playerReset();
+ void playActorDialogue(int actorId, int sentenceId);
+ void playSliceModel(int sliceModelId);
+ void playPhotograph(int photographId);
+
+private:
+ static void mouseDownCallback(int buttonId, void *callbackData);
+ static void mouseUpCallback(int buttonId, void *callbackData);
+ static void loopEnded(void *callbackData, int frame, int loopId);
+
+ void open(int sectionId);
+ void init();
+ void unload();
+ void switchSection(int sectionId);
+
+ void createButtons(int sectionId);
+ void buttonClicked(int buttonId);
+
+ const char *getSectionVqaName(int sectionId);
+ int getVqaLoopMain(int sectionId);
+ int getVqaLoopTransition(int transitionId);
+
+ int getTransitionId(int oldSectionId, int newSectionId);
+ void playTransitionSound(int transitionId);
+
+ void playPrivateAddon();
+};
+
+} // End of namespace BladeRunner
+#endif
diff --git a/engines/bladerunner/ui/kia_log.cpp b/engines/bladerunner/ui/kia_log.cpp
new file mode 100644
index 0000000000..51b922a8f7
--- /dev/null
+++ b/engines/bladerunner/ui/kia_log.cpp
@@ -0,0 +1,128 @@
+/* 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/kia_log.h"
+
+#include "bladerunner/bladerunner.h"
+
+namespace BladeRunner {
+
+KIALog::KIALog(BladeRunnerEngine *vm) {
+ _vm = vm;
+
+ _firstIndex = 0;
+ _lastIndex = 0;
+ _currentIndex = 0;
+ for (int i = 0; i < kSize; ++i) {
+ _entries[i].dataSize = 0;
+ _entries[i].data = nullptr;
+ }
+}
+
+KIALog::~KIALog() {
+ clear();
+}
+
+void KIALog::add(int type, int dataSize, const void *data) {
+ if (_currentIndex == _lastIndex) {
+ _lastIndex = (_lastIndex + 1) % kSize;
+ }
+
+ if (_entries[_currentIndex].data) {
+ delete[] _entries[_currentIndex].data;
+ }
+
+ _entries[_currentIndex].type = type;
+ _entries[_currentIndex].dataSize = dataSize;
+
+ if (dataSize > 0) {
+ char *dataCopy = new char[dataSize];
+ memcpy(dataCopy, data, dataSize);
+ _entries[_currentIndex].data = dataCopy;
+ } else {
+ _entries[_currentIndex].data = nullptr;
+ }
+}
+
+void KIALog::clear() {
+ _firstIndex = 0;
+ _lastIndex = 0;
+ _currentIndex = 0;
+ for (int i = 0; i < kSize; ++i) {
+ if (_entries[i].data) {
+ delete[] _entries[i].data;
+ }
+ _entries[i].dataSize = 0;
+ _entries[i].data = nullptr;
+ }
+}
+
+void KIALog::prev() {
+ if (_currentIndex != _firstIndex) {
+ _currentIndex = (_currentIndex - 1) % kSize;
+ }
+}
+
+void KIALog::next() {
+ if (_currentIndex != _lastIndex) {
+ _currentIndex = (_currentIndex + 1) % kSize;
+ }
+}
+
+void KIALog::clearFuture() {
+ _lastIndex = _currentIndex;
+ int currentIndex = _currentIndex;
+ while (currentIndex != _firstIndex) {
+ if (_entries[currentIndex].data) {
+ delete[] _entries[currentIndex].data;
+ _entries[currentIndex].data = 0;
+ _entries[currentIndex].dataSize = 0;
+ }
+ currentIndex = (currentIndex + 1) % kSize;
+ }
+}
+
+bool KIALog::hasPrev() const {
+ return _currentIndex != _firstIndex;
+}
+
+bool KIALog::hasNext() const {
+ if (_currentIndex == _lastIndex) {
+ return false;
+ }
+
+ return (((_currentIndex + 1) % kSize) != _lastIndex);
+}
+
+int KIALog::getPrevType() const {
+ return _entries[(_currentIndex - 1) % kSize].type;
+}
+
+int KIALog::getNextType() const {
+ return _entries[(_currentIndex + 1) % kSize].type;
+}
+
+const void *KIALog::getCurrentData() const {
+ return _entries[_currentIndex].data;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia_log.h b/engines/bladerunner/ui/kia_log.h
new file mode 100644
index 0000000000..4a89492817
--- /dev/null
+++ b/engines/bladerunner/ui/kia_log.h
@@ -0,0 +1,65 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_KIA_LOG_H
+#define BLADERUNNER_KIA_LOG_H
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class KIALog {
+ static const int kSize = 16;
+
+ struct Entry {
+ int type;
+ int dataSize;
+ const char *data;
+ };
+
+ BladeRunnerEngine *_vm;
+
+ Entry _entries[kSize];
+ int _firstIndex;
+ int _lastIndex;
+ int _currentIndex;
+
+public:
+ KIALog(BladeRunnerEngine *vm);
+ ~KIALog();
+
+ void add(int type, int dataSize, const void *data);
+ void clear();
+
+ void prev();
+ void next();
+ void clearFuture();
+ bool hasPrev() const;
+ bool hasNext() const;
+ int getPrevType() const;
+ int getNextType() const;
+ const void *getCurrentData() const;
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/kia_section_base.cpp b/engines/bladerunner/ui/kia_section_base.cpp
new file mode 100644
index 0000000000..96571e5a48
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_base.cpp
@@ -0,0 +1,35 @@
+/* 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/kia_section_base.h"
+
+namespace BladeRunner {
+
+KIASectionBase::KIASectionBase(BladeRunnerEngine *vm) {
+ _vm = vm;
+ _field0 = false;
+}
+
+KIASectionBase::~KIASectionBase() {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia_section_base.h b/engines/bladerunner/ui/kia_section_base.h
new file mode 100644
index 0000000000..176e30d4b7
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_base.h
@@ -0,0 +1,67 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_KIA_SECTION_BASE_H
+#define BLADERUNNER_KIA_SECTION_BASE_H
+
+
+namespace Common {
+struct KeyState;
+}
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class KIASectionBase {
+protected:
+ BladeRunnerEngine *_vm;
+
+public:
+ bool _field0;
+
+ KIASectionBase(BladeRunnerEngine *vm);
+ virtual ~KIASectionBase();
+
+ virtual void open() {}
+ virtual void close() {}
+
+ virtual void draw(Graphics::Surface &surface) {}
+
+ virtual void handleKeyUp(const Common::KeyState &kbd) {}
+ virtual void handleKeyDown(const Common::KeyState &kbd) {}
+ virtual void handleMouseMove(int mouseX, int mouseY) {}
+ virtual void handleMouseDown(bool mainButton) {}
+ virtual void handleMouseUp(bool mainButton) {}
+
+protected:
+ virtual void onButtonPressed(int buttonId) {}
+
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/kia_section_clues.cpp b/engines/bladerunner/ui/kia_section_clues.cpp
new file mode 100644
index 0000000000..1e80b57ed7
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_clues.cpp
@@ -0,0 +1,422 @@
+/* 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/kia_section_clues.h"
+
+#include "bladerunner/actor_clues.h"
+#include "bladerunner/audio_player.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/crimes_database.h"
+#include "bladerunner/game_constants.h"
+#include "bladerunner/game_flags.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/font.h"
+#include "bladerunner/script/kia.h"
+#include "bladerunner/text_resource.h"
+#include "bladerunner/ui/kia.h"
+#include "bladerunner/ui/kia_log.h"
+#include "bladerunner/ui/kia_shapes.h"
+#include "bladerunner/ui/ui_container.h"
+#include "bladerunner/ui/ui_image_picker.h"
+#include "bladerunner/ui/ui_scroll_box.h"
+
+#include "common/rect.h"
+
+namespace BladeRunner {
+
+KIASectionClues::KIASectionClues(BladeRunnerEngine *vm, ActorClues *clues) : KIASectionBase(vm) {
+ _uiContainer = new UIContainer(_vm);
+
+ _isVisible = false;
+
+ _debugIntangible = false;
+ _debugNop = 0;
+
+ _clues = clues;
+
+ _mouseX = 0;
+ _mouseY = 0;
+
+ _buttons = new UIImagePicker(_vm, 2);
+
+ _cluesScrollBox = new UIScrollBox(_vm, scrollBoxCallback, this, _vm->_gameInfo->getClueCount(), 1, false, Common::Rect(312, 172, 500, 376), Common::Rect(506, 160, 506, 394));
+ _uiContainer->add(_cluesScrollBox);
+
+ _filterScrollBox = new UIScrollBox(_vm, scrollBoxCallback, this, 128, 1, false, Common::Rect(142, 162, 291, 376), Common::Rect(120, 160, 120, 370));
+ _uiContainer->add(_filterScrollBox);
+
+ _assetTypeFilterCount = 4 + 1; // we have 4 asset types
+ _crimeFilterCount = _vm->_gameInfo->getCrimeCount() + 1;
+ _filterCount = _assetTypeFilterCount + _crimeFilterCount;
+ _filters.resize(_filterCount);
+ for (int i = 0; i < _filterCount; ++i) {
+ _filters[i] = true;
+ }
+}
+
+KIASectionClues::~KIASectionClues() {
+ _uiContainer->clear();
+ delete _filterScrollBox;
+ delete _cluesScrollBox;
+ delete _uiContainer;
+}
+
+void KIASectionClues::open() {
+ _isVisible = true;
+
+ _buttons->resetImages();
+ _buttons->defineImage(0, Common::Rect(142, 380, 191, 395), _vm->_kia->_shapes->get(79), _vm->_kia->_shapes->get(80), _vm->_kia->_shapes->get(81), _vm->_textKIA->getText(30));
+ _buttons->defineImage(1, Common::Rect(193, 380, 242, 395), _vm->_kia->_shapes->get(76), _vm->_kia->_shapes->get(77), _vm->_kia->_shapes->get(78), _vm->_textKIA->getText(31));
+
+ _buttons->activate(nullptr, nullptr, nullptr, mouseUpCallback, this);
+ _cluesScrollBox->show();
+ _filterScrollBox->show();
+
+ populateFilters();
+ populateClues();
+}
+
+void KIASectionClues::close() {
+ if (_isVisible) {
+ _isVisible = false;
+
+ _buttons->deactivate();
+ _cluesScrollBox->hide();
+ _filterScrollBox->hide();
+ }
+}
+
+void KIASectionClues::draw(Graphics::Surface &surface) {
+ _uiContainer->draw(surface);
+
+ _vm->_mainFont->drawColor(_vm->_textKIA->getText(0), surface, 300, 162, 0x77DF);
+ _vm->_mainFont->drawColor(_vm->_textKIA->getText(2), surface, 440, 426, 0x2991);
+ _vm->_mainFont->drawColor(_vm->_textKIA->getText(1), surface, 440, 442, 0x2991);
+ _vm->_mainFont->drawColor(_vm->_textKIA->getText(4), surface, 440, 458, 0x2991);
+
+ int clueId = _cluesScrollBox->getSelectedLineData();
+ if (clueId != -1) {
+ Common::String text;
+
+ int actorId = _clues->getFromActorId(clueId);
+ if (actorId != -1) {
+ text = _vm->_textActorNames->getText(actorId);
+ } else {
+ text.clear();
+ }
+ _vm->_mainFont->drawColor(text, surface, 490, 426, 0x46BF);
+
+ int crimeId = _vm->_crimesDatabase->getCrime(clueId);
+ if (crimeId != -1) {
+ text = _vm->_textCrimes->getText(crimeId);
+ } else {
+ text.clear();
+ }
+ _vm->_mainFont->drawColor(text, surface, 490, 442, 0x46BF);
+
+ int assetType = _vm->_crimesDatabase->getAssetType(clueId);
+ if (assetType != -1) {
+ text = _vm->_textClueTypes->getText(assetType);
+ } else {
+ text.clear();
+ }
+ _vm->_mainFont->drawColor(text, surface, 490, 458, 0x46BF);
+ }
+
+ _buttons->draw(surface);
+ _buttons->drawTooltip(surface, _mouseX, _mouseY);
+
+ if (_debugNop) {
+ _vm->_mainFont->drawColor(Common::String::format("Debug display: %s", _vm->_textActorNames->getText(_debugNop)), surface, 120, 132, 0x7FE0);
+ }
+ if (_debugIntangible) {
+ _vm->_mainFont->drawColor("Debug Mode: Showing intangible clues.", surface, 220, 105, 0x7FE0);
+ }
+}
+
+void KIASectionClues::handleMouseMove(int mouseX, int mouseY) {
+ _mouseX = mouseX;
+ _mouseY = mouseY;
+ _buttons->handleMouseAction(mouseX, mouseY, false, false, false);
+ _uiContainer->handleMouseMove(mouseX, mouseY);
+}
+
+void KIASectionClues::handleMouseDown(bool mainButton) {
+ _uiContainer->handleMouseDown(!mainButton);
+ if (mainButton) {
+ _buttons->handleMouseAction(_mouseX, _mouseY, true, false, false);
+ }
+}
+
+void KIASectionClues::handleMouseUp(bool mainButton) {
+ _uiContainer->handleMouseUp(!mainButton);
+ if (mainButton) {
+ _buttons->handleMouseAction(_mouseX, _mouseY, false, true, false);
+ }
+}
+
+void KIASectionClues::saveToLog() {
+ _vm->_kia->_log->add(0, sizeof(bool) * _filterCount, _filters.data());
+}
+
+void KIASectionClues::loadFromLog() {
+ memcpy(_filters.data(), _vm->_kia->_log->getCurrentData(), sizeof(bool) * _filterCount);
+ populateFilters();
+ populateClues();
+}
+
+void KIASectionClues::scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton) {
+ KIASectionClues *self = (KIASectionClues *)callbackData;
+
+ if (source == self->_filterScrollBox && lineData >= 0) {
+ self->_filters[lineData] = !self->_filters[lineData];
+ self->_filterScrollBox->toggleCheckBox(lineData);
+ self->populateClues();
+ } else if (source == self->_cluesScrollBox && lineData >= 0) {
+ if (mouseButton) {
+ if (self->_vm->_gameFlags->query(kFlagKIAPrivacyAddon)) {
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(511), 70, 0, 0, 50, 0);
+
+ if (self->_clues->isPrivate(lineData)) {
+ self->_clues->setPrivate(lineData, false);
+ self->_cluesScrollBox->resetFlags(lineData, 0x08);
+ } else {
+ self->_clues->setPrivate(lineData, true);
+ self->_cluesScrollBox->setFlags(lineData, 0x08);
+ }
+ }
+ } else {
+ self->_clues->setViewed(lineData, true);
+ self->_cluesScrollBox->resetHighlight(lineData);
+ self->_vm->_kia->_script->playClueAssetScript(0, lineData);
+ }
+ }
+}
+
+void KIASectionClues::mouseUpCallback(int buttonId, void *callbackData) {
+ KIASectionClues *self = (KIASectionClues *)callbackData;
+
+ if (buttonId <= 1) {
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(510), 100, 0, 0, 50, 0);
+ }
+
+ self->onButtonPressed(buttonId);
+}
+
+void KIASectionClues::onButtonPressed(int buttonId) {
+ if (buttonId == 1) {
+ disableAllFilters();
+ }
+ if (buttonId == 0) {
+ enableAllFilters();
+ }
+}
+
+void KIASectionClues::enableAllFilters() {
+ for (int i = 0; i < _filterCount; ++i) {
+ if (_filterScrollBox->hasLine(i)) {
+ _filters[i] = true;
+ }
+ }
+ _filterScrollBox->checkAll();
+ populateClues();
+}
+
+void KIASectionClues::disableAllFilters() {
+ for (int i = 0; i < _filterCount; ++i) {
+ if (_filterScrollBox->hasLine(i)) {
+ _filters[i] = false;
+ }
+ }
+ _filterScrollBox->uncheckAll();
+ populateClues();
+}
+
+void KIASectionClues::populateFilters() {
+ _filterScrollBox->clearLines();
+
+ Common::Array<bool> availableFilters(_filterCount);
+ for (int i = 0; i < _filterCount; ++i) {
+ availableFilters[i] = false;
+ }
+
+ Common::String assetTypeNames[] = {
+ _vm->_textKIA->getText(6),
+ _vm->_textKIA->getText(7),
+ _vm->_textKIA->getText(8),
+ _vm->_textKIA->getText(9)
+ };
+
+ for (int i = 0; i < kClueCount; ++i) {
+ if (_clues->isAcquired(i)) {
+ int assetType = _vm->_crimesDatabase->getAssetType(i);
+ int crimeId = _vm->_crimesDatabase->getCrime(i);
+ if (_debugIntangible || assetType != -1) {
+ availableFilters[getLineIdForAssetType(assetType)] = true;
+ availableFilters[getLineIdForCrimeId(crimeId)] = true;
+ }
+ }
+ }
+
+ int assetTypeFiltersAvailable = 0;
+ for (int i = 0; i < _assetTypeFilterCount; ++i) {
+ if (availableFilters[i]) {
+ ++assetTypeFiltersAvailable;
+ }
+ }
+
+ int crimeFiltersAvailable = 0;
+ for (int i = _assetTypeFilterCount; i < _filterCount; ++i) {
+ if (availableFilters[i]) {
+ ++crimeFiltersAvailable;
+ }
+ }
+
+ if (assetTypeFiltersAvailable > 1) {
+ _filterScrollBox->addLine(_vm->_textKIA->getText(11), -1, 0x04);
+
+ for (int i = 0; i < _assetTypeFilterCount; ++i) {
+ if (availableFilters[i]) {
+ int flags = 0x01;
+ if (_filters[i]) {
+ flags |= 0x02;
+ }
+
+ Common::String text;
+ int typeTextId = getClueFilterTypeTextId(i);
+ if (typeTextId == -1) {
+ text = _vm->_textKIA->getText(10);
+ } else {
+ text = assetTypeNames[typeTextId];
+ }
+
+ _filterScrollBox->addLine(text, i, flags);
+ }
+ }
+ }
+
+ if (crimeFiltersAvailable > 1) {
+ if (assetTypeFiltersAvailable > 1) {
+ _filterScrollBox->addLine(" ", -1, 0);
+ }
+
+ _filterScrollBox->addLine(_vm->_textKIA->getText(12), -1, 0x04);
+
+ struct Line {
+ Common::String crimeName;
+ int lineData;
+ int flags;
+ };
+
+ Common::Array<Line> crimeLines;
+ crimeLines.reserve(crimeFiltersAvailable);
+
+ for (int i = _assetTypeFilterCount; i < _filterCount; ++i) {
+ if (availableFilters[i]) {
+ Line line;
+
+ line.lineData = i;
+
+ line.flags = 0x01;
+ if (_filters[i]) {
+ line.flags |= 0x02;
+ }
+
+ int crimeId = getClueFilterCrimeId(i);
+ if (crimeId == -1) {
+ line.crimeName = _vm->_textKIA->getText(5);
+ } else {
+ line.crimeName = _vm->_textCrimes->getText(crimeId);
+ }
+
+ crimeLines.push_back(line);
+ }
+ }
+
+ for (int i = 0; i < crimeFiltersAvailable - 1; ++i) {
+ for (int j = i + 1; j < crimeFiltersAvailable; ++j) {
+ if (crimeLines[i].lineData != _assetTypeFilterCount) {
+ if (crimeLines[i].crimeName.compareToIgnoreCase(crimeLines[j].crimeName) <= 0) {
+ continue;
+ }
+ }
+ SWAP(crimeLines[i], crimeLines[j]);
+ }
+ }
+
+ for (uint i = 0; i < crimeLines.size(); ++i) {
+ _filterScrollBox->addLine(crimeLines[i].crimeName, crimeLines[i].lineData, crimeLines[i].flags);
+ }
+ }
+}
+
+void KIASectionClues::populateClues() {
+ _cluesScrollBox->clearLines();
+ for (int i = 0; i < kClueCount; ++i) {
+ if (_clues->isAcquired(i)) {
+ int assetType = _vm->_crimesDatabase->getAssetType(i);
+ int crimeId = _vm->_crimesDatabase->getCrime(i);
+ if (assetType != -1 || _debugIntangible) {
+ if(_filters[getLineIdForAssetType(assetType)] && _filters[getLineIdForCrimeId(crimeId)]) {
+ int flags = 0x30;
+ if (_clues->isPrivate(i)) {
+ flags = 0x08;
+ } else if (_clues->isViewed(i)) {
+ flags = 0x10;
+ }
+ _cluesScrollBox->addLine(_vm->_crimesDatabase->getClueText(i), i, flags);
+ }
+ }
+ }
+ }
+ _cluesScrollBox->sortLines();
+}
+
+int KIASectionClues::getClueFilterTypeTextId(int i) {
+ if (i) {
+ return i - 1;
+ }
+ return -1;
+}
+
+int KIASectionClues::getClueFilterCrimeId(int filterId) {
+ if (filterId == _assetTypeFilterCount) {
+ return -1;
+ }
+ return filterId - (_assetTypeFilterCount + 1);
+}
+
+int KIASectionClues::getLineIdForAssetType(int assetType) {
+ if (assetType == -1) {
+ return 0;
+ }
+ return assetType + 1;
+}
+
+int KIASectionClues::getLineIdForCrimeId(int crimeId) {
+ if (crimeId == -1) {
+ return _assetTypeFilterCount;
+ }
+ return _assetTypeFilterCount + crimeId + 1;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia_section_clues.h b/engines/bladerunner/ui/kia_section_clues.h
new file mode 100644
index 0000000000..28d9077e6c
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_clues.h
@@ -0,0 +1,95 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_KIA_SECTION_CLUES_H
+#define BLADERUNNER_KIA_SECTION_CLUES_H
+
+#include "bladerunner/ui/kia_section_base.h"
+
+#include "common/array.h"
+#include "common/str.h"
+
+namespace BladeRunner {
+
+class ActorClues;
+class UIContainer;
+class UIImagePicker;
+class UIScrollBox;
+
+class KIASectionClues : public KIASectionBase {
+ static const int kClueCount = 288;
+
+ UIContainer *_uiContainer;
+ UIImagePicker *_buttons;
+ UIScrollBox *_cluesScrollBox;
+ UIScrollBox *_filterScrollBox;
+
+ bool _isVisible;
+ bool _debugIntangible;
+ int _debugNop;
+ ActorClues *_clues;
+
+ int _assetTypeFilterCount;
+ int _crimeFilterCount;
+ int _filterCount;
+ Common::Array<bool> _filters;
+
+ int _mouseX;
+ int _mouseY;
+
+public:
+ KIASectionClues(BladeRunnerEngine *vm, ActorClues *clues);
+ ~KIASectionClues();
+
+ void open();
+ void close();
+
+ void draw(Graphics::Surface &surface);
+
+ void handleMouseMove(int mouseX, int mouseY);
+ void handleMouseDown(bool mainButton);
+ void handleMouseUp(bool mainButton);
+
+ void saveToLog();
+ void loadFromLog();
+
+private:
+ static void scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton);
+ static void mouseUpCallback(int buttonId, void *callbackData);
+
+ void onButtonPressed(int buttonId);
+
+ void enableAllFilters();
+ void disableAllFilters();
+
+ void populateFilters();
+ void populateClues();
+
+ int getClueFilterTypeTextId(int);
+ int getClueFilterCrimeId(int);
+ int getLineIdForAssetType(int assetType);
+ int getLineIdForCrimeId(int crimeId);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/kia_section_crimes.cpp b/engines/bladerunner/ui/kia_section_crimes.cpp
new file mode 100644
index 0000000000..4cfaaedbad
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_crimes.cpp
@@ -0,0 +1,37 @@
+/* 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/kia_section_crimes.h"
+
+#include "bladerunner/bladerunner.h"
+
+namespace BladeRunner {
+
+KIASectionCrimes::KIASectionCrimes(BladeRunnerEngine *vm)
+ : KIASectionBase(vm)
+ , _shape(vm) {
+}
+
+KIASectionCrimes::~KIASectionCrimes() {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia_section_crimes.h b/engines/bladerunner/ui/kia_section_crimes.h
new file mode 100644
index 0000000000..befe5e528c
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_crimes.h
@@ -0,0 +1,82 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_KIA_SECTION_CRIME_H
+#define BLADERUNNER_KIA_SECTION_CRIME_H
+
+#include "bladerunner/shape.h"
+#include "bladerunner/ui/kia_section_base.h"
+
+namespace BladeRunner {
+
+class ActorClues;
+class BladeRunnerEngine;
+class UIContainer;
+class UIImagePicker;
+class UIScrollBox;
+
+class KIASectionCrimes : public KIASectionBase {
+ struct Clue
+ {
+ int clueId;
+ int actorId;
+ };
+
+protected:
+
+ UIContainer *_uiContainer;
+ // void (__cdecl **scrollboxCallback)(int, UIScrollBoxStruc *, int, int);
+ int _isOpen;
+ int *_list;
+ UIImagePicker *_uiImagePicker;
+
+ UIScrollBox *_cluesScrollbox;
+ ActorClues *_clues;
+ int _clueInfoCount;
+ Clue _clueInfo[1000];
+ int _selectedCrimeId;
+ int _crimesFoundCount;
+ int *_crimeIsKnown;
+ int _selectedSuspectId;
+ int _suspectsFoundCount;
+ int *_suspectIsKnown;
+ int *_suspectHasIdentity;
+ int _mouseX;
+ int _mouseY;
+ int _suspectPhotoShapeId;
+ int _field_15;
+ Shape _shape;
+
+public:
+ KIASectionCrimes(BladeRunnerEngine *vm);
+ ~KIASectionCrimes();
+
+ void saveToLog() {}
+ void loadFromLog() {}
+
+protected:
+
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/kia_section_diagnostic.h b/engines/bladerunner/ui/kia_section_diagnostic.h
new file mode 100644
index 0000000000..9a5b74b8af
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_diagnostic.h
@@ -0,0 +1,39 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_KIA_SECTION_DIAGNOSTIC_H
+#define BLADERUNNER_KIA_SECTION_DIAGNOSTIC_H
+
+#include "bladerunner/ui/kia_section_base.h"
+
+namespace BladeRunner {
+
+class KIASectionDiagnostic : public KIASectionBase {
+
+public:
+ KIASectionDiagnostic(BladeRunnerEngine *vm) : KIASectionBase(vm){}
+
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/kia_section_help.cpp b/engines/bladerunner/ui/kia_section_help.cpp
new file mode 100644
index 0000000000..5065382c41
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_help.cpp
@@ -0,0 +1,90 @@
+/* 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/kia_section_help.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/text_resource.h"
+#include "bladerunner/ui/kia.h"
+#include "bladerunner/ui/kia_shapes.h"
+#include "bladerunner/ui/ui_container.h"
+#include "bladerunner/ui/ui_scroll_box.h"
+
+namespace BladeRunner {
+
+KIASectionHelp::KIASectionHelp(BladeRunnerEngine *vm) : KIASectionBase(vm) {
+ _uiContainer = new UIContainer(_vm);
+ _scrollBox = new UIScrollBox(_vm, nullptr, this, 1024, 0, false, Common::Rect(135, 145, 461, 385), Common::Rect(506, 160, 506, 350));
+
+ _uiContainer->add(_scrollBox);
+}
+
+KIASectionHelp::~KIASectionHelp() {
+ _uiContainer->clear();
+ delete _scrollBox;
+ delete _uiContainer;
+}
+
+void KIASectionHelp::open() {
+ TextResource textResource(_vm);
+ textResource.open("HELP");
+
+ _scrollBox->clearLines();
+
+ for (int i = 0; i < textResource.getCount(); ++i) {
+ Common::String textLine = textResource.getText(i);
+ int flags = 0x04;
+ if (textLine.firstChar() == ' ') {
+ flags = 0x00;
+ }
+ _scrollBox->addLine(textLine, -1, flags);
+ }
+
+ _scrollBox->show();
+}
+
+void KIASectionHelp::close() {
+ _scrollBox->hide();
+}
+
+void KIASectionHelp::draw(Graphics::Surface &surface){
+ _vm->_kia->_shapes->get(69)->draw(surface, 501, 123);
+ _uiContainer->draw(surface);
+}
+
+void KIASectionHelp::handleKeyUp(const Common::KeyState &kbd) {
+ _uiContainer->handleKeyUp(kbd);
+}
+
+void KIASectionHelp::handleMouseMove(int mouseX, int mouseY) {
+ _uiContainer->handleMouseMove(mouseX, mouseY);
+}
+
+void KIASectionHelp::handleMouseDown(bool mainButton) {
+ _uiContainer->handleMouseDown(!mainButton);
+}
+
+void KIASectionHelp::handleMouseUp(bool mainButton) {
+ _uiContainer->handleMouseUp(!mainButton);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia_section_help.h b/engines/bladerunner/ui/kia_section_help.h
new file mode 100644
index 0000000000..0bda5d8851
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_help.h
@@ -0,0 +1,54 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_KIA_SECTION_HELP_H
+#define BLADERUNNER_KIA_SECTION_HELP_H
+
+#include "bladerunner/ui/kia_section_base.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class UIContainer;
+class UIScrollBox;
+
+class KIASectionHelp : public KIASectionBase {
+ UIContainer *_uiContainer;
+ UIScrollBox *_scrollBox;
+
+public:
+ KIASectionHelp(BladeRunnerEngine *vm);
+ ~KIASectionHelp();
+
+ void open();
+ void close();
+
+ void draw(Graphics::Surface &surface);
+
+ void handleKeyUp(const Common::KeyState &kbd);
+ void handleMouseMove(int mouseX, int mouseY);
+ void handleMouseDown(bool mainButton);
+ void handleMouseUp(bool mainButton);
+};
+
+} // End of namespace BladeRunner
+#endif
diff --git a/engines/bladerunner/ui/kia_section_load.h b/engines/bladerunner/ui/kia_section_load.h
new file mode 100644
index 0000000000..4cff04d2c4
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_load.h
@@ -0,0 +1,39 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_KIA_SECTION_LOAD_H
+#define BLADERUNNER_KIA_SECTION_LOAD_H
+
+#include "bladerunner/ui/kia_section_base.h"
+
+namespace BladeRunner {
+
+class KIASectionLoad : public KIASectionBase {
+
+public:
+ KIASectionLoad(BladeRunnerEngine *vm): KIASectionBase(vm){}
+
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/kia_section_pogo.h b/engines/bladerunner/ui/kia_section_pogo.h
new file mode 100644
index 0000000000..d2a2edd859
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_pogo.h
@@ -0,0 +1,39 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_KIA_SECTION_POGO_H
+#define BLADERUNNER_KIA_SECTION_POGO_H
+
+#include "bladerunner/ui/kia_section_base.h"
+
+namespace BladeRunner {
+
+class KIASectionPogo : public KIASectionBase {
+
+public:
+ KIASectionPogo(BladeRunnerEngine *vm): KIASectionBase(vm){}
+
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/kia_section_save.h b/engines/bladerunner/ui/kia_section_save.h
new file mode 100644
index 0000000000..5e2f5f26ac
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_save.h
@@ -0,0 +1,39 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_KIA_SECTION_SAVE_H
+#define BLADERUNNER_KIA_SECTION_SAVE_H
+
+#include "bladerunner/ui/kia_section_base.h"
+
+namespace BladeRunner {
+
+class KIASectionSave : public KIASectionBase {
+
+public:
+ KIASectionSave(BladeRunnerEngine *vm): KIASectionBase(vm){}
+
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/kia_section_settings.cpp b/engines/bladerunner/ui/kia_section_settings.cpp
new file mode 100644
index 0000000000..7f2db4ae12
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_settings.cpp
@@ -0,0 +1,301 @@
+/* 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/kia_section_settings.h"
+
+#include "bladerunner/audio_player.h"
+#include "bladerunner/audio_speech.h"
+#include "bladerunner/ambient_sounds.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/font.h"
+#include "bladerunner/game_constants.h"
+#include "bladerunner/game_flags.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/music.h"
+#include "bladerunner/settings.h"
+#include "bladerunner/text_resource.h"
+#include "bladerunner/ui/kia.h"
+#include "bladerunner/ui/kia_shapes.h"
+#include "bladerunner/ui/ui_check_box.h"
+#include "bladerunner/ui/ui_container.h"
+#include "bladerunner/ui/ui_image_picker.h"
+#include "bladerunner/ui/ui_slider.h"
+
+#include "common/keyboard.h"
+
+namespace BladeRunner {
+
+const char *KIASectionSettings::kLeary = "LEARY";
+
+KIASectionSettings::KIASectionSettings(BladeRunnerEngine *vm)
+ : KIASectionBase(vm) {
+
+ _uiContainer = new UIContainer(_vm);
+ _musicVolume = new UISlider(_vm, sliderCallback, this, Common::Rect(180, 160, 460, 170), 101, 0);
+ _soundEffectVolume = new UISlider(_vm, sliderCallback, this, Common::Rect( 180, 185, 460, 195), 101, 0);
+ _ambientSoundVolume = new UISlider(_vm, sliderCallback, this, Common::Rect(180, 210, 460, 220), 101, 0);
+ _speechVolume = new UISlider(_vm, sliderCallback, this, Common::Rect(180, 235, 460, 245), 101, 0);
+ _gammaCorrection = new UISlider(_vm, sliderCallback, this, Common::Rect(180, 260, 460, 270), 101, 0);
+ _directorsCut = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(180, 364, 460, 374), 0, false);
+ _playerAgendaSelector = new UIImagePicker(_vm, 5);
+
+ _uiContainer->add(_musicVolume);
+ _uiContainer->add(_soundEffectVolume);
+ _uiContainer->add(_ambientSoundVolume);
+ _uiContainer->add(_speechVolume);
+ _uiContainer->add(_gammaCorrection);
+ _uiContainer->add(_directorsCut);
+
+ _learyPos = 0;
+}
+
+KIASectionSettings::~KIASectionSettings() {
+ delete _uiContainer;
+ delete _musicVolume;
+ delete _soundEffectVolume;
+ delete _ambientSoundVolume;
+ delete _speechVolume;
+ delete _gammaCorrection;
+ delete _directorsCut;
+ delete _playerAgendaSelector;
+}
+
+void KIASectionSettings::open() {
+ _playerAgendaSelector->resetImages();
+
+ _playerAgendaSelector->defineImage(0, Common::Rect(180, 290, 227, 353), nullptr, nullptr, nullptr, _vm->_textOptions->getText(30));
+ _playerAgendaSelector->defineImage(1, Common::Rect(238, 290, 285, 353), nullptr, nullptr, nullptr, _vm->_textOptions->getText(31));
+ _playerAgendaSelector->defineImage(2, Common::Rect(296, 290, 343, 353), nullptr, nullptr, nullptr, _vm->_textOptions->getText(32));
+ _playerAgendaSelector->defineImage(3, Common::Rect(354, 290, 401, 353), nullptr, nullptr, nullptr, _vm->_textOptions->getText(33));
+ _playerAgendaSelector->defineImage(4, Common::Rect(412, 290, 459, 353), nullptr, nullptr, nullptr, _vm->_textOptions->getText(34));
+ initConversationChoices();
+ _playerAgendaSelector->activate(mouseInCallback, nullptr, nullptr, mouseUpCallback, this);
+
+ _directorsCut->enable();
+}
+
+void KIASectionSettings::close() {
+ _playerAgendaSelector->deactivate();
+}
+
+void KIASectionSettings::draw(Graphics::Surface &surface) {
+ _musicVolume->setValue(_vm->_music->getVolume());
+ _soundEffectVolume->setValue(_vm->_audioPlayer->getVolume());
+ _ambientSoundVolume->setValue(_vm->_ambientSounds->getVolume());
+ _speechVolume->setValue(_vm->_audioSpeech->getVolume());
+ _gammaCorrection->setValue(100.0f);
+ _directorsCut->setChecked(_vm->_gameFlags->query(kFlagDirectorsCut));
+
+ const char *textConversationChoices = _vm->_textOptions->getText(0);
+ const char *textMusic = _vm->_textOptions->getText(2);
+ const char *textSoundEffects = _vm->_textOptions->getText(3);
+ const char *textAmbientSound = _vm->_textOptions->getText(4);
+ const char *textSpeech = _vm->_textOptions->getText(5);
+ const char *textGammaCorrection = _vm->_textOptions->getText(7);
+ const char *textSoft = _vm->_textOptions->getText(10);
+ const char *textLoud = _vm->_textOptions->getText(11);
+ const char *textDark = _vm->_textOptions->getText(14);
+ const char *textLight = _vm->_textOptions->getText(15);
+ const char *textDesignersCut = _vm->_textOptions->getText(18);
+
+ int posConversationChoices = 320 - _vm->_mainFont->getTextWidth(textConversationChoices) / 2;
+ int posMusic = 320 - _vm->_mainFont->getTextWidth(textMusic) / 2;
+ int posSoundEffects = 320 - _vm->_mainFont->getTextWidth(textSoundEffects) / 2;
+ int posAmbientSound = 320 - _vm->_mainFont->getTextWidth(textAmbientSound) / 2;
+ int posSpeech = 320 - _vm->_mainFont->getTextWidth(textSpeech) / 2;
+ int posGammaCorrection = 320 - _vm->_mainFont->getTextWidth(textGammaCorrection) / 2;
+ int posSoft = 178 - _vm->_mainFont->getTextWidth(textSoft);
+ int posDark = 178 - _vm->_mainFont->getTextWidth(textDark);
+
+ _uiContainer->draw(surface);
+ _playerAgendaSelector->draw(surface);
+
+ _vm->_mainFont->drawColor(textConversationChoices, surface, posConversationChoices, 280, 0x7751);
+
+ _vm->_mainFont->drawColor(textMusic, surface, posMusic, 150, 0x7751);
+ _vm->_mainFont->drawColor(textSoft, surface, posSoft, 161, 0x6EEE);
+ _vm->_mainFont->drawColor(textLoud, surface, 462, 161, 0x6EEE);
+
+ _vm->_mainFont->drawColor(textSoundEffects, surface, posSoundEffects, 175, 0x7751);
+ _vm->_mainFont->drawColor(textSoft, surface, posSoft, 186, 0x6EEE);
+ _vm->_mainFont->drawColor(textLoud, surface, 462, 186, 0x6EEE);
+
+ _vm->_mainFont->drawColor(textAmbientSound, surface, posAmbientSound, 200, 0x7751);
+ _vm->_mainFont->drawColor(textSoft, surface, posSoft, 211, 0x6EEE);
+ _vm->_mainFont->drawColor(textLoud, surface, 462, 211, 0x6EEE);
+
+ _vm->_mainFont->drawColor(textSpeech, surface, posSpeech, 225, 0x7751);
+ _vm->_mainFont->drawColor(textSoft, surface, posSoft, 236, 0x6EEE);
+ _vm->_mainFont->drawColor(textLoud, surface, 462, 236, 0x6EEE);
+
+ _vm->_mainFont->drawColor(textGammaCorrection, surface, posGammaCorrection, 250, 0x7751);
+ _vm->_mainFont->drawColor(textDark, surface, posDark, 261, 0x6EEE);
+ _vm->_mainFont->drawColor(textLight, surface, 462, 261, 0x6EEE);
+
+ _vm->_mainFont->drawColor(textDesignersCut, surface, 192, 365, 0x7751);
+
+ _playerAgendaSelector->drawTooltip(surface, _mouseX, _mouseY);
+}
+
+void KIASectionSettings::handleKeyUp(const Common::KeyState &kbd) {
+ if (toupper(kbd.ascii) != kLeary[_learyPos]) {
+ _learyPos = 0;
+ }
+
+ if (toupper(kbd.ascii) == kLeary[_learyPos]) {
+ ++_learyPos;
+ if (!kLeary[_learyPos]) {
+ _vm->_settings->setLearyMode(!_vm->_settings->getLearyMode());
+ _learyPos = 0;
+ initConversationChoices();
+ }
+ }
+}
+
+void KIASectionSettings::handleMouseMove(int mouseX, int mouseY) {
+ _uiContainer->handleMouseMove(mouseX, mouseY);
+ _mouseX = mouseX;
+ _mouseY = mouseY;
+ _playerAgendaSelector->handleMouseAction(mouseX, mouseY, false, false, false);
+}
+
+void KIASectionSettings::handleMouseDown(bool mainButton) {
+ if (mainButton) {
+ _uiContainer->handleMouseDown(false);
+ _playerAgendaSelector->handleMouseAction(_mouseX, _mouseY, true, false, false);
+ }
+}
+
+void KIASectionSettings::handleMouseUp(bool mainButton) {
+ if (mainButton) {
+ _uiContainer->handleMouseUp(false);
+ _playerAgendaSelector->handleMouseAction(_mouseX, _mouseY, false, true, false);
+ }
+}
+
+void KIASectionSettings::sliderCallback(void *callbackData, void *source) {
+ KIASectionSettings *self = (KIASectionSettings *)callbackData;
+
+ if (source == self->_musicVolume) {
+ self->_vm->_music->setVolume(self->_musicVolume->_value);
+ self->_vm->_music->playSample();
+ } else if (source == self->_soundEffectVolume) {
+ self->_vm->_audioPlayer->setVolume(self->_soundEffectVolume->_value);
+ self->_vm->_audioPlayer->playSample();
+ } else if (source == self->_ambientSoundVolume) {
+ self->_vm->_ambientSounds->setVolume(self->_ambientSoundVolume->_value);
+ self->_vm->_ambientSounds->playSample();
+ } else if (source == self->_speechVolume) {
+ self->_vm->_audioSpeech->setVolume(self->_speechVolume->_value);
+ self->_vm->_audioSpeech->playSample();
+ } else if (source == self->_gammaCorrection) {
+ // TODO: gamma, should we support it?
+ // gamma = self->_gammaCorrection._value / 100.0f;
+ // settings::setGamma(&Settings, gamma);
+ // colorFormat = DirectDrawSurfaces_get_colorFormat();
+ // Palette_fill(colorFormat);
+ // Palette_copy(Palette);
+ // kia::resume(KIA);
+ }
+}
+
+void KIASectionSettings::checkBoxCallback(void *callbackData, void *source) {
+ KIASectionSettings *self = (KIASectionSettings *)callbackData;
+ if (source == self->_directorsCut) {
+ if (self->_directorsCut->_isChecked) {
+ self->_vm->_gameFlags->set(kFlagDirectorsCut);
+ } else {
+ self->_vm->_gameFlags->reset(kFlagDirectorsCut);
+ }
+ }
+}
+
+void KIASectionSettings::mouseInCallback(int buttonId, void *callbackData) {
+ KIASectionSettings *self = (KIASectionSettings *)callbackData;
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(508), 100, 0, 0, 50, 0);
+}
+
+void KIASectionSettings::mouseUpCallback(int buttonId, void *callbackData) {
+ KIASectionSettings *self = (KIASectionSettings *)callbackData;
+ self->onButtonPressed(buttonId);
+}
+
+void KIASectionSettings::onButtonPressed(int buttonId) {
+ switch (buttonId) {
+ case 0:
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(513), 90, -30, -30, 50, 0);
+ _vm->_settings->setPlayerAgenda(0);
+ initConversationChoices();
+ break;
+ case 1:
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(513), 90, -15, -15, 50, 0);
+ _vm->_settings->setPlayerAgenda(1);
+ initConversationChoices();
+ break;
+ case 2:
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(513), 90, 0, 0, 50, 0);
+ _vm->_settings->setPlayerAgenda(2);
+ initConversationChoices();
+ break;
+ case 3:
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(513), 90, 15, 15, 50, 0);
+ _vm->_settings->setPlayerAgenda(3);
+ initConversationChoices();
+ break;
+ case 4:
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(513), 90, 30, 30, 50, 0);
+ _vm->_settings->setPlayerAgenda(4);
+ initConversationChoices();
+ break;
+ default:
+ return;
+ }
+}
+
+void KIASectionSettings::initConversationChoices() {
+ for (int i = 0; i < 5; ++i) {
+ const Shape *shape = nullptr;
+ if (_vm->_settings->getPlayerAgenda() == i) {
+ if (i == 4) {
+ shape = _vm->_kia->_shapes->get(122);
+ } else if (_vm->_settings->getLearyMode()) {
+ shape = _vm->_kia->_shapes->get(106 + i);
+ } else {
+ shape = _vm->_kia->_shapes->get(114 + i);
+ }
+ } else {
+ if (i == 4) {
+ shape = _vm->_kia->_shapes->get(123);
+ } else if (_vm->_settings->getLearyMode()) {
+ shape = _vm->_kia->_shapes->get(110 + i);
+ } else {
+ shape = _vm->_kia->_shapes->get(118 + i);
+ }
+ }
+
+ _playerAgendaSelector->setImageShapeUp(i, shape);
+ _playerAgendaSelector->setImageShapeHovered(i, shape);
+ _playerAgendaSelector->setImageShapeDown(i, shape);
+ }
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia_section_settings.h b/engines/bladerunner/ui/kia_section_settings.h
new file mode 100644
index 0000000000..49356266b7
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_settings.h
@@ -0,0 +1,80 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_KIA_SECTION_SETTINGS_H
+#define BLADERUNNER_KIA_SECTION_SETTINGS_H
+
+#include "bladerunner/ui/kia_section_base.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class UIContainer;
+class UICheckBox;
+class UIImagePicker;
+class UISlider;
+
+class KIASectionSettings : public KIASectionBase {
+ static const char *kLeary;
+
+ UIContainer *_uiContainer;
+ UISlider *_musicVolume;
+ UISlider *_soundEffectVolume;
+ UISlider *_ambientSoundVolume;
+ UISlider *_speechVolume;
+ UISlider *_gammaCorrection;
+ UICheckBox *_directorsCut;
+ UIImagePicker *_playerAgendaSelector;
+
+ int _mouseX;
+ int _mouseY;
+
+ int _learyPos;
+
+public:
+ KIASectionSettings(BladeRunnerEngine *vm);
+ ~KIASectionSettings();
+
+ void open();
+ void close();
+
+ void draw(Graphics::Surface &surface);
+
+ void handleKeyUp(const Common::KeyState &kbd);
+ void handleMouseMove(int mouseX, int mouseY);
+ void handleMouseDown(bool mainButton);
+ void handleMouseUp(bool mainButton);
+
+private:
+ static void sliderCallback(void *callbackData, void *source);
+ static void checkBoxCallback(void *callbackData, void *source);
+ static void mouseInCallback(int buttonId, void *callbackData);
+ static void mouseUpCallback(int buttonId, void *callbackData);
+
+ void onButtonPressed(int buttonId);
+
+ void initConversationChoices();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/kia_section_suspects.h b/engines/bladerunner/ui/kia_section_suspects.h
new file mode 100644
index 0000000000..94cf1bfc06
--- /dev/null
+++ b/engines/bladerunner/ui/kia_section_suspects.h
@@ -0,0 +1,41 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_KIA_SECTION_SUSPECTS_H
+#define BLADERUNNER_KIA_SECTION_SUSPECTS_H
+
+#include "bladerunner/ui/kia_section_base.h"
+
+namespace BladeRunner {
+
+class KIASectionSuspects : public KIASectionBase {
+
+public:
+ KIASectionSuspects(BladeRunnerEngine *vm): KIASectionBase(vm) {}
+
+ void saveToLog() {}
+ void loadFromLog() {}
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/kia_shapes.cpp b/engines/bladerunner/ui/kia_shapes.cpp
new file mode 100644
index 0000000000..6835216e26
--- /dev/null
+++ b/engines/bladerunner/ui/kia_shapes.cpp
@@ -0,0 +1,69 @@
+/* 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/kia_shapes.h"
+
+#include "bladerunner/bladerunner.h"
+
+namespace BladeRunner {
+
+KIAShapes::KIAShapes(BladeRunnerEngine *vm) {
+ _vm = vm;
+ _isLoaded = false;
+}
+
+KIAShapes::~KIAShapes() {
+ unload();
+}
+
+void KIAShapes::load() {
+ if (_isLoaded) {
+ return;
+ }
+
+ for (uint i = 0; i < kShapeCount; ++i) {
+ Shape *shape = new Shape(_vm);
+ shape->readFromContainer("kiaopt.shp", i);
+ _shapes[i] = shape;
+ }
+
+ _isLoaded = true;
+}
+
+void KIAShapes::unload() {
+ if (!_isLoaded) {
+ return;
+ }
+
+ for (uint i = 0; i < kShapeCount; ++i) {
+ delete _shapes[i];
+ _shapes[i] = nullptr;
+ }
+
+ _isLoaded = false;
+}
+
+const Shape *KIAShapes::get(int shapeId) const {
+ return _shapes[shapeId];
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia_shapes.h b/engines/bladerunner/ui/kia_shapes.h
new file mode 100644
index 0000000000..e075547542
--- /dev/null
+++ b/engines/bladerunner/ui/kia_shapes.h
@@ -0,0 +1,54 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_UI_SHAPES_H
+#define BLADERUNNER_UI_SHAPES_H
+
+#include "bladerunner/shape.h"
+
+#include "common/array.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class KIAShapes
+{
+private:
+ static const int kShapeCount = 132;
+
+ BladeRunnerEngine *_vm;
+ const Shape *_shapes[kShapeCount];
+ bool _isLoaded;
+
+public:
+ KIAShapes(BladeRunnerEngine *vm);
+ ~KIAShapes();
+
+ void load();
+ void unload();
+ const Shape *get(int shapeId) const;
+};
+
+} // End of namespace BladeRunner
+
+#endif
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
diff --git a/engines/bladerunner/ui/spinner.h b/engines/bladerunner/ui/spinner.h
new file mode 100644
index 0000000000..ec0f8dbe33
--- /dev/null
+++ b/engines/bladerunner/ui/spinner.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.
+ *
+ */
+
+#ifndef BLADERUNNER_SPINNER_H
+#define BLADERUNNER_SPINNER_H
+
+#include "common/array.h"
+#include "common/rect.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class Shape;
+class VQAPlayer;
+class UIImagePicker;
+
+
+class Spinner {
+ static const int kSpinnerDestinations = 10;
+
+ struct Destination {
+ int id;
+ Common::Rect rect;
+ };
+
+ static const Destination kSpinnerDestinationsNear[];
+ static const Destination kSpinnerDestinationsMedium[];
+ static const Destination kSpinnerDestinationsFar[];
+
+ BladeRunnerEngine *_vm;
+ bool _isDestinationSelectable[kSpinnerDestinations];
+ bool _isOpen;
+ VQAPlayer *_vqaPlayer;
+ const Destination *_destinations;
+ int _selectedDestination;
+ Common::Array<Shape *> _shapes;
+ UIImagePicker *_imagePicker;
+
+public:
+ Spinner(BladeRunnerEngine *vm);
+ ~Spinner();
+
+ void setSelectableDestinationFlag(int destination, bool selectable);
+ bool querySelectableDestinationFlag(int destination) const;
+
+ int chooseDestination(int vqaLoopId, bool immediately);
+
+ void open();
+ bool isOpen() const;
+
+ int handleMouseUp(int x, int y);
+ int handleMouseDown(int x, int y);
+
+ void tick();
+ void setSelectedDestination(int destination);
+ void reset();
+ void resume();
+
+private:
+ static void mouseUpCallback(int, void *);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/ui_check_box.cpp b/engines/bladerunner/ui/ui_check_box.cpp
new file mode 100644
index 0000000000..39e120e883
--- /dev/null
+++ b/engines/bladerunner/ui/ui_check_box.cpp
@@ -0,0 +1,140 @@
+/* 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/ui_check_box.h"
+
+#include "bladerunner/audio_player.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/ui/kia.h"
+#include "bladerunner/ui/kia_shapes.h"
+
+namespace BladeRunner {
+
+UICheckBox::UICheckBox(BladeRunnerEngine *vm, UIComponentCallback *valueChangedCallback, void *callbackData, Common::Rect rect, int style, bool isChecked)
+ : UIComponent(vm) {
+
+ _valueChangedCallback = valueChangedCallback;
+ _callbackData = callbackData;
+
+ _isEnabled = true;
+ _hasFocus = false;
+ _isPressed = false;
+ _style = style;
+
+ if (isChecked) {
+ _frame = 5;
+ } else {
+ _frame = 0;
+ }
+
+ _timeLast = _vm->getTotalPlayTime();
+ _rect = rect;
+ _isChecked = isChecked;
+}
+
+
+void UICheckBox::draw(Graphics::Surface &surface) {
+ int shapeId;
+ if (_rect.right > _rect.left && _rect.bottom > _rect.top) {
+ uint timeNow = _vm->getTotalPlayTime();
+ if (timeNow - _timeLast > 67) {
+ int frameDelta = (timeNow - _timeLast) / 67u;
+ _timeLast = timeNow;
+
+ if (_isChecked) {
+ _frame = MIN(_frame + frameDelta, 5);
+ } else {
+ _frame = MAX(_frame - frameDelta, 0);
+ }
+ }
+
+ if (_style) {
+ if (_frame || (_hasFocus && !_isPressed && _isEnabled)) {
+ if (_frame != 5 || (_hasFocus && !_isPressed && _isEnabled)) {
+ shapeId = _frame + 54;
+ } else {
+ shapeId = 53;
+ }
+ } else {
+ shapeId = 52;
+ }
+ } else {
+ if (_frame || (_hasFocus && !_isPressed && _isEnabled)) {
+ if (_frame != 5 || (_hasFocus && !_isPressed && _isEnabled)) {
+ shapeId = _frame + 62;
+ } else {
+ shapeId = 61;
+ }
+ } else {
+ shapeId = 60;
+ }
+ }
+
+ _vm->_kia->_shapes->get(shapeId)->draw(surface, _rect.left, _rect.top + 1);
+ }
+}
+
+void UICheckBox::enable() {
+ _isEnabled = true;
+ _isPressed = false;
+ _hasFocus = false;
+}
+
+void UICheckBox::disable() {
+ _isEnabled = false;
+}
+
+void UICheckBox::setChecked(bool isChecked) {
+ _isChecked = isChecked;
+}
+
+void UICheckBox::handleMouseMove(int mouseX, int mouseY) {
+ if (_rect.contains(mouseX, mouseY)) {
+ if (!_hasFocus && _isEnabled && !_isPressed ) {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(508), 100, 0, 0, 50, 0);
+ }
+ _hasFocus = true;
+ } else {
+ _hasFocus = false;
+ }
+}
+
+void UICheckBox::handleMouseDown(bool alternateButton) {
+ if (!alternateButton) {
+ if (_isEnabled && _hasFocus) {
+ _isChecked = !_isChecked;
+ if (_valueChangedCallback) {
+ _valueChangedCallback(_callbackData, this);
+ }
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(509), 100, 0, 0, 50, 0);
+ } else {
+ _isPressed = true;
+ }
+ }
+}
+
+void UICheckBox::handleMouseUp(bool alternateButton) {
+ _isPressed = false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/ui_check_box.h b/engines/bladerunner/ui/ui_check_box.h
new file mode 100644
index 0000000000..cfd584b09e
--- /dev/null
+++ b/engines/bladerunner/ui/ui_check_box.h
@@ -0,0 +1,64 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_UI_CHECKBOX_H
+#define BLADERUNNER_UI_CHECKBOX_H
+
+#include "bladerunner/ui/ui_component.h"
+
+#include "common/rect.h"
+
+namespace BladeRunner {
+
+class UICheckBox : public UIComponent
+{
+private:
+ UIComponentCallback *_valueChangedCallback;
+ void *_callbackData;
+
+ int _style;
+ int _isEnabled;
+ Common::Rect _rect;
+ int _frame;
+ int _isPressed;
+ uint _timeLast;
+ int _hasFocus;
+
+public:
+ bool _isChecked;
+
+ UICheckBox(BladeRunnerEngine *vm, UIComponentCallback *valueChangedCallback, void *callbackData, Common::Rect rect, int style, bool isChecked);
+
+ void draw(Graphics::Surface &surface);
+
+ void enable();
+ void disable();
+ void setChecked(bool isChecked);
+
+ void handleMouseMove(int mouseX, int mouseY);
+ void handleMouseDown(bool alternateButton);
+ void handleMouseUp(bool alternateButton);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/ui_component.h b/engines/bladerunner/ui/ui_component.h
new file mode 100644
index 0000000000..9c290d9dcb
--- /dev/null
+++ b/engines/bladerunner/ui/ui_component.h
@@ -0,0 +1,62 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_UI_COMPONENT_H
+#define BLADERUNNER_UI_COMPONENT_H
+
+namespace Common{
+struct KeyState;
+}
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+typedef void UIComponentCallback(void *callbackData, void *source);
+
+class UIComponent
+{
+protected:
+ BladeRunnerEngine *_vm;
+
+public:
+ UIComponent(BladeRunnerEngine *vm) {
+ _vm = vm;
+ }
+
+ virtual ~UIComponent() {}
+
+ virtual void draw(Graphics::Surface &surface) {}
+
+ virtual void handleMouseMove(int mouseX, int mouseY) {}
+ virtual void handleMouseDown(bool alternateButton) {}
+ virtual void handleMouseUp(bool alternateButton) {}
+ virtual void handleKeyUp(const Common::KeyState &kbd) {}
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/ui_container.cpp b/engines/bladerunner/ui/ui_container.cpp
new file mode 100644
index 0000000000..78097a9d3d
--- /dev/null
+++ b/engines/bladerunner/ui/ui_container.cpp
@@ -0,0 +1,67 @@
+/* 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/ui_container.h"
+
+#include "common/keyboard.h"
+
+namespace BladeRunner {
+
+void UIContainer::draw(Graphics::Surface &surface) {
+for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); component++) {
+ (*component)->draw(surface);
+ }
+}
+
+void UIContainer::handleMouseMove(int mouseX, int mouseY) {
+ for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); component++) {
+ (*component)->handleMouseMove(mouseX, mouseY);
+ }
+}
+
+void UIContainer::handleMouseDown(bool alternateButton) {
+for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); component++) {
+ (*component)->handleMouseDown(alternateButton);
+ }
+}
+
+void UIContainer::handleMouseUp(bool alternateButton) {
+for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); component++) {
+ (*component)->handleMouseUp(alternateButton);
+ }
+}
+
+void UIContainer::handleKeyUp(const Common::KeyState &kbd) {
+for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); component++) {
+ (*component)->handleKeyUp(kbd);
+ }
+}
+
+void UIContainer::add(UIComponent *component) {
+ _components.push_back(component);
+}
+
+void UIContainer::clear() {
+ _components.clear();
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/ui_container.h b/engines/bladerunner/ui/ui_container.h
new file mode 100644
index 0000000000..9d5bded960
--- /dev/null
+++ b/engines/bladerunner/ui/ui_container.h
@@ -0,0 +1,56 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_UI_CONTAINER_H
+#define BLADERUNNER_UI_CONTAINER_H
+
+#include "bladerunner/ui/ui_component.h"
+
+#include "common/array.h"
+
+namespace BladeRunner {
+
+class UIComponent;
+
+class UIContainer : public UIComponent
+{
+private:
+ Common::Array<UIComponent*> _components;
+
+public:
+ UIContainer(BladeRunnerEngine *vm) : UIComponent(vm) {}
+
+ void draw(Graphics::Surface &surface);
+
+ void handleMouseMove(int mouseX, int mouseY);
+ void handleMouseDown(bool alternateButton);
+ void handleMouseUp(bool alternateButton);
+ void handleKeyUp(const Common::KeyState &kbd);
+
+ void add(UIComponent *component);
+ void clear();
+};
+
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/ui_image_picker.cpp b/engines/bladerunner/ui/ui_image_picker.cpp
new file mode 100644
index 0000000000..997ff7bc5e
--- /dev/null
+++ b/engines/bladerunner/ui/ui_image_picker.cpp
@@ -0,0 +1,331 @@
+/* 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/ui_image_picker.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/font.h"
+#include "bladerunner/mouse.h"
+#include "bladerunner/shape.h"
+
+#include "common/rect.h"
+#include "common/str.h"
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+UIImagePicker::UIImagePicker(BladeRunnerEngine *vm, int imageCount) {
+ _vm = vm;
+ reset();
+ _images.resize(imageCount);
+ _imageCount = imageCount;
+ resetImages();
+}
+
+UIImagePicker::~UIImagePicker() {
+ _images.clear();
+ reset();
+}
+
+void UIImagePicker::resetImages() {
+ for (int i = 0; i != _imageCount; i++) {
+ resetImage(i);
+ }
+}
+
+bool UIImagePicker::defineImage(int i, Common::Rect rect, const Shape *shapeUp, const Shape *shapeHovered, const Shape *shapeDown, const char *tooltip) {
+ if (i < 0 || i >= _imageCount || _images[i].active) {
+ return false;
+ }
+
+ Image &img = _images[i];
+
+ img.rect = rect;
+ // for rect to be inclusive
+ img.rect.right += 1;
+ img.rect.bottom += 1;
+ img.shapeUp = shapeUp;
+ img.shapeHovered = shapeHovered;
+ img.shapeDown = shapeDown;
+ img.active = true;
+
+ if (tooltip != nullptr) {
+ img.tooltip = tooltip;
+ } else {
+ img.tooltip.clear();
+ }
+
+ return true;
+}
+
+bool UIImagePicker::setImageTop(int i, int top) {
+ if (i < 0 || i >= _imageCount || !_images[i].active) {
+ return false;
+ }
+
+ Image &img = _images[i];
+
+ img.rect.moveTo(img.rect.left, top);
+
+ return true;
+}
+
+bool UIImagePicker::setImageLeft(int i, int left) {
+ if (i < 0 || i >= _imageCount || !_images[i].active) {
+ return false;
+ }
+
+ Image &img = _images[i];
+
+ img.rect.moveTo(left, img.rect.top);
+
+ return true;
+}
+
+bool UIImagePicker::setImageShapeUp(int i, const Shape *shapeUp) {
+ if (i < 0 || i >= _imageCount || !_images[i].active) {
+ return false;
+ }
+
+ _images[i].shapeUp = shapeUp;
+
+ return true;
+}
+
+bool UIImagePicker::setImageShapeHovered(int i, const Shape *shapeHovered) {
+ if (i < 0 || i >= _imageCount || !_images[i].active) {
+ return false;
+ }
+
+ _images[i].shapeHovered = shapeHovered;
+
+ return true;
+}
+
+bool UIImagePicker::setImageShapeDown(int i, const Shape *shapeDown) {
+ if (i < 0 || i >= _imageCount || !_images[i].active) {
+ return false;
+ }
+
+ _images[i].shapeDown = shapeDown;
+
+ return true;
+}
+
+bool UIImagePicker::setImageTooltip(int i, const char *tooltip) {
+ if (i < 0 || i >= _imageCount || !_images[i].active) {
+ return false;
+ }
+
+ _images[i].tooltip = tooltip;
+
+ return true;
+}
+
+bool UIImagePicker::resetActiveImage(int i) {
+ if (i < 0 || i >= _imageCount || !_images[i].active) {
+ return false;
+ }
+
+ resetImage(i);
+ return true;
+}
+
+void UIImagePicker::activate(UIImagePickerCallback *mouseInCallback,
+ UIImagePickerCallback *mouseOutCallback,
+ UIImagePickerCallback *mouseDownCallback,
+ UIImagePickerCallback *mouseUpCallback,
+ void *callbackData)
+{
+ _isButtonDown = false;
+ _mouseInCallback = mouseInCallback;
+ _mouseOutCallback = mouseOutCallback;
+ _mouseDownCallback = mouseDownCallback;
+ _mouseUpCallback = mouseUpCallback;
+ _callbackData = callbackData;
+ _hoverStartTimestamp = 0;
+ _isVisible = true;
+ _hoveredImageIndex = -1;
+ _pressedImageIndex = -1;
+}
+
+void UIImagePicker::deactivate() {
+ _isButtonDown = false;
+ _mouseInCallback = nullptr;
+ _mouseOutCallback = nullptr;
+ _mouseDownCallback = nullptr;
+ _mouseUpCallback = nullptr;
+ _callbackData = nullptr;
+ _hoverStartTimestamp = 0;
+ _isVisible = false;
+ _hoveredImageIndex = -1;
+ _pressedImageIndex = -1;
+}
+
+void UIImagePicker::draw(Graphics::Surface &surface) {
+ if (!_isVisible) {
+ return;
+ }
+
+ for (int i = 0; i != _imageCount; ++i) {
+ Image &img = _images[i];
+ if (!img.active) {
+ continue;
+ }
+
+ // TODO: Check interaction with Mouse::isDisabled
+ if (i == _hoveredImageIndex && i == _pressedImageIndex && _isButtonDown) {
+ if (img.shapeDown) {
+ img.shapeDown->draw(surface, img.rect.left, img.rect.top);
+ }
+ } else if (i == _hoveredImageIndex && !_isButtonDown) {
+ if (img.shapeHovered) {
+ img.shapeHovered->draw(surface, img.rect.left, img.rect.top);
+ }
+ } else {
+ if (img.shapeUp) {
+ img.shapeUp->draw(surface, img.rect.left, img.rect.top);
+ }
+ }
+#if BLADERUNNER_DEBUG_RENDERING
+ surface.frameRect(img.rect, 0x7fff);
+#endif
+ }
+}
+
+void UIImagePicker::drawTooltip(Graphics::Surface &surface, int x, int y) {
+ if (!_isVisible) {
+ return;
+ }
+
+ if (_hoveredImageIndex == -1 || _vm->_mouse->isDisabled() || !_images[_hoveredImageIndex].active || _vm->getTotalPlayTime() < _hoverStartTimestamp + 1000) {
+ return;
+ }
+
+ Common::String &tooltip = _images[_hoveredImageIndex].tooltip;
+ int width = _vm->_mainFont->getTextWidth(tooltip) + 1;
+ int height = _vm->_mainFont->getTextHeight(tooltip) + 1;
+
+ Common::Rect rect;
+ rect.left = x - ((width / 2) + 1);
+ if (rect.left < 0) {
+ rect.left = 0;
+ }
+
+ rect.top = y - 10;
+ if (rect.top < 0) {
+ rect.top = 0;
+ }
+
+ rect.right = width + rect.left + 3;
+ if (rect.right >= 640) {
+ rect.right = 639;
+ rect.left = 636 - width;
+ }
+
+ rect.bottom = height + rect.top + 1;
+ if (rect.bottom >= 480) {
+ rect.bottom = 479;
+ rect.top = 478 - height;
+ }
+
+ surface.fillRect(rect, 0);
+ surface.frameRect(rect, 0x7FFF);
+ _vm->_mainFont->drawColor(tooltip, surface, rect.left + 2, rect.top, 0x7FFF);
+}
+
+void UIImagePicker::handleMouseAction(int x, int y, bool down, bool up, bool ignore) {
+ if (!_isVisible || ignore) {
+ return;
+ }
+
+ int hoveredImageIndex = -1;
+ for (int i = 0; i != _imageCount; ++i) {
+ if (_images[i].rect.contains(x, y)) {
+ hoveredImageIndex = i;
+ break;
+ }
+ }
+
+ // If mouse moved to a new image
+ if (hoveredImageIndex != _hoveredImageIndex) {
+ if (!_isButtonDown) {
+ if (hoveredImageIndex == -1) {
+ if (_mouseOutCallback) {
+ _mouseOutCallback(hoveredImageIndex, _callbackData);
+ }
+ } else {
+ if (_mouseInCallback) {
+ _mouseInCallback(hoveredImageIndex, _callbackData);
+ }
+ }
+ }
+ _hoverStartTimestamp = _vm->getTotalPlayTime();
+ _hoveredImageIndex = hoveredImageIndex;
+ }
+
+ // If mouse button changed to pressed
+ if (down && !_isButtonDown) {
+ _isButtonDown = true;
+ _pressedImageIndex = _hoveredImageIndex;
+ if (_hoveredImageIndex != 1) {
+ if (_mouseDownCallback) {
+ _mouseDownCallback(_hoveredImageIndex, _callbackData);
+ }
+ }
+ }
+
+ // If mouse button changed to released
+ if (up) {
+ if (_isButtonDown) {
+ if (_hoveredImageIndex == _pressedImageIndex && _pressedImageIndex != -1) {
+ if (_mouseUpCallback)
+ _mouseUpCallback(_hoveredImageIndex, _callbackData);
+ }
+ }
+ _isButtonDown = false;
+ _pressedImageIndex = -1;
+ }
+}
+
+void UIImagePicker::resetImage(int i) {
+ assert(i >= 0 && i < _imageCount);
+ Image &img = _images[i];
+
+ img.active = false;
+ img.rect.left = -1;
+ img.rect.top = -1;
+ img.rect.right = -1;
+ img.rect.bottom = -1;
+ img.shapeUp = nullptr;
+ img.shapeHovered = nullptr;
+ img.shapeDown = nullptr;
+ img.tooltip.clear();
+}
+
+bool UIImagePicker::hasHoveredImage() {
+ return _hoveredImageIndex >= 0;
+}
+
+void UIImagePicker::reset() {}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/ui_image_picker.h b/engines/bladerunner/ui/ui_image_picker.h
new file mode 100644
index 0000000000..00f2f3dfd9
--- /dev/null
+++ b/engines/bladerunner/ui/ui_image_picker.h
@@ -0,0 +1,104 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_UI_IMAGE_PICKER_H
+#define BLADERUNNER_UI_IMAGE_PICKER_H
+
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/str.h"
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class Shape;
+
+typedef void UIImagePickerCallback(int, void *);
+
+class UIImagePicker {
+ struct Image {
+ int active;
+ Common::Rect rect;
+ const Shape *shapeUp;
+ const Shape *shapeHovered;
+ const Shape *shapeDown;
+ Common::String tooltip;
+ };
+
+ BladeRunnerEngine *_vm;
+
+ int _isVisible;
+ int _imageCount;
+ int _hoveredImageIndex;
+ int _pressedImageIndex;
+ uint32 _hoverStartTimestamp;
+ int _isButtonDown;
+ Common::Array<Image> _images;
+
+ UIImagePickerCallback *_mouseInCallback;
+ UIImagePickerCallback *_mouseOutCallback;
+ UIImagePickerCallback *_mouseDownCallback;
+ UIImagePickerCallback *_mouseUpCallback;
+ void *_callbackData;
+
+public:
+ UIImagePicker(BladeRunnerEngine *vm, int imageCount);
+ ~UIImagePicker();
+
+ void resetImages();
+ bool defineImage(int i, Common::Rect rect, const Shape *shapeUp, const Shape *shapeHovered, const Shape *shapeDown, const char *tooltip);
+
+ bool setImageTop(int i, int top);
+ bool setImageLeft(int i, int left);
+ bool setImageShapeUp(int i, const Shape *shapeUp);
+ bool setImageShapeHovered(int i, const Shape *shapeHovered);
+ bool setImageShapeDown(int i, const Shape *shapeDown);
+ bool setImageTooltip(int i, const char *tooltip);
+
+ bool resetActiveImage(int i);
+
+ void activate(UIImagePickerCallback *mouseInCallback,
+ UIImagePickerCallback *mouseOutCallback,
+ UIImagePickerCallback *mouseDownCallback,
+ UIImagePickerCallback *mouseUpCallback,
+ void *callbackData);
+
+ void deactivate();
+
+ void draw(Graphics::Surface &surface);
+ void drawTooltip(Graphics::Surface &surface, int x, int y);
+
+ void handleMouseAction(int x, int y, bool down, bool up, bool ignore = false);
+
+ void resetImage(int i);
+ bool hasHoveredImage();
+
+ void reset();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/ui_input_box.cpp b/engines/bladerunner/ui/ui_input_box.cpp
new file mode 100644
index 0000000000..409563f73e
--- /dev/null
+++ b/engines/bladerunner/ui/ui_input_box.cpp
@@ -0,0 +1,115 @@
+/* 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/ui_input_box.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/font.h"
+
+#include "common/keyboard.h"
+
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+UIInputBox::UIInputBox(BladeRunnerEngine *vm, UIComponentCallback *valueChangedCallback, void *callbackData, Common::Rect rect, int maxLength, const Common::String &text)
+ : UIComponent(vm) {
+ _valueChangedCallback = valueChangedCallback;
+ _callbackData = callbackData;
+
+ _isVisible = true;
+ _rect = rect;
+
+ _maxLength = maxLength;
+ _length = 0;
+ setText(text);
+
+ _cursorIsVisible = false;
+ _timeLast = _vm->getTotalPlayTime();
+}
+
+void UIInputBox::draw(Graphics::Surface &surface) {
+ if (!_isVisible) {
+ return;
+ }
+
+ int rectHalfWidth = (_rect.right + _rect.left) / 2;
+ int textHalfWidth = _vm->_mainFont->getTextWidth(_text) / 2;
+
+ _vm->_mainFont->drawColor(_text, surface, rectHalfWidth - textHalfWidth, _rect.top, 0x4DC7); // 10011 01110 00111
+
+ if (_cursorIsVisible) {
+ surface.vLine(textHalfWidth + rectHalfWidth + 2, _rect.top, _rect.bottom - 1, 0x7FDD); // 11111 11110 11101
+ }
+
+ if (_vm->getTotalPlayTime() - _timeLast > 500) {
+ _timeLast = _vm->getTotalPlayTime();
+ _cursorIsVisible = !_cursorIsVisible;
+ }
+}
+
+void UIInputBox::setText(const Common::String &text) {
+ _text = text;
+}
+
+const Common::String &UIInputBox::getText() {
+ return _text;
+}
+
+void UIInputBox::show() {
+ _isVisible = true;
+}
+
+void UIInputBox::hide() {
+ _isVisible = false;
+}
+
+void UIInputBox::handleKeyUp(const Common::KeyState &kbd) {
+ if (_isVisible) {
+ if (charIsValid(kbd)) {
+ _text += kbd.ascii;
+ } else if (kbd.keycode == Common::KEYCODE_BACKSPACE) {
+ _text.deleteLastChar();
+ } else if (kbd.keycode == Common::KEYCODE_RETURN && !_text.empty()) {
+ if (_valueChangedCallback) {
+ _valueChangedCallback(_callbackData, this);
+ }
+ }
+ }
+}
+
+bool UIInputBox::charIsValid(const Common::KeyState &kbd)
+{
+ return kbd.ascii >= ' '
+ && kbd.ascii != '<'
+ && kbd.ascii != '>'
+ && kbd.ascii != ':'
+ && kbd.ascii != '"'
+ && kbd.ascii != '/'
+ && kbd.ascii != '\\'
+ && kbd.ascii != '|'
+ && kbd.ascii != '?'
+ && kbd.ascii != '*'
+ && (kbd.ascii <= '¿' || kbd.ascii == '¡' || kbd.ascii == 'ß');
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/ui_input_box.h b/engines/bladerunner/ui/ui_input_box.h
new file mode 100644
index 0000000000..473fe175df
--- /dev/null
+++ b/engines/bladerunner/ui/ui_input_box.h
@@ -0,0 +1,69 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_ui_inputbox_H
+#define BLADERUNNER_ui_inputbox_H
+
+#include "bladerunner/ui/ui_component.h"
+
+#include "common/rect.h"
+#include "common/str.h"
+
+namespace BladeRunner {
+
+class UIInputBox : public UIComponent
+{
+private:
+ UIComponentCallback *_valueChangedCallback;
+ void *_callbackData;
+
+ bool _isVisible;
+ Common::Rect _rect;
+
+ int _maxLength;
+ int _length;
+ Common::String _text;
+
+ bool _cursorIsVisible;
+
+ int _timeLast;
+
+public:
+ UIInputBox(BladeRunnerEngine *vm, UIComponentCallback *valueChangedCallback, void *callbackData, Common::Rect rect, int maxLength, const Common::String &text);
+
+ void draw(Graphics::Surface &surface);
+
+ void setText(const Common::String &text);
+ const Common::String &getText();
+
+ void show();
+ void hide();
+
+ void handleKeyUp(const Common::KeyState &kbd);
+
+private:
+ bool charIsValid(const Common::KeyState &kbd);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/ui_scroll_box.cpp b/engines/bladerunner/ui/ui_scroll_box.cpp
new file mode 100644
index 0000000000..a0d53a444d
--- /dev/null
+++ b/engines/bladerunner/ui/ui_scroll_box.cpp
@@ -0,0 +1,662 @@
+/* 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/ui_scroll_box.h"
+
+#include "bladerunner/audio_player.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/font.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/shape.h"
+#include "bladerunner/ui/kia.h"
+#include "bladerunner/ui/kia_shapes.h"
+
+namespace BladeRunner {
+
+const int UIScrollBox::k3DFrameColors[] = { 0x1083, 0x14A5, 0x14A6, 0x2508, 0x5230, 0x5230, 0x0000, 0x0000 };
+const int UIScrollBox::kTextBackgroundColors[] = { 0x14EA, 0x190C, 0x1D2E, 0x2570, 0x4F1F, 0x0000 };
+const int UIScrollBox::kTextColors1[] = { 0x25B3, 0x31F7, 0x3A5B, 0x46BF, 0x4F1F };
+const int UIScrollBox::kTextColors2[] = { 0x677F, 0x6F9F, 0x73BF, 0x77DF, 0x7FFF };
+const int UIScrollBox::kTextColors3[] = { 0x7BB8, 0x7BBA, 0x7BDB, 0x7FDD, 0x7FFF };
+const int UIScrollBox::kTextColors4[] = { 0x4DC7, 0x5E4B, 0x6EEE, 0x7751, 0x7F92 };
+
+UIScrollBox::UIScrollBox(BladeRunnerEngine *vm, UIScrollBoxCallback *lineSelectedCallback, void *callbackData, int maxLineCount, int style, bool center, Common::Rect rect, Common::Rect scrollBarRect) : UIComponent(vm) {
+ _selectedLineState = 0;
+ _scrollUpButtonState = 0;
+ _scrollDownButtonState = 0;
+ _scrollAreaUpState = 0;
+ _scrollAreaDownState = 0;
+ _scrollBarState = 0;
+
+ _scrollUpButtonHover = false;
+ _scrollDownButtonHover = false;
+ _scrollAreaUpHover = false;
+ _scrollAreaDownHover = false;
+ _scrollBarHover = false;
+
+ _hoveredLine = -1;
+ _selectedLineIndex = -1;
+
+ _lineSelectedCallback = lineSelectedCallback;
+ _callbackData = callbackData;
+
+ _isVisible = false;
+ _style = style;
+ _center = center;
+ _timeLastScroll = _vm->getTotalPlayTime();
+ _timeLastCheckbox = _vm->getTotalPlayTime();
+ _timeLastHighlight = _vm->getTotalPlayTime();
+
+ _highlightFrame = 0;
+
+ _rect = rect;
+ _scrollBarRect = scrollBarRect;
+
+ _lineCount = 0;
+ _maxLineCount = maxLineCount;
+
+ _firstLineVisible = 0;
+
+ _maxLinesVisible = _rect.height() / kLineHeight;
+ _rect.bottom = _rect.top + kLineHeight * _maxLinesVisible - 1;
+
+ _lines.resize(_maxLineCount);
+ for (int i = 0; i < _maxLineCount; ++i) {
+ _lines[i] = new Line();
+ _lines[i]->lineData = -1;
+ _lines[i]->flags = 0x00;
+ _lines[i]->checkboxFrame = 5;
+ }
+}
+
+UIScrollBox::~UIScrollBox() {
+ for (int i = 0; i < _maxLineCount; ++i) {
+ delete _lines[i];
+ }
+}
+
+void UIScrollBox::show() {
+ _selectedLineState = 0;
+ _scrollUpButtonState = 0;
+ _scrollDownButtonState = 0;
+ _scrollAreaUpState = 0;
+ _scrollAreaDownState = 0;
+ _scrollBarState = 0;
+
+ _hoveredLine = -1;
+ _selectedLineIndex = -1;
+
+ _scrollUpButtonHover = false;
+ _scrollDownButtonHover = false;
+ _scrollAreaUpHover = false;
+ _scrollAreaDownHover = false;
+ _scrollBarHover = false;
+
+ _timeLastScroll = _vm->getTotalPlayTime();
+ _timeLastCheckbox = _vm->getTotalPlayTime();
+ _timeLastHighlight = _vm->getTotalPlayTime();
+
+ _highlightFrame = 0;
+ _isVisible = true;
+}
+
+void UIScrollBox::hide() {
+ _isVisible = false;
+}
+
+void UIScrollBox::clearLines(){
+ _lineCount = 0;
+ _firstLineVisible = 0;
+
+}
+
+void UIScrollBox::addLine(const Common::String &text, int lineData, int flags) {
+ _lines[_lineCount]->text = text;
+ _lines[_lineCount]->lineData = lineData;
+ _lines[_lineCount]->flags = flags;
+
+ ++_lineCount;
+}
+
+void UIScrollBox::addLine(const char *text, int lineData, int flags) {
+ _lines[_lineCount]->text = text;
+ _lines[_lineCount]->lineData = lineData;
+ _lines[_lineCount]->flags = flags;
+
+ ++_lineCount;
+}
+
+void UIScrollBox::sortLines() {
+ qsort(_lines.data(), _lineCount, sizeof(Line *), &sortFunction);
+}
+
+void UIScrollBox::handleMouseMove(int mouseX, int mouseY) {
+ if (!_isVisible) {
+ return;
+ }
+
+ if (_rect.contains(mouseX, mouseY)) {
+ int newHoveredLine = (mouseY - _rect.top) / 10 + _firstLineVisible;
+ if (newHoveredLine >= _lineCount) {
+ newHoveredLine = -1;
+ }
+
+ if (newHoveredLine != _hoveredLine && newHoveredLine >= 0 && newHoveredLine < _lineCount) {
+ if (_lines[newHoveredLine]->lineData >= 0 && _selectedLineState == 0) {
+ int soundId = 507;
+ if (_lines[newHoveredLine]->flags & 0x01 ) {
+ soundId = 508;
+ }
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(soundId), 100, 0, 0, 50, 0);
+ }
+ }
+ _hoveredLine = newHoveredLine;
+ } else {
+ _hoveredLine = -1;
+ }
+
+ _scrollUpButtonHover =
+ (mouseX >= _scrollBarRect.left)
+ && (mouseX < _scrollBarRect.left + 15)
+ && (mouseY >= _scrollBarRect.top)
+ && (mouseY < _scrollBarRect.top + 8);
+
+ _scrollDownButtonHover =
+ (mouseX >= _scrollBarRect.left)
+ && (mouseX < _scrollBarRect.left + 15)
+ && (mouseY > _scrollBarRect.bottom - 8)
+ && (mouseY <= _scrollBarRect.bottom);
+
+ int scrollAreaHeight = _scrollBarRect.bottom - _scrollBarRect.top - 15;
+
+ int scrollBarHeight = scrollAreaHeight;
+ if (_lineCount > _maxLinesVisible) {
+ scrollBarHeight = _maxLinesVisible * scrollAreaHeight / _lineCount;
+ }
+ if (scrollBarHeight < 16) {
+ scrollBarHeight = 16;
+ }
+
+ int scrollAreaEmptySize = scrollAreaHeight - scrollBarHeight;
+
+ int scrollBarY = 0;
+ if (_lineCount > _maxLinesVisible) {
+ scrollBarY = scrollAreaEmptySize * _firstLineVisible / (_lineCount - _maxLinesVisible);
+ }
+
+ if (_scrollBarState == 2) {
+ int v12 = scrollBarHeight / 2 + 8;
+ if (mouseY - _scrollBarRect.top > v12 && _lineCount > _maxLinesVisible && scrollAreaEmptySize > 0) {
+ _firstLineVisible = (_lineCount - _maxLinesVisible) * (mouseY - _scrollBarRect.top - v12) / scrollAreaEmptySize;
+ if (_firstLineVisible > _lineCount - _maxLinesVisible) {
+ _firstLineVisible = _lineCount - _maxLinesVisible;
+ }
+ } else {
+ _firstLineVisible = 0;
+ }
+
+ if (_lineCount <= _maxLinesVisible) {
+ scrollBarY = 0;
+ } else {
+ scrollBarY = scrollAreaEmptySize * _firstLineVisible/ (_lineCount - _maxLinesVisible);
+ }
+ }
+ scrollBarY = scrollBarY + _scrollBarRect.top + 8;
+
+ _scrollBarHover =
+ (mouseX >= _scrollBarRect.left)
+ && (mouseX < _scrollBarRect.left + 15)
+ && (mouseY >= scrollBarY)
+ && (mouseY < scrollBarY + scrollBarHeight);
+
+ _scrollAreaUpHover =
+ (mouseX >= _scrollBarRect.left)
+ && (mouseX < _scrollBarRect.left + 15)
+ && (mouseY >= _scrollBarRect.top + 8)
+ && (mouseY < scrollBarY);
+
+ _scrollAreaDownHover =
+ (mouseX >= _scrollBarRect.left)
+ && (mouseX < _scrollBarRect.left + 15)
+ && (mouseY >= scrollBarY + scrollBarHeight)
+ && (mouseY < _scrollBarRect.bottom - 8);
+}
+
+void UIScrollBox::handleMouseDown(bool alternateButton) {
+ if (!_isVisible) {
+ return;
+ }
+
+ _mouseButton = alternateButton;
+ if (_hoveredLine == -1) {
+ _selectedLineState = 1;
+ } else if (_selectedLineIndex == -1) {
+ _selectedLineIndex = _hoveredLine;
+ _selectedLineState = 2;
+ if (_hoveredLine < _lineCount) {
+ if (_lineSelectedCallback) {
+ _lineSelectedCallback(_callbackData, this, _lines[_selectedLineIndex]->lineData, _mouseButton);
+ }
+
+ if (_lines[_selectedLineIndex]->flags & 0x01) {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(509), 100, 0, 0, 50, 0);
+ }
+ }
+ }
+ if (!alternateButton) {
+ if (_scrollUpButtonHover) {
+ _scrollUpButtonState = 2;
+ _timeLastScroll = _vm->getTotalPlayTime() - 160;
+ } else {
+ _scrollUpButtonState = 1;
+ }
+ if (_scrollDownButtonHover) {
+ _scrollDownButtonState = 2;
+ } else {
+ _scrollDownButtonState = 1;
+ }
+ if (_scrollBarHover) {
+ _scrollBarState = 2;
+ } else {
+ _scrollBarState = 1;
+ }
+ if (_scrollAreaUpHover) {
+ _scrollAreaUpState = 2;
+ _timeLastScroll = _vm->getTotalPlayTime() - 160;
+ } else {
+ _scrollAreaUpState = 1;
+ }
+ if (_scrollAreaDownHover) {
+ _scrollAreaDownState = 2;
+ _timeLastScroll = _vm->getTotalPlayTime() - 160;
+ } else {
+ _scrollAreaDownState = 1;
+ }
+ }
+}
+
+void UIScrollBox::handleMouseUp(bool alternateButton) {
+ if (_isVisible) {
+ if ( alternateButton == _mouseButton) {
+ _selectedLineState = 0;
+ _selectedLineIndex = -1;
+ }
+
+ if (!alternateButton) {
+ _scrollUpButtonState = 0;
+ _scrollDownButtonState = 0;
+ _scrollAreaUpState = 0;
+ _scrollAreaDownState = 0;
+ _scrollBarState = 0;
+ }
+ }
+}
+
+int UIScrollBox::getSelectedLineData() {
+ if (_hoveredLine >= 0 && _selectedLineState != 1 && _hoveredLine < _lineCount) {
+ return _lines[_hoveredLine]->lineData;
+ }
+ return -1;
+}
+
+void UIScrollBox::draw(Graphics::Surface &surface) {
+ int timeNow = _vm->getTotalPlayTime();
+
+ // update scrolling
+ if (_scrollUpButtonState == 2 && _scrollUpButtonHover) {
+ if ((timeNow - _timeLastScroll) > 160) {
+ scrollUp();
+ _timeLastScroll = timeNow;
+ }
+ } else if (_scrollDownButtonState == 2 && _scrollDownButtonHover) {
+ if ((timeNow - _timeLastScroll) > 160) {
+ scrollDown();
+ _timeLastScroll = timeNow;
+ }
+ } else if (_scrollAreaUpState == 2 && _scrollAreaUpHover) {
+ if ((timeNow - _timeLastScroll) > 160) {
+ _firstLineVisible -= _maxLinesVisible - 1;
+ _firstLineVisible = CLIP(_firstLineVisible, 0, _lineCount - _maxLinesVisible);
+ _timeLastScroll = timeNow;
+ }
+ } else if (_scrollAreaDownState == 2 && _scrollAreaDownHover) {
+ if ((timeNow - _timeLastScroll) > 160) {
+ _firstLineVisible += _maxLinesVisible - 1;
+ _firstLineVisible = CLIP(_firstLineVisible, 0, _lineCount - _maxLinesVisible);
+ _timeLastScroll = timeNow;
+ }
+ }
+
+ // update checkboxes
+ int timeDiffCheckBox = timeNow - _timeLastCheckbox;
+ if (timeDiffCheckBox > 67) {
+ _timeLastCheckbox = timeNow;
+ for (int i = 0; i < _lineCount; ++i) {
+ if (_lines[i]->flags & 0x01) { // has checkbox
+ if (_lines[i]->flags & 0x02) { // checkbox checked
+ if (_lines[i]->checkboxFrame < 5) {
+ _lines[i]->checkboxFrame += timeDiffCheckBox / 67;
+ }
+ if (_lines[i]->checkboxFrame > 5) {
+ _lines[i]->checkboxFrame = 5;
+ }
+ } else { // checkbox not checked
+ if (_lines[i]->checkboxFrame > 0) {
+ _lines[i]->checkboxFrame -= timeDiffCheckBox / 67;
+ }
+ if (_lines[i]->checkboxFrame < 0) {
+ _lines[i]->checkboxFrame = 0;
+ }
+ }
+ }
+ }
+ }
+
+
+ // update highlight
+ if ((timeNow - _timeLastHighlight) > 67) {
+ _timeLastHighlight = timeNow;
+ _highlightFrame = (_highlightFrame + 1) % 8;
+ }
+
+ // draw text lines
+ int linesVisible = 0;
+ int lastLineVisible = 0;
+
+ if (_maxLinesVisible < _lineCount - _firstLineVisible) {
+ linesVisible = _maxLinesVisible;
+ lastLineVisible = _firstLineVisible + _maxLinesVisible;
+ } else {
+ linesVisible = _lineCount - _firstLineVisible;
+ lastLineVisible = _lineCount;
+ }
+
+ if (_firstLineVisible < lastLineVisible) {
+ int y = _rect.top;
+ int y1 = _rect.top + 8;
+ int y2 = _rect.top + 2;
+ int i = _firstLineVisible;
+ do {
+ int startingColorIndex = 3;
+ if (i - _firstLineVisible < 3) {
+ startingColorIndex = i - _firstLineVisible;
+ }
+
+ int endingColorIndex = 3;
+ if (i - _firstLineVisible >= linesVisible - 3) {
+ endingColorIndex = linesVisible - (i - _firstLineVisible + 1);
+ }
+
+ int colorIndex = endingColorIndex;
+ if (startingColorIndex < endingColorIndex) {
+ colorIndex = startingColorIndex;
+ }
+
+ bool v35 = false;
+ int color = 0;
+
+ if ((((_selectedLineState == 0 && i == _hoveredLine) || (_selectedLineState == 2 && i == _selectedLineIndex && _selectedLineIndex == _hoveredLine)) && _lines[i]->lineData != -1) || _lines[i]->flags & 0x04) {
+ v35 = true;
+ if (_style) {
+ color = kTextColors2[colorIndex];
+ } else {
+ color = kTextColors3[colorIndex];
+ }
+ }
+ else {
+ if (_style) {
+ color = kTextColors1[colorIndex];
+ } else {
+ color = kTextColors4[colorIndex];
+ }
+ }
+
+ int x = _rect.left;
+
+ if (_lines[i]->flags & 0x01) { // has checkbox
+ int checkboxShapeId = 0;
+ if (_style == 0) {
+ if (_lines[i]->checkboxFrame || v35) {
+ if (_lines[i]->checkboxFrame != 5 || v35) {
+ checkboxShapeId = _lines[i]->checkboxFrame + 62;
+ } else {
+ checkboxShapeId = 61;
+ }
+ } else {
+ checkboxShapeId = 60;
+ }
+ } else if (_lines[i]->checkboxFrame || v35) {
+ if (_lines[i]->checkboxFrame != 5 || v35) {
+ checkboxShapeId = _lines[i]->checkboxFrame + 54;
+ } else {
+ checkboxShapeId = 53;
+ }
+ } else {
+ checkboxShapeId = 52;
+ }
+ _vm->_kia->_shapes->get(checkboxShapeId)->draw(surface, x - 1, y);
+ x += 11;
+ }
+
+ if (_lines[i]->flags & 0x10) { // highlighted line
+ if (_lines[i]->flags & 0x20) {
+ int highlightShapeId = _highlightFrame;
+ if (highlightShapeId > 4) {
+ highlightShapeId = 8 - highlightShapeId;
+ }
+ _vm->_kia->_shapes->get(highlightShapeId + 85)->draw(surface, x, y2);
+ }
+ x += 6;
+ }
+
+ if (_lines[i]->flags & 0x08) { // has background rectangle
+ int colorBackground = 0;
+ if (_style) {
+ colorBackground = kTextBackgroundColors[colorIndex];
+ } else {
+ colorBackground = 0x28E4;
+ }
+ surface.fillRect(Common::Rect(x, y, _rect.right + 1, y1 + 1), colorBackground);
+ }
+
+ if (_center) {
+ x = (_rect.width() - _vm->_mainFont->getTextWidth(_lines[i]->text)) / 2;
+ }
+
+ _vm->_mainFont->drawColor(_lines[i]->text, surface, x, y, color);
+
+ y1 += kLineHeight;
+ y2 += kLineHeight;
+ y += kLineHeight;
+ ++i;
+ }
+ while (i < lastLineVisible);
+ }
+
+ // draw scroll up button
+ int scrollUpButtonShapeId = 0;
+ if (_scrollUpButtonState) {
+ if (_scrollUpButtonState == 2) {
+ if (_scrollUpButtonHover) {
+ scrollUpButtonShapeId = 72;
+ } else {
+ scrollUpButtonShapeId = 71;
+ }
+ } else {
+ scrollUpButtonShapeId = 70;
+ }
+ } else if (_scrollUpButtonHover) {
+ scrollUpButtonShapeId = 71;
+ } else {
+ scrollUpButtonShapeId = 70;
+ }
+ _vm->_kia->_shapes->get(scrollUpButtonShapeId)->draw(surface, _scrollBarRect.left, _scrollBarRect.top);
+
+ // draw scroll down button
+ int scrollDownButtonShapeId = 0;
+ if (_scrollDownButtonState) {
+ if (_scrollDownButtonState == 2) {
+ if (_scrollDownButtonHover) {
+ scrollDownButtonShapeId = 75;
+ } else {
+ scrollDownButtonShapeId = 74;
+ }
+ } else {
+ scrollDownButtonShapeId = 73;
+ }
+ } else if (_scrollDownButtonHover) {
+ scrollDownButtonShapeId = 74;
+ } else {
+ scrollDownButtonShapeId = 73;
+ }
+ _vm->_kia->_shapes->get(scrollDownButtonShapeId)->draw(surface, _scrollBarRect.left, _scrollBarRect.bottom - 7);
+
+ int scrollAreaSize = _scrollBarRect.bottom - (_scrollBarRect.top + 15);
+ int scrollBarHeight = 0;
+ if (_lineCount <= _maxLinesVisible) {
+ scrollBarHeight = _scrollBarRect.bottom - (_scrollBarRect.top + 15);
+ } else {
+ scrollBarHeight = _maxLinesVisible * scrollAreaSize / _lineCount;
+ }
+ scrollBarHeight = MAX(scrollBarHeight, 16);
+
+ int v56 = 0;
+ if (_lineCount <= _maxLinesVisible) {
+ v56 = 0;
+ } else {
+ v56 = _firstLineVisible * (scrollAreaSize - scrollBarHeight) / (_lineCount - _maxLinesVisible);
+ }
+
+ int v58 = v56 + _scrollBarRect.top + 8;
+
+ if (_scrollBarState == 2) {
+ draw3DFrame(surface, Common::Rect(_scrollBarRect.left, v58, _scrollBarRect.left + 15, v58 + scrollBarHeight), 1, 1);
+ } else if (!_scrollBarState && _scrollBarHover) {
+ draw3DFrame(surface, Common::Rect(_scrollBarRect.left, v56 + _scrollBarRect.top + 8, _scrollBarRect.left + 15, v58 + scrollBarHeight), 0, 1);
+ } else {
+ draw3DFrame(surface, Common::Rect(_scrollBarRect.left, v58, _scrollBarRect.left + 15, v58 + scrollBarHeight), 0, 0);
+ }
+}
+
+void UIScrollBox::checkAll() {
+ for (int i = 0; i < _lineCount; ++i) {
+ if (_lines[i]->flags & 0x01) {
+ _lines[i]->flags |= 0x02;
+ }
+ }
+}
+
+void UIScrollBox::uncheckAll() {
+ for (int i = 0; i < _lineCount; ++i) {
+ if (_lines[i]->flags & 0x01) {
+ _lines[i]->flags &= ~0x02;
+ }
+ }
+}
+
+void UIScrollBox::toggleCheckBox(int lineData) {
+ int i = findLine(lineData);
+ if (i != -1) {
+ if (_lines[i]->flags & 0x02) {
+ _lines[i]->flags &= ~0x02;
+ } else {
+ _lines[i]->flags |= 0x02;
+ }
+ }
+}
+
+bool UIScrollBox::hasLine(int lineData) {
+ return findLine(lineData) != -1;
+}
+
+void UIScrollBox::resetHighlight(int lineData) {
+ int i = findLine(lineData);
+ if (i != -1) {
+ _lines[i]->flags &= ~0x20;
+ }
+}
+
+void UIScrollBox::setFlags(int lineData, int flags) {
+ int i = findLine(lineData);
+ if (i != -1) {
+ _lines[i]->flags |= flags;
+ }
+}
+
+void UIScrollBox::resetFlags(int lineData, int flags) {
+ int i = findLine(lineData);
+ if (i != -1) {
+ _lines[i]->flags &= ~flags;
+ }
+}
+
+int UIScrollBox::sortFunction(const void *item1, const void *item2) {
+ Line *line1 = *(Line * const *)item1;
+ Line *line2 = *(Line * const *)item2;
+ return line1->text.compareToIgnoreCase(line2->text);
+}
+
+void UIScrollBox::draw3DFrame(Graphics::Surface &surface, Common::Rect rect, bool pressed, int style) {
+ int color1, color2;
+
+ if (pressed) {
+ color1 = k3DFrameColors[style + 6];
+ color2 = k3DFrameColors[style + 4];
+ } else {
+ color1 = k3DFrameColors[style + 4];
+ color2 = k3DFrameColors[style + 6];
+ }
+
+ int fillColor = k3DFrameColors[style + 2];
+
+ surface.fillRect(Common::Rect(rect.left + 1, rect.top + 1, rect.right - 1, rect.bottom - 1), fillColor);
+
+ surface.hLine(rect.left + 1, rect.top, rect.right - 2, color1);
+ surface.hLine(rect.left + 1, rect.bottom - 1, rect.right - 2, color2);
+ surface.vLine(rect.left, rect.top, rect.bottom - 2, color1);
+ surface.vLine(rect.right - 1, rect.top + 1, rect.bottom - 1, color2);
+ surface.hLine(rect.right - 1, rect.top, rect.right - 1, k3DFrameColors[style]);
+ surface.hLine(rect.left, rect.bottom - 1, rect.left, k3DFrameColors[style]);
+}
+
+void UIScrollBox::scrollUp() {
+ if (_firstLineVisible > 0) {
+ --_firstLineVisible;
+ }
+}
+
+void UIScrollBox::scrollDown() {
+ if (_lineCount - _firstLineVisible > _maxLinesVisible) {
+ ++_firstLineVisible;
+ }
+}
+
+int UIScrollBox::findLine(int lineData) {
+ for (int i = 0; i < _lineCount; ++i) {
+ if (_lines[i]->lineData == lineData) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/ui_scroll_box.h b/engines/bladerunner/ui/ui_scroll_box.h
new file mode 100644
index 0000000000..1f416baffc
--- /dev/null
+++ b/engines/bladerunner/ui/ui_scroll_box.h
@@ -0,0 +1,137 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_UI_SCROLLBOX_H
+#define BLADERUNNER_UI_SCROLLBOX_H
+
+#include "bladerunner/ui/ui_component.h"
+
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/str.h"
+
+namespace BladeRunner {
+
+typedef void UIScrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton);
+
+class UIScrollBox : public UIComponent
+{
+private:
+ static const int kLineHeight = 10;
+ static const int k3DFrameColors[];
+ static const int kTextBackgroundColors[];
+ static const int kTextColors1[];
+ static const int kTextColors2[];
+ static const int kTextColors3[];
+ static const int kTextColors4[];
+
+ struct Line {
+ Common::String text;
+ int lineData;
+ int flags;
+ int checkboxFrame;
+ };
+
+ int _selectedLineState;
+ int _scrollUpButtonState;
+ int _scrollDownButtonState;
+ int _scrollAreaUpState;
+ int _scrollAreaDownState;
+ int _scrollBarState;
+
+ int _hoveredLine;
+ int _selectedLineIndex;
+
+ bool _scrollUpButtonHover;
+ bool _scrollDownButtonHover;
+ bool _scrollAreaUpHover;
+ bool _scrollAreaDownHover;
+ bool _scrollBarHover;
+
+ bool _mouseButton;
+
+ UIScrollBoxCallback *_lineSelectedCallback;
+ void *_callbackData;
+
+ bool _isVisible;
+ int _style;
+ bool _center;
+
+ int _timeLastScroll;
+ int _timeLastCheckbox;
+ int _timeLastHighlight;
+
+ int _highlightFrame;
+
+ Common::Rect _rect;
+ Common::Rect _scrollBarRect;
+
+ int _lineCount;
+ int _maxLineCount;
+ Common::Array<Line *> _lines;
+ int _maxLinesVisible;
+ int _firstLineVisible;
+
+public:
+ UIScrollBox(BladeRunnerEngine *vm, UIScrollBoxCallback *lineSelectedCallback, void *callbackData, int maxLineCount, int style, bool center, Common::Rect rect,Common::Rect scrollBarRect);
+ ~UIScrollBox();
+
+ void draw(Graphics::Surface &surface);
+
+ void handleMouseMove(int mouseX, int mouseY);
+ void handleMouseDown(bool alternateButton);
+ void handleMouseUp(bool alternateButton);
+
+ void show();
+ void hide();
+
+ void clearLines();
+ void addLine(const Common::String &text, int lineData, int flags);
+ void addLine(const char *text, int lineData, int flags);
+ void sortLines();
+
+ int getSelectedLineData();
+
+ void checkAll();
+ void uncheckAll();
+ void toggleCheckBox(int lineData);
+
+ bool hasLine(int lineData);
+
+ void resetHighlight(int lineData);
+ void setFlags(int lineData, int flags);
+ void resetFlags(int lineData, int flags);
+
+private:
+ static int sortFunction(const void *line1, const void *line2);
+
+ void draw3DFrame(Graphics::Surface &surface, Common::Rect rect, bool pressed, int style);
+
+ void scrollUp();
+ void scrollDown();
+
+ int findLine(int lineData);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/ui_slider.cpp b/engines/bladerunner/ui/ui_slider.cpp
new file mode 100644
index 0000000000..d25b7fac2c
--- /dev/null
+++ b/engines/bladerunner/ui/ui_slider.cpp
@@ -0,0 +1,153 @@
+/* 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/ui_slider.h"
+
+#include "bladerunner/audio_player.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/game_info.h"
+
+namespace BladeRunner {
+
+const uint16 UISlider::kColors[] = { 0x0000, 0x0821, 0x1061, 0x1C82, 0x24C2, 0x2CE3, 0x3524, 0x4145, 0x4586, 0x4DC7, 0x5609, 0x5E4B, 0x668C, 0x6EEE, 0x7730, 0x7B92 };
+
+UISlider::UISlider(BladeRunnerEngine *vm, UIComponentCallback *valueChangedCallback, void *callbackData, Common::Rect rect, int maxValue, int value)
+ : UIComponent(vm) {
+
+ _valueChangedCallback = valueChangedCallback;
+ _callbackData = callbackData;
+
+ _maxValue = MAX(0, maxValue);
+ _value = CLIP(value, 0, _maxValue - 1);
+
+ _rect = rect;
+ _isEnabled = true;
+ _currentFrameColor = 0;
+ _hasFocus = false;
+ _pressedStatus = 0;
+}
+
+void UISlider::draw(Graphics::Surface &surface) {
+ if (_rect.isEmpty()) {
+ return;
+ }
+
+ int frameColor;
+ if (_pressedStatus == 1) {
+ frameColor = 10;
+ } else if (_hasFocus && _pressedStatus != 2 && _isEnabled) {
+ frameColor = 5;
+ } else {
+ frameColor = 0;
+ }
+
+ if (_currentFrameColor < frameColor) {
+ ++_currentFrameColor;
+ }
+
+ if (_currentFrameColor > frameColor) {
+ --_currentFrameColor;
+ }
+
+ surface.frameRect(_rect, kColors[_currentFrameColor]);
+
+ int sliderX = 0;
+ if (_maxValue <= 1) {
+ sliderX = _rect.left;
+ } else {
+ sliderX = _rect.left + ((_value * _rect.width()) / (_maxValue - 1));
+ }
+
+ if (_pressedStatus == 1) {
+ int sliderValue = ((_maxValue - 1) * (_mouseX - _rect.left)) / _rect.width();
+ sliderX = _rect.left + ((sliderValue * _rect.width()) / (_maxValue - 1));
+ sliderX = CLIP(sliderX, (int)_rect.left, (int)_rect.right);
+ }
+
+ if (_rect.left + 1 < _rect.right - 1) {
+ int striding = _rect.left + sliderX;
+ for (int x = _rect.left + 1; x < _rect.right - 1; x++) {
+ int colorIndex = 15 - (abs(sliderX - x) >> 2);
+
+ if (!_isEnabled) {
+ colorIndex /= 2;
+ }
+
+ if (colorIndex < 3) {
+ colorIndex = 3;
+ }
+
+ uint16 color = kColors[colorIndex];
+ if ((striding + x) & 1 || x == sliderX) {
+ color = 0;
+ }
+
+ surface.vLine(x, _rect.top + 1, _rect.bottom - 2, color);
+ }
+ }
+}
+
+void UISlider::handleMouseMove(int mouseX, int mouseY) {
+ _mouseX = mouseX;
+ if (_rect.contains(mouseX, mouseY)) {
+ if (!_hasFocus && _isEnabled && _pressedStatus == 0) {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(508), 100, 0, 0, 50, 0);
+ }
+ _hasFocus = true;
+ } else {
+ _hasFocus = false;
+ }
+}
+
+void UISlider::handleMouseDown(bool alternateButton) {
+ if (_isEnabled && !alternateButton) {
+ if (_hasFocus) {
+ _pressedStatus = 1;
+ } else {
+ _pressedStatus = 2;
+ }
+ }
+}
+
+void UISlider::handleMouseUp(bool alternateButton) {
+ if (!alternateButton) {
+ if (_pressedStatus == 1) {
+ if (_rect.width() == 0) {
+ _value = 0;
+ } else {
+ _value = ((_maxValue - 1) * (_mouseX - _rect.left)) / _rect.width();
+ }
+ _value = CLIP(_value, 0, _maxValue - 1);
+
+ if (_valueChangedCallback) {
+ _valueChangedCallback(_callbackData, this);
+ }
+ }
+ _pressedStatus = 0;
+ }
+}
+
+void UISlider::setValue(int value) {
+ _value = CLIP(value, 0, _maxValue - 1);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/ui_slider.h b/engines/bladerunner/ui/ui_slider.h
new file mode 100644
index 0000000000..7cbd5bfda7
--- /dev/null
+++ b/engines/bladerunner/ui/ui_slider.h
@@ -0,0 +1,63 @@
+/* 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.
+ *
+ */
+
+#ifndef BLADERUNNER_UI_SLIDER_H
+#define BLADERUNNER_UI_SLIDER_H
+
+#include "bladerunner/ui/ui_component.h"
+
+#include "common/rect.h"
+
+namespace BladeRunner {
+
+class UISlider : public UIComponent
+{
+private:
+ static const uint16 kColors[];
+
+ UIComponentCallback *_valueChangedCallback;
+ void *_callbackData;
+ bool _isEnabled;
+ int _maxValue;
+ Common::Rect _rect;
+ int _currentFrameColor;
+ bool _hasFocus;
+ int _pressedStatus;
+ int _mouseX;
+
+public:
+ int _value;
+
+ UISlider(BladeRunnerEngine *vm, UIComponentCallback *valueChangedCallback, void *callbackData, Common::Rect rect, int maxValue, int value);
+
+ void draw(Graphics::Surface &surface);
+
+ void handleMouseMove(int mouseX, int mouseY);
+ void handleMouseDown(bool alternateButton);
+ void handleMouseUp(bool alternateButton);
+
+ void setValue(int value);
+};
+
+} // End of namespace BladeRunner
+
+#endif