aboutsummaryrefslogtreecommitdiff
path: root/engines/bladerunner/ui
diff options
context:
space:
mode:
authorPeter Kohaut2018-02-10 20:34:28 +0100
committerPeter Kohaut2018-02-10 21:01:15 +0100
commit0b484d51b838d740bbb1d6bc12c06c25d225c197 (patch)
tree931c42a9751703beb7694b429dc6fea023b21745 /engines/bladerunner/ui
parent2ac361782c585a5a0c0d11e12beeab66d651cab5 (diff)
downloadscummvm-rg350-0b484d51b838d740bbb1d6bc12c06c25d225c197.tar.gz
scummvm-rg350-0b484d51b838d740bbb1d6bc12c06c25d225c197.tar.bz2
scummvm-rg350-0b484d51b838d740bbb1d6bc12c06c25d225c197.zip
BLADERUNNER: VK interface
Code unification Removed few memory leaks
Diffstat (limited to 'engines/bladerunner/ui')
-rw-r--r--engines/bladerunner/ui/elevator.cpp2
-rw-r--r--engines/bladerunner/ui/esper.cpp309
-rw-r--r--engines/bladerunner/ui/esper.h16
-rw-r--r--engines/bladerunner/ui/kia.cpp6
-rw-r--r--engines/bladerunner/ui/kia.h4
-rw-r--r--engines/bladerunner/ui/kia_section_clues.cpp3
-rw-r--r--engines/bladerunner/ui/kia_section_crimes.cpp2
-rw-r--r--engines/bladerunner/ui/kia_section_suspects.cpp2
-rw-r--r--engines/bladerunner/ui/ui_image_picker.cpp24
-rw-r--r--engines/bladerunner/ui/vk.cpp917
-rw-r--r--engines/bladerunner/ui/vk.h174
11 files changed, 1274 insertions, 185 deletions
diff --git a/engines/bladerunner/ui/elevator.cpp b/engines/bladerunner/ui/elevator.cpp
index 4c72be2345..2e6f036b4b 100644
--- a/engines/bladerunner/ui/elevator.cpp
+++ b/engines/bladerunner/ui/elevator.cpp
@@ -46,7 +46,7 @@ Elevator::Elevator(BladeRunnerEngine *vm) {
Elevator::~Elevator() {
delete _imagePicker;
- reset();
+ _imagePicker = nullptr;
}
int Elevator::activate(int elevatorId) {
diff --git a/engines/bladerunner/ui/esper.cpp b/engines/bladerunner/ui/esper.cpp
index 3df6f7d11b..79b8f5d3ac 100644
--- a/engines/bladerunner/ui/esper.cpp
+++ b/engines/bladerunner/ui/esper.cpp
@@ -31,7 +31,7 @@
#include "bladerunner/game_info.h"
#include "bladerunner/mouse.h"
#include "bladerunner/shape.h"
-#include "bladerunner/script/esper.h"
+#include "bladerunner/script/esper_script.h"
#include "bladerunner/text_resource.h"
#include "bladerunner/ui/ui_image_picker.h"
#include "bladerunner/vqa_player.h"
@@ -39,8 +39,6 @@
#include "common/rect.h"
#include "common/str.h"
-#include "graphics/surface.h"
-
namespace BladeRunner {
ESPER::ESPER(BladeRunnerEngine *vm) {
@@ -55,12 +53,10 @@ ESPER::ESPER(BladeRunnerEngine *vm) {
_isDrawingSelection = false;
_isOpen = false;
- _photoData = nullptr;
- _viewportData = nullptr;
_shapeButton = nullptr;
_shapeThumbnail = nullptr;
- _vqaMainPlayer = nullptr;
- _vqaPhotoPlayer = nullptr;
+ _vqaPlayerMain = nullptr;
+ _vqaPlayerPhoto = nullptr;
_script = nullptr;
reset();
@@ -94,11 +90,9 @@ void ESPER::open(Graphics::Surface *surface) {
return;
}
- _photoData = new Graphics::Surface();
- _photoData->create(kPhotoWidth, kPhotoHeight, createRGB555());
+ _surfacePhoto.create(kPhotoWidth, kPhotoHeight, createRGB555());
- _viewportData = new Graphics::Surface();
- _viewportData->create(_screen.width(), _screen.height(), createRGB555());
+ _surfaceViewport.create(_screen.width(), _screen.height(), createRGB555());
_viewportNext = _viewport;
@@ -111,11 +105,11 @@ void ESPER::open(Graphics::Surface *surface) {
_shapesPhotos.resize(10);
- _vqaMainPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack);
- if (!_vqaMainPlayer->open("ESPER.VQA")) {
+ _vqaPlayerMain = new VQAPlayer(_vm, &_vm->_surfaceBack);
+ if (!_vqaPlayerMain->open("ESPER.VQA")) {
return;
}
- _vqaMainPlayer->setLoop(2, -1, kLoopSetModeJustStart, nullptr, nullptr);
+ _vqaPlayerMain->setLoop(2, -1, kLoopSetModeJustStart, nullptr, nullptr);
_isOpen = true;
_flash = false;
@@ -143,16 +137,14 @@ void ESPER::close() {
delete _shapeButton;
_shapeButton = nullptr;
- delete _photoData;
- _photoData = nullptr;
+ _surfacePhoto.free();
- delete _viewportData;
- _viewportData = nullptr;
+ _surfaceViewport.free();
- if (_vqaMainPlayer) {
- _vqaMainPlayer->close();
- delete _vqaMainPlayer;
- _vqaMainPlayer= nullptr;
+ if (_vqaPlayerMain) {
+ _vqaPlayerMain->close();
+ delete _vqaPlayerMain;
+ _vqaPlayerMain= nullptr;
}
_vm->closeArchive("MODE.MIX");
@@ -163,7 +155,7 @@ void ESPER::close() {
reset();
}
-bool ESPER::isOpen() {
+bool ESPER::isOpen() const {
return _isOpen;
}
@@ -197,7 +189,7 @@ void ESPER::handleMouseDown(int x, int y, bool mainButton) {
_isMouseDown = true;
playSound(460, 100);
}
- if ( _mouseOverScroll >= 0 && _mouseOverScroll <= 3 && !_isScrolling) {
+ if (_mouseOverScroll >= 0 && _mouseOverScroll <= 3 && !_isScrolling) {
scrollingStart(_mouseOverScroll);
}
tick();
@@ -210,7 +202,7 @@ void ESPER::handleMouseDown(int x, int y, bool mainButton) {
}
void ESPER::tick() {
- if (!_vm->_windowIsActive) {
+ if (!_vm->_gameIsRunning) {
return;
}
@@ -230,7 +222,8 @@ void ESPER::tick() {
draw(_vm->_surfaceFront);
_buttons->draw(_vm->_surfaceFront);
- tickMouse(_vm->_surfaceFront);
+ drawMouse(_vm->_surfaceFront);
+
tickSound();
_vm->blitToScreen(_vm->_surfaceFront);
@@ -315,11 +308,9 @@ void ESPER::mouseUpCallback(int buttonId, void *callbackData) {
}
void ESPER::reset() {
- delete _photoData;
- _photoData = nullptr;
+ _surfacePhoto.free();
- delete _viewportData;
- _viewportData = nullptr;
+ _surfaceViewport.free();
delete _shapeButton;
_shapeButton = nullptr;
@@ -327,11 +318,11 @@ void ESPER::reset() {
delete _shapeThumbnail;
_shapeThumbnail = nullptr;
- delete _vqaMainPlayer;
- _vqaMainPlayer = nullptr;
+ delete _vqaPlayerMain;
+ _vqaPlayerMain = nullptr;
- delete _vqaPhotoPlayer;
- _vqaPhotoPlayer = nullptr;
+ delete _vqaPlayerPhoto;
+ _vqaPlayerPhoto = nullptr;
delete _script;
_script = nullptr;
@@ -343,10 +334,10 @@ void ESPER::reset() {
}
void ESPER::resetData() {
- if (_vqaPhotoPlayer) {
- _vqaPhotoPlayer->close();
- delete _vqaPhotoPlayer;
- _vqaPhotoPlayer = nullptr;
+ if (_vqaPlayerPhoto) {
+ _vqaPlayerPhoto->close();
+ delete _vqaPlayerPhoto;
+ _vqaPlayerPhoto = nullptr;
}
if (_shapeThumbnail) {
@@ -565,7 +556,7 @@ void ESPER::draw(Graphics::Surface &surface) {
if (!_isOpen) {
return;
}
- _vqaMainPlayer->update(false);
+ _vqaPlayerMain->update(false);
switch (_stateMain) {
case kEsperMainStateOpening:
case kEsperMainStateList:
@@ -669,7 +660,7 @@ void ESPER::drawPhotoOpening(Graphics::Surface &surface) {
_timePhotoOpeningNext = timeNow + 20;
}
- copyImageScale(_photoData, _viewport, &surface, Common::Rect(_screen.left, _screen.top, _photoOpeningWidth, _photoOpeningHeight));
+ copyImageScale(&_surfacePhoto, _viewport, &surface, Common::Rect(_screen.left, _screen.top, _photoOpeningWidth, _photoOpeningHeight));
surface.hLine(_screen.left, _photoOpeningHeight, _screen.right - 1, 0x03E0);
surface.vLine(_photoOpeningWidth, _screen.top, _screen.bottom - 1, 0x03E0);
@@ -819,13 +810,13 @@ void ESPER::drawPhotoSharpening(Graphics::Surface &surface) {
}
if (_regionSelectedAck && !_regions[_regionSelected].name.empty()) {
- _vqaPhotoPlayer->update(true, false);
- copyImageBlur(_viewportData, Common::Rect(0, 0, 299, 263), &surface, _screen, _blur);
- copyImageBlit(_viewportData, Common::Rect(0, 0, 0, 0), &surface, Common::Rect(_screen.left, _screen.top, _photoOpeningWidth, _photoOpeningHeight));
+ _vqaPlayerPhoto->update(true, false);
+ copyImageBlur(&_surfaceViewport, Common::Rect(0, 0, 299, 263), &surface, _screen, _blur);
+ copyImageBlit(&_surfaceViewport, Common::Rect(0, 0, 0, 0), &surface, Common::Rect(_screen.left, _screen.top, _photoOpeningWidth, _photoOpeningHeight));
} else {
drawPhoto(surface);
- copyImageScale(_photoData, _viewport, _viewportData, Common::Rect(0, 0, _screen.width(), _screen.height()));
- copyImageBlit(_viewportData, Common::Rect(0, 0, 0, 0), &surface, Common::Rect(_screen.left, _screen.top, _photoOpeningWidth, _photoOpeningHeight));
+ copyImageScale(&_surfacePhoto, _viewport, &_surfaceViewport, Common::Rect(0, 0, _screen.width(), _screen.height()));
+ copyImageBlit(&_surfaceViewport, Common::Rect(0, 0, 0, 0), &surface, Common::Rect(_screen.left, _screen.top, _photoOpeningWidth, _photoOpeningHeight));
}
drawGrid(surface);
@@ -871,14 +862,14 @@ void ESPER::drawPhotoZoomOut(Graphics::Surface &surface) {
}
void ESPER::drawVideoZooming(Graphics::Surface &surface) {
- if (_vqaPhotoPlayer == nullptr) {
- _vqaPhotoPlayer = new VQAPlayer(_vm, _viewportData);
- if (!_vqaPhotoPlayer->open(Common::String(_regions[_regionSelected].name) + ".VQA")) {
+ if (_vqaPlayerPhoto == nullptr) {
+ _vqaPlayerPhoto = new VQAPlayer(_vm, &_surfaceViewport);
+ if (!_vqaPlayerPhoto->open(Common::String(_regions[_regionSelected].name) + ".VQA")) {
setStatePhoto(kEsperPhotoStateShow);
_vm->_mouse->enable();
- delete _vqaPhotoPlayer;
- _vqaPhotoPlayer = nullptr;
+ delete _vqaPlayerPhoto;
+ _vqaPlayerPhoto = nullptr;
return;
}
@@ -897,8 +888,8 @@ void ESPER::drawVideoZooming(Graphics::Surface &surface) {
_blur += _zoomDelta * 5.0f;
}
- int frame = _vqaPhotoPlayer->update(true, advanceFrame);
- if (frame == _vqaPhotoPlayer->getFrameCount() - 1) {
+ int frame = _vqaPlayerPhoto->update(true, advanceFrame);
+ if (frame == _vqaPlayerPhoto->getFrameCount() - 1) {
_vqaLastFrame = frame;
setStatePhoto(kEsperPhotoStatePhotoSharpening);
}
@@ -906,7 +897,7 @@ void ESPER::drawVideoZooming(Graphics::Surface &surface) {
if (flash) {
flashViewport();
}
- copyImageBlur(_viewportData, Common::Rect(0, 0, 299, 263), &surface, _screen, _blur);
+ copyImageBlur(&_surfaceViewport, Common::Rect(0, 0, 299, 263), &surface, _screen, _blur);
drawGrid(surface);
}
@@ -918,8 +909,8 @@ void ESPER::drawVideoZoomOut(Graphics::Surface &surface) {
_timeZoomNext = timeNow + 300;
playSound(419, 25);
//TODO: implement frame loading after seek, then advanceFrame can be removed
- _vqaPhotoPlayer->seekToFrame(_vqaLastFrame);
- int nextFrame = _vqaPhotoPlayer->getFrameCount() / 4;
+ _vqaPlayerPhoto->seekToFrame(_vqaLastFrame);
+ int nextFrame = _vqaPlayerPhoto->getFrameCount() / 4;
if (nextFrame <= 0) {
nextFrame = 1;
} else if (nextFrame > 4) {
@@ -930,29 +921,27 @@ void ESPER::drawVideoZoomOut(Graphics::Surface &surface) {
_vqaLastFrame -= nextFrame;
}
- _vqaPhotoPlayer->update(true, advanceFrame);
+ _vqaPlayerPhoto->update(true, advanceFrame);
if (flash) {
flashViewport();
}
- copyImageBlit(_viewportData, Common::Rect(0, 0, 0, 0), &surface, _screen);
+ copyImageBlit(&_surfaceViewport, Common::Rect(0, 0, 0, 0), &surface, _screen);
drawGrid(surface);
if (timeNow > _timeZoomNext && _vqaLastFrame <= 0) {
- _vqaPhotoPlayer->close();
- delete _vqaPhotoPlayer;
- _vqaPhotoPlayer = nullptr;
+ _vqaPlayerPhoto->close();
+ delete _vqaPlayerPhoto;
+ _vqaPlayerPhoto = nullptr;
- //TODO: there is code to stop zooming, but it is not working properly in original game
- // if (_isMouseDown) {
- // zoomOutStart();
- // } else {
- // zoomOutStop();
- // }
- zoomOutStart();
+ if (_vm->isMouseButtonDown()) {
+ zoomOutStart();
+ } else {
+ zoomOutStop();
+ }
}
}
void ESPER::drawPhoto(Graphics::Surface &surface) {
- copyImageBlur(_photoData, _viewport, &surface, _screen, _blur);
+ copyImageBlur(&_surfacePhoto, _viewport, &surface, _screen, _blur);
}
void ESPER::drawGrid(Graphics::Surface &surface) {
@@ -966,7 +955,7 @@ void ESPER::drawGrid(Graphics::Surface &surface) {
}
void ESPER::drawPhotoWithGrid(Graphics::Surface &surface) {
- copyImageScale(_photoData, _viewport, &surface, _screen);
+ copyImageScale(&_surfacePhoto, _viewport, &surface, _screen);
drawGrid(surface);
}
@@ -1028,8 +1017,8 @@ void ESPER::drawSelection(Graphics::Surface &surface, bool crosshair, int style)
}
void ESPER::drawVideoFrame(Graphics::Surface &surface) {
- _vqaPhotoPlayer->update(true, false);
- copyImageBlit(_viewportData, Common::Rect(0, 0, 0, 0), &surface, _screen);
+ _vqaPlayerPhoto->update(true, false);
+ copyImageBlit(&_surfaceViewport, Common::Rect(0, 0, 0, 0), &surface, _screen);
}
void ESPER::drawTextCoords(Graphics::Surface &surface) {
@@ -1038,9 +1027,92 @@ void ESPER::drawTextCoords(Graphics::Surface &surface) {
_vm->_mainFont->drawColor(Common::String::format("EW %04d", 12 * _viewport.left + 167), surface, 364, 364, 0x001F);
}
+void ESPER::drawMouse(Graphics::Surface &surface) {
+ if (_vm->_mouse->isDisabled()) {
+ return;
+ }
+
+ int cursor = -1;
+
+ Common::Point p = _vm->getMousePos();
+
+ _mouseOverScroll = 4;
+ if (_stateMain == kEsperMainStatePhoto) {
+ if (_screen.contains(p)) {
+ if ((_statePhoto == kEsperPhotoStateShow) && ( _zoom != 2.0f)) {
+ if (_isMouseDown) {
+ if (_isDrawingSelection) {
+ _selection.right = p.x;
+ _selection.bottom = p.y;
+ } else {
+ _selection.left = p.x;
+ _selection.top = p.y;
+ _selection.right = p.x + 1;
+ _selection.bottom = p.y + 1;
+ _isDrawingSelection = true;
+ }
+ } else {
+ if (_isDrawingSelection) {
+ _selection.right = p.x;
+ _selection.bottom = p.y;
+
+ if (_selection.right < _selection.left) {
+ SWAP(_selection.left, _selection.right);
+ }
+ if (_selection.bottom < _selection.top) {
+ SWAP(_selection.bottom, _selection.top);
+ }
+
+ if (_selection.right >= _selection.left + 3) {
+ updateSelection();
+ _vm->_mouse->disable();
+ zoomingStart();
+ } else {
+ resetSelectionRect();
+ }
+ }
+ _isDrawingSelection = false;
+ }
+ }
+ surface.vLine(p.x, p.y - 8, p.y - 1, 0x03E0);
+ surface.vLine(p.x, p.y + 8, p.y + 1, 0x03E0);
+ surface.hLine(p.x - 8, p.y, p.x - 1, 0x03E0);
+ surface.hLine(p.x + 8, p.y, p.x + 1, 0x03E0);
+ _mouseOverScroll = -1;
+ } else if (p.x >= 85 && p.y >= 73 && p.x <= 484 && p.y <= 436) {
+ if (!_isDrawingSelection && _statePhoto != kEsperPhotoStateVideoShow && _zoom != 2.0f) {
+ _mouseOverScroll = (angle_1024((_screen.left + _screen.right) / 2, (_screen.top + _screen.bottom) / 2, p.x, p.y) + 128) / 256;
+ if (_mouseOverScroll >= 4) {
+ _mouseOverScroll = 0;
+ }
+ if (_mouseOverScroll == 0 && this->_viewport.top == 0) {
+ _mouseOverScroll = 4;
+ } else if (_mouseOverScroll == 1 && this->_viewport.right == kPhotoWidth - 1) {
+ _mouseOverScroll = 4;
+ } else if (_mouseOverScroll == 2 && this->_viewport.bottom == kPhotoHeight - 1) {
+ _mouseOverScroll = 4;
+ } else if (_mouseOverScroll == 3 && this->_viewport.left == 0) {
+ _mouseOverScroll = 4;
+ }
+ if (_mouseOverScroll != 4) {
+ cursor = _mouseOverScroll + 2;
+ }
+ }
+ }
+ }
+
+ if (_mouseOverScroll == 4) {
+ cursor = _buttons->hasHoveredImage() ? 1 : 0;
+ }
+ if (cursor != -1) {
+ _vm->_mouse->setCursor(cursor);
+ _vm->_mouse->draw(surface, p.x, p.y);
+ }
+}
+
void ESPER::flashViewport() {
- uint16 *ptr = (uint16 *)_viewportData->getPixels();
- for (int i = 0; i < _viewportData->w * _viewportData->h; ++i) {
+ uint16 *ptr = (uint16 *)_surfaceViewport.getPixels();
+ for (int i = 0; i < _surfaceViewport.w * _surfaceViewport.h; ++i) {
int8 r = (*ptr >> 10) & 0x1F;
int8 g = (*ptr >> 5) & 0x1F;
int8 b = (*ptr ) & 0x1F;
@@ -1303,89 +1375,6 @@ void ESPER::tickSound() {
}
}
-void ESPER::tickMouse(Graphics::Surface &surface) {
- if (_vm->_mouse->isDisabled()) {
- return;
- }
-
- int cursor = -1;
-
- Common::Point p = _vm->getMousePos();
-
- _mouseOverScroll = 4;
- if (_stateMain == kEsperMainStatePhoto) {
- if (_screen.contains(p)) {
- if ((_statePhoto == kEsperPhotoStateShow) && ( _zoom != 2.0f)) {
- if (_isMouseDown) {
- if (_isDrawingSelection) {
- _selection.right = p.x;
- _selection.bottom = p.y;
- } else {
- _selection.left = p.x;
- _selection.top = p.y;
- _selection.right = p.x + 1;
- _selection.bottom = p.y + 1;
- _isDrawingSelection = true;
- }
- } else {
- if (_isDrawingSelection) {
- _selection.right = p.x;
- _selection.bottom = p.y;
-
- if (_selection.right < _selection.left) {
- SWAP(_selection.left, _selection.right);
- }
- if (_selection.bottom < _selection.top) {
- SWAP(_selection.bottom, _selection.top);
- }
-
- if (_selection.right >= _selection.left + 3) {
- updateSelection();
- _vm->_mouse->disable();
- zoomingStart();
- } else {
- resetSelectionRect();
- }
- }
- _isDrawingSelection = false;
- }
- }
- surface.vLine(p.x, p.y - 8, p.y - 1, 0x03E0);
- surface.vLine(p.x, p.y + 8, p.y + 1, 0x03E0);
- surface.hLine(p.x - 8, p.y, p.x - 1, 0x03E0);
- surface.hLine(p.x + 8, p.y, p.x + 1, 0x03E0);
- _mouseOverScroll = -1;
- } else if (p.x >= 85 && p.y >= 73 && p.x <= 484 && p.y <= 436) {
- if (!_isDrawingSelection && _statePhoto != kEsperPhotoStateVideoShow && _zoom != 2.0f) {
- _mouseOverScroll = (angle_1024((_screen.left + _screen.right) / 2, (_screen.top + _screen.bottom) / 2, p.x, p.y) + 128) / 256;
- if (_mouseOverScroll >= 4) {
- _mouseOverScroll = 0;
- }
- if (_mouseOverScroll == 0 && this->_viewport.top == 0) {
- _mouseOverScroll = 4;
- } else if (_mouseOverScroll == 1 && this->_viewport.right == kPhotoWidth - 1) {
- _mouseOverScroll = 4;
- } else if (_mouseOverScroll == 2 && this->_viewport.bottom == kPhotoHeight - 1) {
- _mouseOverScroll = 4;
- } else if (_mouseOverScroll == 3 && this->_viewport.left == 0) {
- _mouseOverScroll = 4;
- }
- if (_mouseOverScroll != 4) {
- cursor = _mouseOverScroll + 2;
- }
- }
- }
- }
-
- if (_mouseOverScroll == 4) {
- cursor = _buttons->hasHoveredImage() ? 1 : 0;
- }
- if (cursor != -1) {
- _vm->_mouse->setCursor(cursor);
- _vm->_mouse->draw(surface, p.x, p.y);
- }
-}
-
void ESPER::tickScroll() {
int timeNow = _vm->getTotalPlayTime();
if (timeNow <= _timeScrollNext) {
@@ -1425,20 +1414,20 @@ void ESPER::selectPhoto(int photoId) {
reset();
}
- int photoSize = _photoData->w * _photoData->h * _photoData->format.bytesPerPixel;
+ int photoSize = _surfacePhoto.w * _surfacePhoto.h * _surfacePhoto.format.bytesPerPixel;
s->skip(3); // not used, but there is compression type
uint width = s->readUint32LE();
uint height = s->readUint32LE();
int photoCompressedSize = s->size() - s->pos();
- uint8 *photoCompressed = (uint8 *)_photoData->getPixels() + photoSize - photoCompressedSize;
+ uint8 *photoCompressed = (uint8 *)_surfacePhoto.getPixels() + photoSize - photoCompressedSize;
s->read(photoCompressed, photoCompressedSize);
- decompress_lcw(photoCompressed, photoCompressedSize, (uint8 *)_photoData->getPixels(), photoSize);
+ decompress_lcw(photoCompressed, photoCompressedSize, (uint8 *)_surfacePhoto.getPixels(), photoSize);
// apply palette
for (uint j = 0; j < width * height; ++j) {
- // _photoData[j] = Palette[_photoData[j]];
+ // _surfacePhoto[j] = Palette[_surfacePhoto[j]];
}
_shapeThumbnail = new Shape(_vm);
diff --git a/engines/bladerunner/ui/esper.h b/engines/bladerunner/ui/esper.h
index d63efa31bd..4a1c606498 100644
--- a/engines/bladerunner/ui/esper.h
+++ b/engines/bladerunner/ui/esper.h
@@ -26,9 +26,7 @@
#include "common/array.h"
#include "common/rect.h"
-namespace Graphics {
-struct Surface;
-}
+#include "graphics/surface.h"
namespace BladeRunner {
@@ -96,11 +94,11 @@ class ESPER {
UIImagePicker *_buttons;
- Graphics::Surface *_photoData;
- Graphics::Surface *_viewportData;
+ Graphics::Surface _surfacePhoto;
+ Graphics::Surface _surfaceViewport;
- VQAPlayer *_vqaMainPlayer;
- VQAPlayer *_vqaPhotoPlayer;
+ VQAPlayer *_vqaPlayerMain;
+ VQAPlayer *_vqaPlayerPhoto;
int _vqaLastFrame;
Shape *_shapeButton;
@@ -190,7 +188,7 @@ public:
void open(Graphics::Surface *surface);
void close();
- bool isOpen();
+ bool isOpen() const;
void handleMouseUp(int x, int y, bool buttonLeft);
void handleMouseDown(int x, int y, bool buttonLeft);
@@ -242,6 +240,7 @@ private:
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();
@@ -250,7 +249,6 @@ private:
void copyImageBlit(Graphics::Surface *src, Common::Rect srcRect, Graphics::Surface *dst, Common::Rect dstRect);
void tickSound();
- void tickMouse(Graphics::Surface &surface);
void tickScroll();
int findEmptyPhoto();
diff --git a/engines/bladerunner/ui/kia.cpp b/engines/bladerunner/ui/kia.cpp
index 729bec8d84..c27a548b3a 100644
--- a/engines/bladerunner/ui/kia.cpp
+++ b/engines/bladerunner/ui/kia.cpp
@@ -33,7 +33,7 @@
#include "bladerunner/mouse.h"
#include "bladerunner/scene.h"
#include "bladerunner/shape.h"
-#include "bladerunner/script/kia.h"
+#include "bladerunner/script/kia_script.h"
#include "bladerunner/settings.h"
#include "bladerunner/slice_renderer.h"
#include "bladerunner/text_resource.h"
@@ -192,7 +192,7 @@ void KIA::open(KIASections sectionId) {
}
}
-bool KIA::isOpen() {
+bool KIA::isOpen() const {
return _currentSectionId != kKIASectionNone;
}
@@ -350,8 +350,8 @@ void KIA::tick() {
_buttons->drawTooltip(_vm->_surfaceFront, mouse.x, mouse.y);
}
_vm->_mouse->draw(_vm->_surfaceFront, mouse.x, mouse.y);
- _vm->blitToScreen(_vm->_surfaceFront);
+ _vm->blitToScreen(_vm->_surfaceFront);
_vm->_system->delayMillis(10);
_timeLast = timeNow;
diff --git a/engines/bladerunner/ui/kia.h b/engines/bladerunner/ui/kia.h
index 0ac7a22600..1c2dc19d9f 100644
--- a/engines/bladerunner/ui/kia.h
+++ b/engines/bladerunner/ui/kia.h
@@ -25,7 +25,6 @@
#include "common/str.h"
-
namespace Common {
struct KeyState;
}
@@ -68,7 +67,6 @@ enum KIASections {
kKIASectionPogo = 10
};
-
class KIA {
static const char *kPogo;
static const int kPlayerActorDialogueQueueCapacity = 31;
@@ -130,7 +128,7 @@ public:
void openLastOpened();
void open(KIASections sectionId);
- bool isOpen();
+ bool isOpen() const;
void tick();
diff --git a/engines/bladerunner/ui/kia_section_clues.cpp b/engines/bladerunner/ui/kia_section_clues.cpp
index fc6270b938..e003e9bb28 100644
--- a/engines/bladerunner/ui/kia_section_clues.cpp
+++ b/engines/bladerunner/ui/kia_section_clues.cpp
@@ -29,7 +29,7 @@
#include "bladerunner/game_flags.h"
#include "bladerunner/game_info.h"
#include "bladerunner/font.h"
-#include "bladerunner/script/kia.h"
+#include "bladerunner/script/kia_script.h"
#include "bladerunner/text_resource.h"
#include "bladerunner/ui/kia.h"
#include "bladerunner/ui/kia_log.h"
@@ -76,6 +76,7 @@ KIASectionClues::~KIASectionClues() {
_uiContainer->clear();
delete _filterScrollBox;
delete _cluesScrollBox;
+ delete _buttons;
delete _uiContainer;
}
diff --git a/engines/bladerunner/ui/kia_section_crimes.cpp b/engines/bladerunner/ui/kia_section_crimes.cpp
index b70f790659..417a0588e0 100644
--- a/engines/bladerunner/ui/kia_section_crimes.cpp
+++ b/engines/bladerunner/ui/kia_section_crimes.cpp
@@ -30,7 +30,7 @@
#include "bladerunner/game_flags.h"
#include "bladerunner/game_info.h"
#include "bladerunner/shape.h"
-#include "bladerunner/script/kia.h"
+#include "bladerunner/script/kia_script.h"
#include "bladerunner/suspects_database.h"
#include "bladerunner/text_resource.h"
#include "bladerunner/ui/kia.h"
diff --git a/engines/bladerunner/ui/kia_section_suspects.cpp b/engines/bladerunner/ui/kia_section_suspects.cpp
index 0cad1123d7..af2c457d92 100644
--- a/engines/bladerunner/ui/kia_section_suspects.cpp
+++ b/engines/bladerunner/ui/kia_section_suspects.cpp
@@ -30,7 +30,7 @@
#include "bladerunner/game_flags.h"
#include "bladerunner/game_info.h"
#include "bladerunner/shape.h"
-#include "bladerunner/script/kia.h"
+#include "bladerunner/script/kia_script.h"
#include "bladerunner/suspects_database.h"
#include "bladerunner/text_resource.h"
#include "bladerunner/ui/kia.h"
diff --git a/engines/bladerunner/ui/ui_image_picker.cpp b/engines/bladerunner/ui/ui_image_picker.cpp
index c0015f1721..639c02f592 100644
--- a/engines/bladerunner/ui/ui_image_picker.cpp
+++ b/engines/bladerunner/ui/ui_image_picker.cpp
@@ -136,7 +136,11 @@ bool UIImagePicker::setImageTooltip(int i, const char *tooltip) {
return false;
}
- _images[i].tooltip = tooltip;
+ if (tooltip != nullptr) {
+ _images[i].tooltip = tooltip;
+ } else {
+ _images[i].tooltip.clear();
+ }
return true;
}
@@ -191,14 +195,17 @@ void UIImagePicker::draw(Graphics::Surface &surface) {
continue;
}
- // TODO: Check interaction with Mouse::isDisabled
if (i == _hoveredImageIndex && i == _pressedImageIndex && _isButtonDown) {
- if (img.shapeDown) {
- img.shapeDown->draw(surface, img.rect.left, img.rect.top);
+ if (!_vm->_mouse->isDisabled()) {
+ if (img.shapeDown) {
+ img.shapeDown->draw(surface, img.rect.left, img.rect.top);
+ }
}
} else if (i == _hoveredImageIndex && !_isButtonDown) {
- if (img.shapeHovered) {
- img.shapeHovered->draw(surface, img.rect.left, img.rect.top);
+ if (!_vm->_mouse->isDisabled()) {
+ if (img.shapeHovered) {
+ img.shapeHovered->draw(surface, img.rect.left, img.rect.top);
+ }
}
} else {
if (img.shapeUp) {
@@ -222,6 +229,11 @@ void UIImagePicker::drawTooltip(Graphics::Surface &surface, int x, int y) {
}
Common::String &tooltip = _images[_hoveredImageIndex].tooltip;
+
+ if (tooltip.empty()) {
+ return;
+ }
+
int width = _vm->_mainFont->getTextWidth(tooltip) + 1;
int height = _vm->_mainFont->getTextHeight(tooltip) + 1;
diff --git a/engines/bladerunner/ui/vk.cpp b/engines/bladerunner/ui/vk.cpp
new file mode 100644
index 0000000000..fab58e994f
--- /dev/null
+++ b/engines/bladerunner/ui/vk.cpp
@@ -0,0 +1,917 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/ui/vk.h"
+
+#include "bladerunner/actor.h"
+#include "bladerunner/ambient_sounds.h"
+#include "bladerunner/audio_player.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/combat.h"
+#include "bladerunner/font.h"
+#include "bladerunner/game_constants.h"
+#include "bladerunner/game_flags.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/mouse.h"
+#include "bladerunner/music.h"
+#include "bladerunner/scene.h"
+#include "bladerunner/shape.h"
+#include "bladerunner/script/vk_script.h"
+#include "bladerunner/slice_renderer.h"
+#include "bladerunner/text_resource.h"
+#include "bladerunner/ui/ui_image_picker.h"
+#include "bladerunner/vqa_player.h"
+
+#include "common/str.h"
+#include "common/keyboard.h"
+
+namespace BladeRunner {
+
+VK::VK(BladeRunnerEngine *vm) {
+ _vm = vm;
+
+ reset();
+}
+
+VK::~VK() {
+ reset();
+}
+
+void VK::open(int actorId, int calibrationRatio) {
+ if (!_vm->openArchive("MODE.MIX")) {
+ return;
+ }
+
+ reset();
+
+ _questions.resize(3);
+ for (int i = 0; i < (int)_questions.size(); ++i) {
+ _questions[i].resize(18);
+ for (int j = 0; j < (int)_questions[i].size(); ++j) {
+ _questions[i][j].isPresent = false;
+ _questions[i][j].wasAsked = false;
+ }
+ }
+
+ _volumeAmbient = _vm->_ambientSounds->getVolume();
+ _volumeMusic = _vm->_music->getVolume();
+
+ _actorId = actorId;
+ _calibrationRatio = calibrationRatio;
+ _calibration = 0;
+
+ _buttons = new UIImagePicker(_vm, 8);
+
+ _shapes.resize(15);
+ for (int i = 0; i < (int)_shapes.size(); ++i) {
+ _shapes[i] = new Shape(_vm);
+ _shapes[i]->open("VK.SHP", i);
+ }
+
+ _vqaPlayerMain = new VQAPlayer(_vm, &_vm->_surfaceBack);
+ if (!_vqaPlayerMain->open("VK.VQA")) {
+ return;
+ }
+
+ Common::String eyeVqa;
+ switch (actorId) {
+ case kActorDektora:
+ eyeVqa = "VKDEKT.VQA";
+ break;
+ case kActorLucy:
+ eyeVqa = "VKLUCY.VQA";
+ break;
+ case kActorGrigorian:
+ eyeVqa = "VKKASH.VQA";
+ break;
+ case kActorBulletBob:
+ eyeVqa = "VKBOB.VQA";
+ break;
+ case kActorRunciter:
+ eyeVqa = "VKRUNC.VQA";
+ break;
+ default:
+ return;
+ }
+
+ _surfaceEye.create(172, 116, createRGB555());
+ _vqaPlayerEye = new VQAPlayer(_vm, &_surfaceEye);
+ if (!_vqaPlayerEye->open(eyeVqa)) {
+ return;
+ }
+ if (!_vqaPlayerEye->setLoop(0, -1, kLoopSetModeEnqueue, nullptr, nullptr)) {
+ return;
+ }
+
+ _isOpen = true;
+
+ _script = new VKScript(_vm);
+
+ //TODO: time->lock()
+
+ init();
+}
+
+bool VK::isOpen() const {
+ return _isOpen;
+}
+
+void VK::close() {
+ if (_vm->_audioPlayer->isActive(_soundTrackId1)) {
+ _vm->_audioPlayer->stop(_soundTrackId1, false);
+ }
+
+ if (_vm->_audioPlayer->isActive(_soundTrackId3)) {
+ _vm->_audioPlayer->stop(_soundTrackId3, false);
+ }
+
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(458), 33, 0, 0, 50, 0);
+
+ _script->shutdown(_actorId, _humanProbability, _replicantProbability, _anxiety);
+
+ delete _script;
+ _script = nullptr;
+
+
+ if (_buttons) {
+ _buttons->deactivate();
+ _buttons->resetImages();
+ delete _buttons;
+ _buttons = nullptr;
+ }
+
+ if (_vqaPlayerEye) {
+ _vqaPlayerEye->close();
+ delete _vqaPlayerEye;
+ _vqaPlayerEye = nullptr;
+ }
+
+ if (_vqaPlayerMain) {
+ _vqaPlayerMain->close();
+ delete _vqaPlayerMain;
+ _vqaPlayerMain = nullptr;
+ }
+
+ _questions.clear();
+
+ for (int i = 0; i < (int)_shapes.size(); ++i) {
+ delete _shapes[i];
+ }
+ _shapes.clear();
+
+ _vm->closeArchive("MODE.MIX");
+ _vm->_music->setVolume(_volumeMusic);
+ _vm->_ambientSounds->setVolume(_volumeAmbient);
+
+ // TODO: time->unlock();
+ // _vm->_scene->resume(false);
+}
+
+void VK::tick() {
+ int mouseX, mouseY;
+ _vm->_mouse->getXY(&mouseX, &mouseY);
+ if (!_vm->_mouse->isDisabled()) {
+ _buttons->handleMouseAction(mouseX, mouseY, false, false, false);
+ }
+
+ draw();
+
+ _vm->blitToScreen(_vm->_surfaceFront);
+ _vm->_system->delayMillis(10);
+
+ if (_isClosing && (int)_vm->getTotalPlayTime() >= _timeClose && !_script->isInsideScript()) {
+ close();
+ _vm->_mouse->enable();
+ reset();
+ }
+}
+
+void VK::handleMouseDown(int mouseX, int mouseY, bool mainButton) {
+ if (!_vm->_mouse->isDisabled()) {
+ if (!_buttons->handleMouseAction(mouseX, mouseY, true, false, false)) {
+ tick();
+ }
+ }
+}
+
+void VK::handleMouseUp(int mouseX, int mouseY, bool mainButton) {
+ if (!_vm->_mouse->isDisabled()) {
+ _buttons->handleMouseAction(mouseX, mouseY, false, true, false);
+ }
+}
+
+void VK::addQuestion(int intensity, int sentenceId, int relatedSentenceId) {
+ for (int i = 0; i < (int)_questions[intensity].size(); ++i) {
+ if (!_questions[intensity][i].isPresent) {
+ _questions[intensity][i].isPresent = true;
+ _questions[intensity][i].sentenceId = sentenceId;
+ _questions[intensity][i].relatedSentenceId = relatedSentenceId;
+ return;
+ }
+ }
+}
+
+void VK::playSpeechLine(int actorId, int sentenceId, float duration) {
+ _vm->gameWaitForActive();
+
+ _vm->_mouse->disable();
+
+ Actor *actor = _vm->_actors[actorId];
+ actor->speechPlay(sentenceId, true);
+
+ while (_vm->_gameIsRunning) {
+ // ActorSpeaking = 1;
+ _vm->_speechSkipped = false;
+ _vm->gameTick();
+ // ActorSpeaking = 0;
+ if (_vm->_speechSkipped || !actor->isSpeeching()) {
+ actor->speechStop();
+ break;
+ }
+ }
+
+ if (duration > 0.0f && !_vm->_speechSkipped) {
+ int timeEnd = duration * 1000.0f + _vm->getTotalPlayTime();
+ while (timeEnd > (int)_vm->getTotalPlayTime() && _vm->_gameIsRunning) {
+ _vm->gameTick();
+ }
+ }
+
+ _vm->_speechSkipped = false;
+
+ _vm->_mouse->enable();
+}
+
+void VK::subjectReacts(int intensity, int humanResponse, int replicantResponse, int anxiety) {
+ humanResponse = CLIP(humanResponse, -20, 20);
+ replicantResponse = CLIP(replicantResponse, -20, 20);
+
+ int timeNow = _vm->getTotalPlayTime();
+
+ if (intensity > 0) {
+ _needleValueTarget = 78 * intensity / 100;
+ _needleValueDelta = (_needleValueTarget - _needleValue) / 10;
+ _timeNextNeedleStep = timeNow + 66;
+ }
+
+ if (humanResponse != 0) {
+ _humanProbability = CLIP(_humanProbability + humanResponse + _calibration, 0, 100);
+ if (_humanProbability >= 80 && !_isClosing) {
+ _isClosing = true;
+ _timeClose = timeNow + 3000;
+ _vm->_mouse->disable();
+ }
+ _humanGaugeTarget = humanResponse;
+ _humanGaugeDelta = humanResponse / 10;
+ if (_humanGaugeDelta == 0) {
+ _humanGaugeDelta = humanResponse / abs(humanResponse);
+ }
+ }
+
+ if (replicantResponse != 0) {
+ _replicantProbability = CLIP(_replicantProbability + replicantResponse - _calibration, 0, 100);
+ if (_replicantProbability >= 80 && !_isClosing) {
+ _isClosing = true;
+ _timeClose = timeNow + 3000;
+ _vm->_mouse->disable();
+ }
+ _replicantGaugeTarget = replicantResponse;
+ _replicantGauge = replicantResponse / 10;
+ if (_replicantGaugeDelta == 0) {
+ _replicantGaugeDelta = replicantResponse / abs(replicantResponse);
+ }
+ }
+
+ _anxiety = CLIP(_anxiety + anxiety, 0, 100);
+ if (_anxiety == 100 && !_isClosing) {
+ _isClosing = true;
+ _timeClose = timeNow + 3000;
+ _vm->_mouse->disable();
+ }
+}
+
+void VK::eyeAnimates(int loopId) {
+ _vqaPlayerEye->setLoop(loopId, -1, kLoopSetModeImmediate, nullptr, nullptr);
+ _vqaPlayerEye->setLoop(0, -1, kLoopSetModeEnqueue, nullptr, nullptr);
+}
+
+void VK::mouseDownCallback(int buttonId, void *callbackData) {
+ VK *self = (VK *)callbackData;
+
+ switch (buttonId) {
+ case 1:
+ self->startAdjustement();
+ break;
+ case 2:
+ case 3:
+ case 4:
+ if (self->_calibrationStarted) {
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(457), 100, 0, 0, 50, 0);
+ }
+ break;
+ case 5:
+ self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(457), 100, 0, 0, 50, 0);
+ break;
+ default:
+ return;
+ }
+}
+
+void VK::mouseUpCallback(int buttonId, void *callbackData) {
+ VK *self = (VK *)callbackData;
+
+ switch (buttonId) {
+ case 0:
+ self->calibrate();
+ break;
+ case 1:
+ self->stopAdjustement();
+ break;
+ case 2:
+ self->askQuestion(0);
+ break;
+ case 3:
+ self->askQuestion(1);
+ break;
+ case 4:
+ self->askQuestion(2);
+ break;
+ case 5:
+ self->_isClosing = true;
+ break;
+ default:
+ return;
+ }
+}
+
+void VK::loopEnded(void *callbackData, int frame, int loopId) {
+ VK *self = (VK *)callbackData;
+
+ self->_vqaLoopEnded = true;
+ self->_vqaPlayerMain->setLoop(2, -1, kLoopSetModeJustStart, nullptr, nullptr);
+}
+
+void VK::reset() {
+ _buttons = nullptr;
+ _vqaPlayerMain = nullptr;
+ _vqaPlayerEye = nullptr;
+
+ _script = nullptr;
+
+ _isOpen = false;
+
+ _shapes.clear();
+
+ _calibrationCounter = 0;
+ _calibrationStarted = false;
+ _calibration = 0;
+
+ _testStarted = false;
+
+ _needleValue = 0;
+ _needleValueTarget = 0;
+ _needleValueDelta = 0;
+ _timeNextNeedleStep = 0;
+ _timeNeedleReturn = 0;
+ _timeNextNeedleOscillate = 0;
+
+ _humanProbability = 0;
+ _humanGauge = 0;
+ _humanGaugeTarget = 0;
+ _humanGaugeDelta = 0;
+ _timeNextHumanGaugeStep = 0;
+
+ _replicantProbability = 0;
+ _replicantGauge = 0;
+ _replicantGaugeTarget = 0;
+ _replicantGaugeDelta = 0;
+ _timeNextReplicantGaugeStep = 0;
+
+ _anxiety = 0;
+
+ _blinkState = 0;
+ _timeNextBlink = 0;
+ _timeNextGaugesBlink = 0;
+
+ _isClosing = false;
+ _timeClose = 0;
+
+ _isAdjusting = false;
+ _adjustment = 154;
+ _adjustmentTarget = 154;
+ _adjustmentDelta = 0;
+
+ _eyeLineSelected = 1;
+ _eyeLineX = 315;
+ _eyeLineXLast = 315;
+ _eyeLineY = 281;
+ _eyeLineYLast = 281;
+ _eyeLineXDelta = 8;
+ _eyeLineYDelta = 8;
+ _timeNextEyeLineStep = 0;
+ _timeNextEyeLineStart = 0;
+
+ _soundTrackId1 = -1;
+ _soundTrackId2 = -1;
+ _soundTrackId3 = -1;
+ _vqaLoopEnded = false;
+
+ _surfaceEye.free();
+}
+
+void VK::init() {
+ _vm->_mouse->disable();
+
+ _buttons->activate(nullptr, nullptr, mouseDownCallback, mouseUpCallback, this);
+ _buttons->defineImage(0, Common::Rect(191, 364, 218, 373), nullptr, _shapes[2], _shapes[3], _vm->_textVK->getText(1));
+ _buttons->defineImage(1, Common::Rect(154, 258, 161, 265), _shapes[4], _shapes[4], _shapes[5], _vm->_textVK->getText(2));
+ _buttons->defineImage(2, Common::Rect(515, 368, 538, 398), nullptr, _shapes[6], _shapes[7], nullptr);
+ _buttons->defineImage(3, Common::Rect(548, 368, 571, 398), nullptr, _shapes[8], _shapes[9], nullptr);
+ _buttons->defineImage(4, Common::Rect(581, 368, 604, 398), nullptr, _shapes[10], _shapes[11], nullptr);
+ _buttons->defineImage(5, Common::Rect( 31, 363, 65, 392), nullptr, _shapes[0], _shapes[1], _vm->_textVK->getText(0));
+ _buttons->defineImage(6, Common::Rect( 59, 262, 87, 277), nullptr, nullptr, nullptr, _vm->_textVK->getText(6));
+ _buttons->defineImage(7, Common::Rect( 59, 306, 87, 322), nullptr, nullptr, nullptr, _vm->_textVK->getText(7));
+
+ _script->initialize(_actorId);
+
+ _vqaPlayerMain->setLoop(0, -1, kLoopSetModeJustStart, nullptr, nullptr);
+ tick();
+ _vqaPlayerMain->setLoop(1, -1, kLoopSetModeEnqueue, loopEnded, this);
+}
+
+void VK::draw() {
+ if (!_isOpen || !_vm->_gameIsRunning) {
+ return;
+ }
+
+ int frame = _vqaPlayerMain->update();
+ if (frame >= 0) {
+ _vqaFrameMain = frame;
+ }
+
+ if (frame == 0) {
+ _soundTrackId2 = _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(426), 33, 0, 0, 50, 0);
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(431), 50, 0, 0, 50, 0);
+ } else if (frame == 26) {
+ _vm->_audioPlayer->stop(_soundTrackId2, false);
+ _soundTrackId1 = _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(429), 50, 30, 30, 50, kAudioPlayerLoop);
+ } else if (frame == 40) {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(428), 33, 0, 0, 50, 0);
+ eyeAnimates(1);
+ } else if (frame == 59) {
+ _vm->_mouse->enable();
+ _buttons->setImageShapeHovered(2, nullptr);
+ _buttons->setImageShapeDown(2, nullptr);
+ _buttons->setImageShapeHovered(3, nullptr);
+ _buttons->setImageShapeDown(3, nullptr);
+ _buttons->setImageShapeHovered(4, nullptr);
+ _buttons->setImageShapeDown(4, nullptr);
+ } else if (frame == 100) {
+ if (_vm->_rnd.getRandomNumberRng(0, 100) > 60) {
+ eyeAnimates(1);
+ }
+ } else if (frame == 140) {
+ if (_vm->_rnd.getRandomNumberRng(0, 10) > 6) {
+ _soundTrackId3 = _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(459), 83, 0, 0, 50, 0);
+ }
+ }
+
+ blit(_vm->_surfaceBack, _vm->_surfaceFront);
+
+ Graphics::Surface &surface = _vm->_surfaceFront;
+
+ int timeNow = _vm->getTotalPlayTime();
+
+ if (_isAdjusting && !_testStarted && !_vm->isMouseButtonDown()) {
+ _isAdjusting = false;
+ }
+
+ if (_vqaFrameMain >= 26) {
+ if (_isClosing && timeNow >= _timeNextGaugesBlink) {
+ if (_blinkState) {
+ _buttons->setImageShapeUp(6, nullptr);
+ _buttons->setImageShapeUp(7, nullptr);
+ _blinkState = 0;
+ } else {
+ if (_humanProbability >= 80) {
+ _buttons->setImageShapeUp(6, _shapes[13]);
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(0), 100, 0, 0, 50, 0);
+ }
+ if (_replicantProbability >= 80) {
+ _buttons->setImageShapeUp(7, _shapes[14]);
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(0), 100, 0, 0, 50, 0);
+ }
+ _blinkState = 1;
+ }
+ _timeNextGaugesBlink = timeNow + 600;
+ }
+
+ _buttons->draw(surface);
+
+ if (_humanGaugeDelta != 0 && timeNow >= _timeNextHumanGaugeStep) {
+ _humanGauge += _humanGaugeDelta;
+
+ if ((_humanGaugeDelta > 0 && _humanGauge >= _humanGaugeTarget)
+ || (_humanGaugeDelta < 0 && _humanGauge <= _humanGaugeTarget)) {
+ _humanGauge = _humanGaugeTarget;
+ }
+
+ if (_humanGauge == _humanGaugeTarget) {
+ if (_humanGaugeTarget != 0) {
+ _humanGaugeTarget = 0;
+ _humanGaugeDelta = -_humanGaugeDelta;
+ _timeNextHumanGaugeStep = timeNow + 500;
+ } else {
+ _humanGaugeDelta = 0;
+ }
+ } else {
+ _timeNextHumanGaugeStep = timeNow + 66;
+ }
+ }
+ drawHumanGauge(surface);
+
+ if (_replicantGaugeDelta != 0 && timeNow >= _timeNextReplicantGaugeStep) {
+ _replicantGauge += _replicantGaugeDelta;
+
+ if ((_replicantGaugeDelta > 0 && _replicantGauge >= _replicantGaugeTarget)
+ || (_replicantGaugeDelta < 0 && _replicantGauge <= _replicantGaugeTarget)) {
+ _replicantGauge = _replicantGaugeTarget;
+ }
+
+ if (_replicantGauge == _replicantGaugeTarget) {
+ if (_replicantGaugeTarget != 0) {
+ _replicantGaugeTarget = 0;
+ _replicantGaugeDelta = -_replicantGaugeDelta;
+ _timeNextReplicantGaugeStep = timeNow + 500;
+ } else {
+ _replicantGaugeDelta = 0;
+ }
+ } else {
+ _timeNextReplicantGaugeStep = timeNow + 66;
+ }
+ }
+ drawReplicantGauge(surface);
+
+ if (!_calibrationStarted && _vqaFrameMain >= 59 && timeNow >= _timeNextBlink) {
+ if (_blinkState) {
+ _buttons->setImageShapeUp(0, nullptr);
+ _blinkState = false;
+ } else {
+ _buttons->setImageShapeUp(0, _shapes[2]);
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(461), 50, 0, 0, 50, 0);
+ _blinkState = true;
+ }
+ _timeNextBlink = timeNow + 600;
+ }
+
+ if (_adjustmentDelta != 0 && timeNow >= _timeNextAdjustementStep) {
+ if (_adjustmentDelta > 0) {
+ _adjustment += 3;
+ if (_adjustment >= _adjustmentTarget) {
+ _adjustment = _adjustmentTarget;
+ _adjustmentDelta = 0;
+ }
+ } else {
+ _adjustment -= 3;
+ if (_adjustment <= _adjustmentTarget) {
+ _adjustment = _adjustmentTarget;
+ _adjustmentDelta = 0;
+ }
+ }
+ setAdjustment(_adjustment + 4);
+ }
+ setAdjustmentFromMouse();
+
+ if (_calibrationStarted && !_testStarted && timeNow >= _timeNextBlink) {
+ if (_blinkState) {
+ _buttons->setImageShapeUp(2, nullptr);
+ _buttons->setImageShapeUp(3, nullptr);
+ _buttons->setImageShapeUp(4, nullptr);
+ _blinkState = 0;
+ } else {
+ _buttons->setImageShapeUp(2, _shapes[7]);
+ _buttons->setImageShapeUp(3, _shapes[9]);
+ _buttons->setImageShapeUp(4, _shapes[11]);
+ _blinkState = 1;
+
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(462), 33, 0, 0, 50, 0);
+ }
+ _timeNextBlink = timeNow + 600;
+ }
+
+ if (_needleValueDelta != 0 && timeNow >= _timeNextNeedleStep) {
+ if (_needleValueDelta > 0) {
+ _needleValue += 4;
+ if (_needleValue >= _needleValueTarget) {
+ _needleValue = _needleValueTarget;
+ _needleValueMax = _needleValueTarget;
+ _needleValueDelta = -_needleValueDelta;
+ _needleValueTarget = 0;
+
+ _timeNeedleReturn = timeNow + 1800;
+
+ if (!_testStarted) {
+ animateAdjustment(_needleValueMax + 165);
+ }
+ }
+ } else if (timeNow >= _timeNeedleReturn) {
+ _needleValue -= 4;
+ if (_needleValue <= _needleValueTarget) {
+ _needleValue = _needleValueTarget;
+ _needleValueDelta = 0;
+ }
+ }
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(455), 20, 0, 0, 50, 0);
+ _timeNextNeedleStep = timeNow + 66;
+ }
+
+ drawNeedle(surface);
+ drawEye(surface);
+ drawEyeCrosshair(surface, timeNow);
+ if (timeNow >= _timeNextNeedleOscillate) {
+ _timeNextNeedleOscillate = timeNow + 66;
+ }
+ int mouseX, mouseY;
+ _vm->_mouse->getXY(&mouseX, &mouseY);
+ _buttons->drawTooltip(surface, mouseX, mouseY);
+ }
+
+ drawMouse(surface);
+}
+
+void VK::drawNeedle(Graphics::Surface &surface) {
+ int x = _needleValue + 165;
+ if ((int)_vm->getTotalPlayTime() >= _timeNextNeedleOscillate && x > 165) {
+ x = CLIP(x + (int)_vm->_rnd.getRandomNumberRng(0, 4) - 2, 165, 245);
+ }
+
+ float needleOffset = abs(38.0f - _needleValue);
+ float y = 345 - sqrt(72.0f * 72.0f - needleOffset * needleOffset);
+
+ float colorIntensity = MIN(78.0f, _needleValue + 39.0f) / 78.0f;
+
+ int r = 6 * colorIntensity;
+ int g = 8 * colorIntensity;
+ int b = 12 * colorIntensity;
+
+ surface.drawLine(203, 324, x - 2, y, ((7 - r ) << 10) | ((18 - g ) << 5) | (23 - b ));
+ surface.drawLine(203, 324, x + 2, y, ((7 - r ) << 10) | ((18 - g ) << 5) | (23 - b ));
+ surface.drawLine(203, 324, x - 1, y, ((7 - r / 2) << 10) | ((18 - g / 2) << 5) | (23 - b / 2));
+ surface.drawLine(203, 324, x + 1, y, ((7 - r / 2) << 10) | ((18 - g / 2) << 5) | (23 - b / 2));
+ surface.drawLine(203, 324, x, y - 1, ((7 - r / 2) << 10) | ((18 - g / 2) << 5) | (23 - b / 2));
+ surface.drawLine(203, 324, x, y, 0x1E57);
+}
+
+void VK::drawEye(Graphics::Surface &surface) {
+ _vqaPlayerEye->update(true);
+ surface.copyRectToSurface(_surfaceEye, 315, 281, Common::Rect(0, 0, _surfaceEye.w, _surfaceEye.h));
+}
+
+void VK::drawEyeCrosshair(Graphics::Surface &surface, int timeNow) {
+ surface.drawLine(315, _eyeLineY, 486, _eyeLineY, 0x848u);
+ surface.drawLine(315, _eyeLineY - 1, 486, _eyeLineY - 1, 0x848u);
+ surface.drawLine(315, _eyeLineY, _vm->_rnd.getRandomNumberRng(10, 20) + 315, _eyeLineY, 0x84Au);
+ surface.drawLine(486 - _vm->_rnd.getRandomNumberRng(10, 20), _eyeLineY, 486, _eyeLineY, 0x84Au);
+ surface.drawLine(486 - _vm->_rnd.getRandomNumberRng(10, 20), _eyeLineY - 1, 486, _eyeLineY - 1, 0x846u);
+ surface.drawLine(315, _eyeLineY - 1, _vm->_rnd.getRandomNumberRng(10, 20) + 315, _eyeLineY - 1, 0x846u);
+
+ surface.drawLine(_eyeLineX, 281, _eyeLineX, 396, 0x848u);
+ surface.drawLine(_eyeLineX - 1, 281, _eyeLineX - 1, 396, 0x848u);
+ surface.drawLine(_eyeLineX, 281, _eyeLineX, _vm->_rnd.getRandomNumberRng(10, 20) + 281, 0x846u);
+ surface.drawLine(_eyeLineX, 396 - _vm->_rnd.getRandomNumberRng(10, 20), _eyeLineX, 396, 0x846u);
+ surface.drawLine(_eyeLineX - 1, 396 - _vm->_rnd.getRandomNumberRng(10, 20), _eyeLineX - 1, 396, 0x84Au);
+ surface.drawLine(_eyeLineX - 1, 281, _eyeLineX - 1, _vm->_rnd.getRandomNumberRng(10, 20) + 281, 0x84Au);
+
+ if (timeNow >= _timeNextEyeLineStart) {
+ if (_eyeLineSelected) {
+ if (_eyeLineYLast != _eyeLineY) {
+ surface.drawLine(315, _eyeLineYLast, 486, _eyeLineYLast, 0x844u);
+ }
+ _eyeLineYLast = _eyeLineY;
+ if (timeNow >= _timeNextEyeLineStep) {
+ _eyeLineY += _eyeLineYDelta;
+ if (_eyeLineYDelta > 0) {
+ if (_eyeLineY >= 396) {
+ _eyeLineY = 396;
+ _eyeLineYDelta = -_eyeLineYDelta;
+ }
+ } else if (_eyeLineY <= 281) {
+ _eyeLineY = 281;
+ _eyeLineYDelta = -_eyeLineYDelta;
+ _eyeLineSelected = 0;
+ _timeNextEyeLineStart = timeNow + 1000;
+ }
+ _timeNextEyeLineStep = timeNow + 50;
+ }
+ } else {
+ if (_eyeLineXLast != _eyeLineX) {
+ surface.drawLine(_eyeLineXLast, 281, _eyeLineXLast, 396, 0x844u);
+ }
+ _eyeLineXLast = _eyeLineX;
+ if (timeNow >= _timeNextEyeLineStep) {
+ _eyeLineX += _eyeLineXDelta;
+ if ( _eyeLineXDelta > 0) {
+ if (_eyeLineX >= 486) {
+ _eyeLineX = 486;
+ _eyeLineXDelta = -_eyeLineXDelta;
+ }
+ } else if (_eyeLineX <= 315) {
+ _eyeLineX = 315;
+ _eyeLineXDelta = -_eyeLineXDelta;
+ _eyeLineSelected = 1;
+ _timeNextEyeLineStart = timeNow + 1000;
+ }
+ _timeNextEyeLineStep = timeNow + 50;
+ }
+ }
+ }
+}
+
+void VK::drawMouse(Graphics::Surface &surface) {
+ if (_vm->_mouse->isDisabled()) {
+ return;
+ }
+
+ Common::Point p = _vm->getMousePos();
+
+ if (_buttons->hasHoveredImage()) {
+ _vm->_mouse->setCursor(1);
+ } else {
+ _vm->_mouse->setCursor(0);
+ }
+
+ _vm->_mouse->draw(surface, p.x, p.y);
+}
+
+void VK::drawGauge(Graphics::Surface &surface, int value, int x, int y, int width) {
+ _shapes[12]->draw(surface, x + (width / 2) * value / 20 , y);
+}
+
+void VK::drawHumanGauge(Graphics::Surface &surface) {
+ drawGauge(surface, _humanGauge, 72, 271, 87);
+}
+
+void VK::drawReplicantGauge(Graphics::Surface &surface) {
+ drawGauge(surface, _replicantGauge, 72, 293, 87);
+}
+
+void VK::calibrate() {
+ if (_calibrationCounter >= 3 || _testStarted) {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(460), 100, 0, 0, 50, 0);
+ } else {
+ _vm->_mouse->disable();
+ _script->calibrate(_actorId);
+ _vm->_mouse->enable();
+ ++_calibrationCounter;
+ if (_calibrationCounter == 3) {
+ _buttons->setImageShapeHovered(0, nullptr);
+ _buttons->setImageShapeDown(0, nullptr);
+ _buttons->setImageTooltip(0, nullptr);
+ }
+ }
+ _calibrationStarted = true;
+ _buttons->setImageShapeUp(0, nullptr);
+
+ _buttons->setImageShapeHovered(2, _shapes[6]);
+ _buttons->setImageShapeDown(2, _shapes[7]);
+ _buttons->setImageTooltip(2, _vm->_textVK->getText(3));
+
+ _buttons->setImageShapeHovered(3, _shapes[8]);
+ _buttons->setImageShapeDown(3, _shapes[9]);
+ _buttons->setImageTooltip(3, _vm->_textVK->getText(4));
+
+ _buttons->setImageShapeHovered(4, _shapes[10]);
+ _buttons->setImageShapeDown(4, _shapes[11]);
+ _buttons->setImageTooltip(4, _vm->_textVK->getText(5));
+}
+
+void VK::beginTest() {
+ if (_calibrationStarted && !_testStarted) {
+ _vm->_mouse->disable();
+ _calibration = ((100.0f / (100.0f - 4.0f) * (_adjustment - 154.0f)) - _calibrationRatio) / 5.0f;
+ _script->beginTest(_actorId);
+ _testStarted = true;
+ _buttons->setImageShapeHovered(0, nullptr);
+ _buttons->setImageShapeDown(0, nullptr);
+ _buttons->setImageTooltip(0, nullptr);
+ _buttons->setImageShapeDown(1, _shapes[4]);
+ _buttons->setImageTooltip(1, nullptr);
+ _buttons->setImageShapeUp(2, nullptr);
+ _buttons->setImageShapeUp(3, nullptr);
+ _buttons->setImageShapeUp(4, nullptr);
+ _vm->_mouse->enable();
+ } else {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(460), 100, 0, 0, 50, 0);
+ }
+}
+
+void VK::startAdjustement() {
+ if (_testStarted) {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(460), 100, 0, 0, 50, 0);
+ } else {
+ _isAdjusting = true;
+ }
+}
+
+void VK::stopAdjustement() {
+ if (_testStarted) {
+ _isAdjusting = false;
+ }
+}
+
+void VK::animateAdjustment(int target) {
+ _adjustmentTarget = MAX(target - 4, 154);
+ _adjustmentDelta = (_adjustmentTarget - _adjustment) / 5;
+ _timeNextAdjustementStep = _vm->getTotalPlayTime() + 50;
+}
+
+void VK::setAdjustment(int x) {
+ _adjustment = CLIP(x - 4, 154, 246);
+ float offset = abs(199.0f - _adjustment);
+ int y = sqrt(88.0f * 88.0f - offset * offset);
+ _buttons->setImageLeft(1, _adjustment);
+ _buttons->setImageTop(1, 345 - y);
+}
+
+void VK::setAdjustmentFromMouse() {
+ if (_isAdjusting && !_testStarted) {
+ int mouseX, mouseY;
+ _vm->_mouse->getXY(&mouseX, &mouseY);
+ setAdjustment(mouseX);
+ if (_adjustmentTarget != _adjustment) {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(456), 100, 0, 0, 50, 0);
+ }
+ _adjustmentTarget = _adjustment;
+ _adjustmentDelta = 0;
+ }
+}
+
+void VK::askQuestion(int intensity) {
+ assert(intensity < (int)_questions.size());
+
+ if (!_testStarted) {
+ beginTest();
+ }
+
+ if (!_testStarted) {
+ return;
+ }
+
+ int foundQuestionIndex = -1;
+ int foundQuestionIndexLast = -1;
+
+ for (int i = 0; i < (int)_questions[intensity].size(); ++i) {
+ if (_questions[intensity][i].isPresent && !_questions[intensity][i].wasAsked) {
+ int relatedQuestion = -1;
+ if (_questions[intensity][i].relatedSentenceId >= 0) {
+ // TODO: but not used in game
+ // relatedQuestion = vk::findQuestionById(this, questions, relatedQuestionId);
+ }
+
+ if (relatedQuestion < 0 || _questions[intensity][relatedQuestion].wasAsked) {
+ foundQuestionIndexLast = i;
+ if (_vm->_rnd.getRandomNumberRng(0, 100) < 20) {
+ foundQuestionIndex = i;
+ break;
+ }
+ }
+ }
+ }
+
+ if (foundQuestionIndex < 0) {
+ foundQuestionIndex = foundQuestionIndexLast;
+ }
+
+ if (foundQuestionIndex >= 0) {
+ _vm->_mouse->disable();
+ _questions[intensity][foundQuestionIndex].wasAsked = true;
+ _script->mcCoyAsksQuestion(_actorId, _questions[intensity][foundQuestionIndex].sentenceId);
+ _script->questionAsked(_actorId, _questions[intensity][foundQuestionIndex].sentenceId);
+ _vm->_mouse->enable();
+ } else if (!_isClosing && !_script->isInsideScript()) {
+ _isClosing = true;
+ _vm->_mouse->disable();
+ _timeClose = _vm->getTotalPlayTime() + 3000;
+ }
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/vk.h b/engines/bladerunner/ui/vk.h
new file mode 100644
index 0000000000..77a419afb5
--- /dev/null
+++ b/engines/bladerunner/ui/vk.h
@@ -0,0 +1,174 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BLADERUNNER_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 Shape;
+class UIImagePicker;
+class VQAPlayer;
+
+class VK {
+ struct Question {
+ bool isPresent;
+ bool wasAsked;
+ int sentenceId;
+ int relatedSentenceId;
+ };
+
+ BladeRunnerEngine *_vm;
+
+ VKScript *_script;
+
+ UIImagePicker *_buttons;
+ Common::Array<Shape *> _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 _volumeAmbient;
+ int _volumeMusic;
+ int _soundTrackId1;
+ int _soundTrackId2;
+ int _soundTrackId3;
+
+ int _calibration;
+ int _calibrationRatio;
+ int _calibrationCounter;
+
+ int _humanProbability;
+ int _humanGauge;
+ int _humanGaugeTarget;
+ int _humanGaugeDelta;
+ int _timeNextHumanGaugeStep;
+
+ int _replicantProbability;
+ int _replicantGauge;
+ int _replicantGaugeTarget;
+ int _replicantGaugeDelta;
+ int _timeNextReplicantGaugeStep;
+
+ int _anxiety;
+
+ int _needleValue;
+ int _needleValueMax;
+ int _needleValueTarget;
+ int _needleValueDelta;
+ int _timeNextNeedleStep;
+ int _timeNextNeedleOscillate;
+ int _timeNeedleReturn;
+
+ bool _isClosing;
+ int _timeClose;
+
+ int _blinkState;
+ int _timeNextBlink;
+ int _timeNextGaugesBlink;
+
+ bool _isAdjusting;
+ int _adjustment;
+ int _adjustmentTarget;
+ int _adjustmentDelta;
+ int _timeNextAdjustementStep;
+
+ int _eyeLineSelected;
+ int _eyeLineX;
+ int _eyeLineXLast;
+ int _eyeLineY;
+ int _eyeLineYLast;
+ int _eyeLineXDelta;
+ int _eyeLineYDelta;
+ int _timeNextEyeLineStep;
+ int _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 duration);
+ 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, int 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 askQuestion(int intensity);
+};
+
+} // End of namespace BladeRunner
+#endif