Initial commit
This commit is contained in:
321
engines/bladerunner/ui/elevator.cpp
Normal file
321
engines/bladerunner/ui/elevator.cpp
Normal file
@@ -0,0 +1,321 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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/time.h"
|
||||
#include "bladerunner/ui/ui_image_picker.h"
|
||||
#include "bladerunner/vqa_player.h"
|
||||
#include "bladerunner/subtitles.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);
|
||||
_shapes = new Shapes(vm);
|
||||
}
|
||||
|
||||
Elevator::~Elevator() {
|
||||
delete _shapes;
|
||||
_shapes = nullptr;
|
||||
|
||||
delete _imagePicker;
|
||||
_imagePicker = nullptr;
|
||||
}
|
||||
|
||||
int Elevator::activate(int elevatorId) {
|
||||
const char *vqaName;
|
||||
|
||||
if (elevatorId == kElevatorMA) {
|
||||
_buttonClicked = 3;
|
||||
vqaName = "MA06ELEV.VQA";
|
||||
} else if (elevatorId == kElevatorPS) {
|
||||
_buttonClicked = 1;
|
||||
vqaName = "PS02ELEV.VQA";
|
||||
} else {
|
||||
error("Invalid elevator id");
|
||||
}
|
||||
|
||||
if (!_vm->openArchive("MODE.MIX")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack, vqaName);
|
||||
if (!_vqaPlayer->open()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_vqaPlayer->setLoop(1, -1, kLoopSetModeJustStart, nullptr, nullptr);
|
||||
_vm->_mouse->setCursor(0);
|
||||
|
||||
_shapes->load("ELEVATOR.SHP");
|
||||
|
||||
_imagePicker->resetImages();
|
||||
|
||||
if (elevatorId == kElevatorMA) {
|
||||
_imagePicker->defineImage(
|
||||
0,
|
||||
Common::Rect(220, 298, 308, 392),
|
||||
nullptr,
|
||||
_shapes->get(11),
|
||||
_shapes->get(14),
|
||||
nullptr);
|
||||
_imagePicker->defineImage(
|
||||
1,
|
||||
Common::Rect(259, 259, 302, 292),
|
||||
nullptr,
|
||||
_shapes->get(10),
|
||||
_shapes->get(13),
|
||||
nullptr);
|
||||
_imagePicker->defineImage(
|
||||
2,
|
||||
Common::Rect(227, 398, 301, 434),
|
||||
nullptr,
|
||||
_shapes->get(12),
|
||||
_shapes->get(15),
|
||||
nullptr);
|
||||
} else { // kElevatorPS
|
||||
_imagePicker->defineImage(
|
||||
4,
|
||||
Common::Rect(395, 131, 448, 164),
|
||||
nullptr,
|
||||
_shapes->get(0),
|
||||
_shapes->get(5),
|
||||
nullptr
|
||||
);
|
||||
_imagePicker->defineImage(
|
||||
3,
|
||||
Common::Rect(395, 165, 448, 198),
|
||||
nullptr,
|
||||
_shapes->get(1),
|
||||
_shapes->get(6),
|
||||
nullptr
|
||||
);
|
||||
_imagePicker->defineImage(
|
||||
5,
|
||||
Common::Rect(395, 199, 448, 232),
|
||||
nullptr,
|
||||
_shapes->get(2),
|
||||
_shapes->get(7),
|
||||
nullptr
|
||||
);
|
||||
_imagePicker->defineImage(
|
||||
6,
|
||||
Common::Rect(395, 233, 448, 264),
|
||||
nullptr,
|
||||
_shapes->get(3),
|
||||
_shapes->get(8),
|
||||
nullptr
|
||||
);
|
||||
_imagePicker->defineImage(
|
||||
7,
|
||||
Common::Rect(395, 265, 448, 295),
|
||||
nullptr,
|
||||
_shapes->get(4),
|
||||
_shapes->get(9),
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
|
||||
_imagePicker->activate(
|
||||
mouseInCallback,
|
||||
mouseOutCallback,
|
||||
mouseDownCallback,
|
||||
mouseUpCallback,
|
||||
this
|
||||
);
|
||||
|
||||
open();
|
||||
|
||||
_vm->_time->pause();
|
||||
|
||||
_buttonClicked = -1;
|
||||
do {
|
||||
_vm->gameTick();
|
||||
} while (_vm->_gameIsRunning && _buttonClicked == -1);
|
||||
|
||||
_imagePicker->deactivate();
|
||||
|
||||
delete _vqaPlayer;
|
||||
_vqaPlayer = nullptr;
|
||||
|
||||
_shapes->unload();
|
||||
|
||||
_vm->closeArchive("MODE.MIX");
|
||||
|
||||
_isOpen = false;
|
||||
|
||||
_vm->_time->resume();
|
||||
|
||||
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->_windowIsActive) {
|
||||
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->_subtitles->tick(_vm->_surfaceFront);
|
||||
|
||||
_vm->blitToScreen(_vm->_surfaceFront);
|
||||
|
||||
tickDescription();
|
||||
}
|
||||
|
||||
void Elevator::buttonClick(int buttonId) {
|
||||
_buttonClicked = buttonId;
|
||||
}
|
||||
|
||||
void Elevator::reset() {
|
||||
_isOpen = false;
|
||||
_vqaPlayer = nullptr;
|
||||
_imagePicker = nullptr;
|
||||
_actorId = -1;
|
||||
_sentenceId = -1;
|
||||
_timeSpeakDescriptionStart = 0u;
|
||||
_buttonClicked = false;
|
||||
}
|
||||
|
||||
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;
|
||||
_timeSpeakDescriptionStart = _vm->_time->current();
|
||||
}
|
||||
|
||||
void Elevator::resetDescription() {
|
||||
_actorId = -1;
|
||||
_sentenceId = -1;
|
||||
_timeSpeakDescriptionStart = 0u;
|
||||
}
|
||||
|
||||
void Elevator::tickDescription() {
|
||||
uint32 now = _vm->_time->current();
|
||||
// unsigned difference is intentional
|
||||
if (_actorId <= 0 || (now - _timeSpeakDescriptionStart < 600u)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_vm->_actors[_actorId]->speechPlay(_sentenceId, false);
|
||||
_actorId = -1;
|
||||
_sentenceId = -1;
|
||||
}
|
||||
|
||||
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);
|
||||
elevator->_vm->_audioPlayer->playAud(elevator->_vm->_gameInfo->getSfxTrack(kSfxELEBUTN1), 100, 0, 0, 50, 0);
|
||||
}
|
||||
|
||||
void Elevator::mouseUpCallback(int buttonId, void *self) {
|
||||
((Elevator *)self)->buttonClick(buttonId);
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
71
engines/bladerunner/ui/elevator.h
Normal file
71
engines/bladerunner/ui/elevator.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_ELEVATOR_H
|
||||
#define BLADERUNNER_ELEVATOR_H
|
||||
|
||||
#include "common/array.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class BladeRunnerEngine;
|
||||
class Shapes;
|
||||
class VQAPlayer;
|
||||
class UIImagePicker;
|
||||
|
||||
class Elevator {
|
||||
BladeRunnerEngine *_vm;
|
||||
bool _isOpen;
|
||||
VQAPlayer *_vqaPlayer;
|
||||
int _buttonClicked;
|
||||
Shapes *_shapes;
|
||||
UIImagePicker *_imagePicker;
|
||||
int _actorId;
|
||||
int _sentenceId;
|
||||
uint32 _timeSpeakDescriptionStart;
|
||||
|
||||
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();
|
||||
|
||||
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
|
||||
319
engines/bladerunner/ui/end_credits.cpp
Normal file
319
engines/bladerunner/ui/end_credits.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
#include "audio/mixer.h"
|
||||
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/game_constants.h"
|
||||
#include "bladerunner/ambient_sounds.h"
|
||||
#include "bladerunner/audio_speech.h"
|
||||
#include "bladerunner/font.h"
|
||||
#include "bladerunner/game_info.h"
|
||||
#include "bladerunner/mouse.h"
|
||||
#include "bladerunner/music.h"
|
||||
#include "bladerunner/text_resource.h"
|
||||
#include "bladerunner/time.h"
|
||||
#include "bladerunner/ui/end_credits.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
EndCredits::EndCredits(BladeRunnerEngine *vm) {
|
||||
_vm = vm;
|
||||
}
|
||||
|
||||
EndCredits::~EndCredits() {
|
||||
}
|
||||
|
||||
// Aux method with hardcoded fixes for the credits
|
||||
// in the official localizations
|
||||
// ENG (not needed)
|
||||
// ITA, FRA, ESP, DEU
|
||||
void EndCredits::creditsCheckAndFix(int &textResourceId, Common::String &textStr) {
|
||||
switch (_vm->_language) {
|
||||
case Common::IT_ITA:
|
||||
switch (textResourceId) {
|
||||
case 71: // Grafici Ideatori
|
||||
textStr = "Ideatori Grafici";
|
||||
break;
|
||||
|
||||
case 211:
|
||||
textStr.trim();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Common::DE_DEU:
|
||||
switch (textResourceId) {
|
||||
case 312:
|
||||
textStr.trim();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Common::FR_FRA:
|
||||
switch (textResourceId) {
|
||||
case 97:
|
||||
// fall through
|
||||
case 265:
|
||||
// fall through
|
||||
case 266:
|
||||
textStr.trim();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (_vm->_language == Common::ES_ESP && _vm->_spanishCreditsCorrection) {
|
||||
// Corrections in credited names according to
|
||||
// https://www.doblajevideojuegos.es/fichajuego/blade-runner
|
||||
// Move 280-283 two lines above to accommodate new addition (Early Q actor)
|
||||
switch (textResourceId) {
|
||||
case 278:
|
||||
textStr = "Voces"; // moved two lines above
|
||||
break;
|
||||
|
||||
case 280:
|
||||
textStr = "McCoy"; // moved two lines above
|
||||
break;
|
||||
|
||||
case 281:
|
||||
textStr = "^Carlos Salamanca"; // from "^Luis Casanovas" (also moved two lines above)
|
||||
break;
|
||||
|
||||
case 282:
|
||||
textStr = "Early Q"; // originally uncredited
|
||||
break;
|
||||
|
||||
case 283:
|
||||
textStr = Common::U32String("^Tino Mart\xedn", Common::kISO8859_1).encode(Common::kDos850); // originally uncredited
|
||||
break;
|
||||
|
||||
case 300:
|
||||
textStr = Common::U32String("Piernas Locas Larry", Common::kISO8859_1).encode(Common::kDos850); // from "Crazylegs" (use translated name as elsewhere)
|
||||
break;
|
||||
|
||||
case 303:
|
||||
textStr = "^Antonio Cobos"; // from "^Antonio Fernández" for Chew
|
||||
break;
|
||||
|
||||
case 304:
|
||||
textStr = "Crystal"; // from "Cristal"
|
||||
break;
|
||||
|
||||
case 311:
|
||||
textStr = Common::U32String("^Carmen Gamb\xedn", Common::kISO8859_1).encode(Common::kDos850); // from "^María Palacios" for Lucy
|
||||
break;
|
||||
|
||||
case 312:
|
||||
textStr = "Bob Bala"; // from "Bollet Bob" (use proper translated name)
|
||||
break;
|
||||
|
||||
case 313:
|
||||
textStr = Common::U32String("^Enrique Jord\xe1", Common::kISO8859_1).encode(Common::kDos850); // from "^Enrique Jorda" for Bullet Bob (accent change)
|
||||
break;
|
||||
|
||||
case 314:
|
||||
textStr = "Peruana"; // from "Peru Lady"
|
||||
break;
|
||||
|
||||
case 317:
|
||||
textStr = Common::U32String("^Beatriz Su\xe1rez Cerrato", Common::kISO8859_1).encode(Common::kDos850); // from "^Beatriz Suarez" for Isabella
|
||||
break;
|
||||
|
||||
case 318:
|
||||
textStr = "Presentadora"; // from "Newscaster" (use translated name as elsewhere)
|
||||
break;
|
||||
|
||||
case 319:
|
||||
textStr = "^Montse Herranz"; // from "^Montse Pastor" for Presentadora (Newscaster)
|
||||
break;
|
||||
|
||||
case 321:
|
||||
textStr = Common::U32String("^Beatriz Su\xe1rez Cerrato", Common::kISO8859_1).encode(Common::kDos850); // from "^Beatriz Cerrato" for Contestador (Answering Machine)
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EndCredits::show() {
|
||||
_vm->_mouse->disable();
|
||||
_vm->_mixer->stopAll();
|
||||
_vm->_ambientSounds->removeAllNonLoopingSounds(true);
|
||||
_vm->_ambientSounds->removeAllLoopingSounds(4u);
|
||||
_vm->_audioSpeech->stopSpeech();
|
||||
|
||||
_vm->_music->play(_vm->_gameInfo->getMusicTrack(kMusicCredits), 100, 0, 2, -1, kMusicLoopPlayOnce, 3);
|
||||
|
||||
Font *fontBig = Font::load(_vm, "TAHOMA24.FON", 1, true);
|
||||
Font *fontSmall = Font::load(_vm, "TAHOMA18.FON", 1, true);
|
||||
|
||||
TextResource *textResource = new TextResource(_vm);
|
||||
textResource->open("ENDCRED");
|
||||
|
||||
int textCount = textResource->getCount();
|
||||
|
||||
int *textYPositions = new int[textCount]();
|
||||
int *textXPositions = new int[textCount]();
|
||||
|
||||
int y = 480 - fontBig->getFontHeight();
|
||||
bool small = false;
|
||||
int textStrWidth = 0;
|
||||
const int bigToSmallTextYPosDiff = ((fontBig->getFontHeight() - fontSmall->getFontHeight()) / 2);
|
||||
const int smallestMarginXToCreditName = 6; // px
|
||||
|
||||
for (int i = 0; i < textCount; ++i) {
|
||||
Common::String s = textResource->getText(i);
|
||||
creditsCheckAndFix(i, s);
|
||||
|
||||
if (s.hasPrefix("^")) {
|
||||
if (!small) {
|
||||
y += fontBig->getFontHeight();
|
||||
}
|
||||
small = false;
|
||||
textYPositions[i] = y;
|
||||
textXPositions[i] = 280;
|
||||
} else {
|
||||
if (small) {
|
||||
y += fontSmall->getFontHeight();
|
||||
} else {
|
||||
y += fontBig->getFontHeight();
|
||||
}
|
||||
small = true;
|
||||
textYPositions[i] = y + bigToSmallTextYPosDiff;
|
||||
if (_vm->_language == Common::ES_ESP
|
||||
&& _vm->_spanishCreditsCorrection
|
||||
&& i == 277) {
|
||||
y += 2 * fontSmall->getFontHeight();
|
||||
}
|
||||
textStrWidth = fontSmall->getStringWidth(s);
|
||||
textXPositions[i] = 270 - textStrWidth;
|
||||
//
|
||||
// Check here if horizontal alignment of this credit "title"
|
||||
// may cause clipping off the right edge of the screen.
|
||||
// Note, that we don't do the same check for a credit "name"
|
||||
// clipping off the left edge of the screen, as this does not happen
|
||||
// with the text resources for the credits in the official releases.
|
||||
// For fan made credits, the new text resources can be designed
|
||||
// with custom line wrapping and line spacing
|
||||
// so as to avoid any clipping, so this is no issue there.
|
||||
if (textXPositions[i] < 0) {
|
||||
textXPositions[i] = 0;
|
||||
if (textStrWidth > 280 - smallestMarginXToCreditName
|
||||
&& (i + 1 < textResource->getCount())) {
|
||||
Common::String sNext = textResource->getText(i + 1);
|
||||
if (sNext.hasPrefix("^")) {
|
||||
// If, for this case, the next string is a credit "name", ie.
|
||||
// aligned starting from the center (or near the center anyway),
|
||||
// then insert an extra line to avoid overlap with the title
|
||||
y += fontSmall->getFontHeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_vqaIsPlaying = true;
|
||||
_vm->_vqaStopIsRequested = false;
|
||||
|
||||
double position = 0.0;
|
||||
uint32 timeLast = _vm->_time->currentSystem();
|
||||
|
||||
Font *font;
|
||||
int height;
|
||||
|
||||
while (!_vm->_vqaStopIsRequested && !_vm->shouldQuit()) {
|
||||
if (position >= textYPositions[textCount - 1]) {
|
||||
break;
|
||||
}
|
||||
|
||||
//soundSystem::tick(SoundSystem);
|
||||
_vm->handleEvents();
|
||||
|
||||
if (!_vm->_windowIsActive) {
|
||||
timeLast = _vm->_time->currentSystem();
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 timeNow = _vm->_time->currentSystem();
|
||||
position += (double)(timeNow - timeLast) * 0.05f; // unsigned difference is intentional
|
||||
timeLast = timeNow;
|
||||
|
||||
_vm->_surfaceFront.fillRect(Common::Rect(BladeRunnerEngine::kOriginalGameWidth, BladeRunnerEngine::kOriginalGameHeight), 0);
|
||||
|
||||
for (int i = 0; i < textCount; ++i) {
|
||||
Common::String s = textResource->getText(i);
|
||||
creditsCheckAndFix(i, s);
|
||||
|
||||
if (s.hasPrefix("^")) {
|
||||
font = fontBig;
|
||||
height = fontBig->getFontHeight();
|
||||
s.deleteChar(0);
|
||||
} else {
|
||||
font = fontSmall;
|
||||
height = fontSmall->getFontHeight();
|
||||
}
|
||||
|
||||
y = textYPositions[i] - (int)position;
|
||||
|
||||
if (y < 452 && y + height > fontBig->getFontHeight()) {
|
||||
font->drawString(&_vm->_surfaceFront, s, textXPositions[i], y, _vm->_surfaceFront.w, 0);
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_surfaceFront.fillRect(Common::Rect(0, 0, BladeRunnerEngine::kOriginalGameWidth, fontBig->getFontHeight()), 0);
|
||||
_vm->_surfaceFront.fillRect(Common::Rect(0, BladeRunnerEngine::kOriginalGameHeight - fontBig->getFontHeight(), BladeRunnerEngine::kOriginalGameWidth, BladeRunnerEngine::kOriginalGameHeight), 0);
|
||||
|
||||
_vm->blitToScreen(_vm->_surfaceFront);
|
||||
}
|
||||
|
||||
_vm->_vqaIsPlaying = false;
|
||||
_vm->_vqaStopIsRequested = false;
|
||||
|
||||
delete[] textYPositions;
|
||||
delete[] textXPositions;
|
||||
delete textResource;
|
||||
|
||||
delete fontSmall;
|
||||
delete fontBig;
|
||||
|
||||
_vm->_music->stop(0u);
|
||||
_vm->_mouse->enable();
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
44
engines/bladerunner/ui/end_credits.h
Normal file
44
engines/bladerunner/ui/end_credits.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_UI_END_CREDITS_H
|
||||
#define BLADERUNNER_UI_END_CREDITS_H
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class BladeRunnerEngine;
|
||||
|
||||
class EndCredits {
|
||||
BladeRunnerEngine *_vm;
|
||||
|
||||
private:
|
||||
void creditsCheckAndFix(int &textResourceId, Common::String &textStr);
|
||||
|
||||
public:
|
||||
EndCredits(BladeRunnerEngine *vm);
|
||||
~EndCredits();
|
||||
|
||||
void show();
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
1808
engines/bladerunner/ui/esper.cpp
Normal file
1808
engines/bladerunner/ui/esper.cpp
Normal file
File diff suppressed because it is too large
Load Diff
284
engines/bladerunner/ui/esper.h
Normal file
284
engines/bladerunner/ui/esper.h
Normal file
@@ -0,0 +1,284 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_ESPER_H
|
||||
#define BLADERUNNER_ESPER_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class BladeRunnerEngine;
|
||||
class Font;
|
||||
class Shape;
|
||||
class Shapes;
|
||||
class VQAPlayer;
|
||||
class UIImagePicker;
|
||||
class ESPERScript;
|
||||
|
||||
// CD-changing logic has been removed
|
||||
|
||||
enum EsperMainStates {
|
||||
kEsperMainStateOpening = 0,
|
||||
kEsperMainStateList = 1,
|
||||
kEsperMainStatePhotoOpening = 2,
|
||||
kEsperMainStateClear = 3,
|
||||
kEsperMainStatePhoto = 5
|
||||
};
|
||||
|
||||
enum EsperPhotoStates {
|
||||
kEsperPhotoStateShow = 0,
|
||||
kEsperPhotoStateOpening = 1,
|
||||
kEsperPhotoStateScrolling = 2,
|
||||
kEsperPhotoStateSelectionZooming = 3,
|
||||
kEsperPhotoStateSelectionBlinking = 4,
|
||||
kEsperPhotoStatePhotoZooming = 5,
|
||||
kEsperPhotoStatePhotoSharpening = 6,
|
||||
kEsperPhotoStatePhotoZoomOut = 7,
|
||||
kEsperPhotoStateVideoZooming = 8,
|
||||
kEsperPhotoStateVideoShow = 9,
|
||||
kEsperPhotoStateVideoZoomOut = 10
|
||||
};
|
||||
|
||||
class ESPER {
|
||||
static const int kPhotoCount = 12;
|
||||
static const int kRegionCount = 6;
|
||||
static const int kPhotoWidth = 1280;
|
||||
static const int kPhotoHeight = 960;
|
||||
static const int kSelectionZoomSteps = 6;
|
||||
|
||||
static const Common::Rect kScreen;
|
||||
|
||||
struct Photo {
|
||||
bool isPresent;
|
||||
int photoId;
|
||||
int shapeId;
|
||||
Common::String name;
|
||||
};
|
||||
|
||||
struct Region {
|
||||
bool isPresent;
|
||||
int regionId;
|
||||
Common::Rect rectInner;
|
||||
Common::Rect rectOuter;
|
||||
Common::Rect rectSelection;
|
||||
Common::String name;
|
||||
};
|
||||
|
||||
BladeRunnerEngine *_vm;
|
||||
ESPERScript *_script;
|
||||
|
||||
bool _isWaiting;
|
||||
bool _isOpen;
|
||||
|
||||
UIImagePicker *_buttons;
|
||||
|
||||
Graphics::Surface _surfacePhoto;
|
||||
Graphics::Surface _surfaceViewport;
|
||||
|
||||
VQAPlayer *_vqaPlayerMain;
|
||||
VQAPlayer *_vqaPlayerPhoto;
|
||||
int _vqaLastFrame;
|
||||
|
||||
Shapes *_shapesButtons;
|
||||
Shapes *_shapesPhotos;
|
||||
const Shape *_shapeThumbnail;
|
||||
|
||||
Photo _photos[kPhotoCount];
|
||||
int _photoIdSelected;
|
||||
|
||||
Region _regions[kRegionCount];
|
||||
int _regionSelected;
|
||||
bool _regionSelectedAck;
|
||||
|
||||
EsperMainStates _stateMain;
|
||||
EsperPhotoStates _statePhoto;
|
||||
|
||||
bool _isDrawingSelection;
|
||||
bool _isMouseDown;
|
||||
int _mouseOverScroll;
|
||||
|
||||
float _zoomHorizontal;
|
||||
float _zoomVertical;
|
||||
float _zoom;
|
||||
float _zoomMin;
|
||||
float _zoomTarget;
|
||||
float _zoomDelta;
|
||||
float _blur;
|
||||
int _zoomSteps;
|
||||
int _zoomStep;
|
||||
uint32 _timeZoomNextDiff;
|
||||
uint32 _timeZoomNextStart;
|
||||
|
||||
bool _isZoomingOut;
|
||||
uint32 _timeZoomOutNextStart;
|
||||
|
||||
Common::Rect _screen;
|
||||
|
||||
Common::Rect _viewport;
|
||||
Common::Rect _viewportNext;
|
||||
int _viewportPositionX;
|
||||
int _viewportPositionY;
|
||||
float _viewportPositionXCurrent;
|
||||
float _viewportPositionYCurrent;
|
||||
int _viewportPositionXTarget;
|
||||
int _viewportPositionYTarget;
|
||||
float _viewportPositionXDelta;
|
||||
float _viewportPositionYDelta;
|
||||
int _viewportWidth;
|
||||
int _viewportHeight;
|
||||
|
||||
int _screenHalfWidth;
|
||||
int _screenHalfHeight;
|
||||
|
||||
int _flash;
|
||||
|
||||
Common::Rect _selection;
|
||||
Common::Rect _selectionTarget;
|
||||
Common::Rect _selectionDelta;
|
||||
int _selectionCrosshairX;
|
||||
int _selectionCrosshairY;
|
||||
|
||||
int _selectionBlinkingCounter;
|
||||
int _selectionBlinkingStyle;
|
||||
uint32 _timeSelectionBlinkingNextStart;
|
||||
|
||||
int _selectionZoomStep;
|
||||
uint32 _timeSelectionZoomNextStart;
|
||||
|
||||
int _photoOpeningWidth;
|
||||
int _photoOpeningHeight;
|
||||
uint32 _timePhotoOpeningNextDiff;
|
||||
uint32 _timePhotoOpeningNextStart;
|
||||
|
||||
bool _isScrolling;
|
||||
int _scrollingDirection;
|
||||
uint32 _timeScrollNextStart;
|
||||
|
||||
int _soundId1;
|
||||
int _volume1; // should be in [0, 100]
|
||||
int _soundId2;
|
||||
int _volume2; // should be in [0, 100]
|
||||
int _soundId3;
|
||||
int _volume3; // should be in [0, 100]
|
||||
int _ambientVolumeFactorOutsideEsper;
|
||||
|
||||
public:
|
||||
ESPER(BladeRunnerEngine *vm);
|
||||
~ESPER();
|
||||
|
||||
void open(Graphics::Surface *surface);
|
||||
void close();
|
||||
bool isOpen() const;
|
||||
|
||||
void handleMouseUp(int x, int y, bool buttonLeft);
|
||||
void handleMouseDown(int x, int y, bool buttonLeft);
|
||||
|
||||
void tick();
|
||||
|
||||
void addPhoto(const char *name, int photoId, int shapeId);
|
||||
void defineRegion(int regionId, Common::Rect inner, Common::Rect outer, Common::Rect selection, const char *name);
|
||||
|
||||
private:
|
||||
static void mouseDownCallback(int, void *);
|
||||
static void mouseUpCallback(int, void *);
|
||||
|
||||
void reset();
|
||||
void resetData();
|
||||
void resetPhotos();
|
||||
void resetRegions();
|
||||
void resetViewport();
|
||||
void resetSelectionRect();
|
||||
void resetSelectionBlinking();
|
||||
void resetPhotoZooming();
|
||||
void resetPhotoOpening();
|
||||
|
||||
void updateViewport();
|
||||
|
||||
void activate(bool withOpening);
|
||||
void setStateMain(EsperMainStates state);
|
||||
void setStatePhoto(EsperPhotoStates state);
|
||||
|
||||
void wait(uint32 timeout);
|
||||
void playSound(int soundId, int volume);
|
||||
|
||||
void draw(Graphics::Surface &surface);
|
||||
|
||||
void drawPhotoOpening(Graphics::Surface &surface);
|
||||
bool drawSelectionZooming(Graphics::Surface &surface);
|
||||
bool drawSelectionBlinking(Graphics::Surface &surface);
|
||||
void drawPhotoZooming(Graphics::Surface &surface);
|
||||
void drawPhotoSharpening(Graphics::Surface &surface);
|
||||
void drawPhotoZoomOut(Graphics::Surface &surface);
|
||||
void drawVideoZooming(Graphics::Surface &surface);
|
||||
void drawVideoZoomOut(Graphics::Surface &surface);
|
||||
|
||||
void drawPhoto(Graphics::Surface &surface);
|
||||
void drawGrid(Graphics::Surface &surface);
|
||||
void drawPhotoWithGrid(Graphics::Surface &surface);
|
||||
void drawSelection(Graphics::Surface &surface, bool crosshair, int style);
|
||||
void drawVideoFrame(Graphics::Surface &surface);
|
||||
void drawTextCoords(Graphics::Surface &surface);
|
||||
void drawMouse(Graphics::Surface &surface);
|
||||
|
||||
void flashViewport();
|
||||
|
||||
void copyImageScale(Graphics::Surface &src, Common::Rect srcRect, Graphics::Surface &dst, Common::Rect dstRect);
|
||||
void copyImageBlur(Graphics::Surface &src, Common::Rect srcRect, Graphics::Surface &dst, Common::Rect dstRect, float u);
|
||||
void copyImageBlit(Graphics::Surface &src, Common::Rect srcRect, Graphics::Surface &dst, Common::Rect dstRect);
|
||||
|
||||
void tickSound();
|
||||
void tickScroll();
|
||||
|
||||
int findEmptyPhoto();
|
||||
void selectPhoto(int photoId);
|
||||
void unloadPhotos();
|
||||
|
||||
int findEmptyRegion();
|
||||
int findRegion(Common::Rect where);
|
||||
|
||||
void zoomingStart();
|
||||
void zoomOutStart();
|
||||
void zoomOutStop();
|
||||
|
||||
void scrollingStart(int direction);
|
||||
void scrollingStop();
|
||||
void scrollUpdate();
|
||||
void scrollLeft();
|
||||
void scrollUp();
|
||||
void scrollRight();
|
||||
void scrollDown();
|
||||
|
||||
void goBack();
|
||||
|
||||
void prepareZoom();
|
||||
void updateSelection();
|
||||
|
||||
int viewportXToScreenX(int x);
|
||||
int viewportYToScreenY(int y);
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
1556
engines/bladerunner/ui/kia.cpp
Normal file
1556
engines/bladerunner/ui/kia.cpp
Normal file
File diff suppressed because it is too large
Load Diff
186
engines/bladerunner/ui/kia.h
Normal file
186
engines/bladerunner/ui/kia.h
Normal file
@@ -0,0 +1,186 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_KIA_H
|
||||
#define BLADERUNNER_KIA_H
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Common {
|
||||
struct KeyState;
|
||||
struct Event;
|
||||
}
|
||||
|
||||
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 Shape;
|
||||
class Shapes;
|
||||
class UIImagePicker;
|
||||
class VQAPlayer;
|
||||
|
||||
enum KIASections {
|
||||
kKIASectionNone = 0,
|
||||
kKIASectionCrimes = 1,
|
||||
kKIASectionSuspects = 2,
|
||||
kKIASectionClues = 3,
|
||||
kKIASectionSettings = 4,
|
||||
kKIASectionHelp = 5,
|
||||
kKIASectionSave = 6,
|
||||
kKIASectionLoad = 7,
|
||||
kKIASectionQuit = 8,
|
||||
kKIASectionDiagnostic = 9,
|
||||
kKIASectionPogo = 10
|
||||
};
|
||||
|
||||
class KIA {
|
||||
static const char *kPogo;
|
||||
static const int kPlayerActorDialogueQueueCapacity = 31;
|
||||
|
||||
struct ActorDialogueQueueEntry {
|
||||
int actorId;
|
||||
int sentenceId;
|
||||
};
|
||||
|
||||
BladeRunnerEngine *_vm;
|
||||
|
||||
int _transitionId;
|
||||
|
||||
uint32 _playerVqaTimeLast;
|
||||
VQAPlayer *_playerVqaPlayer;
|
||||
uint32 _playerVqaFrame;
|
||||
uint32 _playerVisualizerState;
|
||||
int _playerPhotographId;
|
||||
Shapes *_playerPhotographs;
|
||||
int _playerSliceModelId;
|
||||
float _playerSliceModelAngle;
|
||||
Graphics::Surface _playerImage;
|
||||
uint32 _timeLast;
|
||||
|
||||
ActorDialogueQueueEntry _playerActorDialogueQueue[kPlayerActorDialogueQueueCapacity];
|
||||
int _playerActorDialogueQueuePosition;
|
||||
int _playerActorDialogueQueueSize;
|
||||
int _playerActorDialogueState;
|
||||
|
||||
KIASections _currentSectionId;
|
||||
KIASections _lastSectionIdKIA;
|
||||
KIASections _lastSectionIdOptions;
|
||||
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:
|
||||
// Indicates when KIA opens after player has died
|
||||
// or the game just launched and there are existing saved games to load.
|
||||
// In forced open mode, certain KIA tabs are not available,
|
||||
// such as the Save Game tab and the Crime Scene, Suspect, Clue database tabs.
|
||||
bool _forceOpen;
|
||||
|
||||
KIALog *_log;
|
||||
KIAScript *_script;
|
||||
Shapes *_shapes;
|
||||
|
||||
Graphics::Surface _thumbnail;
|
||||
|
||||
public:
|
||||
KIA(BladeRunnerEngine *vm);
|
||||
~KIA();
|
||||
|
||||
void reset();
|
||||
|
||||
void openLastOpened();
|
||||
void open(KIASections sectionId);
|
||||
bool isOpen() const;
|
||||
|
||||
void tick();
|
||||
|
||||
void resume();
|
||||
|
||||
void handleMouseDown(int mouseX, int mouseY, bool mainButton);
|
||||
void handleMouseUp(int mouseX, int mouseY, bool mainButton);
|
||||
void handleMouseScroll(int mouseX, int mouseY, int direction); // Added by ScummVM team
|
||||
void handleKeyUp(const Common::KeyState &kbd);
|
||||
void handleKeyDown(const Common::KeyState &kbd);
|
||||
void handleCustomEventStop(const Common::Event &evt);
|
||||
void handleCustomEventStart(const Common::Event &evt);
|
||||
|
||||
void playerReset();
|
||||
void playActorDialogue(int actorId, int sentenceId);
|
||||
void playSliceModel(int sliceModelId);
|
||||
void playPhotograph(int photographId);
|
||||
void playImage(const Graphics::Surface &image);
|
||||
|
||||
const char *scrambleSuspectsName(const char *name);
|
||||
|
||||
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 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();
|
||||
void playObjectDescription(); // for restored content mode
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
#endif
|
||||
127
engines/bladerunner/ui/kia_log.cpp
Normal file
127
engines/bladerunner/ui/kia_log.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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) {
|
||||
unsigned char *dataCopy = new unsigned 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 = nullptr;
|
||||
_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
|
||||
64
engines/bladerunner/ui/kia_log.h
Normal file
64
engines/bladerunner/ui/kia_log.h
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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 unsigned 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
|
||||
34
engines/bladerunner/ui/kia_section_base.cpp
Normal file
34
engines/bladerunner/ui/kia_section_base.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/kia_section_base.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
KIASectionBase::KIASectionBase(BladeRunnerEngine *vm) {
|
||||
_vm = vm;
|
||||
_scheduledSwitch = false;
|
||||
}
|
||||
|
||||
KIASectionBase::~KIASectionBase() {
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
73
engines/bladerunner/ui/kia_section_base.h
Normal file
73
engines/bladerunner/ui/kia_section_base.h
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_KIA_SECTION_BASE_H
|
||||
#define BLADERUNNER_KIA_SECTION_BASE_H
|
||||
|
||||
#include "common/scummsys.h" // for "override" keyword
|
||||
|
||||
namespace Common {
|
||||
struct KeyState;
|
||||
struct Event;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
struct Surface;
|
||||
}
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class BladeRunnerEngine;
|
||||
|
||||
class KIASectionBase {
|
||||
protected:
|
||||
BladeRunnerEngine *_vm;
|
||||
|
||||
public:
|
||||
bool _scheduledSwitch;
|
||||
|
||||
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 handleCustomEventStart(const Common::Event &evt) {}
|
||||
virtual void handleCustomEventStop(const Common::Event &evt) {}
|
||||
|
||||
virtual void handleMouseMove(int mouseX, int mouseY) {}
|
||||
virtual void handleMouseDown(bool mainButton) {}
|
||||
virtual void handleMouseUp(bool mainButton) {}
|
||||
virtual void handleMouseScroll(int direction) {} // Added by ScummVM team
|
||||
|
||||
protected:
|
||||
virtual void onButtonPressed(int buttonId) {}
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
445
engines/bladerunner/ui/kia_section_clues.cpp
Normal file
445
engines/bladerunner/ui/kia_section_clues.cpp
Normal file
@@ -0,0 +1,445 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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_flags.h"
|
||||
#include "bladerunner/game_info.h"
|
||||
#include "bladerunner/font.h"
|
||||
#include "bladerunner/shape.h"
|
||||
#include "bladerunner/script/kia_script.h"
|
||||
#include "bladerunner/text_resource.h"
|
||||
#include "bladerunner/ui/kia.h"
|
||||
#include "bladerunner/ui/kia_log.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);
|
||||
|
||||
_isOpen = false;
|
||||
|
||||
_debugIntangible = false;
|
||||
_debugNop = 0;
|
||||
|
||||
_clues = clues;
|
||||
|
||||
_mouseX = 0;
|
||||
_mouseY = 0;
|
||||
|
||||
_buttons = new UIImagePicker(_vm, 2);
|
||||
|
||||
_cluesScrollBox = new UIScrollBox(_vm, scrollBoxCallback, this, kClueCount, 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 _buttons;
|
||||
delete _uiContainer;
|
||||
}
|
||||
|
||||
void KIASectionClues::reset() {
|
||||
_debugIntangible = false;
|
||||
_debugNop = 0;
|
||||
|
||||
_mouseX = 0;
|
||||
_mouseY = 0;
|
||||
|
||||
for (int i = 0; i < _filterCount; ++i) {
|
||||
_filters[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionClues::open() {
|
||||
_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();
|
||||
|
||||
populateFilters();
|
||||
populateClues();
|
||||
}
|
||||
|
||||
void KIASectionClues::close() {
|
||||
if (_isOpen) {
|
||||
_isOpen = false;
|
||||
|
||||
_buttons->deactivate();
|
||||
_cluesScrollBox->hide();
|
||||
_filterScrollBox->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionClues::draw(Graphics::Surface &surface) {
|
||||
_uiContainer->draw(surface);
|
||||
|
||||
_vm->_mainFont->drawString(&surface, _vm->_textKIA->getText(0), 300, 162, surface.w, surface.format.RGBToColor(232, 240, 255));
|
||||
_vm->_mainFont->drawString(&surface, _vm->_textKIA->getText(2), 440, 426, surface.w, surface.format.RGBToColor(80, 96, 136));
|
||||
_vm->_mainFont->drawString(&surface, _vm->_textKIA->getText(1), 440, 442, surface.w, surface.format.RGBToColor(80, 96, 136));
|
||||
_vm->_mainFont->drawString(&surface, _vm->_textKIA->getText(4), 440, 458, surface.w, surface.format.RGBToColor(80, 96, 136));
|
||||
|
||||
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->drawString(&surface, text, 490, 426, surface.w, surface.format.RGBToColor(136, 168, 255));
|
||||
|
||||
int crimeId = _vm->_crimesDatabase->getCrime(clueId);
|
||||
if (crimeId != -1) {
|
||||
text = _vm->_textCrimes->getText(crimeId);
|
||||
} else {
|
||||
text.clear();
|
||||
}
|
||||
_vm->_mainFont->drawString(&surface, text, 490, 442, surface.w, surface.format.RGBToColor(136, 168, 255));
|
||||
|
||||
int assetType = _vm->_crimesDatabase->getAssetType(clueId);
|
||||
if (assetType != kClueTypeIntangible) {
|
||||
text = _vm->_textClueTypes->getText(assetType);
|
||||
} else {
|
||||
text.clear();
|
||||
}
|
||||
_vm->_mainFont->drawString(&surface, text, 490, 458, surface.w, surface.format.RGBToColor(136, 168, 255));
|
||||
}
|
||||
|
||||
_buttons->draw(surface);
|
||||
_buttons->drawTooltip(surface, _mouseX, _mouseY);
|
||||
|
||||
if (_debugNop) {
|
||||
_vm->_mainFont->drawString(&surface, Common::String::format("Debug display: %s", _vm->_textActorNames->getText(_debugNop)), 120, 132, surface.w, surface.format.RGBToColor(255, 255, 0));
|
||||
}
|
||||
if (_debugIntangible) {
|
||||
_vm->_mainFont->drawString(&surface, "Debug Mode: Showing intangible clues.", 220, 105, surface.w, surface.format.RGBToColor(255, 255, 0));
|
||||
}
|
||||
}
|
||||
|
||||
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::handleMouseScroll(int direction) {
|
||||
_uiContainer->handleMouseScroll(direction);
|
||||
}
|
||||
|
||||
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(kSfxBEEP15), 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(kSfxBEEP10A), 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) {
|
||||
int clueId = i;
|
||||
if (_clues->isAcquired(clueId)) {
|
||||
int assetType = _vm->_crimesDatabase->getAssetType(clueId);
|
||||
int crimeId = _vm->_crimesDatabase->getCrime(clueId);
|
||||
if (_debugIntangible || assetType != kClueTypeIntangible) {
|
||||
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);
|
||||
|
||||
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) {
|
||||
int clueId = i;
|
||||
if (_clues->isAcquired(clueId)) {
|
||||
int assetType = _vm->_crimesDatabase->getAssetType(clueId);
|
||||
int crimeId = _vm->_crimesDatabase->getCrime(clueId);
|
||||
if (assetType != kClueTypeIntangible || _debugIntangible) {
|
||||
if (_filters[getLineIdForAssetType(assetType)] && _filters[getLineIdForCrimeId(crimeId)]) {
|
||||
int flags = 0x30;
|
||||
#if BLADERUNNER_ORIGINAL_BUGS
|
||||
if (_clues->isPrivate(clueId)) {
|
||||
flags = 0x08;
|
||||
} else if (_clues->isViewed(clueId)) {
|
||||
flags = 0x10;
|
||||
}
|
||||
#else
|
||||
if (_clues->isPrivate(clueId)) {
|
||||
flags |= 0x08;
|
||||
}
|
||||
if (_clues->isViewed(clueId)) {
|
||||
flags &= ~0x20;
|
||||
}
|
||||
if (_vm->_cutContent && _clues->isSharedWithMainframe(clueId)) {
|
||||
flags |= 0x40;
|
||||
}
|
||||
#endif // BLADERUNNER_ORIGINAL_BUGS
|
||||
_cluesScrollBox->addLine(_vm->_crimesDatabase->getClueText(clueId), clueId, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_cluesScrollBox->sortLines();
|
||||
}
|
||||
|
||||
int KIASectionClues::getClueFilterTypeTextId(int filterId) {
|
||||
if (filterId) {
|
||||
return filterId - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int KIASectionClues::getClueFilterCrimeId(int filterId) {
|
||||
if (filterId != _assetTypeFilterCount) {
|
||||
return filterId - (_assetTypeFilterCount + 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int KIASectionClues::getLineIdForAssetType(int assetType) {
|
||||
if (assetType == kClueTypeIntangible) {
|
||||
return 0;
|
||||
}
|
||||
return assetType + 1;
|
||||
}
|
||||
|
||||
int KIASectionClues::getLineIdForCrimeId(int crimeId) {
|
||||
if (crimeId == -1) {
|
||||
return _assetTypeFilterCount;
|
||||
}
|
||||
return _assetTypeFilterCount + crimeId + 1;
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
103
engines/bladerunner/ui/kia_section_clues.h
Normal file
103
engines/bladerunner/ui/kia_section_clues.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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;
|
||||
|
||||
struct Line {
|
||||
Common::String crimeName;
|
||||
int lineData;
|
||||
int flags;
|
||||
};
|
||||
|
||||
UIContainer *_uiContainer;
|
||||
UIImagePicker *_buttons;
|
||||
UIScrollBox *_cluesScrollBox;
|
||||
UIScrollBox *_filterScrollBox;
|
||||
|
||||
bool _isOpen;
|
||||
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() override;
|
||||
|
||||
void reset();
|
||||
|
||||
void open() override;
|
||||
void close() override;
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
|
||||
void handleMouseMove(int mouseX, int mouseY) override;
|
||||
void handleMouseDown(bool mainButton) override;
|
||||
void handleMouseUp(bool mainButton) override;
|
||||
void handleMouseScroll(int direction) override;
|
||||
|
||||
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) override;
|
||||
|
||||
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
|
||||
502
engines/bladerunner/ui/kia_section_crimes.cpp
Normal file
502
engines/bladerunner/ui/kia_section_crimes.cpp
Normal file
@@ -0,0 +1,502 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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_flags.h"
|
||||
#include "bladerunner/game_info.h"
|
||||
#include "bladerunner/shape.h"
|
||||
#include "bladerunner/script/kia_script.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/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, 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;
|
||||
for (int i = 0; i < kClueCount; ++i) {
|
||||
_acquiredClues[i].clueId = -1;
|
||||
_acquiredClues[i].actorId = -1;
|
||||
}
|
||||
|
||||
_crimeSelected = -1;
|
||||
_crimesFoundCount = 0;
|
||||
_crimesFound.resize(_vm->_gameInfo->getCrimeCount());
|
||||
|
||||
_suspectSelected = -1;
|
||||
_suspectPhotoShapeId = -1;
|
||||
_suspectPhotoNotUsed = -1;
|
||||
_suspectPhotoShapes = new Shapes(vm);
|
||||
_suspectsFoundCount = 0;
|
||||
_suspectsFound.resize(_vm->_gameInfo->getSuspectCount());
|
||||
_suspectsWithIdentity.resize(_vm->_gameInfo->getSuspectCount());
|
||||
}
|
||||
|
||||
KIASectionCrimes::~KIASectionCrimes() {
|
||||
delete _suspectPhotoShapes;
|
||||
|
||||
_uiContainer->clear();
|
||||
|
||||
delete _cluesScrollBox;
|
||||
delete _buttons;
|
||||
delete _uiContainer;
|
||||
}
|
||||
|
||||
void KIASectionCrimes::reset() {
|
||||
_acquiredClueCount = 0;
|
||||
_crimesFoundCount = 0;
|
||||
_suspectsFoundCount = 0;
|
||||
_mouseX = 0;
|
||||
_mouseY = 0;
|
||||
_suspectSelected = -1;
|
||||
_crimeSelected = -1;
|
||||
_suspectPhotoShapeId = -1;
|
||||
_suspectPhotoNotUsed = -1;
|
||||
}
|
||||
|
||||
void KIASectionCrimes::open() {
|
||||
_scheduledSwitch = false;
|
||||
|
||||
_suspectPhotoShapes->load("photos.shp");
|
||||
|
||||
_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();
|
||||
_suspectPhotoShapes->unload();
|
||||
}
|
||||
|
||||
void KIASectionCrimes::draw(Graphics::Surface &surface) {
|
||||
const char *text = nullptr;
|
||||
if (_suspectPhotoShapeId != -1) {
|
||||
const Shape *shape = _suspectPhotoShapes->get(_suspectPhotoShapeId);
|
||||
shape->draw(surface, 201 - shape->getWidth() / 2, 223 - shape->getHeight() / 2);
|
||||
}
|
||||
if (_suspectPhotoShapeId == 14 || _suspectPhotoShapeId == 13) {
|
||||
text = _vm->_textKIA->getText(49);
|
||||
_vm->_mainFont->drawString(&surface, text, 201 - _vm->_mainFont->getStringWidth(text) / 2, 218, surface.w, surface.format.RGBToColor(255, 255, 255));
|
||||
}
|
||||
|
||||
surface.fillRect(Common::Rect(120, 134, 250, 145), 0);
|
||||
surface.hLine(120, 133, 250, surface.format.RGBToColor(48, 40, 40));
|
||||
surface.hLine(120, 146, 250, surface.format.RGBToColor(88, 80, 96));
|
||||
surface.vLine(119, 134, 145, surface.format.RGBToColor(48, 40, 40));
|
||||
surface.vLine(251, 134, 145, surface.format.RGBToColor(88, 80, 96));
|
||||
surface.hLine(251, 146, 251, surface.format.RGBToColor(72, 64, 72));
|
||||
|
||||
if (_crimeSelected == -1) {
|
||||
text = _vm->_textKIA->getText(49);
|
||||
} else {
|
||||
text = _vm->_textCrimes->getText(_crimeSelected);
|
||||
}
|
||||
|
||||
_vm->_mainFont->drawString(&surface, text, 185 - _vm->_mainFont->getStringWidth(text) / 2, 136, surface.w, surface.format.RGBToColor(136, 168, 255));
|
||||
|
||||
surface.fillRect(Common::Rect(136, 304, 266, 315), 0);
|
||||
surface.hLine(136, 303, 266, surface.format.RGBToColor(48, 40, 40));
|
||||
surface.hLine(136, 316, 266, surface.format.RGBToColor(88, 80, 96));
|
||||
surface.vLine(135, 304, 315, surface.format.RGBToColor(48, 40, 40));
|
||||
surface.vLine(267, 304, 315, surface.format.RGBToColor(88, 80, 96));
|
||||
surface.hLine(267, 316, 267, surface.format.RGBToColor(72, 64, 72));
|
||||
|
||||
Common::String generatedText;
|
||||
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()) {
|
||||
generatedText = Common::String::format("%s %s", _vm->_textKIA->getText(20), _vm->_kia->scrambleSuspectsName(suspectName));
|
||||
text = generatedText.c_str();
|
||||
} else {
|
||||
generatedText = Common::String::format("%s %s", _vm->_textKIA->getText(21), _vm->_kia->scrambleSuspectsName(suspectName));
|
||||
text = generatedText.c_str();
|
||||
}
|
||||
}
|
||||
_vm->_mainFont->drawString(&surface, text, 201 - _vm->_mainFont->getStringWidth(text) / 2, 306, surface.w, surface.format.RGBToColor(136, 168, 255));
|
||||
|
||||
_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::handleMouseScroll(int direction) {
|
||||
_uiContainer->handleMouseScroll(direction);
|
||||
}
|
||||
|
||||
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(kSfxBEEP15), 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) {
|
||||
int clueId = i;
|
||||
if (_clues->isAcquired(clueId)) {
|
||||
_acquiredClues[_acquiredClueCount].clueId = clueId;
|
||||
_acquiredClues[_acquiredClueCount].actorId = _clues->getFromActorId(clueId);
|
||||
++_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 (int i = 0; i < kClueCount; ++i) {
|
||||
int clueId = i;
|
||||
if (_vm->_crimesDatabase->getAssetType(clueId) != kClueTypeIntangible
|
||||
&& _vm->_crimesDatabase->getCrime(clueId) == _crimeSelected
|
||||
&& _clues->isAcquired(clueId)
|
||||
) {
|
||||
int flags = 0x30;
|
||||
#if BLADERUNNER_ORIGINAL_BUGS
|
||||
if (_clues->isPrivate(clueId)) {
|
||||
flags = 0x08;
|
||||
} else if (_clues->isViewed(clueId)) {
|
||||
flags = 0x10;
|
||||
}
|
||||
#else
|
||||
if (_clues->isPrivate(clueId)) {
|
||||
flags |= 0x08;
|
||||
}
|
||||
if (_clues->isViewed(clueId)) {
|
||||
flags &= ~0x20;
|
||||
}
|
||||
if (_vm->_cutContent && _clues->isSharedWithMainframe(clueId)) {
|
||||
flags |= 0x40;
|
||||
}
|
||||
#endif // BLADERUNNER_ORIGINAL_BUGS
|
||||
_cluesScrollBox->addLine(_vm->_crimesDatabase->getClueText(clueId), clueId, flags);
|
||||
}
|
||||
}
|
||||
_cluesScrollBox->sortLines();
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionCrimes::updateSuspectPhoto() {
|
||||
if (_suspectSelected == -1) {
|
||||
_suspectPhotoShapeId = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
SuspectDatabaseEntry *suspect = _vm->_suspectsDatabase->get(_suspectSelected);
|
||||
|
||||
_suspectPhotoShapeId = -1;
|
||||
_suspectPhotoNotUsed = -1;
|
||||
int photoCluesCount = suspect->getPhotoCount();
|
||||
if (photoCluesCount > 0) {
|
||||
for (int i = 0 ; i < photoCluesCount; ++i) {
|
||||
//TODO: weird stuff going on here... original game is using internal clue index instead id
|
||||
if (_clues->isAcquired(suspect->getPhotoClueId(i))) {
|
||||
_suspectPhotoShapeId = suspect->getPhotoShapeId(i);
|
||||
_suspectPhotoNotUsed = suspect->getPhotoNotUsed(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_suspectPhotoShapeId == -1 && _suspectPhotoNotUsed == -1) {
|
||||
if (suspect->getSex()) {
|
||||
_suspectPhotoShapeId = 14;
|
||||
} else {
|
||||
_suspectPhotoShapeId = 13;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
119
engines/bladerunner/ui/kia_section_crimes.h
Normal file
119
engines/bladerunner/ui/kia_section_crimes.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_KIA_SECTION_CRIME_H
|
||||
#define BLADERUNNER_KIA_SECTION_CRIME_H
|
||||
|
||||
#include "bladerunner/ui/kia_section_base.h"
|
||||
|
||||
#include "common/array.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class ActorClues;
|
||||
class BladeRunnerEngine;
|
||||
class Shapes;
|
||||
class UIContainer;
|
||||
class UIImagePicker;
|
||||
class UIScrollBox;
|
||||
|
||||
class KIASectionCrimes : public KIASectionBase {
|
||||
// _vm->_gameInfo->getClueCount()
|
||||
static const int kClueCount = 288;
|
||||
|
||||
struct AcquiredClue {
|
||||
int clueId;
|
||||
int actorId;
|
||||
};
|
||||
|
||||
bool _isOpen;
|
||||
|
||||
UIContainer *_uiContainer;
|
||||
UIImagePicker *_buttons;
|
||||
UIScrollBox *_cluesScrollBox;
|
||||
|
||||
ActorClues *_clues;
|
||||
|
||||
int _acquiredClueCount;
|
||||
AcquiredClue _acquiredClues[kClueCount];
|
||||
|
||||
int _crimeSelected;
|
||||
|
||||
int _crimesFoundCount;
|
||||
Common::Array<bool> _crimesFound;
|
||||
|
||||
int _suspectsFoundCount;
|
||||
Common::Array<bool> _suspectsFound;
|
||||
Common::Array<bool> _suspectsWithIdentity;
|
||||
|
||||
int _mouseX;
|
||||
int _mouseY;
|
||||
|
||||
int _suspectPhotoShapeId;
|
||||
int _suspectPhotoNotUsed;
|
||||
Shapes *_suspectPhotoShapes;
|
||||
|
||||
public:
|
||||
int _suspectSelected;
|
||||
|
||||
public:
|
||||
KIASectionCrimes(BladeRunnerEngine *vm, ActorClues *clues);
|
||||
~KIASectionCrimes() override;
|
||||
|
||||
void reset();
|
||||
|
||||
void open() override;
|
||||
void close() override;
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
|
||||
void handleMouseMove(int mouseX, int mouseY) override;
|
||||
void handleMouseDown(bool mainButton) override;
|
||||
void handleMouseUp(bool mainButton) override;
|
||||
void handleMouseScroll(int direction) override;
|
||||
|
||||
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) override;
|
||||
|
||||
void populateAcquiredClues();
|
||||
void populateCrimes();
|
||||
void populateSuspects();
|
||||
void populateVisibleClues();
|
||||
void updateSuspectPhoto();
|
||||
|
||||
void nextCrime();
|
||||
void prevCrime();
|
||||
|
||||
void nextSuspect();
|
||||
void prevSuspect();
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
103
engines/bladerunner/ui/kia_section_diagnostic.cpp
Normal file
103
engines/bladerunner/ui/kia_section_diagnostic.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/kia_section_diagnostic.h"
|
||||
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/font.h"
|
||||
#include "bladerunner/game_constants.h"
|
||||
#include "bladerunner/text_resource.h"
|
||||
#include "bladerunner/time.h"
|
||||
#include "bladerunner/ui/kia.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
const Color256 KIASectionDiagnostic::kTextColors[] = {
|
||||
{ 0, 0, 0 },
|
||||
{ 16, 8, 8 },
|
||||
{ 32, 24, 8 },
|
||||
{ 56, 32, 16 },
|
||||
{ 72, 48, 16 },
|
||||
{ 88, 56, 24 },
|
||||
{ 104, 72, 32 },
|
||||
{ 128, 80, 40 },
|
||||
{ 136, 96, 48 },
|
||||
{ 152, 112, 56 },
|
||||
{ 168, 128, 72 },
|
||||
{ 184, 144, 88 },
|
||||
{ 200, 160, 96 },
|
||||
{ 216, 184, 112 },
|
||||
{ 232, 200, 128 },
|
||||
{ 240, 224, 144 }
|
||||
};
|
||||
|
||||
KIASectionDiagnostic::KIASectionDiagnostic(BladeRunnerEngine *vm) : KIASectionBase(vm) {
|
||||
_text = nullptr;
|
||||
_offset = 0;
|
||||
_timeLast = 0;
|
||||
}
|
||||
|
||||
void KIASectionDiagnostic::open() {
|
||||
_text = new TextResource(_vm);
|
||||
if (!_text->open("KIACRED")) {
|
||||
return;
|
||||
}
|
||||
_vm->_kia->playActorDialogue(kActorRunciter, 140);
|
||||
_offset = 0;
|
||||
_timeLast = _vm->_time->currentSystem();
|
||||
}
|
||||
|
||||
void KIASectionDiagnostic::close() {
|
||||
delete _text;
|
||||
}
|
||||
|
||||
void KIASectionDiagnostic::draw(Graphics::Surface &surface) {
|
||||
uint32 timeNow = _vm->_time->currentSystem();
|
||||
|
||||
for (int i = 0; i < _text->getCount(); ++i) {
|
||||
int y = kLineHeight * i + 366 - _offset;
|
||||
if (y >= 150 && y < 366) {
|
||||
int colorIndex = 15;
|
||||
if (y < 182) {
|
||||
colorIndex = (y - 150) / 2;
|
||||
} else if (y >= 334) {
|
||||
colorIndex = (365 - y) / 2;
|
||||
}
|
||||
|
||||
const char *text = _text->getText(i);
|
||||
if (text) {
|
||||
_vm->_mainFont->drawString(&surface, text, 320 - _vm->_mainFont->getStringWidth(text) / 2, y, surface.w, surface.format.RGBToColor(kTextColors[colorIndex].r, kTextColors[colorIndex].g, kTextColors[colorIndex].b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Timing fixed for 60Hz by ScummVM team
|
||||
// unsigned difference is intentional
|
||||
if (timeNow - _timeLast > (1000u / 60u)) {
|
||||
++_offset;
|
||||
if (_offset > kLineHeight * _text->getCount() + 366) {
|
||||
_offset = 0;
|
||||
}
|
||||
_timeLast = timeNow;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
51
engines/bladerunner/ui/kia_section_diagnostic.h
Normal file
51
engines/bladerunner/ui/kia_section_diagnostic.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_KIA_SECTION_DIAGNOSTIC_H
|
||||
#define BLADERUNNER_KIA_SECTION_DIAGNOSTIC_H
|
||||
|
||||
#include "bladerunner/color.h"
|
||||
#include "bladerunner/ui/kia_section_base.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class TextResource;
|
||||
|
||||
class KIASectionDiagnostic : public KIASectionBase {
|
||||
static const Color256 kTextColors[];
|
||||
static const int kLineHeight = 18;
|
||||
|
||||
TextResource *_text;
|
||||
int _offset;
|
||||
uint32 _timeLast;
|
||||
|
||||
public:
|
||||
KIASectionDiagnostic(BladeRunnerEngine *vm);
|
||||
|
||||
void open() override;
|
||||
void close() override;
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
96
engines/bladerunner/ui/kia_section_help.cpp
Normal file
96
engines/bladerunner/ui/kia_section_help.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/kia_section_help.h"
|
||||
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/shape.h"
|
||||
#include "bladerunner/text_resource.h"
|
||||
#include "bladerunner/ui/kia.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);
|
||||
#if BLADERUNNER_ORIGINAL_BUGS
|
||||
_scrollBox = new UIScrollBox(_vm, nullptr, this, 1024, 0, false, Common::Rect(135, 145, 461, 385), Common::Rect(506, 160, 506, 350));
|
||||
#else
|
||||
// Increase width of scollable area, to eliminate the (significant) area to the right,
|
||||
// before the scroll bar, where scrolling would not work.
|
||||
_scrollBox = new UIScrollBox(_vm, nullptr, this, 1024, 0, false, Common::Rect(135, 145, 502, 385), Common::Rect(506, 160, 506, 350));
|
||||
#endif
|
||||
_uiContainer->add(_scrollBox);
|
||||
}
|
||||
|
||||
KIASectionHelp::~KIASectionHelp() {
|
||||
_uiContainer->clear();
|
||||
delete _scrollBox;
|
||||
delete _uiContainer;
|
||||
}
|
||||
|
||||
void KIASectionHelp::open() {
|
||||
TextResource textResource(_vm);
|
||||
if (!textResource.open("HELP")) {
|
||||
return;
|
||||
}
|
||||
|
||||
_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::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);
|
||||
}
|
||||
|
||||
void KIASectionHelp::handleMouseScroll(int direction) {
|
||||
_uiContainer->handleMouseScroll(direction);
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
53
engines/bladerunner/ui/kia_section_help.h
Normal file
53
engines/bladerunner/ui/kia_section_help.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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() override;
|
||||
|
||||
void open() override;
|
||||
void close() override;
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
|
||||
void handleMouseMove(int mouseX, int mouseY) override;
|
||||
void handleMouseDown(bool mainButton) override;
|
||||
void handleMouseUp(bool mainButton) override;
|
||||
void handleMouseScroll(int direction) override;
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
#endif
|
||||
183
engines/bladerunner/ui/kia_section_load.cpp
Normal file
183
engines/bladerunner/ui/kia_section_load.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/kia_section_load.h"
|
||||
|
||||
#include "bladerunner/audio_player.h"
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/game_info.h"
|
||||
#include "bladerunner/savefile.h"
|
||||
#include "bladerunner/shape.h"
|
||||
#include "bladerunner/text_resource.h"
|
||||
#include "bladerunner/time.h"
|
||||
#include "bladerunner/game_constants.h"
|
||||
#include "bladerunner/ui/kia.h"
|
||||
#include "bladerunner/ui/ui_container.h"
|
||||
#include "bladerunner/ui/ui_scroll_box.h"
|
||||
|
||||
#include "common/error.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
KIASectionLoad::KIASectionLoad(BladeRunnerEngine *vm) : KIASectionBase(vm) {
|
||||
_uiContainer = new UIContainer(_vm);
|
||||
// There is a small area to the right of the save games list, before the scroll bar,
|
||||
// where scrolling does not work.
|
||||
// However, unlike kia_section_help, if we increase the width of the scrollable area here,
|
||||
// we would noticeably mess with the centering of the title label and the saved game names in the list.
|
||||
_scrollBox = new UIScrollBox(_vm, scrollBoxCallback, this, 1025, 0, true, Common::Rect(155, 158, 461, 346), Common::Rect(506, 160, 506, 350));
|
||||
_uiContainer->add(_scrollBox);
|
||||
|
||||
_timeLast = 0u;
|
||||
_timeLeft = 0u;
|
||||
|
||||
_hoveredLineId = -1;
|
||||
_displayingLineId = -1;
|
||||
_newGameEasyLineId = -1;
|
||||
_newGameMediumLineId = -1;
|
||||
_newGameHardLineId = -1;
|
||||
}
|
||||
|
||||
KIASectionLoad::~KIASectionLoad() {
|
||||
_uiContainer->clear();
|
||||
delete _scrollBox;
|
||||
delete _uiContainer;
|
||||
}
|
||||
|
||||
void KIASectionLoad::open() {
|
||||
_scheduledSwitch = false;
|
||||
_scrollBox->show();
|
||||
_scrollBox->clearLines();
|
||||
|
||||
_saveList = SaveFileManager::list(_vm->getMetaEngine(), _vm->getTargetName());
|
||||
|
||||
if (!_saveList.empty()) {
|
||||
_scrollBox->addLine(_vm->_textOptions->getText(36), -1, 4); // Load game:
|
||||
for (uint i = 0; i < _saveList.size(); ++i) {
|
||||
_scrollBox->addLine(_saveList[i].getDescription().encode(Common::kDos850), i, 0);
|
||||
}
|
||||
_scrollBox->addLine("", -1, 4);
|
||||
}
|
||||
|
||||
_newGameEasyLineId = _saveList.size();
|
||||
_newGameMediumLineId = _saveList.size() + 1;
|
||||
_newGameHardLineId = _saveList.size() + 2;
|
||||
|
||||
_scrollBox->addLine(_vm->_textOptions->getText(37), -1, 4); // New game:
|
||||
_scrollBox->addLine(_vm->_textOptions->getText(20), _newGameEasyLineId, 0); // Easy
|
||||
_scrollBox->addLine(_vm->_textOptions->getText(28), _newGameMediumLineId, 0); // Medium
|
||||
_scrollBox->addLine(_vm->_textOptions->getText(29), _newGameHardLineId, 0); // Hard
|
||||
|
||||
_hoveredLineId = -1;
|
||||
_timeLast = _vm->_time->currentSystem();
|
||||
_timeLeft = 800u;
|
||||
}
|
||||
|
||||
void KIASectionLoad::close() {
|
||||
_scrollBox->hide();
|
||||
_vm->_kia->playerReset();
|
||||
|
||||
_saveList.clear();
|
||||
}
|
||||
|
||||
void KIASectionLoad::draw(Graphics::Surface &surface) {
|
||||
_vm->_kia->_shapes->get(69)->draw(surface, 501, 123);
|
||||
|
||||
_uiContainer->draw(surface);
|
||||
|
||||
int selectedLineId = _scrollBox->getSelectedLineData();
|
||||
|
||||
if (_hoveredLineId != selectedLineId) {
|
||||
if (selectedLineId >= 0 && selectedLineId < (int)_saveList.size() && _displayingLineId != selectedLineId) {
|
||||
if (_timeLeft == 0u) {
|
||||
SaveStateDescriptor desc = SaveFileManager::queryMetaInfos(_vm->getMetaEngine(), _vm->getTargetName(), selectedLineId);
|
||||
const Graphics::Surface *thumbnail = desc.getThumbnail();
|
||||
if (thumbnail != nullptr) {
|
||||
_vm->_kia->playImage(*thumbnail);
|
||||
_displayingLineId = selectedLineId;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_vm->_kia->playerReset();
|
||||
_timeLeft = 800u;
|
||||
_displayingLineId = -1;
|
||||
}
|
||||
_hoveredLineId = selectedLineId;
|
||||
}
|
||||
|
||||
uint32 now = _vm->_time->currentSystem();
|
||||
if (selectedLineId >= 0 && selectedLineId < (int)_saveList.size() && _displayingLineId != selectedLineId) {
|
||||
if (_timeLeft) {
|
||||
uint32 timeDiff = now - _timeLast; // unsigned difference is intentional
|
||||
if (timeDiff >= _timeLeft) {
|
||||
SaveStateDescriptor desc = SaveFileManager::queryMetaInfos(_vm->getMetaEngine(), _vm->getTargetName(), _saveList[selectedLineId].getSaveSlot());
|
||||
const Graphics::Surface *thumbnail = desc.getThumbnail();
|
||||
if (thumbnail != nullptr) {
|
||||
_vm->_kia->playImage(*thumbnail);
|
||||
_displayingLineId = selectedLineId;
|
||||
}
|
||||
} else {
|
||||
_timeLeft = (_timeLeft < timeDiff) ? 0u : (_timeLeft - timeDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_timeLast = now;
|
||||
}
|
||||
|
||||
void KIASectionLoad::handleMouseMove(int mouseX, int mouseY) {
|
||||
_uiContainer->handleMouseMove(mouseX, mouseY);
|
||||
}
|
||||
|
||||
void KIASectionLoad::handleMouseDown(bool mainButton) {
|
||||
_uiContainer->handleMouseDown(!mainButton);
|
||||
}
|
||||
|
||||
void KIASectionLoad::handleMouseUp(bool mainButton) {
|
||||
_uiContainer->handleMouseUp(!mainButton);
|
||||
}
|
||||
|
||||
void KIASectionLoad::handleMouseScroll(int direction) {
|
||||
_uiContainer->handleMouseScroll(direction);
|
||||
}
|
||||
|
||||
void KIASectionLoad::scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton) {
|
||||
KIASectionLoad *self = (KIASectionLoad *)callbackData;
|
||||
|
||||
if (mouseButton == 0 && source == self->_scrollBox && lineData >= 0) {
|
||||
if (lineData == self->_newGameEasyLineId) {
|
||||
self->_vm->newGame(kGameDifficultyEasy);
|
||||
} else if (lineData == self->_newGameMediumLineId) {
|
||||
self->_vm->newGame(kGameDifficultyMedium);
|
||||
} else if (lineData == self->_newGameHardLineId) {
|
||||
self->_vm->newGame(kGameDifficultyHard);
|
||||
} else {
|
||||
self->_vm->loadGameState(self->_saveList[lineData].getSaveSlot());
|
||||
}
|
||||
|
||||
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxELECBP1), 90, 0, 0, 50, 0);
|
||||
self->_vm->_kia->resume();
|
||||
self->_scheduledSwitch = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
76
engines/bladerunner/ui/kia_section_load.h
Normal file
76
engines/bladerunner/ui/kia_section_load.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_KIA_SECTION_LOAD_H
|
||||
#define BLADERUNNER_KIA_SECTION_LOAD_H
|
||||
|
||||
#include "bladerunner/ui/kia_section_base.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
|
||||
#include "engines/savestate.h"
|
||||
|
||||
namespace Graphics {
|
||||
struct Surface;
|
||||
}
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class UIContainer;
|
||||
class UIScrollBox;
|
||||
|
||||
class KIASectionLoad : public KIASectionBase {
|
||||
UIContainer *_uiContainer;
|
||||
UIScrollBox *_scrollBox;
|
||||
|
||||
uint32 _timeLast;
|
||||
uint32 _timeLeft;
|
||||
|
||||
SaveStateList _saveList;
|
||||
|
||||
int _hoveredLineId;
|
||||
int _displayingLineId;
|
||||
int _newGameEasyLineId;
|
||||
int _newGameMediumLineId;
|
||||
int _newGameHardLineId;
|
||||
|
||||
public:
|
||||
KIASectionLoad(BladeRunnerEngine *vm);
|
||||
~KIASectionLoad() override;
|
||||
|
||||
void open() override;
|
||||
void close() override;
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
|
||||
void handleMouseMove(int mouseX, int mouseY) override;
|
||||
void handleMouseDown(bool mainButton) override;
|
||||
void handleMouseUp(bool mainButton) override;
|
||||
void handleMouseScroll(int direction) override;
|
||||
|
||||
private:
|
||||
static void scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton);
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
292
engines/bladerunner/ui/kia_section_pogo.cpp
Normal file
292
engines/bladerunner/ui/kia_section_pogo.cpp
Normal file
@@ -0,0 +1,292 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/kia_section_pogo.h"
|
||||
|
||||
#include "bladerunner/audio_player.h"
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/font.h"
|
||||
#include "bladerunner/game_info.h"
|
||||
#include "bladerunner/text_resource.h"
|
||||
#include "bladerunner/time.h"
|
||||
#include "bladerunner/game_constants.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
const Color256 KIASectionPogo::kTextColors[] = {
|
||||
{ 0, 0, 0 },
|
||||
{ 16, 8, 8 },
|
||||
{ 32, 24, 8 },
|
||||
{ 56, 32, 16 },
|
||||
{ 72, 48, 16 },
|
||||
{ 88, 56, 24 },
|
||||
{ 104, 72, 32 },
|
||||
{ 128, 80, 40 },
|
||||
{ 136, 96, 48 },
|
||||
{ 152, 112, 56 },
|
||||
{ 168, 128, 72 },
|
||||
{ 184, 144, 88 },
|
||||
{ 200, 160, 96 },
|
||||
{ 216, 184, 112 },
|
||||
{ 232, 200, 128 },
|
||||
{ 240, 224, 144 }
|
||||
};
|
||||
|
||||
const char *KIASectionPogo::kStrings[] = {
|
||||
"Air Conditioning",
|
||||
"Amy Shoopman",
|
||||
"Andy B. and the Milk Carton Kids",
|
||||
"Area 51",
|
||||
"Aspirin",
|
||||
"Babylon 5",
|
||||
"Bandit",
|
||||
"Bauer Inline Skates",
|
||||
"Bill Randolph",
|
||||
"Bill (Mr. Motorola) and Sarah",
|
||||
"Boo Berry and Frankenberry",
|
||||
"Brett W. Sperry",
|
||||
"Brianhead Ski Resort",
|
||||
"\"Bubba\"",
|
||||
"Bubbles",
|
||||
"Building 2 Parking",
|
||||
"The Buke",
|
||||
"Chan \"The Emporer\" Lee",
|
||||
"Cheezy Poofs",
|
||||
"Chuck \"Walter\" Karras",
|
||||
"Cinco De Mayo",
|
||||
"Club Med",
|
||||
"Code Complete",
|
||||
"Coffee Pub, Las Vegas",
|
||||
"Coke",
|
||||
"Coin Magic",
|
||||
"Count Chocula",
|
||||
"Dad",
|
||||
"David Arkenstone",
|
||||
"Digital Camera",
|
||||
"Direct X Team",
|
||||
"Denis and Joanne Dyack",
|
||||
"Blue Bayou, Disneyland",
|
||||
"Dongle-Boy",
|
||||
"Doves and Sparrows",
|
||||
"Dovey",
|
||||
"Draracles",
|
||||
"Dry Air",
|
||||
"Ed Del Castillo",
|
||||
"Eric \"Kick Ass\" Cartman",
|
||||
"FHM",
|
||||
"Fog City Diner",
|
||||
"Fog Studios",
|
||||
"Gatorade",
|
||||
"Gandhi Cuisine of India",
|
||||
"Giant Lava Lamp",
|
||||
"Eric and Nancy Gooch",
|
||||
"Grayford Family",
|
||||
"Comet Hale-Bopp",
|
||||
"Joseph B. Hewitt IV",
|
||||
"Hercules",
|
||||
"Hillbilly Jeopardy",
|
||||
"Home Cookin'",
|
||||
"Hooey Stick",
|
||||
"The Hypnotist",
|
||||
"Insects on the Move",
|
||||
"Intel",
|
||||
"James Hong",
|
||||
"Jasmine",
|
||||
"The Mysterious Cockatiel",
|
||||
"Joe's Frog",
|
||||
"\"Jed\"",
|
||||
"Jeeps",
|
||||
"\"Jeeter\"",
|
||||
"Jeff Brown",
|
||||
"JoeB",
|
||||
"\"Joe-Bob McClintock\"",
|
||||
"Joseph Turkel",
|
||||
"Jose Cuervo",
|
||||
"Juggling Balls",
|
||||
"Keith Parkinson",
|
||||
"Khan",
|
||||
"King of the Hill",
|
||||
"Kurt O. and the Toothbrush Squad",
|
||||
"Leonard and Shirley Legg",
|
||||
"\"Leroy\"",
|
||||
"Brion James",
|
||||
"Louis and his \"friend\"",
|
||||
"M.C. Crammer and Janie",
|
||||
"Men's Room Magna-Doodle",
|
||||
"Mark and Deepti Rowland",
|
||||
"Metro Pizza, Las Vegas",
|
||||
"Matt Vella",
|
||||
"Maui",
|
||||
"1 Million Candlepower Spotlight",
|
||||
"Mom",
|
||||
"Movie-makers",
|
||||
"Mr. Nonsense",
|
||||
"\"Needles\"",
|
||||
"Nerf Weaponry",
|
||||
"Nimbus",
|
||||
"Norm Vordahl",
|
||||
"KNPR",
|
||||
"Olive Garden",
|
||||
"Onkyo",
|
||||
"Orangey",
|
||||
"Osbur, the Human Resource Manager",
|
||||
"Our Cheery Friend Leary",
|
||||
"Ousted Gnome King",
|
||||
"Pepsi",
|
||||
"Peta Wilson",
|
||||
"Pogo the Mockingbird",
|
||||
"Poker Nights",
|
||||
"Pirates",
|
||||
"Playmate Lingerie Calendar",
|
||||
"Pop-Ice",
|
||||
"Powerhouse Gym",
|
||||
"Rade McDowell",
|
||||
"Red Rock Canyon",
|
||||
"Refrigeration",
|
||||
"Rhoda",
|
||||
"Richard and Kimberly Weier",
|
||||
"Ridley Scott",
|
||||
"Ruud the Dude",
|
||||
"Our old pal Rick Parks",
|
||||
"Ruby's Diner",
|
||||
"Savatage",
|
||||
"Scully and Mulder",
|
||||
"Sean Young",
|
||||
"Seinfeld",
|
||||
"The Shadow",
|
||||
"\"Shakes\"",
|
||||
"Shorts",
|
||||
"Silly Putty",
|
||||
"The Simpsons",
|
||||
"Thomas Christensen",
|
||||
"We love you Steve Wetherill!!!",
|
||||
"\"Skank\"",
|
||||
"\"Slice\"",
|
||||
"SSG",
|
||||
"Steve and Anne Tall",
|
||||
"South Park",
|
||||
"Snap 'n Pops",
|
||||
"Sneaker",
|
||||
"Star Wars Trilogy",
|
||||
"Nonstop Summer Pool Parties",
|
||||
"Sunsets",
|
||||
"T-Bone and Angie",
|
||||
"T-shirts",
|
||||
"Julio Schembari, Tango Pools",
|
||||
"The Thermostat Key",
|
||||
"The Wizard",
|
||||
"Tomb Raider",
|
||||
"Tom Elmer II",
|
||||
"Tujia Linden",
|
||||
"Turbo",
|
||||
"Tweeter",
|
||||
"Twonky",
|
||||
"Ty and Judy Coon",
|
||||
"The Courtyard",
|
||||
"U.F.C.",
|
||||
"Uli Boehnke",
|
||||
"\"Virgil\"",
|
||||
"Virtual Boy",
|
||||
"Westwood Offroad Excursion Team",
|
||||
"William Sanderson",
|
||||
"Xena",
|
||||
"Zion National Park"
|
||||
};
|
||||
|
||||
KIASectionPogo::KIASectionPogo(BladeRunnerEngine *vm) : KIASectionBase(vm) {
|
||||
_stringIndex = 0;
|
||||
_timeLast = 0;
|
||||
|
||||
for (int i = 0; i < kStringCount; ++i) {
|
||||
_strings[i] = nullptr;
|
||||
}
|
||||
|
||||
for (int i = 0; i < kLineCount; ++i) {
|
||||
_lineTexts[i] = nullptr;
|
||||
_lineTimeouts[i] = 0;
|
||||
_lineOffsets[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionPogo::open() {
|
||||
_stringIndex = 0;
|
||||
for (int i = 0; i < kStringCount; ++i) {
|
||||
_strings[i] = kStrings[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < kStringCount; ++i) {
|
||||
int j = _vm->_rnd.getRandomNumberRng(i, kStringCount - 1);
|
||||
SWAP<const char *>(_strings[i], kStrings[j]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < kLineCount; ++i) {
|
||||
_lineTexts[i] = nullptr;
|
||||
_lineTimeouts[i] = _vm->_rnd.getRandomNumberRng(0, 63);
|
||||
_lineOffsets[i] = 0;
|
||||
}
|
||||
|
||||
_timeLast = _vm->_time->currentSystem();
|
||||
|
||||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxAUDLAFF1), 100, 0, 0, 50, 0);
|
||||
}
|
||||
|
||||
void KIASectionPogo::draw(Graphics::Surface &surface) {
|
||||
// Timing fixed for 60Hz by ScummVM team
|
||||
uint32 timeNow = _vm->_time->currentSystem();
|
||||
bool updateTimeout = false;
|
||||
// unsigned difference is intentional
|
||||
if (timeNow - _timeLast > (1000u / 60u)) {
|
||||
updateTimeout = true;
|
||||
_timeLast = timeNow;
|
||||
}
|
||||
|
||||
const char *title = "We 3 coders give special thanks to:";
|
||||
_vm->_mainFont->drawString(&surface, title, 313 - _vm->_mainFont->getStringWidth(title) / 2, 143, surface.w, surface.format.RGBToColor(240, 232, 192));
|
||||
|
||||
int y = 158;
|
||||
int lineTextWidth;
|
||||
for (int i = 0; i < kLineCount; ++i) {
|
||||
if (updateTimeout) {
|
||||
if (_lineTimeouts[i] > 0) {
|
||||
--_lineTimeouts[i];
|
||||
} else {
|
||||
_lineTexts[i] = _strings[_stringIndex];
|
||||
_lineTimeouts[i] = 63;
|
||||
lineTextWidth = _vm->_mainFont->getStringWidth(_lineTexts[i]);
|
||||
_lineOffsets[i] = _vm->_rnd.getRandomNumberRng(0, (306 - lineTextWidth) > 0 ? (306 - lineTextWidth) : 0) + 155;
|
||||
|
||||
_stringIndex = (_stringIndex + 1) % kStringCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (_lineTexts[i]) {
|
||||
int colorIndex = _lineTimeouts[i];
|
||||
if (colorIndex >= 32) {
|
||||
colorIndex = 63 - colorIndex;
|
||||
}
|
||||
colorIndex /= 2;
|
||||
_vm->_mainFont->drawString(&surface, _lineTexts[i], _lineOffsets[i], y, surface.w, surface.format.RGBToColor(kTextColors[colorIndex].r, kTextColors[colorIndex].g, kTextColors[colorIndex].b));
|
||||
}
|
||||
y += 10;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
55
engines/bladerunner/ui/kia_section_pogo.h
Normal file
55
engines/bladerunner/ui/kia_section_pogo.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_KIA_SECTION_POGO_H
|
||||
#define BLADERUNNER_KIA_SECTION_POGO_H
|
||||
|
||||
#include "bladerunner/color.h"
|
||||
#include "bladerunner/ui/kia_section_base.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class KIASectionPogo : public KIASectionBase {
|
||||
static const int kStringCount = 158;
|
||||
static const int kLineCount = 22;
|
||||
static const char *kStrings[];
|
||||
static const Color256 kTextColors[];
|
||||
|
||||
const char *_strings[kStringCount];
|
||||
int _stringIndex;
|
||||
|
||||
const char *_lineTexts[kLineCount];
|
||||
int _lineTimeouts[kLineCount];
|
||||
int _lineOffsets[kLineCount];
|
||||
|
||||
uint32 _timeLast;
|
||||
|
||||
public:
|
||||
KIASectionPogo(BladeRunnerEngine *vm);
|
||||
|
||||
void open() override;
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
456
engines/bladerunner/ui/kia_section_save.cpp
Normal file
456
engines/bladerunner/ui/kia_section_save.cpp
Normal file
@@ -0,0 +1,456 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/kia_section_save.h"
|
||||
|
||||
#include "bladerunner/audio_player.h"
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/font.h"
|
||||
#include "bladerunner/game_info.h"
|
||||
#include "bladerunner/savefile.h"
|
||||
#include "bladerunner/shape.h"
|
||||
#include "bladerunner/text_resource.h"
|
||||
#include "bladerunner/time.h"
|
||||
#include "bladerunner/game_constants.h"
|
||||
#include "bladerunner/ui/kia.h"
|
||||
#include "bladerunner/ui/ui_container.h"
|
||||
#include "bladerunner/ui/ui_image_picker.h"
|
||||
#include "bladerunner/ui/ui_input_box.h"
|
||||
#include "bladerunner/ui/ui_scroll_box.h"
|
||||
|
||||
#include "common/error.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
KIASectionSave::KIASectionSave(BladeRunnerEngine *vm) : KIASectionBase(vm) {
|
||||
_uiContainer = new UIContainer(_vm);
|
||||
|
||||
// There is a small area to the right of the save games list, before the scroll bar,
|
||||
// where scrolling does not work.
|
||||
// However, unlike kia_section_help, if we increase the width of the scrollable area here,
|
||||
// we would noticeably mess with the centering of the title label and the saved game names in the list.
|
||||
_scrollBox = new UIScrollBox(_vm, scrollBoxCallback, this, 1024, 0, true, Common::Rect(155, 158, 461, 346), Common::Rect(506, 160, 506, 350));
|
||||
_uiContainer->add(_scrollBox);
|
||||
|
||||
_inputBox = new UIInputBox(_vm, inputBoxCallback, this, Common::Rect(155, 367, 461, 376), SaveFileManager::kNameLength, ""); // original game has limit 41 characters
|
||||
_uiContainer->add(_inputBox);
|
||||
_inputBox->hide();
|
||||
|
||||
_buttons = new UIImagePicker(_vm, 3);
|
||||
|
||||
_timeLast = 0u;
|
||||
_timeLeft = 0u;
|
||||
|
||||
_state = kStateNormal;
|
||||
|
||||
_mouseX = 0;
|
||||
_mouseY = 0;
|
||||
|
||||
_hoveredLineId = -1;
|
||||
_displayingLineId = -1;
|
||||
_selectedLineId = -1;
|
||||
_newSaveLineId = -1;
|
||||
}
|
||||
|
||||
KIASectionSave::~KIASectionSave() {
|
||||
delete _buttons;
|
||||
|
||||
_uiContainer->clear();
|
||||
delete _inputBox;
|
||||
delete _scrollBox;
|
||||
delete _uiContainer;
|
||||
}
|
||||
|
||||
void KIASectionSave::open() {
|
||||
_scheduledSwitch = false;
|
||||
_state = kStateNormal;
|
||||
|
||||
_buttons->resetImages();
|
||||
_buttons->defineImage(
|
||||
0,
|
||||
Common::Rect(460, 366, 497, 402),
|
||||
_vm->_kia->_shapes->get(82),
|
||||
_vm->_kia->_shapes->get(83),
|
||||
_vm->_kia->_shapes->get(84),
|
||||
_vm->_textOptions->getText(22) // Save
|
||||
);
|
||||
|
||||
_scrollBox->show();
|
||||
|
||||
_saveList = SaveFileManager::list(_vm->getMetaEngine(), _vm->getTargetName());
|
||||
|
||||
bool ableToSaveGame = true;
|
||||
|
||||
_newSaveLineId = _saveList.size();
|
||||
|
||||
if (!_saveList.empty() || ableToSaveGame) {
|
||||
|
||||
_buttons->activate(onButtonHovered, nullptr, nullptr, onKSSButtonPressed, this);
|
||||
_inputBox->show();
|
||||
|
||||
_scrollBox->clearLines();
|
||||
|
||||
if (ableToSaveGame) {
|
||||
_scrollBox->addLine(_vm->_textOptions->getText(23), _newSaveLineId, 0);
|
||||
}
|
||||
|
||||
for (uint i = 0; i < _saveList.size(); ++i) {
|
||||
_scrollBox->addLine(_saveList[i].getDescription().encode(Common::kDos850), i, 0);
|
||||
}
|
||||
|
||||
if (ableToSaveGame) {
|
||||
// New save
|
||||
_selectedLineId = _newSaveLineId;
|
||||
_inputBox->setText("");
|
||||
} else {
|
||||
// Overwrite first save
|
||||
_selectedLineId = 0;
|
||||
_inputBox->setText(_saveList[_selectedLineId].getDescription());
|
||||
}
|
||||
|
||||
_scrollBox->setFlags(_selectedLineId, 8);
|
||||
}
|
||||
|
||||
_hoveredLineId = -1;
|
||||
_timeLast = _vm->_time->currentSystem();
|
||||
_timeLeft = 800u;
|
||||
}
|
||||
|
||||
void KIASectionSave::close() {
|
||||
_inputBox->hide();
|
||||
_scrollBox->hide();
|
||||
_buttons->deactivate();
|
||||
|
||||
_vm->_kia->playerReset();
|
||||
|
||||
_saveList.clear();
|
||||
}
|
||||
|
||||
void KIASectionSave::draw(Graphics::Surface &surface) {
|
||||
_vm->_kia->_shapes->get(69)->draw(surface, 501, 123);
|
||||
_buttons->draw(surface);
|
||||
|
||||
if (_state == kStateNormal) {
|
||||
const char *textChooseSlot = _vm->_textOptions->getText(24); // Choose a slot ...
|
||||
int textChooseSlotWidth = _vm->_mainFont->getStringWidth(textChooseSlot);
|
||||
_vm->_mainFont->drawString(&surface, textChooseSlot, 308 - textChooseSlotWidth / 2, 143, surface.w, surface.format.RGBToColor(240, 232, 192));
|
||||
|
||||
// Original game shows warnings/error here, but we don't have any
|
||||
|
||||
const char *textTypeName = _vm->_textOptions->getText(25); // Type a name ...
|
||||
int textTypeNameWidth = _vm->_mainFont->getStringWidth(textTypeName);
|
||||
_vm->_mainFont->drawString(&surface, textTypeName, 308 - textTypeNameWidth / 2, 352, surface.w, surface.format.RGBToColor(240, 232, 192));
|
||||
|
||||
_uiContainer->draw(surface);
|
||||
} else if (_state == kStateOverwrite) {
|
||||
surface.fillRect(Common::Rect(155, 230, 462, 239), surface.format.RGBToColor(80, 56, 32));
|
||||
|
||||
const Common::String &saveName = _saveList[_selectedLineId].getDescription();
|
||||
int saveNameWidth = _vm->_mainFont->getStringWidth(saveName);
|
||||
_vm->_mainFont->drawString(&surface, saveName, 308 - saveNameWidth / 2, 230, surface.w, surface.format.RGBToColor(232, 208, 136));
|
||||
|
||||
const char *textOverwrite = _vm->_textOptions->getText(35); // Overwrite previously saved game?
|
||||
int textOverwriteWidth = _vm->_mainFont->getStringWidth(textOverwrite);
|
||||
_vm->_mainFont->drawString(&surface, textOverwrite, 308 - textOverwriteWidth / 2, 240, surface.w, surface.format.RGBToColor(240, 232, 192));
|
||||
} else if (_state == kStateDelete) {
|
||||
surface.fillRect(Common::Rect(155, 230, 462, 239), surface.format.RGBToColor(80, 56, 32));
|
||||
|
||||
const Common::String &saveName = _saveList[_selectedLineId].getDescription();
|
||||
int saveNameWidth = _vm->_mainFont->getStringWidth(saveName); // Delete this game?
|
||||
_vm->_mainFont->drawString(&surface, saveName, 308 - saveNameWidth / 2, 230, surface.w, surface.format.RGBToColor(232, 208, 136));
|
||||
|
||||
const char *textDelete = _vm->_textOptions->getText(40);
|
||||
int textDeleteWidth = _vm->_mainFont->getStringWidth(textDelete);
|
||||
_vm->_mainFont->drawString(&surface, textDelete, 308 - textDeleteWidth / 2, 240, surface.w, surface.format.RGBToColor(240, 232, 192));
|
||||
}
|
||||
|
||||
int selectedLineId = _scrollBox->getSelectedLineData();
|
||||
|
||||
if (selectedLineId != _hoveredLineId) {
|
||||
if (selectedLineId >= 0 && selectedLineId < (int)_saveList.size() && _displayingLineId != selectedLineId) {
|
||||
if (_timeLeft == 0u) {
|
||||
SaveStateDescriptor desc = SaveFileManager::queryMetaInfos(_vm->getMetaEngine(), _vm->getTargetName(), selectedLineId);
|
||||
const Graphics::Surface *thumbnail = desc.getThumbnail();
|
||||
if (thumbnail != nullptr) {
|
||||
_vm->_kia->playImage(*thumbnail);
|
||||
_displayingLineId = selectedLineId;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_vm->_kia->playerReset();
|
||||
_timeLeft = 800u;
|
||||
_displayingLineId = -1;
|
||||
}
|
||||
_hoveredLineId = selectedLineId;
|
||||
}
|
||||
|
||||
uint32 now = _vm->_time->currentSystem();
|
||||
if (selectedLineId >= 0 && selectedLineId < (int)_saveList.size() && _displayingLineId != selectedLineId) {
|
||||
if (_timeLeft) {
|
||||
uint32 timeDiff = now - _timeLast; // unsigned difference is intentional
|
||||
if (timeDiff >= _timeLeft) {
|
||||
SaveStateDescriptor desc = SaveFileManager::queryMetaInfos(_vm->getMetaEngine(), _vm->getTargetName(), _saveList[selectedLineId].getSaveSlot());
|
||||
const Graphics::Surface *thumbnail = desc.getThumbnail();
|
||||
if (thumbnail != nullptr) {
|
||||
_vm->_kia->playImage(*thumbnail);
|
||||
_displayingLineId = selectedLineId;
|
||||
}
|
||||
} else {
|
||||
_timeLeft = (_timeLeft < timeDiff) ? 0u : (_timeLeft - timeDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_timeLast = now;
|
||||
_buttons->drawTooltip(surface, _mouseX, _mouseY);
|
||||
}
|
||||
|
||||
void KIASectionSave::handleKeyUp(const Common::KeyState &kbd) {
|
||||
if (_state == kStateNormal) {
|
||||
_uiContainer->handleKeyUp(kbd);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSave::handleKeyDown(const Common::KeyState &kbd) {
|
||||
if (_state == kStateNormal) {
|
||||
_uiContainer->handleKeyDown(kbd);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSave::handleCustomEventStop(const Common::Event &evt) {
|
||||
if (_state == kStateNormal) {
|
||||
_uiContainer->handleCustomEventStop(evt);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSave::handleCustomEventStart(const Common::Event &evt) {
|
||||
if (_state == kStateNormal) {
|
||||
// Delete a saved game entry either with Delete key or numpad's (keypad's) Del key (when Num Lock Off)
|
||||
if (_selectedLineId != _newSaveLineId
|
||||
&& evt.customType == BladeRunnerEngine::BladeRunnerEngineMappableAction::kMpDeleteSelectedSvdGame) {
|
||||
changeState(kStateDelete);
|
||||
}
|
||||
_uiContainer->handleCustomEventStart(evt);
|
||||
} else if (_state == kStateOverwrite) {
|
||||
if (evt.customType == BladeRunnerEngine::BladeRunnerEngineMappableAction::kMpConfirmDlg) {
|
||||
save();
|
||||
changeState(kStateNormal);
|
||||
}
|
||||
} else if (_state == kStateDelete) {
|
||||
if (evt.customType == BladeRunnerEngine::BladeRunnerEngineMappableAction::kMpConfirmDlg) {
|
||||
deleteSave();
|
||||
changeState(kStateNormal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSave::handleMouseMove(int mouseX, int mouseY) {
|
||||
_mouseX = mouseX;
|
||||
_mouseY = mouseY;
|
||||
|
||||
_buttons->handleMouseAction(_mouseX, _mouseY, false, false, false);
|
||||
|
||||
if (_state == kStateNormal) {
|
||||
_uiContainer->handleMouseMove(_mouseX, _mouseY);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSave::handleMouseDown(bool mainButton) {
|
||||
if (mainButton) {
|
||||
if (_state == kStateNormal) {
|
||||
_uiContainer->handleMouseDown(false);
|
||||
}
|
||||
|
||||
_buttons->handleMouseAction(_mouseX, _mouseY, true, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSave::handleMouseUp(bool mainButton) {
|
||||
if (mainButton) {
|
||||
_buttons->handleMouseAction(_mouseX, _mouseY, false, true, false);
|
||||
|
||||
if (_state == kStateNormal) {
|
||||
_uiContainer->handleMouseUp(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSave::handleMouseScroll(int direction) {
|
||||
if (_state == kStateNormal) {
|
||||
_uiContainer->handleMouseScroll(direction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KIASectionSave::scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton) {
|
||||
KIASectionSave *self = (KIASectionSave *)callbackData;
|
||||
|
||||
if (mouseButton == 0 && source == self->_scrollBox && lineData >= 0 && lineData <= (int)self->_saveList.size()) {
|
||||
self->_scrollBox->resetFlags(self->_selectedLineId, 8);
|
||||
self->_selectedLineId = lineData;
|
||||
self->_scrollBox->setFlags(self->_selectedLineId, 8);
|
||||
|
||||
if (self->_selectedLineId == self->_newSaveLineId) {
|
||||
self->_inputBox->setText("");
|
||||
} else {
|
||||
self->_inputBox->setText(self->_saveList[self->_selectedLineId].getDescription().encode(Common::kDos850));
|
||||
}
|
||||
|
||||
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxSPNBEEP3), 40, 0, 0, 50, 0);
|
||||
self->_vm->_kia->resume();
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSave::inputBoxCallback(void *callbackData, void *source) {
|
||||
KIASectionSave *self = (KIASectionSave *)callbackData;
|
||||
if (source == self->_inputBox) {
|
||||
if (self->_selectedLineId == self->_newSaveLineId) {
|
||||
self->save();
|
||||
} else {
|
||||
self->changeState(kStateOverwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSave::onButtonHovered(int buttonId, void *callbackData) {
|
||||
KIASectionSave *self = (KIASectionSave *)callbackData;
|
||||
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxTEXT3), 100, 0, 0, 50, 0);
|
||||
}
|
||||
|
||||
void KIASectionSave::onKSSButtonPressed(int buttonId, void *callbackData) {
|
||||
KIASectionSave *self = (KIASectionSave *)callbackData;
|
||||
|
||||
if (buttonId == 0) {
|
||||
if (self->_selectedLineId == self->_newSaveLineId) {
|
||||
self->save();
|
||||
} else {
|
||||
self->changeState(kStateOverwrite);
|
||||
}
|
||||
} else if (buttonId == 1) {
|
||||
self->changeState(kStateNormal);
|
||||
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxSPNBEEP6), 90, -50, -50, 50, 0);
|
||||
} else if (buttonId == 2) {
|
||||
if (self->_state == kStateOverwrite) {
|
||||
self->save();
|
||||
self->changeState(kStateNormal);
|
||||
} else if (self->_state == kStateDelete) {
|
||||
self->deleteSave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSave::changeState(State state) {
|
||||
if (_state == state)
|
||||
return;
|
||||
|
||||
_state = state;
|
||||
if (state == kStateNormal) {
|
||||
_buttons->resetImages();
|
||||
_buttons->defineImage(
|
||||
0,
|
||||
Common::Rect(460, 366, 497, 402),
|
||||
_vm->_kia->_shapes->get(82),
|
||||
_vm->_kia->_shapes->get(83),
|
||||
_vm->_kia->_shapes->get(84),
|
||||
_vm->_textOptions->getText(22) // Save
|
||||
);
|
||||
} else {
|
||||
_buttons->resetImages();
|
||||
_buttons->defineImage(
|
||||
1,
|
||||
Common::Rect(318, 260, 357, 299),
|
||||
_vm->_kia->_shapes->get(126),
|
||||
_vm->_kia->_shapes->get(127),
|
||||
_vm->_kia->_shapes->get(128),
|
||||
_vm->_textOptions->getText(38) // No
|
||||
);
|
||||
_buttons->defineImage(
|
||||
2,
|
||||
Common::Rect(258, 260, 297, 299),
|
||||
_vm->_kia->_shapes->get(129),
|
||||
_vm->_kia->_shapes->get(130),
|
||||
_vm->_kia->_shapes->get(131),
|
||||
_vm->_textOptions->getText(39) // Yes
|
||||
);
|
||||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxSPNBEEP7), 90, 0, 0, 50, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSave::save() {
|
||||
int slot = -1;
|
||||
// Do not allow empty string for saved game name
|
||||
// Note: We do allow a series of blank spaces for name, though
|
||||
// (this is the behavior in the original game).
|
||||
Common::String inpBoxTextStr = _inputBox->getText();
|
||||
if (inpBoxTextStr.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_selectedLineId < (int)_saveList.size()) {
|
||||
slot = _saveList[_selectedLineId].getSaveSlot();
|
||||
} else {
|
||||
// Find first available save slot
|
||||
int maxSlot = -1;
|
||||
for (int i = 0; i < (int)_saveList.size(); ++i) {
|
||||
maxSlot = MAX(maxSlot, _saveList[i].getSaveSlot());
|
||||
if (_saveList[i].getSaveSlot() != i) {
|
||||
slot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (slot == -1) {
|
||||
slot = maxSlot + 1;
|
||||
}
|
||||
}
|
||||
|
||||
Common::OutSaveFile *saveFile = BladeRunner::SaveFileManager::openForSaving(_vm->getTargetName(), slot);
|
||||
if (saveFile == nullptr || saveFile->err()) {
|
||||
delete saveFile;
|
||||
warning("KIASectionSave::save(): Can not open savegame file for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
BladeRunner::SaveFileHeader header;
|
||||
header._name = Common::U32String(inpBoxTextStr).encode(Common::kUtf8);
|
||||
header._playTime = _vm->getTotalPlayTime();
|
||||
|
||||
BladeRunner::SaveFileManager::writeHeader(*saveFile, header);
|
||||
|
||||
_vm->saveGame(*saveFile, &_vm->_kia->_thumbnail);
|
||||
|
||||
saveFile->finalize();
|
||||
|
||||
delete saveFile;
|
||||
|
||||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxELECBP1), 90, 0, 0, 50, 0);
|
||||
|
||||
_scheduledSwitch = true;
|
||||
}
|
||||
void KIASectionSave::deleteSave() {
|
||||
BladeRunner::SaveFileManager::remove(_vm->getTargetName(), _saveList[_selectedLineId].getSaveSlot());
|
||||
close();
|
||||
open();
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
104
engines/bladerunner/ui/kia_section_save.h
Normal file
104
engines/bladerunner/ui/kia_section_save.h
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_KIA_SECTION_SAVE_H
|
||||
#define BLADERUNNER_KIA_SECTION_SAVE_H
|
||||
|
||||
#include "bladerunner/ui/kia_section_base.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
|
||||
#include "engines/savestate.h"
|
||||
|
||||
namespace Graphics {
|
||||
struct Surface;
|
||||
}
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class UIContainer;
|
||||
class UIScrollBox;
|
||||
class UIInputBox;
|
||||
class UIImagePicker;
|
||||
|
||||
class KIASectionSave : public KIASectionBase {
|
||||
enum State {
|
||||
kStateNormal = 0,
|
||||
kStateOverwrite = 1,
|
||||
kStateDelete = 2
|
||||
};
|
||||
|
||||
UIContainer *_uiContainer;
|
||||
UIScrollBox *_scrollBox;
|
||||
UIInputBox *_inputBox;
|
||||
UIImagePicker *_buttons;
|
||||
|
||||
uint32 _timeLast;
|
||||
uint32 _timeLeft;
|
||||
|
||||
SaveStateList _saveList;
|
||||
|
||||
State _state;
|
||||
|
||||
int _mouseX;
|
||||
int _mouseY;
|
||||
|
||||
int _hoveredLineId;
|
||||
int _displayingLineId;
|
||||
int _selectedLineId;
|
||||
int _newSaveLineId;
|
||||
|
||||
public:
|
||||
KIASectionSave(BladeRunnerEngine *vm);
|
||||
~KIASectionSave() override;
|
||||
|
||||
void open() override;
|
||||
void close() override;
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
|
||||
void handleKeyUp(const Common::KeyState &kbd) override;
|
||||
void handleKeyDown(const Common::KeyState &kbd) override;
|
||||
void handleMouseMove(int mouseX, int mouseY) override;
|
||||
void handleMouseDown(bool mainButton) override;
|
||||
void handleMouseUp(bool mainButton) override;
|
||||
void handleMouseScroll(int direction) override;
|
||||
|
||||
void handleCustomEventStart(const Common::Event &evt) override;
|
||||
void handleCustomEventStop(const Common::Event &evt) override;
|
||||
private:
|
||||
static void scrollBoxCallback(void *callbackData, void *source, int lineData, int mouseButton);
|
||||
static void inputBoxCallback(void *callbackData, void *source);
|
||||
|
||||
static void onButtonHovered(int buttonId, void *callbackData);
|
||||
// NOTE: Renamed the method from onButtonPressed() to onKSSButtonPressed(),
|
||||
// since this static method hides the virtual method of KIASectionBase (which is not static and has different signature)
|
||||
static void onKSSButtonPressed(int buttonId, void *callbackData);
|
||||
|
||||
void changeState(State state);
|
||||
void save();
|
||||
void deleteSave();
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
584
engines/bladerunner/ui/kia_section_settings.cpp
Normal file
584
engines/bladerunner/ui/kia_section_settings.cpp
Normal file
@@ -0,0 +1,584 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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/shape.h"
|
||||
#include "bladerunner/subtitles.h"
|
||||
#include "bladerunner/text_resource.h"
|
||||
#include "bladerunner/ui/kia.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 "bladerunner/ui/ui_scroll_box.h"
|
||||
#include "bladerunner/ui/ui_dropdown.h"
|
||||
|
||||
#include "audio/mixer.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
const char *KIASectionSettings::kLeary = "LEARY";
|
||||
|
||||
const Color256 KIASectionSettings::kColors[] = {
|
||||
{ 0, 0, 0 }, // Black - unpressed (framing rectange)
|
||||
{ 16, 8, 8 },
|
||||
{ 32, 24, 8 },
|
||||
{ 56, 32, 16 },
|
||||
{ 72, 48, 16 },
|
||||
{ 88, 56, 24 }, // Mouse-over (framing rectange)
|
||||
{ 104, 72, 32 },
|
||||
{ 128, 80, 40 },
|
||||
{ 136, 96, 48 },
|
||||
{ 152, 112, 56 },
|
||||
{ 168, 128, 72 } // Pressed (framing rectange)
|
||||
};
|
||||
|
||||
KIASectionSettings::KIASectionSettings(BladeRunnerEngine *vm)
|
||||
: KIASectionBase(vm) {
|
||||
|
||||
_uiContainer = new UIContainer(_vm);
|
||||
|
||||
#if BLADERUNNER_ORIGINAL_SETTINGS
|
||||
_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);
|
||||
#else
|
||||
_musicVolume = new UISlider(_vm, sliderCallback, this, Common::Rect(180, 160, 460, 170), _vm->_mixer->kMaxMixerVolume, 0);
|
||||
_soundEffectVolume = new UISlider(_vm, sliderCallback, this, Common::Rect(180, 185, 460, 195), _vm->_mixer->kMaxMixerVolume, 0);
|
||||
_ambientSoundVolume = new UISlider(_vm, sliderCallback, this, Common::Rect(180, 210, 460, 220), _vm->_mixer->kMaxMixerVolume, 0);
|
||||
_speechVolume = new UISlider(_vm, sliderCallback, this, Common::Rect(180, 235, 460, 245), _vm->_mixer->kMaxMixerVolume, 0);
|
||||
#endif
|
||||
_subtitlesEnable = nullptr;
|
||||
|
||||
if (_vm->_language == Common::RU_RUS) {
|
||||
// expanded click-bounding box x-axis
|
||||
_directorsCut = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(180, 364, 436, 374), 0, false);
|
||||
if (_vm->_subtitles->isSystemActive()) {
|
||||
// moved to new line
|
||||
_subtitlesEnable = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(276, 376, 345, 386), 0, false);
|
||||
}
|
||||
} else {
|
||||
_directorsCut = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(180, 364, 270, 374), 0, false);
|
||||
if (_vm->_subtitles->isSystemActive()) {
|
||||
// moved further to the right to avoid overlap with 'Designer's Cut' in some language versions (ESP)
|
||||
_subtitlesEnable = new UICheckBox(_vm, checkBoxCallback, this, Common::Rect(311, 364, 380, 374), 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
_selectedTextLanguageStr = "";
|
||||
_selectedTextLanguageId = -1;
|
||||
_textLanguageDropdown = nullptr;
|
||||
//
|
||||
// Section commented out for 2.2.0 release since it's not ready for production
|
||||
//
|
||||
//if (_vm->_subtitles->isSystemActive()) {
|
||||
// // TODO initialize with default values or ConfMan() in open()?
|
||||
// _selectedTextLanguageStr = "";
|
||||
// _selectedTextLanguageId = -1;
|
||||
// // Put at height on top of Music setting
|
||||
// // This avoids interference and handling the case of when BLADERUNNER_ORIGINAL_SETTINGS is set
|
||||
// // (in which case the middle part of the KIA screen is filled with controls)
|
||||
// _textLanguageDropdown = new UIDropDown(_vm,
|
||||
// dropdownSelectedCallback,
|
||||
// dropdownCancelledCallback,
|
||||
// dropdownClickedTopFrameCallback,
|
||||
// this,
|
||||
// "",
|
||||
// 0,
|
||||
// 136,
|
||||
// Subtitles::kMaxLanguageSelectionNum);
|
||||
//}
|
||||
|
||||
_playerAgendaSelector = new UIImagePicker(_vm, 5);
|
||||
|
||||
_uiContainer->add(_musicVolume);
|
||||
_uiContainer->add(_soundEffectVolume);
|
||||
_uiContainer->add(_ambientSoundVolume);
|
||||
_uiContainer->add(_speechVolume);
|
||||
#if BLADERUNNER_ORIGINAL_SETTINGS
|
||||
_uiContainer->add(_gammaCorrection);
|
||||
#endif
|
||||
_uiContainer->add(_directorsCut);
|
||||
if (_vm->_subtitles->isSystemActive()) {
|
||||
_uiContainer->add(_subtitlesEnable);
|
||||
// Note: Keep _textLanguageDropdown last added to _uiContainer
|
||||
// in order to be able to set it as the only active object
|
||||
// when the language selection dropdown is shown.
|
||||
//
|
||||
// commented out for 2.2.0 release since _textLanguageDropdown is not ready for production
|
||||
//
|
||||
//_uiContainer->add(_textLanguageDropdown);
|
||||
}
|
||||
|
||||
_state = kStateNormal;
|
||||
|
||||
_mouseX = 0;
|
||||
_mouseY = 0;
|
||||
|
||||
_learyPos = 0;
|
||||
}
|
||||
|
||||
KIASectionSettings::~KIASectionSettings() {
|
||||
delete _uiContainer;
|
||||
delete _musicVolume;
|
||||
delete _soundEffectVolume;
|
||||
delete _ambientSoundVolume;
|
||||
delete _speechVolume;
|
||||
#if BLADERUNNER_ORIGINAL_SETTINGS
|
||||
delete _gammaCorrection;
|
||||
#endif
|
||||
delete _directorsCut;
|
||||
if (_vm->_subtitles->isSystemActive()) {
|
||||
//
|
||||
// commented out for 2.2.0 release since _textLanguageDropdown is not ready for production
|
||||
//
|
||||
//delete _textLanguageDropdown;
|
||||
delete _subtitlesEnable;
|
||||
}
|
||||
delete _playerAgendaSelector;
|
||||
}
|
||||
|
||||
void KIASectionSettings::open() {
|
||||
_state = kStateNormal;
|
||||
|
||||
_playerAgendaSelector->resetImages();
|
||||
|
||||
_playerAgendaSelector->defineImage(kPlayerAgendaPolite, Common::Rect(180, 290, 227, 353), nullptr, nullptr, nullptr, _vm->_textOptions->getText(30));
|
||||
_playerAgendaSelector->defineImage(kPlayerAgendaNormal, Common::Rect(238, 290, 285, 353), nullptr, nullptr, nullptr, _vm->_textOptions->getText(31));
|
||||
_playerAgendaSelector->defineImage(kPlayerAgendaSurly, Common::Rect(296, 290, 343, 353), nullptr, nullptr, nullptr, _vm->_textOptions->getText(32));
|
||||
_playerAgendaSelector->defineImage(kPlayerAgendaErratic, Common::Rect(354, 290, 401, 353), nullptr, nullptr, nullptr, _vm->_textOptions->getText(33));
|
||||
_playerAgendaSelector->defineImage(kPlayerAgendaUserChoice, Common::Rect(412, 290, 459, 353), nullptr, nullptr, nullptr, _vm->_textOptions->getText(34));
|
||||
initConversationChoices();
|
||||
_playerAgendaSelector->activate(mouseInCallback, nullptr, nullptr, mouseUpCallback, this);
|
||||
|
||||
_directorsCut->enable();
|
||||
if (_vm->_subtitles->isSystemActive()) {
|
||||
_subtitlesEnable->enable();
|
||||
//
|
||||
// commented out for 2.2.0 release since _textLanguageDropdown is not ready for production
|
||||
//
|
||||
//_textLanguageDropdown->activate();
|
||||
populateLanguageSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSettings::close() {
|
||||
_playerAgendaSelector->deactivate();
|
||||
//
|
||||
// commented out for 2.2.0 release since _textLanguageDropdown is not ready for production
|
||||
//
|
||||
//if (_vm->_subtitles->isSystemActive()) {
|
||||
// _textLanguageDropdown->deactivate();
|
||||
//}
|
||||
}
|
||||
|
||||
void KIASectionSettings::draw(Graphics::Surface &surface) {
|
||||
#if BLADERUNNER_ORIGINAL_SETTINGS
|
||||
_musicVolume->setValue(_vm->_music->getVolume());
|
||||
_soundEffectVolume->setValue(_vm->_audioPlayer->getVolume());
|
||||
_ambientSoundVolume->setValue(_vm->_ambientSounds->getVolume());
|
||||
_speechVolume->setValue(_vm->_audioSpeech->getVolume());
|
||||
_gammaCorrection->setValue(100.0f);
|
||||
#else
|
||||
_musicVolume->setValue(_vm->_mixer->getVolumeForSoundType(_vm->_mixer->kMusicSoundType));
|
||||
_soundEffectVolume->setValue(_vm->_mixer->getVolumeForSoundType(_vm->_mixer->kSFXSoundType));
|
||||
_ambientSoundVolume->setValue(_vm->_mixer->getVolumeForSoundType(_vm->_mixer->kPlainSoundType));
|
||||
_speechVolume->setValue(_vm->_mixer->getVolumeForSoundType(_vm->_mixer->kSpeechSoundType));
|
||||
#endif
|
||||
|
||||
_directorsCut->setChecked(_vm->_gameFlags->query(kFlagDirectorsCut));
|
||||
|
||||
if (_vm->_subtitles->isSystemActive()) {
|
||||
_subtitlesEnable->setChecked(_vm->isSubtitlesEnabled());
|
||||
}
|
||||
|
||||
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 *textSoft = _vm->_textOptions->getText(10);
|
||||
const char *textLoud = _vm->_textOptions->getText(11);
|
||||
const char *textDesignersCut = _vm->_textOptions->getText(18);
|
||||
#if BLADERUNNER_ORIGINAL_SETTINGS
|
||||
const char *textGammaCorrection = _vm->_textOptions->getText(7);
|
||||
const char *textDark = _vm->_textOptions->getText(14);
|
||||
const char *textLight = _vm->_textOptions->getText(15);
|
||||
#endif
|
||||
|
||||
int posConversationChoices = 320 - _vm->_mainFont->getStringWidth(textConversationChoices) / 2;
|
||||
int posMusic = 320 - _vm->_mainFont->getStringWidth(textMusic) / 2;
|
||||
int posSoundEffects = 320 - _vm->_mainFont->getStringWidth(textSoundEffects) / 2;
|
||||
int posAmbientSound = 320 - _vm->_mainFont->getStringWidth(textAmbientSound) / 2;
|
||||
int posSpeech = 320 - _vm->_mainFont->getStringWidth(textSpeech) / 2;
|
||||
int posSoft = 178 - _vm->_mainFont->getStringWidth(textSoft);
|
||||
#if BLADERUNNER_ORIGINAL_SETTINGS
|
||||
int posGammaCorrection = 320 - _vm->_mainFont->getStringWidth(textGammaCorrection) / 2;
|
||||
int posDark = 178 - _vm->_mainFont->getStringWidth(textDark);
|
||||
#endif
|
||||
|
||||
_playerAgendaSelector->draw(surface);
|
||||
|
||||
_vm->_mainFont->drawString(&surface, textConversationChoices, posConversationChoices, 280, surface.w, surface.format.RGBToColor(232, 208, 136));
|
||||
|
||||
_vm->_mainFont->drawString(&surface, textMusic, posMusic, 150, surface.w, surface.format.RGBToColor(232, 208, 136));
|
||||
_vm->_mainFont->drawString(&surface, textSoft, posSoft, 161, surface.w, surface.format.RGBToColor(216, 184, 112));
|
||||
_vm->_mainFont->drawString(&surface, textLoud, 462, 161, surface.w, surface.format.RGBToColor(216, 184, 112));
|
||||
|
||||
_vm->_mainFont->drawString(&surface, textSoundEffects, posSoundEffects, 175, surface.w, surface.format.RGBToColor(232, 208, 136));
|
||||
_vm->_mainFont->drawString(&surface, textSoft, posSoft, 186, surface.w, surface.format.RGBToColor(216, 184, 112));
|
||||
_vm->_mainFont->drawString(&surface, textLoud, 462, 186, surface.w, surface.format.RGBToColor(216, 184, 112));
|
||||
|
||||
_vm->_mainFont->drawString(&surface, textAmbientSound, posAmbientSound, 200, surface.w, surface.format.RGBToColor(232, 208, 136));
|
||||
_vm->_mainFont->drawString(&surface, textSoft, posSoft, 211, surface.w, surface.format.RGBToColor(216, 184, 112));
|
||||
_vm->_mainFont->drawString(&surface, textLoud, 462, 211, surface.w, surface.format.RGBToColor(216, 184, 112));
|
||||
|
||||
_vm->_mainFont->drawString(&surface, textSpeech, posSpeech, 225, surface.w, surface.format.RGBToColor(232, 208, 136));
|
||||
_vm->_mainFont->drawString(&surface, textSoft, posSoft, 236, surface.w, surface.format.RGBToColor(216, 184, 112));
|
||||
_vm->_mainFont->drawString(&surface, textLoud, 462, 236, surface.w, surface.format.RGBToColor(216, 184, 112));
|
||||
|
||||
#if BLADERUNNER_ORIGINAL_SETTINGS
|
||||
_vm->_mainFont->drawString(&surface, textGammaCorrection, posGammaCorrection, 250, surface.w, surface.format.RGBToColor(232, 208, 136));
|
||||
_vm->_mainFont->drawString(&surface, textDark, posDark, 261, surface.w, surface.format.RGBToColor(216, 184, 112));
|
||||
_vm->_mainFont->drawString(&surface, textLight, 462, 261, surface.w, surface.format.RGBToColor(216, 184, 112));
|
||||
#endif
|
||||
|
||||
_vm->_mainFont->drawString(&surface, textDesignersCut, 192, 365, surface.w, surface.format.RGBToColor(232, 208, 136));
|
||||
|
||||
if (_vm->_subtitles->isSystemActive()) {
|
||||
// Allow this to be loading as an extra text item in the resource for text options
|
||||
const char *subtitlesTranslation = nullptr;
|
||||
const char *languageSelectTranslation = nullptr;
|
||||
switch (_vm->_language) {
|
||||
case Common::EN_ANY:
|
||||
default:
|
||||
subtitlesTranslation = "Subtitles";
|
||||
languageSelectTranslation = "Text Language:";
|
||||
break;
|
||||
case Common::DE_DEU:
|
||||
subtitlesTranslation = "Untertitel";
|
||||
languageSelectTranslation = "Text Language:"; // TODO DEUTCH translation
|
||||
break;
|
||||
case Common::FR_FRA:
|
||||
subtitlesTranslation = "Sous-titres";
|
||||
languageSelectTranslation = "Text Language:"; // TODO FRENCH translation
|
||||
break;
|
||||
case Common::IT_ITA:
|
||||
subtitlesTranslation = "Sottotitoli";
|
||||
languageSelectTranslation = "Text Language:"; // TODO ITALIAN translation
|
||||
break;
|
||||
case Common::ES_ESP:
|
||||
// the spanish text must have accented í
|
||||
subtitlesTranslation = "Subt\xa1tulos";
|
||||
languageSelectTranslation = "Text Language:"; // TODO SPANISH translation
|
||||
break;
|
||||
case Common::RU_RUS:
|
||||
// субтитры
|
||||
if (_vm->_russianCP1251) {
|
||||
// Patched translation by Siberian Studio is using Windows-1251 encoding
|
||||
subtitlesTranslation = "\xf1\xf3\xe1\xf2\xe8\xf2\xf0\xfb";
|
||||
languageSelectTranslation = "Text Language:"; // TODO RUSSIAN translation + proper characters for encoding
|
||||
} else {
|
||||
// Original release uses custom encoding
|
||||
subtitlesTranslation = "CE,NBNHS";
|
||||
languageSelectTranslation = "Text Language:"; // TODO RUSSIAN translation + proper characters for this encoding
|
||||
}
|
||||
break;
|
||||
}
|
||||
// +2 to the max of original index of textOptions which is 41
|
||||
const char *textSubtitles = strcmp(_vm->_textOptions->getText(42), "") == 0 ? subtitlesTranslation : _vm->_textOptions->getText(42);
|
||||
const char *textLanguageSelect = strcmp(_vm->_textOptions->getText(43), "") == 0 ? languageSelectTranslation : _vm->_textOptions->getText(43);
|
||||
debug(9, "TODO: Implement _textLanguageDropdown for %s", textLanguageSelect);
|
||||
|
||||
if (_vm->_language == Common::RU_RUS) {
|
||||
// special case for Russian version, put the option in a new line to avoid overlap
|
||||
_vm->_mainFont->drawString(&surface, textSubtitles, 288, 376, surface.w, surface.format.RGBToColor(232, 208, 136));
|
||||
} else {
|
||||
// moved further to the right to avoid overlap with 'Designer's Cut' in some language versions (ESP)
|
||||
_vm->_mainFont->drawString(&surface, textSubtitles, 323, 365, surface.w, surface.format.RGBToColor(232, 208, 136));
|
||||
}
|
||||
|
||||
// Vertical Align with "Soft" label
|
||||
//
|
||||
// commented out for 2.2.0 release since _textLanguageDropdown is not ready for production
|
||||
//
|
||||
//_textLanguageDropdown->setControlLeft(posSoft);
|
||||
//_textLanguageDropdown->setLabelStr(textLanguageSelect);
|
||||
}
|
||||
|
||||
// Draw uiContainer contained objects after drawing the text on the section for music, sound, speech etc.
|
||||
_uiContainer->draw(surface);
|
||||
|
||||
_playerAgendaSelector->drawTooltip(surface, _mouseX, _mouseY);
|
||||
}
|
||||
|
||||
void KIASectionSettings::handleKeyDown(const Common::KeyState &kbd) {
|
||||
if (_state == kStateNormal) {
|
||||
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::handleMouseScroll(int direction) {
|
||||
if (_vm->_subtitles->isSystemActive() && _state == kStateLanguageSelect) {
|
||||
_uiContainer->handleMouseScroll(direction);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSettings::sliderCallback(void *callbackData, void *source) {
|
||||
KIASectionSettings *self = (KIASectionSettings *)callbackData;
|
||||
|
||||
#if BLADERUNNER_ORIGINAL_SETTINGS
|
||||
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);
|
||||
}
|
||||
#else
|
||||
if (source == self->_musicVolume) {
|
||||
ConfMan.setInt("music_volume", self->_musicVolume->_value);
|
||||
self->_vm->syncSoundSettings();
|
||||
self->_vm->_music->playSample();
|
||||
} else if (source == self->_soundEffectVolume) {
|
||||
ConfMan.setInt("sfx_volume", self->_soundEffectVolume->_value);
|
||||
self->_vm->syncSoundSettings();
|
||||
self->_vm->_audioPlayer->playSample();
|
||||
} else if (source == self->_ambientSoundVolume) {
|
||||
ConfMan.setInt("ambient_volume", self->_ambientSoundVolume->_value);
|
||||
self->_vm->syncSoundSettings();
|
||||
self->_vm->_ambientSounds->playSample();
|
||||
} else if (source == self->_speechVolume) {
|
||||
ConfMan.setInt("speech_volume", self->_speechVolume->_value);
|
||||
self->_vm->syncSoundSettings();
|
||||
self->_vm->_audioSpeech->playSample();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
} else if (self->_vm->_subtitles->isSystemActive() && source == self->_subtitlesEnable) {
|
||||
self->_vm->setSubtitlesEnabled(self->_subtitlesEnable->_isChecked);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSettings::mouseInCallback(int buttonId, void *callbackData) {
|
||||
KIASectionSettings *self = (KIASectionSettings *)callbackData;
|
||||
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxTEXT3), 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 kPlayerAgendaPolite:
|
||||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxELECBP1), 90, -30, -30, 50, 0);
|
||||
_vm->_settings->setPlayerAgenda(kPlayerAgendaPolite);
|
||||
initConversationChoices();
|
||||
break;
|
||||
case kPlayerAgendaNormal:
|
||||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxELECBP1), 90, -15, -15, 50, 0);
|
||||
_vm->_settings->setPlayerAgenda(kPlayerAgendaNormal);
|
||||
initConversationChoices();
|
||||
break;
|
||||
case kPlayerAgendaSurly:
|
||||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxELECBP1), 90, 0, 0, 50, 0);
|
||||
_vm->_settings->setPlayerAgenda(kPlayerAgendaSurly);
|
||||
initConversationChoices();
|
||||
break;
|
||||
case kPlayerAgendaErratic:
|
||||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxELECBP1), 90, 15, 15, 50, 0);
|
||||
_vm->_settings->setPlayerAgenda(kPlayerAgendaErratic);
|
||||
initConversationChoices();
|
||||
break;
|
||||
case kPlayerAgendaUserChoice:
|
||||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxELECBP1), 90, 30, 30, 50, 0);
|
||||
_vm->_settings->setPlayerAgenda(kPlayerAgendaUserChoice);
|
||||
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 == kPlayerAgendaUserChoice) {
|
||||
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 == kPlayerAgendaUserChoice) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSettings::populateLanguageSelection() {
|
||||
if (_textLanguageDropdown != nullptr) {
|
||||
_textLanguageDropdown->clearLines();
|
||||
_textLanguageDropdown->addLine("English v7 [ENG] (SCUMMVM)", 1);
|
||||
_textLanguageDropdown->addLine("French v7 [FRA] (Kwama57)", 2);
|
||||
_textLanguageDropdown->addLine("Spanish v7 [ESP] (Victor G. Fraile & GeekOb)", 3);
|
||||
_textLanguageDropdown->addLine("Greek v1 [ENG] (Praetorian)", 4);
|
||||
_textLanguageDropdown->addLine("Hebrew v1 [ENG] (Rzil)", 5);
|
||||
_textLanguageDropdown->addLine("Chinese v0 [ENG] (*)", 6);
|
||||
_textLanguageDropdown->addLine("Russian v1 [ENG] (*)", 7);
|
||||
_textLanguageDropdown->addLine("Italian v0 [ITA] (*)", 8);
|
||||
_textLanguageDropdown->addLine("Deutsch v0 [DEU] (*)", 9);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSettings::changeState(State state) {
|
||||
_state = state;
|
||||
if (state != kStateNormal) {
|
||||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxSPNBEEP7), 90, 0, 0, 50, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSettings::dropdownSelectedCallback(void *callbackData, void *source, int lineData, int mouseButton) {
|
||||
KIASectionSettings *self = (KIASectionSettings *)callbackData;
|
||||
|
||||
if (source == self->_textLanguageDropdown && lineData >= 0) {
|
||||
self->_selectedTextLanguageStr = self->_textLanguageDropdown->getLineSelectedStr();
|
||||
self->_selectedTextLanguageId = lineData;
|
||||
self->showTextSelectionDropdown(false);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSettings::dropdownCancelledCallback(void *callbackData, void *source) {
|
||||
KIASectionSettings *self = (KIASectionSettings *)callbackData;
|
||||
if (source == self->_textLanguageDropdown) {
|
||||
self->showTextSelectionDropdown(false);
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSettings::dropdownClickedTopFrameCallback(void *callbackData, void *source) {
|
||||
KIASectionSettings *self = (KIASectionSettings *)callbackData;
|
||||
|
||||
if (source == self->_textLanguageDropdown) {
|
||||
self->showTextSelectionDropdown(!self->_textLanguageDropdown->isDropDownMenuExpanded());
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSettings::showTextSelectionDropdown(bool showToggle) {
|
||||
if (showToggle) {
|
||||
// scrollable area will be expanded
|
||||
populateLanguageSelection();
|
||||
_uiContainer->setHandleSpecificNumOfTopLayers(1);
|
||||
changeState(kStateLanguageSelect);
|
||||
} else {
|
||||
// scrollable area will be collapsed
|
||||
_uiContainer->setHandleSpecificNumOfTopLayers(0);
|
||||
changeState(kStateNormal);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
110
engines/bladerunner/ui/kia_section_settings.h
Normal file
110
engines/bladerunner/ui/kia_section_settings.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_KIA_SECTION_SETTINGS_H
|
||||
#define BLADERUNNER_KIA_SECTION_SETTINGS_H
|
||||
|
||||
#include "bladerunner/bladerunner.h" // for BLADERUNNER_ORIGINAL_SETTINGS macro
|
||||
#include "bladerunner/color.h"
|
||||
#include "bladerunner/ui/kia_section_base.h"
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class BladeRunnerEngine;
|
||||
class UIContainer;
|
||||
class UICheckBox;
|
||||
class UIImagePicker;
|
||||
class UISlider;
|
||||
class UIScrollBox;
|
||||
class UIDropDown;
|
||||
|
||||
class KIASectionSettings : public KIASectionBase {
|
||||
enum State {
|
||||
kStateNormal = 0,
|
||||
kStateLanguageSelect = 1
|
||||
};
|
||||
|
||||
static const char *kLeary;
|
||||
static const Color256 kColors[];
|
||||
|
||||
UIContainer *_uiContainer;
|
||||
UISlider *_musicVolume;
|
||||
UISlider *_soundEffectVolume;
|
||||
UISlider *_speechVolume;
|
||||
UISlider *_ambientSoundVolume;
|
||||
#if BLADERUNNER_ORIGINAL_SETTINGS
|
||||
UISlider *_gammaCorrection;
|
||||
#endif
|
||||
UICheckBox *_directorsCut;
|
||||
UICheckBox *_subtitlesEnable;
|
||||
Common::String _selectedTextLanguageStr;
|
||||
int _selectedTextLanguageId;
|
||||
|
||||
UIDropDown *_textLanguageDropdown;
|
||||
UIImagePicker *_playerAgendaSelector;
|
||||
|
||||
int _mouseX;
|
||||
int _mouseY;
|
||||
|
||||
int _learyPos;
|
||||
|
||||
State _state;
|
||||
|
||||
public:
|
||||
KIASectionSettings(BladeRunnerEngine *vm);
|
||||
~KIASectionSettings() override;
|
||||
|
||||
void open() override;
|
||||
void close() override;
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
|
||||
void handleKeyDown(const Common::KeyState &kbd) override;
|
||||
void handleMouseMove(int mouseX, int mouseY) override;
|
||||
void handleMouseDown(bool mainButton) override;
|
||||
void handleMouseUp(bool mainButton) override;
|
||||
void handleMouseScroll(int direction) override;
|
||||
|
||||
void showTextSelectionDropdown(bool showToggle);
|
||||
|
||||
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);
|
||||
static void dropdownSelectedCallback(void *callbackData, void *source, int lineData, int mouseButton);
|
||||
static void dropdownCancelledCallback(void *callbackData, void *source);
|
||||
static void dropdownClickedTopFrameCallback(void *callbackData, void *source);
|
||||
|
||||
void onButtonPressed(int buttonId) override;
|
||||
|
||||
void initConversationChoices();
|
||||
void populateLanguageSelection();
|
||||
|
||||
void changeState(State state);
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
551
engines/bladerunner/ui/kia_section_suspects.cpp
Normal file
551
engines/bladerunner/ui/kia_section_suspects.cpp
Normal file
@@ -0,0 +1,551 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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_flags.h"
|
||||
#include "bladerunner/game_info.h"
|
||||
#include "bladerunner/shape.h"
|
||||
#include "bladerunner/script/kia_script.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/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, kClueCount, 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;
|
||||
for (int i = 0; i < kClueCount; ++i) {
|
||||
_acquiredClues[i].clueId = -1;
|
||||
_acquiredClues[i].actorId = -1;
|
||||
}
|
||||
|
||||
_crimeSelected = -1;
|
||||
|
||||
_suspectSelected = -1;
|
||||
_suspectPhotoShapeId = -1;
|
||||
_suspectPhotoNotUsed = -1;
|
||||
_suspectPhotoShapes = new Shapes(vm);
|
||||
_suspectsFoundCount = 0;
|
||||
_suspectsFound.resize(_vm->_gameInfo->getSuspectCount());
|
||||
_suspectsWithIdentity.resize(_vm->_gameInfo->getSuspectCount());
|
||||
}
|
||||
|
||||
KIASectionSuspects::~KIASectionSuspects() {
|
||||
delete _suspectPhotoShapes;
|
||||
|
||||
_uiContainer->clear();
|
||||
|
||||
delete _crimesScrollBox;
|
||||
delete _cluesScrollBox;
|
||||
delete _othersCheckBox;
|
||||
delete _nonReplicantCheckBox;
|
||||
delete _replicantCheckBox;
|
||||
delete _MOCheckBox;
|
||||
delete _whereaboutsCheckBox;
|
||||
delete _buttons;
|
||||
delete _uiContainer;
|
||||
}
|
||||
|
||||
void KIASectionSuspects::reset() {
|
||||
_acquiredClueCount = 0;
|
||||
_suspectsFoundCount = 0;
|
||||
_mouseX = 0;
|
||||
_mouseY = 0;
|
||||
_suspectSelected = -1;
|
||||
_crimeSelected = -1;
|
||||
_suspectPhotoShapeId = -1;
|
||||
_suspectPhotoNotUsed = -1;
|
||||
_whereaboutsFilter = true;
|
||||
_MOFilter = true;
|
||||
_replicantFilter = true;
|
||||
_nonReplicantFilter = true;
|
||||
_othersFilter = true;
|
||||
}
|
||||
|
||||
void KIASectionSuspects::open() {
|
||||
_scheduledSwitch = false;
|
||||
|
||||
_suspectPhotoShapes->load("photos.shp");
|
||||
|
||||
_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();
|
||||
|
||||
_suspectPhotoShapes->unload();
|
||||
}
|
||||
|
||||
void KIASectionSuspects::draw(Graphics::Surface &surface) {
|
||||
const char *text = nullptr;
|
||||
if (_suspectPhotoShapeId != -1) {
|
||||
_suspectPhotoShapes->get(_suspectPhotoShapeId)->draw(surface, 142, 150);
|
||||
}
|
||||
if (_suspectPhotoShapeId == 14 || _suspectPhotoShapeId == 13) {
|
||||
text = _vm->_textKIA->getText(49);
|
||||
_vm->_mainFont->drawString(&surface, text, 190 - _vm->_mainFont->getStringWidth(text) / 2, 201, surface.w, surface.format.RGBToColor(255, 255, 255));
|
||||
}
|
||||
|
||||
_whereaboutsCheckBox->setChecked(_whereaboutsFilter);
|
||||
_MOCheckBox->setChecked(_MOFilter);
|
||||
_replicantCheckBox->setChecked(_replicantFilter);
|
||||
_nonReplicantCheckBox->setChecked(_nonReplicantFilter);
|
||||
_othersCheckBox->setChecked(_othersFilter);
|
||||
|
||||
_uiContainer->draw(surface);
|
||||
|
||||
_vm->_mainFont->drawString(&surface, _vm->_textKIA->getText(0), 300, 162, surface.w, surface.format.RGBToColor(232, 240, 248));
|
||||
_vm->_mainFont->drawString(&surface, _vm->_textKIA->getText(46), 142, 248, surface.w, surface.format.RGBToColor(232, 240, 248));
|
||||
_vm->_mainFont->drawString(&surface, _vm->_textKIA->getText(47), 142, 308, surface.w, surface.format.RGBToColor(232, 240, 248));
|
||||
_vm->_mainFont->drawString(&surface, _vm->_textKIA->getText(14), 154, 319, surface.w, surface.format.RGBToColor(72, 104, 152));
|
||||
_vm->_mainFont->drawString(&surface, _vm->_textKIA->getText(15), 154, 329, surface.w, surface.format.RGBToColor(96, 120, 184));
|
||||
_vm->_mainFont->drawString(&surface, _vm->_textKIA->getText(16), 154, 339, surface.w, surface.format.RGBToColor(112, 144, 216));
|
||||
_vm->_mainFont->drawString(&surface, _vm->_textKIA->getText(17), 154, 349, surface.w, surface.format.RGBToColor(96, 120, 184));
|
||||
_vm->_mainFont->drawString(&surface, _vm->_textKIA->getText(48), 154, 359, surface.w, surface.format.RGBToColor(72, 104, 152));
|
||||
|
||||
|
||||
surface.fillRect(Common::Rect(120, 134, 250, 145), 0);
|
||||
surface.hLine(120, 133, 250, surface.format.RGBToColor(48, 40, 40));
|
||||
surface.hLine(120, 146, 250, surface.format.RGBToColor(88, 80, 96));
|
||||
surface.vLine(119, 134, 145, surface.format.RGBToColor(48, 40, 40));
|
||||
surface.vLine(251, 134, 145, surface.format.RGBToColor(88, 80, 96));
|
||||
surface.hLine(251, 146, 251, surface.format.RGBToColor(72, 64, 72));
|
||||
|
||||
Common::String generatedText;
|
||||
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()) {
|
||||
generatedText = Common::String::format("%s %s", _vm->_textKIA->getText(20), _vm->_kia->scrambleSuspectsName(suspectName));
|
||||
text = generatedText.c_str();
|
||||
} else {
|
||||
generatedText = Common::String::format("%s %s", _vm->_textKIA->getText(21), _vm->_kia->scrambleSuspectsName(suspectName));
|
||||
text = generatedText.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_mainFont->drawString(&surface, text, 185 - _vm->_mainFont->getStringWidth(text) / 2, 136, surface.w, surface.format.RGBToColor(136, 168, 248));
|
||||
|
||||
_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::handleMouseScroll(int direction) {
|
||||
_uiContainer->handleMouseScroll(direction);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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(kSfxBEEP15), 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) {
|
||||
int clueId = i;
|
||||
if (_clues->isAcquired(clueId)) {
|
||||
_acquiredClues[_acquiredClueCount].clueId = clueId;
|
||||
_acquiredClues[_acquiredClueCount].actorId = _clues->getFromActorId(clueId);
|
||||
++_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(clueId) != kClueTypeIntangible) {
|
||||
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 BLADERUNNER_ORIGINAL_BUGS
|
||||
if (_clues->isPrivate(clueId)) {
|
||||
flags = 0x08;
|
||||
} else if (_clues->isViewed(clueId)) {
|
||||
flags = 0x10;
|
||||
}
|
||||
#else
|
||||
if (_clues->isPrivate(clueId)) {
|
||||
flags |= 0x08;
|
||||
}
|
||||
if (_clues->isViewed(clueId)) {
|
||||
flags &= ~0x20;
|
||||
}
|
||||
if (_vm->_cutContent && _clues->isSharedWithMainframe(clueId)) {
|
||||
flags |= 0x40;
|
||||
}
|
||||
#endif // BLADERUNNER_ORIGINAL_BUGS
|
||||
_cluesScrollBox->addLine(_vm->_crimesDatabase->getClueText(clueId), clueId, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
_cluesScrollBox->sortLines();
|
||||
}
|
||||
}
|
||||
|
||||
void KIASectionSuspects::updateSuspectPhoto() {
|
||||
if (_suspectSelected == -1) {
|
||||
_suspectPhotoShapeId = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
SuspectDatabaseEntry *suspect = _vm->_suspectsDatabase->get(_suspectSelected);
|
||||
|
||||
_suspectPhotoShapeId = -1;
|
||||
_suspectPhotoNotUsed = -1;
|
||||
int photoCluesCount = suspect->getPhotoCount();
|
||||
if (photoCluesCount > 0) {
|
||||
for (int i = 0 ; i < photoCluesCount; ++i) {
|
||||
//TODO: weird stuff going on here... original game is using internal clue index instead id
|
||||
if (_clues->isAcquired(suspect->getPhotoClueId(i))) {
|
||||
_suspectPhotoShapeId = suspect->getPhotoShapeId(i);
|
||||
_suspectPhotoNotUsed = suspect->getPhotoNotUsed(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_suspectPhotoShapeId == -1 && _suspectPhotoNotUsed == -1) {
|
||||
if (suspect->getSex()) {
|
||||
_suspectPhotoShapeId = 14;
|
||||
} else {
|
||||
_suspectPhotoShapeId = 13;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
129
engines/bladerunner/ui/kia_section_suspects.h
Normal file
129
engines/bladerunner/ui/kia_section_suspects.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_KIA_SECTION_SUSPECTS_H
|
||||
#define BLADERUNNER_KIA_SECTION_SUSPECTS_H
|
||||
|
||||
#include "bladerunner/ui/kia_section_base.h"
|
||||
|
||||
#include "common/array.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class ActorClues;
|
||||
class BladeRunnerEngine;
|
||||
class Shapes;
|
||||
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<bool> _suspectsFound;
|
||||
Common::Array<bool> _suspectsWithIdentity;
|
||||
|
||||
int _mouseX;
|
||||
int _mouseY;
|
||||
|
||||
int _suspectPhotoShapeId;
|
||||
int _suspectPhotoNotUsed;
|
||||
Shapes *_suspectPhotoShapes;
|
||||
|
||||
public:
|
||||
int _crimeSelected;
|
||||
|
||||
public:
|
||||
KIASectionSuspects(BladeRunnerEngine *vm, ActorClues *clues);
|
||||
~KIASectionSuspects() override;
|
||||
|
||||
void reset();
|
||||
|
||||
void open() override;
|
||||
void close() override;
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
|
||||
void handleMouseMove(int mouseX, int mouseY) override;
|
||||
void handleMouseDown(bool mainButton) override;
|
||||
void handleMouseUp(bool mainButton) override;
|
||||
void handleMouseScroll(int direction) override;
|
||||
|
||||
void saveToLog();
|
||||
void loadFromLog();
|
||||
|
||||
void selectSuspect(int suspectId);
|
||||
|
||||
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) override;
|
||||
|
||||
void populateAcquiredClues();
|
||||
void populateSuspects();
|
||||
void populateCrimes();
|
||||
void populateVisibleClues();
|
||||
void updateSuspectPhoto();
|
||||
|
||||
void nextSuspect();
|
||||
void prevSuspect();
|
||||
|
||||
void enableAllFilters();
|
||||
void disableAllFilters();
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
220
engines/bladerunner/ui/scores.cpp
Normal file
220
engines/bladerunner/ui/scores.cpp
Normal file
@@ -0,0 +1,220 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/scores.h"
|
||||
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/font.h"
|
||||
#include "bladerunner/savefile.h"
|
||||
#include "bladerunner/scene.h"
|
||||
#include "bladerunner/text_resource.h"
|
||||
#include "bladerunner/time.h"
|
||||
#include "bladerunner/vqa_player.h"
|
||||
|
||||
#include "common/keyboard.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
Scores::Scores(BladeRunnerEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
_font = nullptr;
|
||||
_txtScorers = nullptr;
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
Scores::~Scores() {
|
||||
}
|
||||
|
||||
void Scores::open() {
|
||||
if (!_vm->openArchive("MODE.MIX")) {
|
||||
return;
|
||||
}
|
||||
|
||||
_vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack, "SCORE.VQA");
|
||||
|
||||
if (!_vqaPlayer->open()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_vqaPlayer->setLoop(1, -1, 0, nullptr, nullptr);
|
||||
|
||||
_vm->_time->pause();
|
||||
|
||||
_txtScorers = new TextResource(_vm);
|
||||
_txtScorers->open("SCORERS");
|
||||
|
||||
_font = Font::load(_vm, "TAHOMA24.FON", 1, true);
|
||||
|
||||
fill();
|
||||
|
||||
_isOpen = true;
|
||||
_isLoaded = false;
|
||||
}
|
||||
|
||||
bool Scores::isOpen() const {
|
||||
return _isOpen;
|
||||
}
|
||||
|
||||
void Scores::close() {
|
||||
_isOpen = false;
|
||||
|
||||
delete _font;
|
||||
_font = nullptr;
|
||||
|
||||
delete _txtScorers;
|
||||
_txtScorers = nullptr;
|
||||
|
||||
if (_vqaPlayer) {
|
||||
_vqaPlayer->close();
|
||||
delete _vqaPlayer;
|
||||
_vqaPlayer = nullptr;
|
||||
}
|
||||
|
||||
_vm->closeArchive("MODE.MIX");
|
||||
|
||||
_vm->_time->resume();
|
||||
_vm->_scene->resume();
|
||||
}
|
||||
|
||||
void Scores::set(int index, int value) {
|
||||
if (value > _scores[index]) {
|
||||
_scores[index] = value;
|
||||
}
|
||||
|
||||
_lastScoreId = index;
|
||||
_lastScoreValue = value;
|
||||
}
|
||||
|
||||
void Scores::handleCustomEventStart(const Common::Event &evt) {
|
||||
close();
|
||||
}
|
||||
|
||||
void Scores::handleKeyDown(const Common::KeyState &kbd) {
|
||||
close();
|
||||
}
|
||||
|
||||
int Scores::handleMouseUp(int x, int y) {
|
||||
if (_isLoaded) {
|
||||
close();
|
||||
}
|
||||
|
||||
_isLoaded = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int Scores::handleMouseDown(int x, int y) {
|
||||
_isLoaded = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Scores::tick() {
|
||||
if (!_vm->_windowIsActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
int frame = _vqaPlayer->update();
|
||||
assert(frame >= -1);
|
||||
|
||||
// vqaPlayer renders to _surfaceBack
|
||||
blit(_vm->_surfaceBack, _vm->_surfaceFront);
|
||||
|
||||
_vm->_surfaceFront.hLine(200, 139, 400, _vm->_surfaceFront.format.RGBToColor(0, 248, 0));
|
||||
_vm->_surfaceFront.hLine(200, 347, 400, _vm->_surfaceFront.format.RGBToColor(0, 0, 248));
|
||||
|
||||
_font->drawString(&_vm->_surfaceFront, _txtScorers->getText(7), 200, 114, _vm->_surfaceFront.w, 0);
|
||||
|
||||
int y = 140;
|
||||
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
_font->drawString(&_vm->_surfaceFront, _txtScorers->getText(_scorers[i]), 220, y, _vm->_surfaceFront.w, 0);
|
||||
_font->drawString(&_vm->_surfaceFront, Common::String::format("%d", _scores[_scorers[i]]), 360, y, _vm->_surfaceFront.w, 0);
|
||||
|
||||
y += 26;
|
||||
}
|
||||
|
||||
_font->drawString(&_vm->_surfaceFront, _txtScorers->getText(8), 200, 322, _vm->_surfaceFront.w, 0);
|
||||
_font->drawString(&_vm->_surfaceFront, _txtScorers->getText(_lastScoreId), 220, 348, _vm->_surfaceFront.w, 0);
|
||||
_font->drawString(&_vm->_surfaceFront, Common::String::format("%d", _lastScoreValue), 360, 348, _vm->_surfaceFront.w, 0);
|
||||
|
||||
_vm->blitToScreen(_vm->_surfaceFront);
|
||||
}
|
||||
|
||||
void Scores::fill() {
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
_scorers[i] = i;
|
||||
}
|
||||
|
||||
// Network sorting using Bose-Nelson Algorithm
|
||||
const byte network[32] = { // Bose-Nelson
|
||||
1,2, 3,4, 5,6,
|
||||
0,2, 3,5, 4,6,
|
||||
0,1, 4,5, 2,6,
|
||||
0,4, 1,5,
|
||||
0,3, 2,5,
|
||||
1,3, 2,4,
|
||||
2,3
|
||||
};
|
||||
|
||||
for (int i = 0; i < 32; i += 2) {
|
||||
int i1 = network[i], i2 = network[i + 1];
|
||||
if (_scores[_scorers[i1]] < _scores[_scorers[i2]]) {
|
||||
SWAP(_scorers[i1], _scorers[i2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Scores::reset() {
|
||||
_isOpen = false;
|
||||
_isLoaded = false;
|
||||
_vqaPlayer = nullptr;
|
||||
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
_scores[i] = -80;
|
||||
_scorers[i] = 0;
|
||||
}
|
||||
|
||||
_lastScoreId = 0;
|
||||
_lastScoreValue = 0;
|
||||
}
|
||||
|
||||
void Scores::save(SaveFileWriteStream &f) {
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
f.writeInt(_scores[i]);
|
||||
}
|
||||
|
||||
f.writeInt(_lastScoreId);
|
||||
f.writeInt(_lastScoreValue);
|
||||
}
|
||||
|
||||
void Scores::load(SaveFileReadStream &f) {
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
_scores[i] = f.readInt();
|
||||
}
|
||||
|
||||
_lastScoreId = f.readInt();
|
||||
_lastScoreValue = f.readInt();
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
83
engines/bladerunner/ui/scores.h
Normal file
83
engines/bladerunner/ui/scores.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_SCORES_H
|
||||
#define BLADERUNNER_SCORES_H
|
||||
|
||||
#include "common/array.h"
|
||||
|
||||
namespace Common {
|
||||
struct KeyState;
|
||||
struct Event;
|
||||
}
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class BladeRunnerEngine;
|
||||
class Font;
|
||||
class Shape;
|
||||
class SaveFileReadStream;
|
||||
class SaveFileWriteStream;
|
||||
class TextResource;
|
||||
class VQAPlayer;
|
||||
class UIImagePicker;
|
||||
|
||||
class Scores {
|
||||
BladeRunnerEngine *_vm;
|
||||
bool _isOpen;
|
||||
bool _isLoaded;
|
||||
VQAPlayer *_vqaPlayer;
|
||||
int _scores[7];
|
||||
int _scorers[7];
|
||||
|
||||
int _lastScoreId;
|
||||
int _lastScoreValue;
|
||||
|
||||
Font *_font;
|
||||
TextResource *_txtScorers;
|
||||
|
||||
public:
|
||||
Scores(BladeRunnerEngine *vm);
|
||||
~Scores();
|
||||
|
||||
void open();
|
||||
bool isOpen() const;
|
||||
void close();
|
||||
|
||||
int query(int index) { return _scores[index]; }
|
||||
void set(int index, int value);
|
||||
|
||||
void handleCustomEventStart(const Common::Event &evt);
|
||||
void handleKeyDown(const Common::KeyState &kbd);
|
||||
int handleMouseUp(int x, int y);
|
||||
int handleMouseDown(int x, int y);
|
||||
|
||||
void tick();
|
||||
void fill();
|
||||
|
||||
void reset();
|
||||
void save(SaveFileWriteStream &f);
|
||||
void load(SaveFileReadStream &f);
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
429
engines/bladerunner/ui/spinner.cpp
Normal file
429
engines/bladerunner/ui/spinner.cpp
Normal file
@@ -0,0 +1,429 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/spinner.h"
|
||||
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/actor.h"
|
||||
#include "bladerunner/audio_player.h"
|
||||
#include "bladerunner/ambient_sounds.h"
|
||||
#include "bladerunner/game_info.h"
|
||||
#include "bladerunner/subtitles.h"
|
||||
#include "bladerunner/game_constants.h"
|
||||
#include "bladerunner/mouse.h"
|
||||
#include "bladerunner/savefile.h"
|
||||
#include "bladerunner/scene.h"
|
||||
#include "bladerunner/shape.h"
|
||||
#include "bladerunner/text_resource.h"
|
||||
#include "bladerunner/time.h"
|
||||
#include "bladerunner/ui/ui_image_picker.h"
|
||||
#include "bladerunner/vqa_player.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;
|
||||
_shapes = new Shapes(vm);
|
||||
}
|
||||
|
||||
Spinner::~Spinner() {
|
||||
delete _imagePicker;
|
||||
delete _vqaPlayer;
|
||||
delete _shapes;
|
||||
reset();
|
||||
}
|
||||
|
||||
void Spinner::setSelectableDestinationFlag(int destination, bool selectable) {
|
||||
_isDestinationSelectable[destination] = selectable;
|
||||
}
|
||||
|
||||
bool Spinner::querySelectableDestinationFlag(int destination) const {
|
||||
return _isDestinationSelectable[destination];
|
||||
}
|
||||
|
||||
int Spinner::chooseDestination(int loopId, bool immediately) {
|
||||
if (_vm->_cutContent) {
|
||||
resetDescription();
|
||||
}
|
||||
_selectedDestination = 0;
|
||||
if (!_vm->openArchive("MODE.MIX")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (loopId < 0) {
|
||||
// call Spinner:open()
|
||||
open();
|
||||
} else {
|
||||
_vm->playerLosesControl();
|
||||
_vm->_scene->loopStartSpecial(kSceneLoopModeSpinner, loopId, immediately);
|
||||
while (_vm->_gameIsRunning && !_isOpen) {
|
||||
_vm->gameTick();
|
||||
}
|
||||
_vm->playerGainsControl();
|
||||
}
|
||||
|
||||
_vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack, "SPINNER.VQA");
|
||||
if (!_vqaPlayer->open()) {
|
||||
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 spinnerLoopId = 4;
|
||||
|
||||
// mapmask determines which map version will be displayed
|
||||
// Depending on which destinations are available, mapmaks will have value:
|
||||
// 1: For the near view (first chapter locations, and animoid row for some reason)
|
||||
// 3: For medium view locations (includes the near view ones)
|
||||
// 7: For far view locations (includes all the previous ones)
|
||||
// This values are determined in mapmaskv table
|
||||
//
|
||||
// Since the checks below use bitwise AND, we need to check in order
|
||||
// from the "far" version to the "near" version
|
||||
if (mapmask & 4) {
|
||||
_destinations = getDestinationsFar();
|
||||
spinnerLoopId = 4;
|
||||
} else if (mapmask & 2) {
|
||||
_destinations = getDestinationsMedium();
|
||||
spinnerLoopId = 2;
|
||||
} else if (mapmask & 1) {
|
||||
_destinations = getDestinationsNear();
|
||||
spinnerLoopId = 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
_vqaPlayer->setLoop(spinnerLoopId, -1, kLoopSetModeImmediate, nullptr, nullptr);
|
||||
_vqaPlayer->setLoop(spinnerLoopId + 1, -1, kLoopSetModeJustStart, nullptr, nullptr);
|
||||
|
||||
_shapes->load("SPINNER.SHP");
|
||||
|
||||
_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->get(dest->shapeId),
|
||||
_shapes->get(dest->shapeIdOver),
|
||||
_shapes->get(dest->shapeIdOver),
|
||||
tooltip
|
||||
);
|
||||
}
|
||||
|
||||
if (_vm->_cutContent) {
|
||||
_imagePicker->activate(
|
||||
mouseInCallback,
|
||||
mouseOutCallback,
|
||||
mouseDownCallback,
|
||||
mouseUpCallback,
|
||||
this
|
||||
);
|
||||
_vm->_actors[kActorAnsweringMachine]->speechPlay(480, false);
|
||||
_vm->_ambientSounds->addSound(kSfxSPINAMB2, 5u, 30u, 30, 45, 0, 0, -101, -101, 0, 0);
|
||||
} else {
|
||||
_imagePicker->activate(
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
mouseUpCallback,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
_vm->_time->pause();
|
||||
|
||||
_selectedDestination = -1;
|
||||
do {
|
||||
_vm->gameTick();
|
||||
} while (_vm->_gameIsRunning && _selectedDestination == -1);
|
||||
|
||||
_imagePicker->deactivate();
|
||||
|
||||
_shapes->unload();
|
||||
|
||||
delete _vqaPlayer;
|
||||
_vqaPlayer = nullptr;
|
||||
|
||||
_vm->closeArchive("MODE.MIX");
|
||||
|
||||
_isOpen = false;
|
||||
|
||||
_vm->_time->resume();
|
||||
_vm->_scene->resume();
|
||||
|
||||
if (_vm->_cutContent) {
|
||||
_vm->_ambientSounds->removeNonLoopingSound(kSfxSPINAMB2, true);
|
||||
}
|
||||
return _selectedDestination;
|
||||
}
|
||||
|
||||
// cut content
|
||||
void Spinner::mouseInCallback(int destinationImage, void *self) {
|
||||
((Spinner *)self)->destinationFocus(destinationImage);
|
||||
}
|
||||
|
||||
// cut content
|
||||
void Spinner::mouseOutCallback(int, void *self) {
|
||||
((Spinner *)self)->destinationFocus(-1);
|
||||
}
|
||||
|
||||
// cut content
|
||||
void Spinner::mouseDownCallback(int, void *self) {
|
||||
((Spinner *)self)->_vm->_audioPlayer->playAud(((Spinner *)self)->_vm->_gameInfo->getSfxTrack(kSfxSPNBEEP9), 100, 0, 0, 50, 0);
|
||||
}
|
||||
|
||||
void Spinner::mouseUpCallback(int destinationImage, void *self) {
|
||||
if (destinationImage >= 0 && destinationImage < 10) {
|
||||
((Spinner *)self)->setSelectedDestination(destinationImage);
|
||||
}
|
||||
}
|
||||
|
||||
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->_windowIsActive) {
|
||||
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);
|
||||
|
||||
if (_vm->_cutContent) {
|
||||
_vm->_subtitles->tick(_vm->_surfaceFront);
|
||||
}
|
||||
_vm->blitToScreen(_vm->_surfaceFront);
|
||||
|
||||
if (_vm->_cutContent) {
|
||||
tickDescription();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
_actorId = -1;
|
||||
_sentenceId = -1;
|
||||
_timeSpeakDescriptionStart = 0u;
|
||||
}
|
||||
|
||||
void Spinner::resume() {
|
||||
if (_vqaPlayer == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
//_vqa->clear();
|
||||
_vqaPlayer->setLoop(0, -1, kLoopSetModeImmediate, nullptr, nullptr);
|
||||
tick();
|
||||
_vqaPlayer->setLoop(1, -1, kLoopSetModeJustStart, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void Spinner::save(SaveFileWriteStream &f) {
|
||||
assert(!_isOpen);
|
||||
|
||||
for (int i = 0; i != kSpinnerDestinations; ++i) {
|
||||
f.writeBool(_isDestinationSelectable[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Spinner::load(SaveFileReadStream &f) {
|
||||
for (int i = 0; i != kSpinnerDestinations; ++i) {
|
||||
_isDestinationSelectable[i] = f.readBool();
|
||||
}
|
||||
}
|
||||
|
||||
const Spinner::Destination *Spinner::getDestinationsFar() {
|
||||
static const Destination destinations[] = {
|
||||
{ 0, Common::Rect(220, 227, 246, 262), 26 , 36 },
|
||||
{ 1, Common::Rect(260, 252, 286, 279), 27 , 37 },
|
||||
{ 2, Common::Rect(286, 178, 302, 196), 28 , 38 },
|
||||
{ 3, Common::Rect(244, 178, 263, 195), 29 , 39 },
|
||||
{ 4, Common::Rect(288, 216, 306, 228), 30 , 40 },
|
||||
{ 5, Common::Rect(249, 77, 353, 124), 31 , 41 },
|
||||
{ 6, Common::Rect(190, 127, 208, 138), 32 , 42 },
|
||||
{ 7, Common::Rect(185, 149, 206, 170), 33 , 43 },
|
||||
{ 8, Common::Rect(398, 249, 419, 268), 34 , 44 },
|
||||
{ 9, Common::Rect(390, 218, 419, 236), 35 , 45 },
|
||||
{ -1, Common::Rect(-1, -1, -1, -1), 0, 0 }
|
||||
};
|
||||
return destinations;
|
||||
}
|
||||
|
||||
const Spinner::Destination *Spinner::getDestinationsMedium() {
|
||||
static const Destination destinations[] = {
|
||||
{ 0, Common::Rect(252, 242, 279, 283), 10, 18 },
|
||||
{ 1, Common::Rect(301, 273, 328, 304), 11, 19 },
|
||||
{ 2, Common::Rect(319, 182, 336, 200), 12, 20 },
|
||||
{ 3, Common::Rect(269, 181, 293, 200), 13, 21 },
|
||||
{ 4, Common::Rect(325, 227, 345, 240), 14, 22 },
|
||||
{ 5, Common::Rect(259, 74, 380, 119), 15, 23 },
|
||||
{ 6, Common::Rect(203, 124, 224, 136), 16, 24 },
|
||||
{ 7, Common::Rect(200, 147, 222, 170), 17, 25 },
|
||||
{ -1, Common::Rect(-1,-1,-1,-1), 0, 0 }
|
||||
};
|
||||
return destinations;
|
||||
}
|
||||
|
||||
const Spinner::Destination *Spinner::getDestinationsNear() {
|
||||
static const Destination destinations[] = {
|
||||
{ 0, Common::Rect(210, 263, 263, 332), 0, 5 },
|
||||
{ 1, Common::Rect(307, 330, 361, 381), 1, 6 },
|
||||
{ 2, Common::Rect(338, 137, 362, 169), 2, 7 },
|
||||
{ 3, Common::Rect(248, 135, 289, 168), 3, 8 },
|
||||
{ 4, Common::Rect(352, 222, 379, 238), 4, 9 },
|
||||
{ -1, Common::Rect(-1,-1,-1,-1), 0, 0 }
|
||||
};
|
||||
return destinations;
|
||||
}
|
||||
|
||||
void Spinner::destinationFocus(int destinationImage) {
|
||||
// TODO 590, 600 are "Third Sector", "Fourth Sector" maybe restore those too?
|
||||
switch (destinationImage) {
|
||||
case kSpinnerDestinationPoliceStation:
|
||||
setupDescription(kActorAnsweringMachine, 500);
|
||||
break;
|
||||
case kSpinnerDestinationMcCoysApartment:
|
||||
setupDescription(kActorAnsweringMachine, 510);
|
||||
break;
|
||||
case kSpinnerDestinationRuncitersAnimals:
|
||||
setupDescription(kActorAnsweringMachine, 490);
|
||||
break;
|
||||
case kSpinnerDestinationChinatown:
|
||||
setupDescription(kActorAnsweringMachine, 520);
|
||||
break;
|
||||
case kSpinnerDestinationAnimoidRow:
|
||||
setupDescription(kActorAnsweringMachine, 550);
|
||||
break;
|
||||
case kSpinnerDestinationTyrellBuilding:
|
||||
setupDescription(kActorAnsweringMachine, 560);
|
||||
break;
|
||||
case kSpinnerDestinationDNARow:
|
||||
setupDescription(kActorAnsweringMachine, 530);
|
||||
break;
|
||||
case kSpinnerDestinationBradburyBuilding:
|
||||
setupDescription(kActorAnsweringMachine, 540);
|
||||
break;
|
||||
case kSpinnerDestinationNightclubRow:
|
||||
setupDescription(kActorAnsweringMachine, 570);
|
||||
break;
|
||||
case kSpinnerDestinationHysteriaHall:
|
||||
setupDescription(kActorAnsweringMachine, 580);
|
||||
break;
|
||||
default:
|
||||
resetDescription();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// copied from elevator.cpp code
|
||||
void Spinner::setupDescription(int actorId, int sentenceId) {
|
||||
_actorId = actorId;
|
||||
_sentenceId = sentenceId;
|
||||
_timeSpeakDescriptionStart = _vm->_time->current();
|
||||
}
|
||||
|
||||
// copied from elevator.cpp code
|
||||
void Spinner::resetDescription() {
|
||||
_actorId = -1;
|
||||
_sentenceId = -1;
|
||||
_timeSpeakDescriptionStart = 0u;
|
||||
}
|
||||
|
||||
// copied from elevator.cpp code
|
||||
void Spinner::tickDescription() {
|
||||
uint32 now = _vm->_time->current();
|
||||
// unsigned difference is intentional
|
||||
if (_actorId <= 0 || (now - _timeSpeakDescriptionStart < 600u)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_vm->_mouse->isDisabled()) {
|
||||
// mouse can still move when "disabled", so hover callbacks will work while the cursor is invisible,
|
||||
// so postpone the speech until mouse is visible again
|
||||
_vm->_actors[_actorId]->speechPlay(_sentenceId, false);
|
||||
_actorId = -1;
|
||||
_sentenceId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
100
engines/bladerunner/ui/spinner.h
Normal file
100
engines/bladerunner/ui/spinner.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_SPINNER_H
|
||||
#define BLADERUNNER_SPINNER_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class BladeRunnerEngine;
|
||||
class SaveFileReadStream;
|
||||
class SaveFileWriteStream;
|
||||
class Shapes;
|
||||
class UIImagePicker;
|
||||
class VQAPlayer;
|
||||
|
||||
class Spinner {
|
||||
static const int kSpinnerDestinations = 10;
|
||||
|
||||
struct Destination {
|
||||
int id;
|
||||
Common::Rect rect;
|
||||
int shapeId;
|
||||
int shapeIdOver;
|
||||
};
|
||||
|
||||
BladeRunnerEngine *_vm;
|
||||
bool _isDestinationSelectable[kSpinnerDestinations];
|
||||
bool _isOpen;
|
||||
VQAPlayer *_vqaPlayer;
|
||||
const Destination *_destinations;
|
||||
int _selectedDestination;
|
||||
Shapes *_shapes;
|
||||
UIImagePicker *_imagePicker;
|
||||
|
||||
int _actorId;
|
||||
int _sentenceId;
|
||||
uint32 _timeSpeakDescriptionStart;
|
||||
|
||||
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();
|
||||
|
||||
void destinationFocus(int destination);
|
||||
void setupDescription(int actorId, int sentenceId);
|
||||
void resetDescription();
|
||||
void tickDescription();
|
||||
|
||||
void save(SaveFileWriteStream &f);
|
||||
void load(SaveFileReadStream &f);
|
||||
|
||||
private:
|
||||
static void mouseInCallback(int, void *);
|
||||
static void mouseOutCallback(int, void *);
|
||||
static void mouseDownCallback(int, void *);
|
||||
static void mouseUpCallback(int, void *);
|
||||
static const Destination *getDestinationsFar();
|
||||
static const Destination *getDestinationsMedium();
|
||||
static const Destination *getDestinationsNear();
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
144
engines/bladerunner/ui/ui_check_box.cpp
Normal file
144
engines/bladerunner/ui/ui_check_box.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/ui_check_box.h"
|
||||
|
||||
#include "bladerunner/audio_player.h"
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/game_constants.h"
|
||||
#include "bladerunner/game_info.h"
|
||||
#include "bladerunner/shape.h"
|
||||
#include "bladerunner/time.h"
|
||||
#include "bladerunner/ui/kia.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 = 5u;
|
||||
} else {
|
||||
_frame = 0u;
|
||||
}
|
||||
|
||||
_timeLast = _vm->_time->currentSystem();
|
||||
_rect = rect;
|
||||
_isChecked = isChecked;
|
||||
}
|
||||
|
||||
|
||||
void UICheckBox::draw(Graphics::Surface &surface) {
|
||||
if (_rect.right > _rect.left && _rect.bottom > _rect.top) {
|
||||
uint32 shapeId;
|
||||
|
||||
uint32 timeNow = _vm->_time->currentSystem();
|
||||
// unsigned difference is intentional
|
||||
if (timeNow - _timeLast > 67u) {
|
||||
// unsigned difference is intentional
|
||||
uint32 frameDelta = (timeNow - _timeLast) / 67u;
|
||||
_timeLast = timeNow;
|
||||
|
||||
if (_isChecked) {
|
||||
_frame = MIN<uint32>(_frame + frameDelta, 5u);
|
||||
} else {
|
||||
_frame = (_frame < frameDelta) ? 0 : MAX<uint32>(_frame - frameDelta, 0u);
|
||||
}
|
||||
}
|
||||
|
||||
if (_style) {
|
||||
if (_frame || (_hasFocus && !_isPressed && _isEnabled)) {
|
||||
if (_frame != 5u || (_hasFocus && !_isPressed && _isEnabled)) {
|
||||
shapeId = _frame + 54u;
|
||||
} else {
|
||||
shapeId = 53u;
|
||||
}
|
||||
} else {
|
||||
shapeId = 52u;
|
||||
}
|
||||
} else {
|
||||
if (_frame || (_hasFocus && !_isPressed && _isEnabled)) {
|
||||
if (_frame != 5u || (_hasFocus && !_isPressed && _isEnabled)) {
|
||||
shapeId = _frame + 62u;
|
||||
} else {
|
||||
shapeId = 61u;
|
||||
}
|
||||
} else {
|
||||
shapeId = 60u;
|
||||
}
|
||||
}
|
||||
|
||||
_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(kSfxTEXT3), 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(kSfxBEEP10), 100, 0, 0, 50, 0);
|
||||
} else {
|
||||
_isPressed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UICheckBox::handleMouseUp(bool alternateButton) {
|
||||
_isPressed = false;
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
61
engines/bladerunner/ui/ui_check_box.h
Normal file
61
engines/bladerunner/ui/ui_check_box.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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 {
|
||||
UIComponentCallback *_valueChangedCallback;
|
||||
void *_callbackData;
|
||||
|
||||
int _style;
|
||||
int _isEnabled;
|
||||
Common::Rect _rect;
|
||||
uint32 _frame;
|
||||
int _isPressed;
|
||||
uint32 _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) override;
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
void setChecked(bool isChecked);
|
||||
|
||||
void handleMouseMove(int mouseX, int mouseY) override;
|
||||
void handleMouseDown(bool alternateButton) override;
|
||||
void handleMouseUp(bool alternateButton) override;
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
65
engines/bladerunner/ui/ui_component.h
Normal file
65
engines/bladerunner/ui/ui_component.h
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_UI_COMPONENT_H
|
||||
#define BLADERUNNER_UI_COMPONENT_H
|
||||
|
||||
namespace Common{
|
||||
struct KeyState;
|
||||
struct Event;
|
||||
}
|
||||
|
||||
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 handleMouseScroll(int direction) {} // Added by ScummVM team
|
||||
virtual void handleKeyUp(const Common::KeyState &kbd) {}
|
||||
virtual void handleKeyDown(const Common::KeyState &kbd) {}
|
||||
virtual void handleCustomEventStop(const Common::Event &evt) {}
|
||||
virtual void handleCustomEventStart(const Common::Event &evt) {}
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
178
engines/bladerunner/ui/ui_container.cpp
Normal file
178
engines/bladerunner/ui/ui_container.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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) {
|
||||
if (_handleSpecificNumOfTopLayers <= 0) {
|
||||
for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); ++component) {
|
||||
(*component)->handleMouseMove(mouseX, mouseY);
|
||||
}
|
||||
} else {
|
||||
int countOfTopLayersToHandle = _handleSpecificNumOfTopLayers;
|
||||
Common::Array<UIComponent*>::iterator component = _components.end();
|
||||
do {
|
||||
--component;
|
||||
--countOfTopLayersToHandle;
|
||||
(*component)->handleMouseMove(mouseX, mouseY);
|
||||
} while (component != _components.begin() && countOfTopLayersToHandle != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void UIContainer::handleMouseDown(bool alternateButton) {
|
||||
if (_handleSpecificNumOfTopLayers <= 0) {
|
||||
for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); ++component) {
|
||||
(*component)->handleMouseDown(alternateButton);
|
||||
}
|
||||
} else {
|
||||
int countOfTopLayersToHandle = _handleSpecificNumOfTopLayers;
|
||||
Common::Array<UIComponent*>::iterator component = _components.end();
|
||||
do {
|
||||
--component;
|
||||
--countOfTopLayersToHandle;
|
||||
(*component)->handleMouseDown(alternateButton);
|
||||
} while (component != _components.begin() && countOfTopLayersToHandle != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void UIContainer::handleMouseUp(bool alternateButton) {
|
||||
if (_handleSpecificNumOfTopLayers <= 0) {
|
||||
for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); ++component) {
|
||||
(*component)->handleMouseUp(alternateButton);
|
||||
}
|
||||
} else {
|
||||
int countOfTopLayersToHandle = _handleSpecificNumOfTopLayers;
|
||||
Common::Array<UIComponent*>::iterator component = _components.end();
|
||||
do {
|
||||
--component;
|
||||
--countOfTopLayersToHandle;
|
||||
(*component)->handleMouseUp(alternateButton);
|
||||
} while (component != _components.begin() && countOfTopLayersToHandle != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void UIContainer::handleMouseScroll(int direction) {
|
||||
if (_handleSpecificNumOfTopLayers <= 0) {
|
||||
for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); ++component) {
|
||||
(*component)->handleMouseScroll(direction);
|
||||
}
|
||||
} else {
|
||||
int countOfTopLayersToHandle = _handleSpecificNumOfTopLayers;
|
||||
Common::Array<UIComponent*>::iterator component = _components.end();
|
||||
do {
|
||||
--component;
|
||||
--countOfTopLayersToHandle;
|
||||
(*component)->handleMouseScroll(direction);
|
||||
} while (component != _components.begin() && countOfTopLayersToHandle != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void UIContainer::handleKeyUp(const Common::KeyState &kbd) {
|
||||
if (_handleSpecificNumOfTopLayers <= 0) {
|
||||
for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); ++component) {
|
||||
(*component)->handleKeyUp(kbd);
|
||||
}
|
||||
} else {
|
||||
int countOfTopLayersToHandle = _handleSpecificNumOfTopLayers;
|
||||
Common::Array<UIComponent*>::iterator component = _components.end();
|
||||
do {
|
||||
--component;
|
||||
--countOfTopLayersToHandle;
|
||||
(*component)->handleKeyUp(kbd);
|
||||
} while (component != _components.begin() && countOfTopLayersToHandle != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void UIContainer::handleKeyDown(const Common::KeyState &kbd) {
|
||||
if (_handleSpecificNumOfTopLayers <= 0) {
|
||||
for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); ++component) {
|
||||
(*component)->handleKeyDown(kbd);
|
||||
}
|
||||
} else {
|
||||
int countOfTopLayersToHandle = _handleSpecificNumOfTopLayers;
|
||||
Common::Array<UIComponent*>::iterator component = _components.end();
|
||||
do {
|
||||
--component;
|
||||
--countOfTopLayersToHandle;
|
||||
(*component)->handleKeyDown(kbd);
|
||||
} while (component != _components.begin() && countOfTopLayersToHandle != 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void UIContainer::handleCustomEventStop(const Common::Event &evt) {
|
||||
if (_handleSpecificNumOfTopLayers <= 0) {
|
||||
for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); ++component) {
|
||||
(*component)->handleCustomEventStop(evt);
|
||||
}
|
||||
} else {
|
||||
int countOfTopLayersToHandle = _handleSpecificNumOfTopLayers;
|
||||
Common::Array<UIComponent*>::iterator component = _components.end();
|
||||
do {
|
||||
--component;
|
||||
--countOfTopLayersToHandle;
|
||||
(*component)->handleCustomEventStop(evt);
|
||||
} while (component != _components.begin() && countOfTopLayersToHandle != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void UIContainer::handleCustomEventStart(const Common::Event &evt) {
|
||||
if (_handleSpecificNumOfTopLayers <= 0) {
|
||||
for (Common::Array<UIComponent*>::iterator component = _components.begin(); component != _components.end(); ++component) {
|
||||
(*component)->handleCustomEventStart(evt);
|
||||
}
|
||||
} else {
|
||||
int countOfTopLayersToHandle = _handleSpecificNumOfTopLayers;
|
||||
Common::Array<UIComponent*>::iterator component = _components.end();
|
||||
do {
|
||||
--component;
|
||||
--countOfTopLayersToHandle;
|
||||
(*component)->handleCustomEventStart(evt);
|
||||
} while (component != _components.begin() && countOfTopLayersToHandle != 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void UIContainer::add(UIComponent *component) {
|
||||
_components.push_back(component);
|
||||
}
|
||||
|
||||
void UIContainer::clear() {
|
||||
_components.clear();
|
||||
_handleSpecificNumOfTopLayers = 0;
|
||||
}
|
||||
|
||||
void UIContainer::setHandleSpecificNumOfTopLayers(int count) {
|
||||
_handleSpecificNumOfTopLayers = count;
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
63
engines/bladerunner/ui/ui_container.h
Normal file
63
engines/bladerunner/ui/ui_container.h
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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 {
|
||||
Common::Array<UIComponent*> _components;
|
||||
|
||||
int _handleSpecificNumOfTopLayers;
|
||||
|
||||
public:
|
||||
UIContainer(BladeRunnerEngine *vm) : UIComponent(vm) {
|
||||
_handleSpecificNumOfTopLayers = 0;
|
||||
}
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
|
||||
void handleMouseMove(int mouseX, int mouseY) override;
|
||||
void handleMouseDown(bool alternateButton) override;
|
||||
void handleMouseUp(bool alternateButton) override;
|
||||
void handleMouseScroll(int direction) override; // Added by ScummVM team
|
||||
void handleKeyUp(const Common::KeyState &kbd) override;
|
||||
void handleKeyDown(const Common::KeyState &kbd) override;
|
||||
void handleCustomEventStop(const Common::Event &evt) override;
|
||||
void handleCustomEventStart(const Common::Event &evt) override;
|
||||
|
||||
void add(UIComponent *component);
|
||||
void clear();
|
||||
|
||||
void setHandleSpecificNumOfTopLayers(int count);
|
||||
};
|
||||
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
351
engines/bladerunner/ui/ui_dropdown.cpp
Normal file
351
engines/bladerunner/ui/ui_dropdown.cpp
Normal file
@@ -0,0 +1,351 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/ui_dropdown.h"
|
||||
|
||||
#include "bladerunner/audio_player.h"
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/ui/kia.h"
|
||||
#include "bladerunner/ui/ui_image_picker.h"
|
||||
#include "bladerunner/ui/ui_scroll_box.h"
|
||||
#include "bladerunner/subtitles.h"
|
||||
#include "bladerunner/font.h"
|
||||
#include "bladerunner/game_info.h"
|
||||
#include "bladerunner/shape.h"
|
||||
#include "bladerunner/game_constants.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
const Color256 UIDropDown::kColors[] = {
|
||||
{ 0, 0, 0 }, // Black - unpressed (framing rectange)
|
||||
{ 16, 8, 8 },
|
||||
{ 32, 24, 8 },
|
||||
{ 56, 32, 16 },
|
||||
{ 72, 48, 16 },
|
||||
{ 88, 56, 24 }, // Mouse-over (framing rectange)
|
||||
{ 104, 72, 32 },
|
||||
{ 128, 80, 40 },
|
||||
{ 136, 96, 48 },
|
||||
{ 152, 112, 56 },
|
||||
{ 168, 128, 72 } // Pressed (framing rectange)
|
||||
};
|
||||
|
||||
UIDropDown::UIDropDown(BladeRunnerEngine *vm,
|
||||
UIDropDownLineSelectedCallback *ddlLineSelectedCallback,
|
||||
UIDropDownGenericCallback *ddlCancelledCallback,
|
||||
UIDropDownGenericCallback *ddlTopFrameClickCallback,
|
||||
void *callbackData,
|
||||
Common::String labelStr,
|
||||
int controlLeftX,
|
||||
int controlTopY,
|
||||
int scrollBoxMaxLineCount) : UIComponent(vm) {
|
||||
|
||||
_isVisible = false;
|
||||
|
||||
_labelStr = labelStr;
|
||||
_controlLeftX = MAX(controlLeftX, 0);
|
||||
// TODO The id should be used to eg. grab info about the selected subtitles from an engine's subtitles object
|
||||
_lineSelectedId = -1;
|
||||
|
||||
_lineSelectorFrameRectColor = 0;
|
||||
_lineSelectorFrameRectHasFocus = false;
|
||||
// A framing (outlining) rectangle to highlight the selected option field on top of the scrollbox
|
||||
controlTopY = CLIP(controlTopY, 0, 600);
|
||||
_lineSelectorFrameRect = Common::Rect(0, controlTopY, 0, controlTopY + kDropDownButtonShapeHeight);
|
||||
|
||||
// TODO This eventually should be set to a default probably by the outside caller class(kia_section_settings)
|
||||
// Current explicit assignment only serves as placeholder / proof of concept
|
||||
_lineSelectedStr = "English (SCUMMVM) v7 [ENG]";
|
||||
_lineSelectorScrollBox = new UIScrollBox(_vm, scrollBoxLineSelectCallback, this, scrollBoxMaxLineCount, 2, false, Common::Rect(0, 0, 0, 55 + kFrameRectPaddingPx), Common::Rect(0, 0, 0, 55));
|
||||
_lineSelectorScrollBoxMaxLineWidth = 0;
|
||||
|
||||
_lineDropdownBtn = new UIImagePicker(_vm, 2);
|
||||
|
||||
_ddlLineSelectedCallback = ddlLineSelectedCallback;
|
||||
_ddlCancelledCallback = ddlCancelledCallback;
|
||||
_ddlTopFrameClickCallback = ddlTopFrameClickCallback;
|
||||
_callbackData = callbackData;
|
||||
|
||||
_mouseX = 0;
|
||||
_mouseY = 0;
|
||||
}
|
||||
|
||||
UIDropDown::~UIDropDown() {
|
||||
delete _lineSelectorScrollBox;
|
||||
delete _lineDropdownBtn;
|
||||
}
|
||||
|
||||
void UIDropDown::activate() {
|
||||
_lineDropdownBtn->resetImages();
|
||||
// Actual button shape
|
||||
// defineImage actually increases internally the bottom and right bounds for the rect to be inclusive (for the contains() method)
|
||||
_lineDropdownBtn->defineImage(0, Common::Rect(0, _lineSelectorFrameRect.top + 1, kDropDownButtonShapeWidth - 1, _lineSelectorFrameRect.bottom - 1), _vm->_kia->_shapes->get(73), _vm->_kia->_shapes->get(74), _vm->_kia->_shapes->get(75), nullptr);
|
||||
// Clickable Selected/Active Line Description area
|
||||
_lineDropdownBtn->defineImage(1, Common::Rect(0, _lineSelectorFrameRect.top, kDropDownButtonShapeWidth - 1, _lineSelectorFrameRect.bottom - 1), nullptr, nullptr, nullptr, nullptr);
|
||||
_lineDropdownBtn->activate(nullptr, nullptr, mouseDownLDBCallback, nullptr, this);
|
||||
|
||||
_lineSelectorScrollBox->setBoxTop(_lineSelectorFrameRect.bottom);
|
||||
_lineSelectorScrollBox->setScrollbarTop(_lineSelectorFrameRect.bottom);
|
||||
|
||||
_lineSelectorScrollBox->hide(); // show upon click on field or dropdown button
|
||||
show();
|
||||
}
|
||||
|
||||
|
||||
void UIDropDown::deactivate() {
|
||||
_isVisible = false;
|
||||
|
||||
_lineDropdownBtn->deactivate();
|
||||
_lineSelectorScrollBox->hide();
|
||||
}
|
||||
|
||||
void UIDropDown::draw(Graphics::Surface &surface) {
|
||||
if (!_isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
int posStartOfSelectedLineDesc = _controlLeftX + _vm->_mainFont->getStringWidth(_labelStr) + _vm->_mainFont->getCharWidth(' ');
|
||||
_vm->_mainFont->drawString(&surface, _labelStr, _controlLeftX, _lineSelectorFrameRect.top, surface.w, surface.format.RGBToColor(232, 208, 136));
|
||||
_vm->_mainFont->drawString(&surface, _lineSelectedStr,
|
||||
posStartOfSelectedLineDesc,
|
||||
_lineSelectorFrameRect.top, surface.w, surface.format.RGBToColor(240, 232, 192));
|
||||
|
||||
// TODO add a clipping for description field here
|
||||
int posEndOfSelectedLineDesc = posStartOfSelectedLineDesc + _vm->_mainFont->getStringWidth(_lineSelectedStr) + _vm->_mainFont->getCharWidth(' ');
|
||||
|
||||
_lineDropdownBtn->setImageLeft(0, posEndOfSelectedLineDesc );
|
||||
|
||||
_lineDropdownBtn->setImageLeft(1, posStartOfSelectedLineDesc - kFrameRectPaddingPx);
|
||||
_lineDropdownBtn->setImageWidth(1, posEndOfSelectedLineDesc + kFrameRectPaddingPx - posStartOfSelectedLineDesc);
|
||||
|
||||
_lineDropdownBtn->draw(surface);
|
||||
// _lineDropdownBtn->drawTooltip(surface, _mouseX, _mouseY);
|
||||
|
||||
_lineSelectorFrameRect.moveTo(posStartOfSelectedLineDesc - kFrameRectPaddingPx, _lineSelectorFrameRect.top);
|
||||
_lineSelectorFrameRect.setWidth(posEndOfSelectedLineDesc + kDropDownButtonShapeWidth + kFrameRectPaddingPx - posStartOfSelectedLineDesc);
|
||||
|
||||
_lineSelectorScrollBox->draw(surface);
|
||||
|
||||
int lineSelectorFrameRectTargetColor;
|
||||
if (_lineSelectorScrollBox->isVisible()) {
|
||||
lineSelectorFrameRectTargetColor = 10;
|
||||
} else if (_lineSelectorFrameRectHasFocus) {
|
||||
lineSelectorFrameRectTargetColor = 5;
|
||||
} else {
|
||||
lineSelectorFrameRectTargetColor = 0;
|
||||
}
|
||||
|
||||
// Ensures animated transition of the frame's (outlining rectangle's) color to the new one
|
||||
if (_lineSelectorFrameRectColor < lineSelectorFrameRectTargetColor) {
|
||||
++_lineSelectorFrameRectColor;
|
||||
}
|
||||
|
||||
// Ensures animated transition of the frame's (outlining rectangle's) color to the new one
|
||||
if (_lineSelectorFrameRectColor > lineSelectorFrameRectTargetColor) {
|
||||
--_lineSelectorFrameRectColor;
|
||||
}
|
||||
surface.frameRect(_lineSelectorFrameRect,
|
||||
surface.format.RGBToColor(kColors[_lineSelectorFrameRectColor].r,
|
||||
kColors[_lineSelectorFrameRectColor].g,
|
||||
kColors[_lineSelectorFrameRectColor].b));
|
||||
}
|
||||
|
||||
void UIDropDown::show() {
|
||||
_isVisible = true;
|
||||
}
|
||||
|
||||
void UIDropDown::hide() {
|
||||
_isVisible = false;
|
||||
}
|
||||
|
||||
bool UIDropDown::isVisible() {
|
||||
return _isVisible;
|
||||
}
|
||||
|
||||
bool UIDropDown::isDropDownMenuExpanded() {
|
||||
return _lineSelectorScrollBox->isVisible();
|
||||
}
|
||||
|
||||
void UIDropDown::clearLines() {
|
||||
_lineSelectorScrollBox->clearLines();
|
||||
_lineSelectorScrollBoxMaxLineWidth = 0;
|
||||
}
|
||||
|
||||
void UIDropDown::addLine(const Common::String &text, int lineData) {
|
||||
_lineSelectorScrollBox->addLine(text, lineData, 0x08);
|
||||
_lineSelectorScrollBoxMaxLineWidth = MAX(_vm->_mainFont->getStringWidth(text), _lineSelectorScrollBoxMaxLineWidth);
|
||||
}
|
||||
|
||||
void UIDropDown::addLine(const char *text, int lineData) {
|
||||
_lineSelectorScrollBox->addLine(text, lineData, 0x08);
|
||||
_lineSelectorScrollBoxMaxLineWidth = MAX(_vm->_mainFont->getStringWidth(text), _lineSelectorScrollBoxMaxLineWidth);
|
||||
}
|
||||
|
||||
void UIDropDown::sortLines() {
|
||||
_lineSelectorScrollBox->sortLines();
|
||||
}
|
||||
|
||||
void UIDropDown::handleMouseMove(int mouseX, int mouseY) {
|
||||
if (!_isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
_mouseX = mouseX;
|
||||
_mouseY = mouseY;
|
||||
|
||||
// contains() does not include right or bottom boundary "line"
|
||||
if (_lineSelectorFrameRect.contains(mouseX, mouseY)) {
|
||||
if (!_lineSelectorFrameRectHasFocus && !_lineSelectorScrollBox->isVisible()) {
|
||||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxTEXT3), 100, 0, 0, 50, 0);
|
||||
}
|
||||
_lineSelectorFrameRectHasFocus = true;
|
||||
} else {
|
||||
_lineSelectorFrameRectHasFocus = false;
|
||||
}
|
||||
|
||||
_lineSelectorScrollBox->handleMouseMove(mouseX, mouseY);
|
||||
_lineDropdownBtn->handleMouseAction(mouseX, mouseY, false, false, false);
|
||||
}
|
||||
|
||||
void UIDropDown::handleMouseDown(bool alternateButton) {
|
||||
if (!_isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!alternateButton) {
|
||||
_lineSelectorScrollBox->handleMouseDown(false);
|
||||
_lineDropdownBtn->handleMouseAction(_mouseX, _mouseY, true, false, false);
|
||||
if (!_lineSelectorFrameRectHasFocus
|
||||
&& _lineSelectorScrollBox->isVisible()
|
||||
&& !_lineSelectorScrollBox->hasFocus()
|
||||
) {
|
||||
_ddlCancelledCallback(_callbackData, this);
|
||||
showSelectionDropdown(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIDropDown::handleMouseScroll(int direction) {
|
||||
if (!_isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_lineSelectorScrollBox->isVisible()) {
|
||||
_lineSelectorScrollBox->handleMouseScroll(direction);
|
||||
}
|
||||
}
|
||||
|
||||
void UIDropDown::handleMouseUp(bool alternateButton) {
|
||||
if (!_isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!alternateButton) {
|
||||
_lineSelectorScrollBox->handleMouseUp(false);
|
||||
_lineDropdownBtn->handleMouseAction(_mouseX, _mouseY, false, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
void UIDropDown::scrollBoxLineSelectCallback(void *callbackData, void *source, int lineData, int mouseButton) {
|
||||
UIDropDown *self = (UIDropDown *)callbackData;
|
||||
|
||||
if (source == self->_lineSelectorScrollBox && lineData >= 0) {
|
||||
Common::String selectedLangDescStr = self->_lineSelectorScrollBox->getLineText(lineData);
|
||||
self->_lineSelectedId = lineData;
|
||||
self->_lineSelectedStr = selectedLangDescStr;
|
||||
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxELECBP1), 90, 0, 0, 50, 0);
|
||||
self->_ddlLineSelectedCallback(self->_callbackData, self, lineData, mouseButton);
|
||||
self->showSelectionDropdown(false);
|
||||
//debug("text selected: %s", selectedLangDescStr.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Callback from _lineDropdownBtn items
|
||||
void UIDropDown::mouseDownLDBCallback(int buttonId, void *callbackData) {
|
||||
UIDropDown *self = (UIDropDown *)callbackData;
|
||||
self->onButtonPressed(buttonId);
|
||||
}
|
||||
|
||||
void UIDropDown::onButtonPressed(int buttonId) {
|
||||
switch (buttonId) {
|
||||
case 0:
|
||||
// Pressed DDL dropdown button (0)
|
||||
// fall through
|
||||
case 1:
|
||||
// if (buttonId == 1) {
|
||||
// // Pressed DDL clickable area (1)
|
||||
// debug("Pressed DDL clickable area (1)");
|
||||
// }
|
||||
_ddlTopFrameClickCallback(_callbackData, this);
|
||||
showSelectionDropdown(!_lineSelectorScrollBox->isVisible());
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void UIDropDown::showSelectionDropdown(bool showToggle) {
|
||||
int prevDropdownBtnLeft = _lineDropdownBtn->getImageLeft(0);
|
||||
if (showToggle) {
|
||||
_lineSelectorScrollBox->setBoxTop(_lineSelectorFrameRect.bottom);
|
||||
_lineSelectorScrollBox->setBoxLeft(_lineDropdownBtn->getImageLeft(1));
|
||||
// TODO width should be retrieved from the maximum width of a language description in SUBTITLES.MIX (or a max width to clip to)
|
||||
_lineSelectorScrollBox->setBoxWidth(MAX(_lineDropdownBtn->getImageWidth(1), _lineSelectorScrollBoxMaxLineWidth + _vm->_mainFont->getCharWidth(' ')));
|
||||
|
||||
if (_lineDropdownBtn->getImageLeft(0) < kFurthestLeftForScrollBar) {
|
||||
// CLIP expects the first boundary argument to be the min of the two.
|
||||
_lineSelectorScrollBox->setScrollbarLeft(CLIP( _lineSelectorScrollBox->getBoxLeft() + _lineSelectorScrollBox->getBoxWidth(), _lineDropdownBtn->getImageLeft(0), kFurthestLeftForScrollBar));
|
||||
} else {
|
||||
_lineSelectorScrollBox->setScrollbarLeft(MAX( _lineSelectorScrollBox->getBoxLeft() + _lineSelectorScrollBox->getBoxWidth(), kFurthestLeftForScrollBar));
|
||||
}
|
||||
|
||||
_lineSelectorScrollBox->setScrollbarTop(_lineSelectorFrameRect.bottom);
|
||||
_lineSelectorScrollBox->setScrollbarWidth(kDropDownButtonShapeWidth);
|
||||
_lineSelectorScrollBox->show();
|
||||
// change dropdown button icon too
|
||||
_lineDropdownBtn->resetActiveImage(0);
|
||||
_lineDropdownBtn->defineImage(0, Common::Rect(prevDropdownBtnLeft, _lineSelectorFrameRect.top + 1, prevDropdownBtnLeft + kDropDownButtonShapeWidth - 1, _lineSelectorFrameRect.bottom - 1), _vm->_kia->_shapes->get(70), _vm->_kia->_shapes->get(71), _vm->_kia->_shapes->get(72), nullptr);
|
||||
_lineSelectorFrameRectColor = 10;
|
||||
} else {
|
||||
// hide scrollable area
|
||||
_lineSelectorScrollBox->hide();
|
||||
// change dropdown button icon too
|
||||
_lineDropdownBtn->resetActiveImage(0);
|
||||
_lineDropdownBtn->defineImage(0, Common::Rect(prevDropdownBtnLeft, _lineSelectorFrameRect.top + 1, prevDropdownBtnLeft + kDropDownButtonShapeWidth - 1, _lineSelectorFrameRect.bottom - 1), _vm->_kia->_shapes->get(73), _vm->_kia->_shapes->get(74), _vm->_kia->_shapes->get(75), nullptr);
|
||||
_lineSelectorFrameRectColor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void UIDropDown::setLabelStr(Common::String newLabel) {
|
||||
_labelStr = newLabel;
|
||||
}
|
||||
|
||||
void UIDropDown::setControlLeft(int controlLeftX) {
|
||||
_controlLeftX = controlLeftX;
|
||||
}
|
||||
|
||||
Common::String UIDropDown::getLineSelectedStr() {
|
||||
return _lineSelectedStr;
|
||||
}
|
||||
|
||||
}
|
||||
123
engines/bladerunner/ui/ui_dropdown.h
Normal file
123
engines/bladerunner/ui/ui_dropdown.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_UI_DROPDOWN_H
|
||||
#define BLADERUNNER_UI_DROPDOWN_H
|
||||
|
||||
#include "bladerunner/color.h"
|
||||
#include "bladerunner/ui/ui_component.h"
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class BladeRunnerEngine;
|
||||
class UIImagePicker;
|
||||
class UIScrollBox;
|
||||
|
||||
typedef void UIDropDownLineSelectedCallback(void *callbackData, void *source, int data, int mouseButton);
|
||||
typedef void UIDropDownGenericCallback(void *callbackData, void *source);
|
||||
|
||||
class UIDropDown : public UIComponent {
|
||||
|
||||
static const int kDropDownButtonShapeWidth = 15;
|
||||
static const int kDropDownButtonShapeHeight = 10;
|
||||
static const uint8 kFrameRectPaddingPx = 2;
|
||||
static const int kFurthestLeftForScrollBar = 495;
|
||||
|
||||
static const Color256 kColors[];
|
||||
|
||||
int _controlLeftX;
|
||||
Common::String _labelStr;
|
||||
|
||||
bool _isVisible;
|
||||
|
||||
int _lineSelectedId;
|
||||
Common::String _lineSelectedStr;
|
||||
UIScrollBox *_lineSelectorScrollBox;
|
||||
UIImagePicker *_lineDropdownBtn;
|
||||
//int _lineDropdownBtnTopY;
|
||||
//int _lineDropdownBtnHeight;
|
||||
|
||||
Common::Rect _lineSelectorFrameRect;
|
||||
int _lineSelectorFrameRectColor;
|
||||
bool _lineSelectorFrameRectHasFocus;
|
||||
int _lineSelectorScrollBoxMaxLineWidth;
|
||||
|
||||
UIDropDownLineSelectedCallback *_ddlLineSelectedCallback;
|
||||
UIDropDownGenericCallback *_ddlCancelledCallback;
|
||||
UIDropDownGenericCallback *_ddlTopFrameClickCallback;
|
||||
void *_callbackData;
|
||||
|
||||
int _mouseX;
|
||||
int _mouseY;
|
||||
|
||||
public:
|
||||
UIDropDown(BladeRunnerEngine *vm, UIDropDownLineSelectedCallback *ddlLineSelectedCallback,
|
||||
UIDropDownGenericCallback *ddlCancelledCallback,
|
||||
UIDropDownGenericCallback *ddlTopFrameClickCallback,
|
||||
void *callbackData,
|
||||
Common::String labelStr,
|
||||
int controlLeftX,
|
||||
int controlTopY,
|
||||
int scrollBoxMaxLineCount);
|
||||
~UIDropDown() override;
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
|
||||
void handleMouseMove(int mouseX, int mouseY) override;
|
||||
void handleMouseDown(bool alternateButton) override;
|
||||
void handleMouseUp(bool alternateButton) override;
|
||||
void handleMouseScroll(int direction) override;
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
bool isVisible();
|
||||
bool isDropDownMenuExpanded();
|
||||
|
||||
void activate();
|
||||
void deactivate();
|
||||
|
||||
void clearLines();
|
||||
void addLine(const Common::String &text, int lineData);
|
||||
void addLine(const char *text, int lineData);
|
||||
|
||||
void sortLines();
|
||||
|
||||
void setLabelStr(Common::String newLabel);
|
||||
void setControlLeft(int controlLeftX);
|
||||
|
||||
Common::String getLineSelectedStr();
|
||||
|
||||
private:
|
||||
static void mouseDownLDBCallback(int buttonId, void *callbackData);
|
||||
static void scrollBoxLineSelectCallback(void *callbackData, void *source, int lineData, int mouseButton);
|
||||
|
||||
void onButtonPressed(int buttonId);
|
||||
|
||||
void showSelectionDropdown(bool showToggle);
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
409
engines/bladerunner/ui/ui_image_picker.cpp
Normal file
409
engines/bladerunner/ui/ui_image_picker.cpp
Normal file
@@ -0,0 +1,409 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/ui_image_picker.h"
|
||||
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/debugger.h"
|
||||
#include "bladerunner/font.h"
|
||||
#include "bladerunner/mouse.h"
|
||||
#include "bladerunner/shape.h"
|
||||
#include "bladerunner/time.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);
|
||||
++(img.rect.bottom);
|
||||
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::setImageWidth(int i, int16 width) {
|
||||
if (i < 0 || i >= _imageCount || !_images[i].active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Image &img = _images[i];
|
||||
|
||||
img.rect.setWidth(width);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (tooltip != nullptr) {
|
||||
_images[i].tooltip = tooltip;
|
||||
} else {
|
||||
_images[i].tooltip.clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int UIImagePicker::getImageTop(int i) {
|
||||
if (i < 0 || i >= _imageCount || !_images[i].active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Image &img = _images[i];
|
||||
|
||||
return img.rect.top;
|
||||
}
|
||||
|
||||
int UIImagePicker::getImageLeft(int i) {
|
||||
if (i < 0 || i >= _imageCount || !_images[i].active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Image &img = _images[i];
|
||||
|
||||
return img.rect.left;
|
||||
}
|
||||
|
||||
int UIImagePicker::getImageWidth(int i) {
|
||||
if (i < 0 || i >= _imageCount || !_images[i].active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Image &img = _images[i];
|
||||
|
||||
return img.rect.width();
|
||||
}
|
||||
|
||||
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 = 0u;
|
||||
_isVisible = true;
|
||||
_hoveredImageIndex = -1;
|
||||
_pressedImageIndex = -1;
|
||||
}
|
||||
|
||||
void UIImagePicker::deactivate() {
|
||||
_isButtonDown = false;
|
||||
_mouseInCallback = nullptr;
|
||||
_mouseOutCallback = nullptr;
|
||||
_mouseDownCallback = nullptr;
|
||||
_mouseUpCallback = nullptr;
|
||||
_callbackData = nullptr;
|
||||
_hoverStartTimestamp = 0u;
|
||||
_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;
|
||||
}
|
||||
|
||||
if (i == _hoveredImageIndex && i == _pressedImageIndex && _isButtonDown
|
||||
&& !_vm->_mouse->isDisabled()
|
||||
&& img.shapeDown) {
|
||||
img.shapeDown->draw(surface, img.rect.left, img.rect.top);
|
||||
} else if (i == _hoveredImageIndex && !_isButtonDown
|
||||
&& !_vm->_mouse->isDisabled()
|
||||
&& img.shapeHovered) {
|
||||
img.shapeHovered->draw(surface, img.rect.left, img.rect.top);
|
||||
} else {
|
||||
// this shape should always be the fall back shape to prevent blinking
|
||||
if (img.shapeUp) {
|
||||
img.shapeUp->draw(surface, img.rect.left, img.rect.top);
|
||||
}
|
||||
}
|
||||
|
||||
if (_vm->_debugger->_viewUI) {
|
||||
surface.frameRect(img.rect, surface.format.RGBToColor(255, 255, 255));
|
||||
_vm->_mainFont->drawString(&surface, Common::String::format("%d", i), (img.rect.left + img.rect.right) / 2, (img.rect.top + img.rect.bottom) / 2, surface.w, surface.format.RGBToColor(255, 255, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIImagePicker::drawTooltip(Graphics::Surface &surface, int x, int y) {
|
||||
if (!_isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
(_hoveredImageIndex == -1) ||
|
||||
(_vm->_mouse->isDisabled()) ||
|
||||
(!_images[_hoveredImageIndex].active) ||
|
||||
(_vm->_time->current() - _hoverStartTimestamp < 1000u)
|
||||
) { // unsigned difference is intentional (time difference)
|
||||
return;
|
||||
}
|
||||
|
||||
Common::String &tooltip = _images[_hoveredImageIndex].tooltip;
|
||||
|
||||
if (tooltip.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int width = _vm->_mainFont->getStringWidth(tooltip) + 1;
|
||||
int height = _vm->_mainFont->getFontHeight() + 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 >= BladeRunnerEngine::kOriginalGameWidth) {
|
||||
rect.right = BladeRunnerEngine::kOriginalGameWidth - 1;
|
||||
rect.left = BladeRunnerEngine::kOriginalGameWidth - 4 - width;
|
||||
if (rect.left < 0) rect.left = 0; // should never happen
|
||||
if (rect.right < 0) rect.right = 0; // should never happen
|
||||
}
|
||||
|
||||
rect.bottom = height + rect.top + 2;
|
||||
if (rect.bottom >= BladeRunnerEngine::kOriginalGameHeight) {
|
||||
rect.bottom = BladeRunnerEngine::kOriginalGameHeight - 1;
|
||||
rect.top = BladeRunnerEngine::kOriginalGameHeight - 3 - height;
|
||||
if (rect.top < 0) rect.top = 0; // should never happen
|
||||
if (rect.bottom < 0) rect.bottom = 0; // should never happen
|
||||
}
|
||||
|
||||
surface.fillRect(rect, surface.format.RGBToColor(0, 0, 0));
|
||||
surface.frameRect(rect, surface.format.RGBToColor(255, 255, 255));
|
||||
_vm->_mainFont->drawString(&surface, tooltip, rect.left + 2, rect.top, surface.w, surface.format.RGBToColor(255, 255, 255));
|
||||
}
|
||||
|
||||
bool UIImagePicker::handleMouseAction(int x, int y, bool down, bool up, bool ignore) {
|
||||
if (!_isVisible || ignore) {
|
||||
return false;
|
||||
}
|
||||
bool actionHandled = false;
|
||||
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->_time->current();
|
||||
_hoveredImageIndex = hoveredImageIndex;
|
||||
}
|
||||
|
||||
// If mouse button changed to pressed
|
||||
if (down && !_isButtonDown) {
|
||||
_isButtonDown = true;
|
||||
_pressedImageIndex = _hoveredImageIndex;
|
||||
if (_hoveredImageIndex != -1) {
|
||||
if (_mouseDownCallback) {
|
||||
_mouseDownCallback(_hoveredImageIndex, _callbackData);
|
||||
actionHandled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If mouse button changed to released
|
||||
if (up) {
|
||||
if (_isButtonDown) {
|
||||
if (_hoveredImageIndex == _pressedImageIndex && _pressedImageIndex != -1) {
|
||||
if (_mouseUpCallback) {
|
||||
_mouseUpCallback(_hoveredImageIndex, _callbackData);
|
||||
actionHandled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
_isButtonDown = false;
|
||||
_pressedImageIndex = -1;
|
||||
}
|
||||
|
||||
return actionHandled;
|
||||
}
|
||||
|
||||
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() {
|
||||
_isVisible = false;
|
||||
_hoveredImageIndex = -1;
|
||||
_pressedImageIndex = -1;
|
||||
_hoverStartTimestamp = 0u;
|
||||
_isButtonDown = false;
|
||||
_mouseInCallback = nullptr;
|
||||
_mouseOutCallback = nullptr;
|
||||
_mouseDownCallback = nullptr;
|
||||
_mouseUpCallback = nullptr;
|
||||
_callbackData = nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
108
engines/bladerunner/ui/ui_image_picker.h
Normal file
108
engines/bladerunner/ui/ui_image_picker.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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 setImageWidth(int i, int16 width);
|
||||
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);
|
||||
|
||||
int getImageTop(int i);
|
||||
int getImageLeft(int i);
|
||||
int getImageWidth(int i);
|
||||
|
||||
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);
|
||||
|
||||
bool 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
|
||||
154
engines/bladerunner/ui/ui_input_box.cpp
Normal file
154
engines/bladerunner/ui/ui_input_box.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/ui_input_box.h"
|
||||
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/font.h"
|
||||
#include "bladerunner/time.h"
|
||||
|
||||
#include "common/keyboard.h"
|
||||
#include "common/system.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;
|
||||
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
|
||||
|
||||
_maxLength = maxLength;
|
||||
setText(text);
|
||||
|
||||
_cursorIsVisible = false;
|
||||
_timeLast = _vm->_time->currentSystem();
|
||||
}
|
||||
|
||||
void UIInputBox::draw(Graphics::Surface &surface) {
|
||||
if (!_isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
int rectHalfWidth = (_rect.right + _rect.left) / 2;
|
||||
int textHalfWidth = _vm->_mainFont->getStringWidth(_text) / 2;
|
||||
|
||||
_vm->_mainFont->drawString(&surface, _text, rectHalfWidth - textHalfWidth, _rect.top, surface.w, surface.format.RGBToColor(152, 112, 56));
|
||||
|
||||
if (_cursorIsVisible) {
|
||||
surface.vLine(textHalfWidth + rectHalfWidth + 2, _rect.top, _rect.bottom - 1, surface.format.RGBToColor(248, 240, 232));
|
||||
}
|
||||
|
||||
if (_vm->_time->currentSystem() - _timeLast > 500) {
|
||||
_timeLast = _vm->_time->currentSystem();
|
||||
_cursorIsVisible = !_cursorIsVisible;
|
||||
}
|
||||
}
|
||||
|
||||
void UIInputBox::setText(const Common::String &text) {
|
||||
_text = text;
|
||||
}
|
||||
|
||||
const Common::String &UIInputBox::getText() {
|
||||
return _text;
|
||||
}
|
||||
|
||||
void UIInputBox::show() {
|
||||
_isVisible = true;
|
||||
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
|
||||
}
|
||||
|
||||
void UIInputBox::hide() {
|
||||
_isVisible = false;
|
||||
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
|
||||
}
|
||||
|
||||
void UIInputBox::handleKeyDown(const Common::KeyState &kbd) {
|
||||
if (_isVisible) {
|
||||
uint8 kc = 0;
|
||||
if (getValidChar(kbd.ascii, kc) && _text.size() < _maxLength) {
|
||||
_text += kc;
|
||||
} else if (kbd.keycode == Common::KEYCODE_BACKSPACE) {
|
||||
_text.deleteLastChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIInputBox::handleCustomEventStart(const Common::Event &evt) {
|
||||
if (_isVisible
|
||||
&& evt.customType == BladeRunnerEngine::BladeRunnerEngineMappableAction::kMpConfirmDlg
|
||||
&& !_text.empty()
|
||||
&& _valueChangedCallback) {
|
||||
_valueChangedCallback(_callbackData, this);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIInputBox::getValidChar(const uint16 &kAscii16bit, uint8 &targetAscii) {
|
||||
if (kAscii16bit != 0) {
|
||||
// The above check for kAscii16bit > 0 gets rid of the tentative warning:
|
||||
// "Adding \0 to String. This is permitted, but can have unwanted consequences."
|
||||
// which was triggered by the .encode(Common::kDos850) operation below.
|
||||
//
|
||||
// The values that the KeyState::ascii field receives from the SDL backend are actually ISO 8859-1 encoded. They need to be
|
||||
// reencoded to DOS so as to match the game font encoding (although we currently use UIInputBox::charIsValid() to block most
|
||||
// extra characters, so it might not make much of a difference).
|
||||
targetAscii = (uint8)(Common::U32String(Common::String::format("%c", kAscii16bit), Common::kISO8859_1).encode(Common::kDos850).firstChar());
|
||||
return charIsValid(targetAscii);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIInputBox::charIsValid(const uint8 &kc) {
|
||||
// The in-game font for text input is KIA6PT which follows IBM PC Code page 437 (CCSID 437)
|
||||
// This code page is identical to Code page 850 for the first 128 codes.
|
||||
// This method is:
|
||||
// 1) Filtering out characters not allowed in a DOS filename.
|
||||
// Note, however, that it does allow ',', '.', ';', '=', '[' and ']'
|
||||
// TODO Is that a bug?
|
||||
// 2) Allowing codes for glyphs that exist in KIA6PT up to code 0xA8 (glyph '¿')
|
||||
// and also the extra codes for 0xAD (glyph '¡') and 0xE1 (glyph 'ß')
|
||||
// (in order for these extra extended ASCII codes to be included,
|
||||
// the comparisons in the return clause should be between uint values).
|
||||
// 3) Additionally disallows the '\x7F' character which caused a glyph '⊐' to be printed
|
||||
// when the Delete key was pressed with no saved game selected,
|
||||
// ie. the highlighted line on the KIA save screen is "<< NEW SLOT >>".
|
||||
// The original does not show this glyph either but seems to filter the key earlier (not in this method).
|
||||
// It's more effective to completely block the glyph in this method, though.
|
||||
return kc >= ' '
|
||||
&& kc != '<'
|
||||
&& kc != '>'
|
||||
&& kc != ':'
|
||||
&& kc != '"'
|
||||
&& kc != '/'
|
||||
&& kc != '\\'
|
||||
&& kc != '|'
|
||||
&& kc != '?'
|
||||
&& kc != '*'
|
||||
&& kc != (uint8)'\x7F'
|
||||
&& (kc <= (uint8)'\xA8' || kc == (uint8)'\xAD' || kc == (uint8)'\xE1');
|
||||
}
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
67
engines/bladerunner/ui/ui_input_box.h
Normal file
67
engines/bladerunner/ui/ui_input_box.h
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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 {
|
||||
UIComponentCallback *_valueChangedCallback;
|
||||
void *_callbackData;
|
||||
|
||||
bool _isVisible;
|
||||
Common::Rect _rect;
|
||||
|
||||
uint _maxLength;
|
||||
Common::String _text;
|
||||
|
||||
bool _cursorIsVisible;
|
||||
|
||||
uint32 _timeLast;
|
||||
|
||||
public:
|
||||
UIInputBox(BladeRunnerEngine *vm, UIComponentCallback *valueChangedCallback, void *callbackData, Common::Rect rect, int maxLength, const Common::String &text);
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
|
||||
void setText(const Common::String &text);
|
||||
const Common::String &getText();
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
|
||||
void handleKeyDown(const Common::KeyState &kbd) override;
|
||||
void handleCustomEventStart(const Common::Event &evt) override;
|
||||
|
||||
private:
|
||||
bool getValidChar(const uint16 &kc16bit, uint8 &kc8bit);
|
||||
bool charIsValid(const uint8 &kc16bit);
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
824
engines/bladerunner/ui/ui_scroll_box.cpp
Normal file
824
engines/bladerunner/ui/ui_scroll_box.cpp
Normal file
@@ -0,0 +1,824 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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/time.h"
|
||||
#include "bladerunner/game_constants.h"
|
||||
#include "bladerunner/ui/kia.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
const Color256 UIScrollBox::k3DFrameColors[] = {
|
||||
{ 32, 32, 24 },
|
||||
{ 40, 40, 40 },
|
||||
{ 40, 40, 48 },
|
||||
{ 72, 64, 64 },
|
||||
{ 160, 136, 128 },
|
||||
{ 160, 136, 128 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
const Color256 UIScrollBox::kTextBackgroundColors[] = {
|
||||
{ 40, 56, 80 },
|
||||
{ 48, 64, 96 },
|
||||
{ 56, 72, 112 },
|
||||
{ 72, 88, 128 },
|
||||
{ 152, 192, 248 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
const Color256 UIScrollBox::kTextColors1[] = {
|
||||
{ 72, 104, 152 },
|
||||
{ 96, 120, 184 },
|
||||
{ 112, 144, 216 },
|
||||
{ 136, 168, 248 },
|
||||
{ 152, 192, 248 }
|
||||
};
|
||||
const Color256 UIScrollBox::kTextColors2[] = {
|
||||
{ 200, 216, 248 },
|
||||
{ 216, 224, 248 },
|
||||
{ 224, 232, 248 },
|
||||
{ 232, 240, 248 },
|
||||
{ 248, 248, 248 }
|
||||
};
|
||||
const Color256 UIScrollBox::kTextColors3[] = {
|
||||
{ 240, 232, 192 },
|
||||
{ 240, 232, 208 },
|
||||
{ 240, 240, 216 },
|
||||
{ 248, 240, 232 },
|
||||
{ 248, 248, 248 }
|
||||
};
|
||||
const Color256 UIScrollBox::kTextColors4[] = {
|
||||
{ 152, 112, 56 },
|
||||
{ 184, 144, 88 },
|
||||
{ 216, 184, 112 },
|
||||
{ 232, 208, 136 },
|
||||
{ 248, 224, 144 }
|
||||
};
|
||||
|
||||
UIScrollBox::UIScrollBox(BladeRunnerEngine *vm,
|
||||
UIScrollBoxClickedCallback *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; // 0, 1 or (new) 2. "2" is similar to "1" but with solid background for main area and scroll bar
|
||||
_center = center;
|
||||
_timeLastScroll = _vm->_time->currentSystem();
|
||||
_timeLastCheckbox = _vm->_time->currentSystem();
|
||||
_timeLastHighlight = _vm->_time->currentSystem();
|
||||
|
||||
_highlightFrame = 0;
|
||||
|
||||
_rect = rect;
|
||||
_scrollBarRect = scrollBarRect;
|
||||
_scrollBarRect.right += 15; // right side was not used, but it's useful for determining if the control is selected
|
||||
|
||||
_lineCount = 0;
|
||||
_maxLineCount = maxLineCount;
|
||||
|
||||
_firstLineVisible = 0;
|
||||
_maxLinesVisible = _rect.height() / kLineHeight;
|
||||
|
||||
_mouseButton = false;
|
||||
|
||||
_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 = 5u;
|
||||
}
|
||||
|
||||
_mouseOver = false;
|
||||
}
|
||||
|
||||
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->_time->currentSystem();
|
||||
_timeLastCheckbox = _vm->_time->currentSystem();
|
||||
_timeLastHighlight = _vm->_time->currentSystem();
|
||||
|
||||
_highlightFrame = 0;
|
||||
_isVisible = true;
|
||||
|
||||
_mouseOver = false;
|
||||
}
|
||||
|
||||
void UIScrollBox::hide() {
|
||||
_isVisible = false;
|
||||
}
|
||||
|
||||
bool UIScrollBox::isVisible() {
|
||||
return _isVisible;
|
||||
}
|
||||
|
||||
bool UIScrollBox::hasFocus() {
|
||||
return _mouseOver;
|
||||
}
|
||||
|
||||
void UIScrollBox::setBoxTop(int top) {
|
||||
_rect.moveTo(_rect.left, top);
|
||||
|
||||
_rect.bottom = _rect.top + kLineHeight * _maxLinesVisible - 1;
|
||||
}
|
||||
|
||||
void UIScrollBox::setBoxLeft(int left) {
|
||||
_rect.moveTo(left, _rect.top);
|
||||
}
|
||||
|
||||
void UIScrollBox::setBoxWidth(uint16 width) {
|
||||
_rect.setWidth(width);
|
||||
}
|
||||
|
||||
int UIScrollBox::getBoxLeft() {
|
||||
return _rect.left;
|
||||
}
|
||||
|
||||
uint16 UIScrollBox::getBoxWidth() {
|
||||
return _rect.width();
|
||||
}
|
||||
|
||||
void UIScrollBox::setScrollbarTop(int top) {
|
||||
_scrollBarRect.moveTo(_scrollBarRect.left, top);
|
||||
}
|
||||
|
||||
void UIScrollBox::setScrollbarLeft(int left) {
|
||||
_scrollBarRect.moveTo(left, _scrollBarRect.top);
|
||||
}
|
||||
|
||||
void UIScrollBox::setScrollbarWidth(uint16 width) {
|
||||
_scrollBarRect.setWidth(width);
|
||||
_scrollBarRect.right += 15; // right side was not used, but it's useful for determining if the control is selected
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
_mouseOver = _rect.contains(mouseX, mouseY) || _scrollBarRect.contains(mouseX, mouseY);
|
||||
|
||||
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 = kSfxTEXT1;
|
||||
if (_lines[newHoveredLine]->flags & 0x01 ) {
|
||||
soundId = kSfxTEXT3;
|
||||
}
|
||||
_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(kSfxBEEP10), 100, 0, 0, 50, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!alternateButton) {
|
||||
if (_scrollUpButtonHover) {
|
||||
_scrollUpButtonState = 2;
|
||||
_timeLastScroll = _vm->_time->currentSystem() - 160u;
|
||||
} else {
|
||||
_scrollUpButtonState = 1;
|
||||
}
|
||||
if (_scrollDownButtonHover) {
|
||||
_scrollDownButtonState = 2;
|
||||
} else {
|
||||
_scrollDownButtonState = 1;
|
||||
}
|
||||
if (_scrollBarHover) {
|
||||
_scrollBarState = 2;
|
||||
} else {
|
||||
_scrollBarState = 1;
|
||||
}
|
||||
if (_scrollAreaUpHover) {
|
||||
_scrollAreaUpState = 2;
|
||||
_timeLastScroll = _vm->_time->currentSystem() - 160u;
|
||||
} else {
|
||||
_scrollAreaUpState = 1;
|
||||
}
|
||||
if (_scrollAreaDownHover) {
|
||||
_scrollAreaDownState = 2;
|
||||
_timeLastScroll = _vm->_time->currentSystem() - 160u;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIScrollBox::handleMouseScroll(int direction) {
|
||||
if (_mouseOver) {
|
||||
if (direction > 0) {
|
||||
scrollDown();
|
||||
} else if (direction < 0) {
|
||||
scrollUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int UIScrollBox::getSelectedLineData() {
|
||||
if (_hoveredLine >= 0 && _selectedLineState != 1 && _hoveredLine < _lineCount) {
|
||||
return _lines[_hoveredLine]->lineData;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
Common::String UIScrollBox::getLineText(int lineData) {
|
||||
if (hasLine(lineData)) {
|
||||
return _lines[_hoveredLine]->text;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int UIScrollBox::getMaxLinesVisible() {
|
||||
return _maxLinesVisible;
|
||||
}
|
||||
|
||||
int UIScrollBox::getLineCount() {
|
||||
return _lineCount;
|
||||
}
|
||||
|
||||
void UIScrollBox::draw(Graphics::Surface &surface) {
|
||||
if (!_isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 timeNow = _vm->_time->currentSystem();
|
||||
|
||||
// update scrolling
|
||||
if (_scrollUpButtonState == 2 && _scrollUpButtonHover) {
|
||||
// unsigned difference is intentional
|
||||
if ((timeNow - _timeLastScroll) > 160u) {
|
||||
scrollUp();
|
||||
_timeLastScroll = timeNow;
|
||||
}
|
||||
} else if (_scrollDownButtonState == 2 && _scrollDownButtonHover) {
|
||||
// unsigned difference is intentional
|
||||
if ((timeNow - _timeLastScroll) > 160u) {
|
||||
scrollDown();
|
||||
_timeLastScroll = timeNow;
|
||||
}
|
||||
} else if (_scrollAreaUpState == 2 && _scrollAreaUpHover) {
|
||||
// unsigned difference is intentional
|
||||
if ((timeNow - _timeLastScroll) > 160u) {
|
||||
_firstLineVisible -= _maxLinesVisible - 1;
|
||||
_firstLineVisible = CLIP(_firstLineVisible, 0, _lineCount - _maxLinesVisible);
|
||||
_timeLastScroll = timeNow;
|
||||
}
|
||||
} else if (_scrollAreaDownState == 2 && _scrollAreaDownHover) {
|
||||
// unsigned difference is intentional
|
||||
if ((timeNow - _timeLastScroll) > 160u) {
|
||||
_firstLineVisible += _maxLinesVisible - 1;
|
||||
_firstLineVisible = CLIP(_firstLineVisible, 0, _lineCount - _maxLinesVisible);
|
||||
_timeLastScroll = timeNow;
|
||||
}
|
||||
}
|
||||
|
||||
// update checkboxes
|
||||
// unsigned difference is intentional
|
||||
uint32 timeDiffCheckBox = timeNow - _timeLastCheckbox;
|
||||
if (timeDiffCheckBox > 67u) {
|
||||
_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 < 5u) {
|
||||
_lines[i]->checkboxFrame += timeDiffCheckBox / 67u;
|
||||
}
|
||||
if (_lines[i]->checkboxFrame > 5u) {
|
||||
_lines[i]->checkboxFrame = 5u;
|
||||
}
|
||||
} else { // checkbox not checked
|
||||
if (_lines[i]->checkboxFrame > 0u) {
|
||||
_lines[i]->checkboxFrame = (_lines[i]->checkboxFrame < (timeDiffCheckBox / 67u)) ? 0u : _lines[i]->checkboxFrame - (timeDiffCheckBox / 67u);
|
||||
}
|
||||
if (_lines[i]->checkboxFrame == 0u) { // original was < 0, int
|
||||
_lines[i]->checkboxFrame = 0u;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// update highlight
|
||||
// unsigned difference is intentional
|
||||
if ((timeNow - _timeLastHighlight) > 67u) {
|
||||
_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 = surface.format.RGBToColor(kTextColors2[colorIndex].r, kTextColors2[colorIndex].g, kTextColors2[colorIndex].b);
|
||||
} else {
|
||||
color = surface.format.RGBToColor(kTextColors3[colorIndex].r, kTextColors3[colorIndex].g, kTextColors3[colorIndex].b);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (_style) {
|
||||
color = surface.format.RGBToColor(kTextColors1[colorIndex].r, kTextColors1[colorIndex].g, kTextColors1[colorIndex].b);
|
||||
} else {
|
||||
color = surface.format.RGBToColor(kTextColors4[colorIndex].r, kTextColors4[colorIndex].g, kTextColors4[colorIndex].b);
|
||||
}
|
||||
}
|
||||
|
||||
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 != 5u || v35) {
|
||||
checkboxShapeId = _lines[i]->checkboxFrame + 62u;
|
||||
} else {
|
||||
checkboxShapeId = 61;
|
||||
}
|
||||
} else {
|
||||
checkboxShapeId = 60;
|
||||
}
|
||||
} else if (_lines[i]->checkboxFrame || v35) {
|
||||
if (_lines[i]->checkboxFrame != 5u || v35) {
|
||||
checkboxShapeId = _lines[i]->checkboxFrame + 54u;
|
||||
} 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 (_vm->_cutContent && (_lines[i]->flags & 0x40)) {
|
||||
// A KIA clue marked as hidden/private, but already shared with Mainframe
|
||||
// Note, proper hidden clues will not have this mark and will get colorBackground
|
||||
// from below (case _style > 0)
|
||||
colorBackground = surface.format.RGBToColor(80, 46, 22);
|
||||
} else {
|
||||
if (_style == 2) {
|
||||
colorBackground = surface.format.RGBToColor(kTextBackgroundColors[colorIndex].r / 8, kTextBackgroundColors[colorIndex].g / 8, kTextBackgroundColors[colorIndex].b / 8);
|
||||
} else if (_style > 0) {
|
||||
colorBackground = surface.format.RGBToColor(kTextBackgroundColors[colorIndex].r, kTextBackgroundColors[colorIndex].g, kTextBackgroundColors[colorIndex].b);
|
||||
} else {
|
||||
colorBackground = surface.format.RGBToColor(80, 56, 32);
|
||||
}
|
||||
}
|
||||
|
||||
if (_style == 2) {
|
||||
// New: style = 2 (original unused)
|
||||
// original behavior -- No padding between the colored background of lines, simulate solid background (gradient)
|
||||
surface.fillRect(Common::Rect(CLIP(x - 1, 0, 639), y, _rect.right + 1, y + kLineHeight), colorBackground);
|
||||
} else {
|
||||
// original behavior -- there is padding between the colored background of lines
|
||||
surface.fillRect(Common::Rect(x, y, _rect.right + 1, y1 + 1), colorBackground);
|
||||
}
|
||||
}
|
||||
|
||||
if (_center) {
|
||||
x = _rect.left + (_rect.width() - _vm->_mainFont->getStringWidth(_lines[i]->text)) / 2;
|
||||
}
|
||||
|
||||
_vm->_mainFont->drawString(&surface, _lines[i]->text, x, y, surface.w, color);
|
||||
|
||||
y1 += kLineHeight;
|
||||
y2 += kLineHeight;
|
||||
y += kLineHeight;
|
||||
++i;
|
||||
} while (i < lastLineVisible);
|
||||
}
|
||||
|
||||
if (_style == 2 && getLineCount() >= getMaxLinesVisible()) {
|
||||
// New: style = 2 (original unused)
|
||||
// Solid background color for scrollbar
|
||||
int scrollBarFillColor = surface.format.RGBToColor(k3DFrameColors[0].r / 2, k3DFrameColors[0].g / 2, k3DFrameColors[0].b / 2);
|
||||
surface.fillRect(Common::Rect(_scrollBarRect.left, _scrollBarRect.top, CLIP(_scrollBarRect.left + 15, 0, 639), _scrollBarRect.bottom), scrollBarFillColor);
|
||||
}
|
||||
|
||||
if (_style != 2
|
||||
|| (_style == 2 && getLineCount() >= getMaxLinesVisible())
|
||||
) {
|
||||
// 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 = surface.format.RGBToColor(k3DFrameColors[style + 6].r, k3DFrameColors[style + 6].g, k3DFrameColors[style + 6].b);
|
||||
color2 = surface.format.RGBToColor(k3DFrameColors[style + 4].r, k3DFrameColors[style + 4].g, k3DFrameColors[style + 4].b);
|
||||
} else {
|
||||
color1 = surface.format.RGBToColor(k3DFrameColors[style + 4].r, k3DFrameColors[style + 4].g, k3DFrameColors[style + 4].b);
|
||||
color2 = surface.format.RGBToColor(k3DFrameColors[style + 6].r, k3DFrameColors[style + 6].g, k3DFrameColors[style + 6].b);
|
||||
}
|
||||
|
||||
int color3 = surface.format.RGBToColor(k3DFrameColors[style].r, k3DFrameColors[style].g, k3DFrameColors[style].b);
|
||||
int fillColor = surface.format.RGBToColor(k3DFrameColors[style + 2].r, k3DFrameColors[style + 2].g, k3DFrameColors[style + 2].b);
|
||||
|
||||
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, color3);
|
||||
surface.hLine(rect.left, rect.bottom - 1, rect.left, color3);
|
||||
}
|
||||
|
||||
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
|
||||
162
engines/bladerunner/ui/ui_scroll_box.h
Normal file
162
engines/bladerunner/ui/ui_scroll_box.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_UI_SCROLLBOX_H
|
||||
#define BLADERUNNER_UI_SCROLLBOX_H
|
||||
|
||||
#include "bladerunner/color.h"
|
||||
#include "bladerunner/ui/ui_component.h"
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
typedef void UIScrollBoxClickedCallback(void *callbackData, void *source, int lineData, int mouseButton);
|
||||
|
||||
class UIScrollBox : public UIComponent {
|
||||
static const int kLineHeight = 10;
|
||||
static const Color256 k3DFrameColors[];
|
||||
static const Color256 kTextBackgroundColors[];
|
||||
static const Color256 kTextColors1[];
|
||||
static const Color256 kTextColors2[];
|
||||
static const Color256 kTextColors3[];
|
||||
static const Color256 kTextColors4[];
|
||||
|
||||
struct Line {
|
||||
Common::String text;
|
||||
int lineData;
|
||||
int flags;
|
||||
uint32 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;
|
||||
|
||||
UIScrollBoxClickedCallback *_lineSelectedCallback;
|
||||
void *_callbackData;
|
||||
|
||||
bool _isVisible;
|
||||
int _style;
|
||||
bool _center;
|
||||
|
||||
uint32 _timeLastScroll;
|
||||
uint32 _timeLastCheckbox;
|
||||
uint32 _timeLastHighlight;
|
||||
|
||||
int _highlightFrame;
|
||||
|
||||
Common::Rect _rect;
|
||||
Common::Rect _scrollBarRect;
|
||||
|
||||
int _lineCount;
|
||||
int _maxLineCount;
|
||||
Common::Array<Line *> _lines;
|
||||
int _maxLinesVisible;
|
||||
int _firstLineVisible;
|
||||
|
||||
bool _mouseOver;
|
||||
|
||||
public:
|
||||
UIScrollBox(BladeRunnerEngine *vm,
|
||||
UIScrollBoxClickedCallback *lineSelectedCallback,
|
||||
void *callbackData,
|
||||
int maxLineCount,
|
||||
int style,
|
||||
bool center,
|
||||
Common::Rect rect,
|
||||
Common::Rect scrollBarRect);
|
||||
|
||||
~UIScrollBox() override;
|
||||
|
||||
void draw(Graphics::Surface &surface) override;
|
||||
|
||||
void handleMouseMove(int mouseX, int mouseY) override;
|
||||
void handleMouseDown(bool alternateButton) override;
|
||||
void handleMouseUp(bool alternateButton) override;
|
||||
void handleMouseScroll(int direction) override;
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
bool isVisible();
|
||||
bool hasFocus();
|
||||
|
||||
void setBoxTop(int top);
|
||||
void setBoxLeft(int left);
|
||||
void setBoxWidth(uint16 width);
|
||||
void setScrollbarTop(int top);
|
||||
void setScrollbarLeft(int left);
|
||||
void setScrollbarWidth(uint16 width);
|
||||
|
||||
int getBoxLeft();
|
||||
uint16 getBoxWidth();
|
||||
|
||||
|
||||
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();
|
||||
Common::String getLineText(int lineData);
|
||||
int getMaxLinesVisible();
|
||||
int getLineCount();
|
||||
|
||||
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
|
||||
173
engines/bladerunner/ui/ui_slider.cpp
Normal file
173
engines/bladerunner/ui/ui_slider.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bladerunner/ui/ui_slider.h"
|
||||
|
||||
#include "bladerunner/audio_player.h"
|
||||
#include "bladerunner/bladerunner.h"
|
||||
#include "bladerunner/game_info.h"
|
||||
#include "bladerunner/game_constants.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
const Color256 UISlider::kColors[] = {
|
||||
{ 0, 0, 0 }, // Black - unpressed (framing rectange)
|
||||
{ 16, 8, 8 },
|
||||
{ 32, 24, 8 },
|
||||
{ 56, 32, 16 },
|
||||
{ 72, 48, 16 },
|
||||
{ 88, 56, 24 }, // Mouse-over (framing rectange)
|
||||
{ 104, 72, 32 },
|
||||
{ 128, 80, 40 },
|
||||
{ 136, 96, 48 },
|
||||
{ 152, 112, 56 },
|
||||
{ 168, 128, 72 }, // Pressed (framing rectange)
|
||||
{ 184, 144, 88 },
|
||||
{ 200, 160, 96 },
|
||||
{ 216, 184, 112 },
|
||||
{ 232, 200, 128 },
|
||||
{ 240, 224, 144 }
|
||||
};
|
||||
|
||||
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;
|
||||
_mouseX = 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;
|
||||
}
|
||||
|
||||
// Ensures animated transition of the frame's (outlining rectangle's) color to the new one
|
||||
if (_currentFrameColor < frameColor) {
|
||||
++_currentFrameColor;
|
||||
}
|
||||
|
||||
// Ensures animated transition of the frame's (outlining rectangle's) color to the new one
|
||||
if (_currentFrameColor > frameColor) {
|
||||
--_currentFrameColor;
|
||||
}
|
||||
|
||||
surface.frameRect(_rect, surface.format.RGBToColor(kColors[_currentFrameColor].r, kColors[_currentFrameColor].g, kColors[_currentFrameColor].b));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
uint32 color = surface.format.RGBToColor(kColors[colorIndex].r, kColors[colorIndex].g, kColors[colorIndex].b);
|
||||
if ((striding + x) & 1 || x == sliderX) {
|
||||
color = surface.format.RGBToColor(0, 0, 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(kSfxTEXT3), 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
|
||||
61
engines/bladerunner/ui/ui_slider.h
Normal file
61
engines/bladerunner/ui/ui_slider.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_UI_SLIDER_H
|
||||
#define BLADERUNNER_UI_SLIDER_H
|
||||
|
||||
#include "bladerunner/color.h"
|
||||
#include "bladerunner/ui/ui_component.h"
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class UISlider : public UIComponent {
|
||||
static const Color256 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) override;
|
||||
|
||||
void handleMouseMove(int mouseX, int mouseY) override;
|
||||
void handleMouseDown(bool alternateButton) override;
|
||||
void handleMouseUp(bool alternateButton) override;
|
||||
|
||||
void setValue(int value);
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
|
||||
#endif
|
||||
1065
engines/bladerunner/ui/vk.cpp
Normal file
1065
engines/bladerunner/ui/vk.cpp
Normal file
File diff suppressed because it is too large
Load Diff
178
engines/bladerunner/ui/vk.h
Normal file
178
engines/bladerunner/ui/vk.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLADERUNNER_VK_H
|
||||
#define BLADERUNNER_VK_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/str.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace BladeRunner {
|
||||
|
||||
class BladeRunnerEngine;
|
||||
class VKScript;
|
||||
class Shapes;
|
||||
class UIImagePicker;
|
||||
class VQAPlayer;
|
||||
|
||||
class VK {
|
||||
friend class Debugger;
|
||||
|
||||
struct Question {
|
||||
bool isPresent;
|
||||
bool wasAsked;
|
||||
int sentenceId;
|
||||
int relatedSentenceId;
|
||||
};
|
||||
|
||||
BladeRunnerEngine *_vm;
|
||||
|
||||
VKScript *_script;
|
||||
|
||||
UIImagePicker *_buttons;
|
||||
Shapes *_shapes;
|
||||
|
||||
VQAPlayer *_vqaPlayerMain;
|
||||
VQAPlayer *_vqaPlayerEye;
|
||||
int _vqaFrameMain;
|
||||
bool _vqaLoopEnded;
|
||||
|
||||
Graphics::Surface _surfaceEye;
|
||||
|
||||
bool _isOpen;
|
||||
int _actorId;
|
||||
bool _calibrationStarted;
|
||||
bool _testStarted;
|
||||
|
||||
Common::Array<Common::Array<Question> > _questions;
|
||||
|
||||
int _ambientVolumeFactorOutsideVK; // should be in [0, 100]
|
||||
int _musicVolumeFactorOutsideVK; // should be in [0, 100]
|
||||
int _soundTrackId1;
|
||||
int _soundTrackId2;
|
||||
int _soundTrackId3;
|
||||
|
||||
int _calibration;
|
||||
int _calibrationRatio;
|
||||
int _calibrationCounter;
|
||||
|
||||
int _humanProbability;
|
||||
int _humanGauge;
|
||||
int _humanGaugeTarget;
|
||||
int _humanGaugeDelta;
|
||||
uint32 _timeNextHumanGaugeStepDiff;
|
||||
uint32 _timeNextHumanGaugeStepStart;
|
||||
|
||||
int _replicantProbability;
|
||||
int _replicantGauge;
|
||||
int _replicantGaugeTarget;
|
||||
int _replicantGaugeDelta;
|
||||
uint32 _timeNextReplicantGaugeStepDiff;
|
||||
uint32 _timeNextReplicantGaugeStepStart;
|
||||
|
||||
int _anxiety;
|
||||
|
||||
int _needleValue;
|
||||
int _needleValueMax;
|
||||
int _needleValueTarget;
|
||||
int _needleValueDelta;
|
||||
uint32 _timeNextNeedleStepStart;
|
||||
uint32 _timeNextNeedleOscillateStart;
|
||||
uint32 _timeNeedleReturnStart;
|
||||
|
||||
bool _isClosing;
|
||||
uint32 _timeCloseStart;
|
||||
|
||||
int _blinkState;
|
||||
uint32 _timeNextBlinkStart;
|
||||
uint32 _timeNextGaugesBlinkStart;
|
||||
|
||||
bool _isAdjusting;
|
||||
int _adjustment;
|
||||
int _adjustmentTarget;
|
||||
int _adjustmentDelta;
|
||||
uint32 _timeNextAdjustementStepStart;
|
||||
|
||||
int _eyeLineSelected;
|
||||
int _eyeLineX;
|
||||
int _eyeLineXLast;
|
||||
int _eyeLineY;
|
||||
int _eyeLineYLast;
|
||||
int _eyeLineXDelta;
|
||||
int _eyeLineYDelta;
|
||||
uint32 _timeNextEyeLineStepStart;
|
||||
uint32 _timeNextEyeLineStart;
|
||||
|
||||
public:
|
||||
VK(BladeRunnerEngine *vm);
|
||||
~VK();
|
||||
|
||||
void open(int actorId, int calibrationRatio);
|
||||
bool isOpen() const;
|
||||
void close();
|
||||
|
||||
void tick();
|
||||
|
||||
// void resume();
|
||||
|
||||
void handleMouseDown(int mouseX, int mouseY, bool mainButton);
|
||||
void handleMouseUp(int mouseX, int mouseY, bool mainButton);
|
||||
|
||||
void playSpeechLine(int actorId, int sentenceId, float pauseDuration);
|
||||
void addQuestion(int intensity, int sentenceId, int relatedSentenceId);
|
||||
void subjectReacts(int intensity, int humanResponse, int replicantResponse, int anxiety);
|
||||
void eyeAnimates(int loopId);
|
||||
|
||||
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 reset();
|
||||
void init();
|
||||
|
||||
void draw();
|
||||
|
||||
void drawNeedle(Graphics::Surface &surface);
|
||||
void drawEye(Graphics::Surface &surface);
|
||||
void drawEyeCrosshair(Graphics::Surface &surface, uint32 timeNow);
|
||||
void drawMouse(Graphics::Surface &surface);
|
||||
void drawGauge(Graphics::Surface &surface, int value, int x, int y, int width);
|
||||
void drawHumanGauge(Graphics::Surface &surface);
|
||||
void drawReplicantGauge(Graphics::Surface &surface);
|
||||
|
||||
void calibrate();
|
||||
void beginTest();
|
||||
|
||||
void startAdjustement();
|
||||
void stopAdjustement();
|
||||
void animateAdjustment(int target);
|
||||
void setAdjustment(int x);
|
||||
void setAdjustmentFromMouse();
|
||||
|
||||
void findRelatedQuestionBySentenceId(int inSentenceId, int &outRelatedQuestionId, int &outRelatedIntensity);
|
||||
void askQuestion(int intensity);
|
||||
};
|
||||
|
||||
} // End of namespace BladeRunner
|
||||
#endif
|
||||
Reference in New Issue
Block a user