From 0c930b06ed7030686c7774f18126b3d37a678d60 Mon Sep 17 00:00:00 2001 From: Peter Kohaut Date: Sun, 28 Jan 2018 20:59:12 +0100 Subject: BLADERUNNER: Added KIA interfaces Crimes interface done Suspects interface done Added some game constants Fixed font rendering for other languages Fixed anoying clang warning --- engines/bladerunner/ui/kia.cpp | 14 +- engines/bladerunner/ui/kia_section_base.cpp | 2 +- engines/bladerunner/ui/kia_section_base.h | 2 +- engines/bladerunner/ui/kia_section_clues.cpp | 24 +- engines/bladerunner/ui/kia_section_clues.h | 3 +- engines/bladerunner/ui/kia_section_crimes.cpp | 449 ++++++++++++++++++- engines/bladerunner/ui/kia_section_crimes.h | 88 ++-- engines/bladerunner/ui/kia_section_suspects.cpp | 555 ++++++++++++++++++++++++ engines/bladerunner/ui/kia_section_suspects.h | 93 +++- engines/bladerunner/ui/spinner.cpp | 85 ++-- engines/bladerunner/ui/spinner.h | 8 +- 11 files changed, 1225 insertions(+), 98 deletions(-) create mode 100644 engines/bladerunner/ui/kia_section_suspects.cpp (limited to 'engines/bladerunner/ui') diff --git a/engines/bladerunner/ui/kia.cpp b/engines/bladerunner/ui/kia.cpp index 09c5918872..7e08a148fb 100644 --- a/engines/bladerunner/ui/kia.cpp +++ b/engines/bladerunner/ui/kia.cpp @@ -107,8 +107,8 @@ KIA::KIA(BladeRunnerEngine *vm) { _buttons = new UIImagePicker(_vm, 22); - _crimesSection = new KIASectionCrimes(_vm); // PlayerActor->_clues - _suspectsSection = new KIASectionSuspects(_vm); // PlayerActor->_clues + _crimesSection = new KIASectionCrimes(_vm, _vm->_playerActor->_clues); + _suspectsSection = new KIASectionSuspects(_vm, _vm->_playerActor->_clues); _cluesSection = new KIASectionClues(_vm, _vm->_playerActor->_clues); _settingsSection = new KIASectionSettings(_vm); _helpSection = new KIASectionHelp(_vm); @@ -318,15 +318,15 @@ void KIA::handleMouseUp(int mouseX, int mouseY, bool mainButton) { if (_currentSection) { _currentSection->handleMouseUp(mainButton); } - if (_currentSection && _currentSection->_field0) { + if (_currentSection && _currentSection->_scheduledSwitch) { if (_currentSectionId == kKIASectionCrimes) { open(kKIASectionSuspects); - // kiaSuspects::sub_45290C(_suspectsMenu, _crimesMenu->selectedSuspectId); + _suspectsSection->selectSuspect(_crimesSection->_suspectSelected); _log->next(); _log->clearFuture(); } else if (_currentSectionId == kKIASectionSuspects) { open(kKIASectionCrimes); - // kiaCrimes::updateCrime(_crimesMenu, *&_suspectsMenu->data[8052]); + _crimesSection->selectCrime(_suspectsSection->_crimeSelected); _log->next(); _log->clearFuture(); } else { @@ -361,7 +361,7 @@ void KIA::handleKeyUp(const Common::KeyState &kbd) { _currentSection->handleKeyUp(kbd); } } - if (_currentSection && _currentSection->_field0) { + if (_currentSection && _currentSection->_scheduledSwitch) { open(kKIASectionNone); } } @@ -418,7 +418,7 @@ void KIA::handleKeyDown(const Common::KeyState &kbd) { } break; } - if (_currentSection && _currentSection->_field0) { + if (_currentSection && _currentSection->_scheduledSwitch) { open(kKIASectionNone); } } diff --git a/engines/bladerunner/ui/kia_section_base.cpp b/engines/bladerunner/ui/kia_section_base.cpp index 96571e5a48..95f025e336 100644 --- a/engines/bladerunner/ui/kia_section_base.cpp +++ b/engines/bladerunner/ui/kia_section_base.cpp @@ -26,7 +26,7 @@ namespace BladeRunner { KIASectionBase::KIASectionBase(BladeRunnerEngine *vm) { _vm = vm; - _field0 = false; + _scheduledSwitch = false; } KIASectionBase::~KIASectionBase() { diff --git a/engines/bladerunner/ui/kia_section_base.h b/engines/bladerunner/ui/kia_section_base.h index 176e30d4b7..ea69d89768 100644 --- a/engines/bladerunner/ui/kia_section_base.h +++ b/engines/bladerunner/ui/kia_section_base.h @@ -41,7 +41,7 @@ protected: BladeRunnerEngine *_vm; public: - bool _field0; + bool _scheduledSwitch; KIASectionBase(BladeRunnerEngine *vm); virtual ~KIASectionBase(); diff --git a/engines/bladerunner/ui/kia_section_clues.cpp b/engines/bladerunner/ui/kia_section_clues.cpp index 9c8da60ff9..25ff27ba8d 100644 --- a/engines/bladerunner/ui/kia_section_clues.cpp +++ b/engines/bladerunner/ui/kia_section_clues.cpp @@ -46,7 +46,7 @@ namespace BladeRunner { KIASectionClues::KIASectionClues(BladeRunnerEngine *vm, ActorClues *clues) : KIASectionBase(vm) { _uiContainer = new UIContainer(_vm); - _isVisible = false; + _isOpen = false; _debugIntangible = false; _debugNop = 0; @@ -81,13 +81,13 @@ KIASectionClues::~KIASectionClues() { } void KIASectionClues::open() { - _isVisible = true; + _isOpen = 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(); @@ -96,8 +96,8 @@ void KIASectionClues::open() { } void KIASectionClues::close() { - if (_isVisible) { - _isVisible = false; + if (_isOpen) { + _isOpen = false; _buttons->deactivate(); _cluesScrollBox->hide(); @@ -385,22 +385,22 @@ void KIASectionClues::populateClues() { _cluesScrollBox->sortLines(); } -int KIASectionClues::getClueFilterTypeTextId(int i) { - if (i) { - return i - 1; +int KIASectionClues::getClueFilterTypeTextId(int filterId) { + if (filterId) { + return filterId - 1; } return -1; } int KIASectionClues::getClueFilterCrimeId(int filterId) { - if (filterId == _assetTypeFilterCount) { - return -1; + if (filterId != _assetTypeFilterCount) { + return filterId - (_assetTypeFilterCount + 1); } - return filterId - (_assetTypeFilterCount + 1); + return -1; } int KIASectionClues::getLineIdForAssetType(int assetType) { - if (assetType == -1) { + if (assetType == kClueTypeIntangible) { return 0; } return assetType + 1; diff --git a/engines/bladerunner/ui/kia_section_clues.h b/engines/bladerunner/ui/kia_section_clues.h index 74f7b55f65..3f6a13d135 100644 --- a/engines/bladerunner/ui/kia_section_clues.h +++ b/engines/bladerunner/ui/kia_section_clues.h @@ -36,6 +36,7 @@ class UIImagePicker; class UIScrollBox; class KIASectionClues : public KIASectionBase { + //TODO: use gameInfo->getClueCount(), not in original game static const int kClueCount = 288; struct Line { @@ -49,7 +50,7 @@ class KIASectionClues : public KIASectionBase { UIScrollBox *_cluesScrollBox; UIScrollBox *_filterScrollBox; - bool _isVisible; + bool _isOpen; bool _debugIntangible; int _debugNop; ActorClues *_clues; diff --git a/engines/bladerunner/ui/kia_section_crimes.cpp b/engines/bladerunner/ui/kia_section_crimes.cpp index 4cfaaedbad..b0b3d7c234 100644 --- a/engines/bladerunner/ui/kia_section_crimes.cpp +++ b/engines/bladerunner/ui/kia_section_crimes.cpp @@ -22,16 +22,459 @@ #include "bladerunner/ui/kia_section_crimes.h" +#include "bladerunner/actor_clues.h" +#include "bladerunner/audio_player.h" #include "bladerunner/bladerunner.h" +#include "bladerunner/crimes_database.h" +#include "bladerunner/font.h" +#include "bladerunner/game_constants.h" +#include "bladerunner/game_flags.h" +#include "bladerunner/game_info.h" +#include "bladerunner/shape.h" +#include "bladerunner/script/kia.h" +#include "bladerunner/suspects_database.h" +#include "bladerunner/text_resource.h" +#include "bladerunner/ui/kia.h" +#include "bladerunner/ui/kia_log.h" +#include "bladerunner/ui/kia_section_suspects.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 "graphics/surface.h" namespace BladeRunner { -KIASectionCrimes::KIASectionCrimes(BladeRunnerEngine *vm) - : KIASectionBase(vm) - , _shape(vm) { +KIASectionCrimes::KIASectionCrimes(BladeRunnerEngine *vm, ActorClues *clues) : KIASectionBase(vm) { + _uiContainer = new UIContainer(_vm); + _isOpen = false; + _clues = clues; + + _mouseX = 0; + _mouseY = 0; + + _buttons = new UIImagePicker(_vm, 5); + + _cluesScrollBox = new UIScrollBox(_vm, scrollBoxCallback, this, 50, 1, false, Common::Rect(312, 172, 500, 376), Common::Rect(506, 160, 506, 394)); + _uiContainer->add(_cluesScrollBox); + + _acquiredClueCount = 0; + + _crimeSelected = -1; + _crimesFoundCount = 0; + _crimesFound.resize(_vm->_gameInfo->getCrimeCount()); + + _suspectSelected = -1; + _suspectPhotoShapeId = -1; + _suspectPhotoShape = nullptr; + _suspectsFoundCount = 0; + _suspectsFound.resize(_vm->_gameInfo->getSuspectCount()); + _suspectsWithIdentity.resize(_vm->_gameInfo->getSuspectCount()); } KIASectionCrimes::~KIASectionCrimes() { + delete _suspectPhotoShape; + + _uiContainer->clear(); + + delete _cluesScrollBox; + delete _buttons; + delete _uiContainer; +} + +void KIASectionCrimes::open() { + _scheduledSwitch = false; + + _buttons->resetImages(); + _buttons->defineImage(0, Common::Rect(136, 326, 185, 342), nullptr, _vm->_kia->_shapes->get(32), _vm->_kia->_shapes->get(36), _vm->_textKIA->getText(32)); + _buttons->defineImage(1, Common::Rect(218, 326, 269, 342), nullptr, _vm->_kia->_shapes->get(33), _vm->_kia->_shapes->get(37), _vm->_textKIA->getText(33)); + _buttons->defineImage(2, Common::Rect(354, 128, 404, 144), nullptr, _vm->_kia->_shapes->get(30), _vm->_kia->_shapes->get(34), _vm->_textKIA->getText(34)); + _buttons->defineImage(3, Common::Rect(425, 128, 474, 144), nullptr, _vm->_kia->_shapes->get(31), _vm->_kia->_shapes->get(35), _vm->_textKIA->getText(35)); + _buttons->defineImage(4, Common::Rect(142, 150, 260, 297), nullptr, nullptr, nullptr, _vm->_textKIA->getText(36)); + _buttons->activate(nullptr, nullptr, nullptr, mouseUpCallback, this); + + _cluesScrollBox->show(); + + populateAcquiredClues(); + populateCrimes(); + populateSuspects(); + populateVisibleClues(); + updateSuspectPhoto(); + + _isOpen = true; +} + +void KIASectionCrimes::close() { + if (!_isOpen) { + return; + } + _isOpen = false; + _buttons->deactivate(); + _cluesScrollBox->hide(); + if (_suspectPhotoShapeId != -1) { + delete _suspectPhotoShape; + _suspectPhotoShape = nullptr; + _suspectPhotoShapeId = -1; + } +} + +void KIASectionCrimes::draw(Graphics::Surface &surface) { + const char *text = nullptr; + if (_suspectPhotoShapeId != -1) { + _suspectPhotoShape->draw(surface, 201 - _suspectPhotoShape->getWidth() / 2, 223 - _suspectPhotoShape->getHeight() / 2); + } + if (_suspectPhotoShapeId == 14 || _suspectPhotoShapeId == 13) { + text = _vm->_textKIA->getText(49); + _vm->_mainFont->drawColor(text, surface, 201 - _vm->_mainFont->getTextWidth(text) / 2, 218, 0x7FFF); + } + + surface.fillRect(Common::Rect(120, 134, 250, 145), 0); + surface.hLine(120, 133, 250, 0x18A5); + surface.hLine(120, 146, 250, 0x2D4C); + surface.vLine(119, 134, 145, 0x18A5); + surface.vLine(251, 134, 145, 0x2D4C); + surface.hLine(251, 146, 251, 0x2509); + + if (_crimeSelected == -1) { + text = _vm->_textKIA->getText(49); + } else { + text = _vm->_textCrimes->getText(_crimeSelected); + } + + _vm->_mainFont->drawColor(text, surface, 185 - _vm->_mainFont->getTextWidth(text) / 2, 136, 0x46BF); + + surface.fillRect(Common::Rect(136, 304, 266, 315), 0); + surface.hLine(136, 303, 266, 0x18A5); + surface.hLine(136, 316, 266, 0x2D4C); + surface.vLine(135, 304, 315, 0x18A5); + surface.vLine(267, 304, 315, 0x2D4C); + surface.hLine(267, 316, 267, 0x2509); + + char generatedText[64]; + if (_suspectSelected == -1) { + text = _vm->_textKIA->getText(22); + } else { + const char *suspectName = _vm->_suspectsDatabase->get(_suspectSelected)->getName(); + if (_suspectsWithIdentity[_suspectSelected]) { + text = suspectName; + } else if (_vm->_suspectsDatabase->get(_suspectSelected)->getSex()) { + sprintf(generatedText, "%s %s", _vm->_textKIA->getText(20), KIASectionSuspects::scrambleSuspectsName(suspectName)); + text = generatedText; + } else { + sprintf(generatedText, "%s %s", _vm->_textKIA->getText(21), KIASectionSuspects::scrambleSuspectsName(suspectName)); + text = generatedText; + } + } + _vm->_mainFont->drawColor(text, surface, 201 - _vm->_mainFont->getTextWidth(text) / 2, 306, 0x46BF); + + _uiContainer->draw(surface); + _buttons->draw(surface); + _buttons->drawTooltip(surface, _mouseX, _mouseY); +} + +void KIASectionCrimes::handleMouseMove(int mouseX, int mouseY) { + _mouseX = mouseX; + _mouseY = mouseY; + _buttons->handleMouseAction(mouseX, mouseY, false, false, false); + _uiContainer->handleMouseMove(mouseX, mouseY); +} + +void KIASectionCrimes::handleMouseDown(bool mainButton) { + if (mainButton) { + _buttons->handleMouseAction(_mouseX, _mouseY, true, false, false); + } + _uiContainer->handleMouseDown(!mainButton); +} + +void KIASectionCrimes::handleMouseUp(bool mainButton) { + if (mainButton) { + _buttons->handleMouseAction(_mouseX, _mouseY, false, true, false); + } + _uiContainer->handleMouseUp(!mainButton); +} + +void KIASectionCrimes::saveToLog() { + int data[] = { _crimeSelected, _suspectSelected }; + _vm->_kia->_log->add(2, sizeof(data), &data); +} + +void KIASectionCrimes::loadFromLog() { + const int *data = (const int*)_vm->_kia->_log->getCurrentData(); + _crimeSelected = data[0]; + _suspectSelected = data[1]; + populateSuspects(); + populateVisibleClues(); +} + +void KIASectionCrimes::selectCrime(int crimeId) { + _crimeSelected = crimeId; + populateSuspects(); + populateVisibleClues(); + updateSuspectPhoto(); +} + +void KIASectionCrimes::scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton) { + KIASectionCrimes *self = (KIASectionCrimes *)callbackData; + + 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 KIASectionCrimes::mouseUpCallback(int buttonId, void *callbackData) { + ((KIASectionCrimes *)callbackData)->onButtonPressed(buttonId); +} + +void KIASectionCrimes::onButtonPressed(int buttonId) { + switch (buttonId) { + case 0: + prevSuspect(); + break; + case 1: + nextSuspect(); + break; + case 2: + prevCrime(); + break; + case 3: + nextCrime(); + break; + case 4: + if (_suspectSelected != -1) { + _scheduledSwitch = true; + } + break; + } +} + +void KIASectionCrimes::populateAcquiredClues() { + _acquiredClueCount = 0; + for (int i = 0; i < kClueCount; ++i) { + if (_clues->isAcquired(i)) { + _acquiredClues[_acquiredClueCount].clueId = i; + _acquiredClues[_acquiredClueCount].actorId = _clues->getFromActorId(i); + ++_acquiredClueCount; + } + } + // sort clues by name, is it necessary +} + +void KIASectionCrimes::populateCrimes() { + int firstCrime = -1; + int crimeCount = _vm->_gameInfo->getCrimeCount(); + for (int i = 0; i < crimeCount; ++i) { + _crimesFound[i] = false; + } + + _crimesFoundCount = 0; + + if (!_acquiredClueCount) { + return; + } + + for (int i = 0; i < crimeCount; ++i) { + for (int j = 0; j < _acquiredClueCount; ++j) { + if (_vm->_crimesDatabase->getCrime(_acquiredClues[j].clueId) == i) { + if (firstCrime == -1) { + firstCrime = i; + } + _crimesFound[i] = true; + ++_crimesFoundCount; + } + } + } + + if (_crimesFoundCount > 0 && _crimeSelected == -1) { + _crimeSelected = firstCrime; + } +} + +void KIASectionCrimes::populateSuspects() { + int firstSuspect = -1; + int suspectCount = _vm->_gameInfo->getSuspectCount(); + + for (int i = 0; i < suspectCount; ++i) { + _suspectsFound[i] = false; + _suspectsWithIdentity[i] = false; + } + + _suspectsFoundCount = 0; + + if (!_acquiredClueCount || _crimeSelected == -1) { + return; + } + + for (int i = 0; i < suspectCount; ++i) { + for (int j = 0; j < _acquiredClueCount; ++j) { + if (_vm->_crimesDatabase->getCrime(_acquiredClues[j].clueId) == _crimeSelected + && _vm->_suspectsDatabase->get(i)->hasClue(_acquiredClues[j].clueId) + ) { + if (firstSuspect == -1) { + firstSuspect = i; + } + _suspectsFound[i] = true; + ++_suspectsFoundCount; + } + } + + if (_suspectsFound[i]) { + for (int j = 0; j < _acquiredClueCount; ++j) { + if (_vm->_suspectsDatabase->get(i)->hasIdentityClue(_acquiredClues[j].clueId)) { + _suspectsWithIdentity[i] = true; + } + } + } + } + + if (_suspectsFoundCount) { + if (_suspectSelected == -1 || !_suspectsFound[_suspectSelected]) { + _suspectSelected = firstSuspect; + } + } else { + _suspectSelected = -1; + } +} + +void KIASectionCrimes::populateVisibleClues() { + _cluesScrollBox->clearLines(); + if (_crimeSelected != -1) { + for (uint i = 0; i < _vm->_gameInfo->getClueCount(); ++i) { + if (_vm->_crimesDatabase->getAssetType(i) != -1 + && _vm->_crimesDatabase->getCrime(i) == _crimeSelected + && _clues->isAcquired(i) + ) { + 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(); + } +} + +void KIASectionCrimes::updateSuspectPhoto() { + if (_suspectPhotoShapeId != -1) { + delete _suspectPhotoShape; + _suspectPhotoShape = nullptr; + } + + if (_suspectSelected == -1) { + _suspectPhotoShapeId = -1; + return; + } + + SuspectDatabaseEntry *suspect = _vm->_suspectsDatabase->get(_suspectSelected); + + _suspectPhotoShapeId = -1; + int photoCluesCount = suspect->getPhotoCount(); + if (photoCluesCount > 0) { + for (int i = 0 ; i < photoCluesCount; i++) { + //TODO: weird stuff going on here... it's using index instead id, also some field is used but its always -1 + if (_clues->isAcquired(suspect->getPhotoClueId(i))) { + _suspectPhotoShapeId = suspect->getPhotoShapeId(i); + break; + } + } + } + + if (_suspectPhotoShapeId == -1) { + if (suspect->getSex()) { + _suspectPhotoShapeId = 14; + } else { + _suspectPhotoShapeId = 13; + } + } + + if (_suspectPhotoShapeId != -1) { + _suspectPhotoShape = new Shape(_vm); + _suspectPhotoShape->readFromContainer("photos.shp", _suspectPhotoShapeId); + } +} + +void KIASectionCrimes::nextCrime() { + if (_crimesFoundCount >= 2) { + while (true) { + ++_crimeSelected; + if (_crimeSelected >= (int)_vm->_gameInfo->getCrimeCount()){ + _crimeSelected = 0; + } + + if (_crimesFound[_crimeSelected]) { + selectCrime(_crimeSelected); + break; + } + } + } +} + +void KIASectionCrimes::prevCrime() { + if (_crimesFoundCount >= 2) { + while (true) { + --_crimeSelected; + if (_crimeSelected < 0) { + _crimeSelected = _vm->_gameInfo->getCrimeCount() - 1; + } + + if (_crimesFound[_crimeSelected]) { + selectCrime(_crimeSelected); + break; + } + } + } +} + +void KIASectionCrimes::nextSuspect() { + if (_suspectsFoundCount >= 2) { + while (true) { + ++_suspectSelected; + if (_suspectSelected >= (int)_vm->_gameInfo->getSuspectCount()){ + _suspectSelected = 0; + } + + if (_suspectsFound[_suspectSelected]) { + updateSuspectPhoto(); + break; + } + } + } +} + +void KIASectionCrimes::prevSuspect() { + if (_suspectsFoundCount >= 2) { + while (true) { + --_suspectSelected; + if (_suspectSelected < 0){ + _suspectSelected = _vm->_gameInfo->getSuspectCount() - 1; + } + + if (_suspectsFound[_suspectSelected]) { + updateSuspectPhoto(); + break; + } + } + } } } // End of namespace BladeRunner diff --git a/engines/bladerunner/ui/kia_section_crimes.h b/engines/bladerunner/ui/kia_section_crimes.h index befe5e528c..1ca60eb02b 100644 --- a/engines/bladerunner/ui/kia_section_crimes.h +++ b/engines/bladerunner/ui/kia_section_crimes.h @@ -26,6 +26,8 @@ #include "bladerunner/shape.h" #include "bladerunner/ui/kia_section_base.h" +#include "common/array.h" + namespace BladeRunner { class ActorClues; @@ -35,46 +37,78 @@ class UIImagePicker; class UIScrollBox; class KIASectionCrimes : public KIASectionBase { - struct Clue - { + // _vm->_gameInfo->getClueCount() + static const int kClueCount = 288; + + struct AcquiredClue { int clueId; int actorId; }; -protected: + bool _isOpen; - UIContainer *_uiContainer; - // void (__cdecl **scrollboxCallback)(int, UIScrollBoxStruc *, int, int); - int _isOpen; - int *_list; - UIImagePicker *_uiImagePicker; + UIContainer *_uiContainer; + UIImagePicker *_buttons; + UIScrollBox *_cluesScrollBox; - 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; + + int _acquiredClueCount; + AcquiredClue _acquiredClues[kClueCount]; + + int _crimeSelected; + + int _crimesFoundCount; + Common::Array _crimesFound; + + int _suspectsFoundCount; + Common::Array _suspectsFound; + Common::Array _suspectsWithIdentity; + + int _mouseX; + int _mouseY; + + int _suspectPhotoShapeId; + Shape *_suspectPhotoShape; public: - KIASectionCrimes(BladeRunnerEngine *vm); + int _suspectSelected; + +public: + KIASectionCrimes(BladeRunnerEngine *vm, ActorClues *clues); ~KIASectionCrimes(); - void saveToLog() {} - void loadFromLog() {} + 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(); + + void selectCrime(int crimeId); + +private: + static void scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton); + static void mouseUpCallback(int buttonId, void *callbackData); + + void onButtonPressed(int buttonId); + + void populateAcquiredClues(); + void populateCrimes(); + void populateSuspects(); + void populateVisibleClues(); + void updateSuspectPhoto(); -protected: + void nextCrime(); + void prevCrime(); + void nextSuspect(); + void prevSuspect(); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/ui/kia_section_suspects.cpp b/engines/bladerunner/ui/kia_section_suspects.cpp new file mode 100644 index 0000000000..ce13243f76 --- /dev/null +++ b/engines/bladerunner/ui/kia_section_suspects.cpp @@ -0,0 +1,555 @@ +/* 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_suspects.h" + +#include "bladerunner/actor_clues.h" +#include "bladerunner/audio_player.h" +#include "bladerunner/bladerunner.h" +#include "bladerunner/crimes_database.h" +#include "bladerunner/font.h" +#include "bladerunner/game_constants.h" +#include "bladerunner/game_flags.h" +#include "bladerunner/game_info.h" +#include "bladerunner/shape.h" +#include "bladerunner/script/kia.h" +#include "bladerunner/suspects_database.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_check_box.h" +#include "bladerunner/ui/ui_container.h" +#include "bladerunner/ui/ui_image_picker.h" +#include "bladerunner/ui/ui_scroll_box.h" + + +#include "graphics/surface.h" + +namespace BladeRunner { + +KIASectionSuspects::KIASectionSuspects(BladeRunnerEngine *vm, ActorClues *clues) : KIASectionBase(vm) { + _uiContainer = new UIContainer(_vm); + _isOpen = false; + _clues = clues; + + _mouseX = 0; + _mouseY = 0; + + _whereaboutsFilter = true; + _MOFilter = true; + _replicantFilter = true; + _nonReplicantFilter = true; + _othersFilter = true; + + _buttons = new UIImagePicker(_vm, 4); + + _whereaboutsCheckBox = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(142, 318, 275, 328), 1, _whereaboutsFilter); + _MOCheckBox = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(142, 328, 275, 338), 1, _MOFilter); + _replicantCheckBox = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(142, 338, 275, 348), 1, _replicantFilter); + _nonReplicantCheckBox = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(142, 348, 275, 358), 1, _nonReplicantFilter); + _othersCheckBox = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(142, 358, 275, 368), 1, _othersFilter); + _cluesScrollBox = new UIScrollBox(_vm, scrollBoxCallback, this,_vm->_gameInfo->getClueCount(), 1, false, Common::Rect(312, 172, 500, 376), Common::Rect(506, 160, 506, 394)); + _crimesScrollBox = new UIScrollBox(_vm, scrollBoxCallback, this, 50, 1, false, Common::Rect(154, 258, 291, 298), Common::Rect(120, 249, 120, 297)); + _uiContainer->add(_whereaboutsCheckBox); + _uiContainer->add(_MOCheckBox); + _uiContainer->add(_replicantCheckBox); + _uiContainer->add(_nonReplicantCheckBox); + _uiContainer->add(_othersCheckBox); + _uiContainer->add(_cluesScrollBox); + _uiContainer->add(_crimesScrollBox); + + _acquiredClueCount = 0; + + _suspectSelected = -1; + _suspectPhotoShapeId = -1; + _suspectPhotoShape = nullptr; + _suspectsFoundCount = 0; + _suspectsFound.resize(_vm->_gameInfo->getSuspectCount()); + _suspectsWithIdentity.resize(_vm->_gameInfo->getSuspectCount()); + + _crimeSelected = -1; +} + +KIASectionSuspects::~KIASectionSuspects() { + delete _suspectPhotoShape; + + _uiContainer->clear(); + + delete _crimesScrollBox; + delete _cluesScrollBox; + delete _othersCheckBox; + delete _nonReplicantCheckBox; + delete _replicantCheckBox; + delete _MOCheckBox; + delete _whereaboutsCheckBox; + delete _buttons; + delete _uiContainer; +} + +void KIASectionSuspects::open() { + _scheduledSwitch = false; + + _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(77), _vm->_textKIA->getText(31)); + _buttons->defineImage(2, Common::Rect(354, 128, 404, 144), nullptr, _vm->_kia->_shapes->get(30), _vm->_kia->_shapes->get(34), _vm->_textKIA->getText(32)); + _buttons->defineImage(3, Common::Rect(424, 128, 474, 144), nullptr, _vm->_kia->_shapes->get(31), _vm->_kia->_shapes->get(35), _vm->_textKIA->getText(33)); + _buttons->activate(nullptr, nullptr, nullptr, mouseUpCallback, this); + + _cluesScrollBox->show(); + _crimesScrollBox->show(); + _whereaboutsCheckBox->enable(); + _MOCheckBox->enable(); + _replicantCheckBox->enable(); + _nonReplicantCheckBox->enable(); + _othersCheckBox->enable(); + _cluesScrollBox->show(); + _crimesScrollBox->show(); + + populateAcquiredClues(); + populateSuspects(); + populateCrimes(); + populateVisibleClues(); + updateSuspectPhoto(); + + _isOpen = true; +} + +void KIASectionSuspects::close() { + if (!_isOpen) { + return; + } + _isOpen = false; + _buttons->deactivate(); + _cluesScrollBox->hide(); + if (_suspectPhotoShapeId != -1) { + delete _suspectPhotoShape; + _suspectPhotoShape = nullptr; + _suspectPhotoShapeId = -1; + } +} + +void KIASectionSuspects::draw(Graphics::Surface &surface) { + const char *text = nullptr; + if (_suspectPhotoShapeId != -1) { + _suspectPhotoShape->draw(surface, 142, 150); + } + if (_suspectPhotoShapeId == 14 || _suspectPhotoShapeId == 13) { + text = _vm->_textKIA->getText(49); + _vm->_mainFont->drawColor(text, surface, 190 - _vm->_mainFont->getTextWidth(text) / 2, 201, 0x7FFF); + } + + _whereaboutsCheckBox->setChecked(_whereaboutsFilter); + _MOCheckBox->setChecked(_MOFilter); + _replicantCheckBox->setChecked(_replicantFilter); + _nonReplicantCheckBox->setChecked(_nonReplicantFilter); + _othersCheckBox->setChecked(_othersFilter); + + _uiContainer->draw(surface); + + + _vm->_mainFont->drawColor(_vm->_textKIA->getText(0), surface, 300, 162, 0x77DF); + _vm->_mainFont->drawColor(_vm->_textKIA->getText(46), surface, 142, 248, 0x77DF); + _vm->_mainFont->drawColor(_vm->_textKIA->getText(47), surface, 142, 308, 0x77DF); + _vm->_mainFont->drawColor(_vm->_textKIA->getText(14), surface, 154, 319, 0x25B3); + _vm->_mainFont->drawColor(_vm->_textKIA->getText(15), surface, 154, 329, 0x31F7); + _vm->_mainFont->drawColor(_vm->_textKIA->getText(16), surface, 154, 339, 0x3A5B); + _vm->_mainFont->drawColor(_vm->_textKIA->getText(17), surface, 154, 349, 0x31F7); + _vm->_mainFont->drawColor(_vm->_textKIA->getText(48), surface, 154, 359, 0x25B3); + + + surface.fillRect(Common::Rect(120, 134, 250, 145), 0); + surface.hLine(120, 133, 250, 0x18A5); + surface.hLine(120, 146, 250, 0x2D4C); + surface.vLine(119, 134, 145, 0x18A5); + surface.vLine(251, 134, 145, 0x2D4C); + surface.hLine(251, 146, 251, 0x2509); + + char generatedText[64]; + if (_suspectSelected == -1) { + text = _vm->_textKIA->getText(22); + } else { + const char *suspectName = _vm->_suspectsDatabase->get(_suspectSelected)->getName(); + if (_suspectsWithIdentity[_suspectSelected]) { + text = suspectName; + } else if (_vm->_suspectsDatabase->get(_suspectSelected)->getSex()) { + sprintf(generatedText, "%s %s", _vm->_textKIA->getText(20), scrambleSuspectsName(suspectName)); + text = generatedText; + } else { + sprintf(generatedText, "%s %s", _vm->_textKIA->getText(21), scrambleSuspectsName(suspectName)); + text = generatedText; + } + } + + _vm->_mainFont->drawColor(text, surface, 185 - _vm->_mainFont->getTextWidth(text) / 2, 136, 0x46BF); + + _buttons->draw(surface); + _buttons->drawTooltip(surface, _mouseX, _mouseY); +} + +void KIASectionSuspects::handleMouseMove(int mouseX, int mouseY) { + _mouseX = mouseX; + _mouseY = mouseY; + _buttons->handleMouseAction(mouseX, mouseY, false, false, false); + _uiContainer->handleMouseMove(mouseX, mouseY); +} + +void KIASectionSuspects::handleMouseDown(bool mainButton) { + if (mainButton) { + _buttons->handleMouseAction(_mouseX, _mouseY, true, false, false); + } + _uiContainer->handleMouseDown(!mainButton); +} + +void KIASectionSuspects::handleMouseUp(bool mainButton) { + if (mainButton) { + _buttons->handleMouseAction(_mouseX, _mouseY, false, true, false); + } + _uiContainer->handleMouseUp(!mainButton); +} + +void KIASectionSuspects::saveToLog() { + int data[] = { + _crimeSelected, + _suspectSelected, + _whereaboutsFilter, + _MOFilter, + _replicantFilter, + _nonReplicantFilter, + _othersFilter + }; + _vm->_kia->_log->add(1, sizeof(data), &data); +} + +void KIASectionSuspects::loadFromLog() { + const int *data = (const int*)_vm->_kia->_log->getCurrentData(); + _crimeSelected = data[0]; + _suspectSelected = data[1]; + _whereaboutsFilter = data[2]; + _MOFilter = data[3]; + _replicantFilter = data[4]; + _nonReplicantFilter = data[5]; + _othersFilter = data[6]; + populateCrimes(); + populateVisibleClues(); +} + +void KIASectionSuspects::selectSuspect(int suspectId) { + _suspectSelected = suspectId; + populateCrimes(); + populateVisibleClues(); + updateSuspectPhoto(); +} + +const char *KIASectionSuspects::scrambleSuspectsName(const char *name) { + static char buffer[32]; + + char *bufferPtr = buffer; + const char *namePtr = name; + + for (int i = 0 ; i < 6; ++i) { + if (Common::isAlpha(*namePtr)) { + char upper = toupper(*namePtr); + if ( upper < 'J' ){ + *bufferPtr++ = upper - 16; + } else { + *bufferPtr++ = upper - 9; + } + } else { + *bufferPtr++ = '0'; + } + if (*namePtr) { + ++namePtr; + } + if (i == 1) { + *bufferPtr++ = '-'; + } + } + *bufferPtr = 0; + return buffer; +} + +void KIASectionSuspects::scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton) { + KIASectionSuspects *self = (KIASectionSuspects *)callbackData; + + 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); + } + } else if (source == self->_crimesScrollBox && lineData >= 0 && !mouseButton) { + self->_crimeSelected = lineData - 5; + self->_scheduledSwitch = true; + } +} + +void KIASectionSuspects::checkBoxCallback(void *callbackData, void *source) { + KIASectionSuspects *self = (KIASectionSuspects *)callbackData; + UICheckBox *checkBox = (UICheckBox *)source; + + if (checkBox == self->_whereaboutsCheckBox) { + self->_whereaboutsFilter = checkBox->_isChecked; + } else if (checkBox == self->_MOCheckBox) { + self->_MOFilter = checkBox->_isChecked; + } else if (checkBox == self->_replicantCheckBox) { + self->_replicantFilter = checkBox->_isChecked; + } else if (checkBox == self->_nonReplicantCheckBox) { + self->_nonReplicantFilter = checkBox->_isChecked; + } else if (checkBox == self->_othersCheckBox) { + self->_othersFilter = checkBox->_isChecked; + } + self->populateVisibleClues(); +} + +void KIASectionSuspects::mouseUpCallback(int buttonId, void *callbackData) { + ((KIASectionSuspects *)callbackData)->onButtonPressed(buttonId); +} + +void KIASectionSuspects::onButtonPressed(int buttonId) { + switch (buttonId) { + case 0: + enableAllFilters(); + break; + case 1: + disableAllFilters(); + break; + case 2: + prevSuspect(); + break; + case 3: + nextSuspect(); + break; + } +} + +void KIASectionSuspects::populateAcquiredClues() { + _acquiredClueCount = 0; + for (int i = 0; i < kClueCount; ++i) { + if (_clues->isAcquired(i)) { + _acquiredClues[_acquiredClueCount].clueId = i; + _acquiredClues[_acquiredClueCount].actorId = _clues->getFromActorId(i); + ++_acquiredClueCount; + } + } + // sort clues by name, is it necessary +} + +void KIASectionSuspects::populateSuspects() { + int firstSuspect = -1; + int suspectCount = _vm->_gameInfo->getSuspectCount(); + + for (int i = 0; i < suspectCount; ++i) { + _suspectsFound[i] = false; + _suspectsWithIdentity[i] = false; + } + + _suspectsFoundCount = 0; + + if (!_acquiredClueCount) { + return; + } + + for (int i = 0; i < suspectCount; ++i) { + for (int j = 0; j < _acquiredClueCount; ++j) { + if (_vm->_crimesDatabase->getCrime(_acquiredClues[j].clueId) != -1 + && _vm->_suspectsDatabase->get(i)->hasClue(_acquiredClues[j].clueId) + ) { + if (firstSuspect == -1) { + firstSuspect = i; + } + _suspectsFound[i] = true; + ++_suspectsFoundCount; + } + } + + if (_suspectsFound[i]) { + for (int j = 0; j < _acquiredClueCount; ++j) { + if (_vm->_suspectsDatabase->get(i)->hasIdentityClue(_acquiredClues[j].clueId)) { + _suspectsWithIdentity[i] = true; + } + } + } + } + + if (_suspectsFoundCount && _suspectSelected == -1) { + _suspectSelected = firstSuspect; + } +} + +void KIASectionSuspects::populateCrimes() { + _crimesScrollBox->clearLines(); + if (_suspectsFoundCount > 0 && _suspectSelected != -1) { + for (int i = 0; i < (int)_vm->_gameInfo->getCrimeCount(); ++i) { + for (int j = 0; j < _acquiredClueCount; ++j) { + if (_vm->_crimesDatabase->getCrime(_acquiredClues[j].clueId) == i + && _vm->_suspectsDatabase->get(_suspectSelected)->hasClue(_acquiredClues[j].clueId)) { + _crimesScrollBox->addLine(_vm->_textCrimes->getText(i), i + 5, 0); + break; + } + } + } + _crimesScrollBox->sortLines(); + } +} + +void KIASectionSuspects::populateVisibleClues() { + _cluesScrollBox->clearLines(); + if (_suspectsFoundCount > 0 && _suspectSelected != -1) { + for (int i = 0; i < _acquiredClueCount; ++i) { + int clueId = _acquiredClues[i].clueId; + + if (_vm->_crimesDatabase->getAssetType(i) != -1) { + SuspectDatabaseEntry *suspect = _vm->_suspectsDatabase->get(_suspectSelected); + + bool showClue = false; + + if (_whereaboutsFilter && suspect->hasWhereaboutsClue(clueId)) { + showClue = true; + } else if (_MOFilter && suspect->hasMOClue(clueId)) { + showClue = true; + } else if (_replicantFilter && suspect->hasReplicantClue(clueId)) { + showClue = true; + } else if (_nonReplicantFilter && suspect->hasNonReplicantClue(clueId)) { + showClue = true; + } else if (_othersFilter && suspect->hasOtherClue(clueId)) { + showClue = true; + } + + if (showClue) { + int flags = 0x30; + if (_clues->isPrivate(clueId)) { + flags = 0x08; + } else if (_clues->isViewed(clueId)) { + flags = 0x10; + } + _cluesScrollBox->addLine(_vm->_crimesDatabase->getClueText(clueId), clueId, flags); + } + } + } + _cluesScrollBox->sortLines(); + } +} + +void KIASectionSuspects::updateSuspectPhoto() { + if (_suspectPhotoShapeId != -1) { + delete _suspectPhotoShape; + _suspectPhotoShape = nullptr; + } + + if (_suspectSelected == -1) { + _suspectPhotoShapeId = -1; + return; + } + + SuspectDatabaseEntry *suspect = _vm->_suspectsDatabase->get(_suspectSelected); + + _suspectPhotoShapeId = -1; + int photoCluesCount = suspect->getPhotoCount(); + if (photoCluesCount > 0) { + for (int i = 0 ; i < photoCluesCount; i++) { + //TODO: weird stuff going on here... it's using index instead id, also some field is used but its always -1 + if (_clues->isAcquired(suspect->getPhotoClueId(i))) { + _suspectPhotoShapeId = suspect->getPhotoShapeId(i); + break; + } + } + } + + if (_suspectPhotoShapeId == -1) { + if (suspect->getSex()) { + _suspectPhotoShapeId = 14; + } else { + _suspectPhotoShapeId = 13; + } + } + + if (_suspectPhotoShapeId != -1) { + _suspectPhotoShape = new Shape(_vm); + _suspectPhotoShape->readFromContainer("photos.shp", _suspectPhotoShapeId); + } +} + +void KIASectionSuspects::nextSuspect() { + if (_suspectsFoundCount >= 2) { + while (true) { + ++_suspectSelected; + if (_suspectSelected >= (int)_vm->_gameInfo->getSuspectCount()){ + _suspectSelected = 0; + } + + if (_suspectsFound[_suspectSelected]) { + selectSuspect(_suspectSelected); + break; + } + } + } +} + +void KIASectionSuspects::prevSuspect() { + if (_suspectsFoundCount >= 2) { + while (true) { + --_suspectSelected; + if (_suspectSelected < 0){ + _suspectSelected = _vm->_gameInfo->getSuspectCount() - 1; + } + + if (_suspectsFound[_suspectSelected]) { + selectSuspect(_suspectSelected); + break; + } + } + } +} + +void KIASectionSuspects::enableAllFilters() { + _whereaboutsFilter = true; + _MOFilter = true; + _replicantFilter = true; + _nonReplicantFilter = true; + _othersFilter = true; + populateVisibleClues(); +} + +void KIASectionSuspects::disableAllFilters() { + _whereaboutsFilter = false; + _MOFilter = false; + _replicantFilter = false; + _nonReplicantFilter = false; + _othersFilter = false; + populateVisibleClues(); +} + +} // End of namespace BladeRunner diff --git a/engines/bladerunner/ui/kia_section_suspects.h b/engines/bladerunner/ui/kia_section_suspects.h index 94cf1bfc06..0cc957f609 100644 --- a/engines/bladerunner/ui/kia_section_suspects.h +++ b/engines/bladerunner/ui/kia_section_suspects.h @@ -25,15 +25,102 @@ #include "bladerunner/ui/kia_section_base.h" +#include "common/array.h" + namespace BladeRunner { +class ActorClues; +class BladeRunnerEngine; +class Shape; +class UICheckBox; +class UIContainer; +class UIImagePicker; +class UIScrollBox; + class KIASectionSuspects : public KIASectionBase { + // _vm->_gameInfo->getClueCount() + static const int kClueCount = 288; + + struct AcquiredClue { + int clueId; + int actorId; + }; + + bool _isOpen; + + UIContainer *_uiContainer; + UIImagePicker *_buttons; + UIScrollBox *_cluesScrollBox; + UIScrollBox *_crimesScrollBox; + UICheckBox *_whereaboutsCheckBox; + UICheckBox *_MOCheckBox; + UICheckBox *_replicantCheckBox; + UICheckBox *_nonReplicantCheckBox; + UICheckBox *_othersCheckBox; + + bool _whereaboutsFilter; + bool _MOFilter; + bool _replicantFilter; + bool _nonReplicantFilter; + bool _othersFilter; + + ActorClues *_clues; + + int _acquiredClueCount; + AcquiredClue _acquiredClues[kClueCount]; + + int _suspectSelected; + int _suspectsFoundCount; + Common::Array _suspectsFound; + Common::Array _suspectsWithIdentity; + + int _mouseX; + int _mouseY; + + int _suspectPhotoShapeId; + Shape *_suspectPhotoShape; public: - KIASectionSuspects(BladeRunnerEngine *vm): KIASectionBase(vm) {} + int _crimeSelected; + +public: + KIASectionSuspects(BladeRunnerEngine *vm, ActorClues *clues); + ~KIASectionSuspects(); + + 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(); + + void selectSuspect(int suspectId); + + static const char *scrambleSuspectsName(const char *name); + +private: + static void scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton); + static void checkBoxCallback(void *callbackData, void *source); + static void mouseUpCallback(int buttonId, void *callbackData); + + void onButtonPressed(int buttonId); + + void populateAcquiredClues(); + void populateSuspects(); + void populateCrimes(); + void populateVisibleClues(); + void updateSuspectPhoto(); + + void nextSuspect(); + void prevSuspect(); - void saveToLog() {} - void loadFromLog() {} + void enableAllFilters(); + void disableAllFilters(); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/ui/spinner.cpp b/engines/bladerunner/ui/spinner.cpp index 9018de15e6..cc913e3a9c 100644 --- a/engines/bladerunner/ui/spinner.cpp +++ b/engines/bladerunner/ui/spinner.cpp @@ -61,41 +61,6 @@ 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")) { @@ -137,17 +102,17 @@ int Spinner::chooseDestination(int loopId, bool immediately) { mapmask = 1; if (mapmask & 4) { - _destinations = kSpinnerDestinationsFar; + _destinations = getDestinationsFar(); firstShapeId = 26; shapeCount = 20; spinnerLoopId = 4; } else if (mapmask & 2) { - _destinations = kSpinnerDestinationsMedium; + _destinations = getDestinationsMedium(); firstShapeId = 10; shapeCount = 16; spinnerLoopId = 2; } else if (mapmask & 1) { - _destinations = kSpinnerDestinationsNear; + _destinations = getDestinationsNear(); firstShapeId = 0; shapeCount = 10; spinnerLoopId = 0; @@ -300,4 +265,48 @@ void Spinner::resume() { _vqaPlayer->setLoop(1, -1, kLoopSetModeJustStart, nullptr, nullptr); } +const Spinner::Destination *Spinner::getDestinationsFar() { + static const Destination destinations[] = { + { 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) } + }; + return destinations; +} + +const Spinner::Destination *Spinner::getDestinationsMedium() { + static const Destination destinations[] = { + { 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) } + }; + return destinations; +} + +const Spinner::Destination *Spinner::getDestinationsNear() { + static const Destination destinations[] = { + { 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) } + }; + return destinations; +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/ui/spinner.h b/engines/bladerunner/ui/spinner.h index ec0f8dbe33..b1785a57eb 100644 --- a/engines/bladerunner/ui/spinner.h +++ b/engines/bladerunner/ui/spinner.h @@ -33,7 +33,6 @@ class Shape; class VQAPlayer; class UIImagePicker; - class Spinner { static const int kSpinnerDestinations = 10; @@ -42,10 +41,6 @@ class Spinner { Common::Rect rect; }; - static const Destination kSpinnerDestinationsNear[]; - static const Destination kSpinnerDestinationsMedium[]; - static const Destination kSpinnerDestinationsFar[]; - BladeRunnerEngine *_vm; bool _isDestinationSelectable[kSpinnerDestinations]; bool _isOpen; @@ -77,6 +72,9 @@ public: private: static void mouseUpCallback(int, void *); + static const Destination *getDestinationsFar(); + static const Destination *getDestinationsMedium(); + static const Destination *getDestinationsNear(); }; } // End of namespace BladeRunner -- cgit v1.2.3