mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-24 21:21:05 +00:00
1807 lines
51 KiB
C++
1807 lines
51 KiB
C++
/* 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/esper.h"
|
||
|
||
#include "bladerunner/actor.h"
|
||
#include "bladerunner/ambient_sounds.h"
|
||
#include "bladerunner/audio_player.h"
|
||
#include "bladerunner/bladerunner.h"
|
||
#include "bladerunner/debugger.h"
|
||
#include "bladerunner/decompress_lcw.h"
|
||
#include "bladerunner/font.h"
|
||
#include "bladerunner/game_info.h"
|
||
#include "bladerunner/mouse.h"
|
||
#include "bladerunner/scene.h"
|
||
#include "bladerunner/shape.h"
|
||
#include "bladerunner/script/esper_script.h"
|
||
#include "bladerunner/text_resource.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"
|
||
|
||
namespace BladeRunner {
|
||
|
||
ESPER::ESPER(BladeRunnerEngine *vm) {
|
||
_vm = vm;
|
||
|
||
_screen = Common::Rect(135, 123, 435, 387);
|
||
|
||
_isWaiting = false;
|
||
_regionSelectedAck = false;
|
||
_isDrawingSelection = false;
|
||
|
||
_isOpen = false;
|
||
_shapesButtons = new Shapes(vm);
|
||
_shapesPhotos = new Shapes(vm);
|
||
_shapeThumbnail = nullptr;
|
||
_vqaPlayerMain = nullptr;
|
||
_vqaPlayerPhoto = nullptr;
|
||
_script = nullptr;
|
||
|
||
_buttons = new UIImagePicker(vm, kPhotoCount + 4);
|
||
|
||
reset();
|
||
}
|
||
|
||
ESPER::~ESPER() {
|
||
reset();
|
||
|
||
delete _buttons;
|
||
delete _shapesPhotos;
|
||
delete _shapesButtons;
|
||
}
|
||
|
||
void ESPER::open(Graphics::Surface *surface) {
|
||
// CD-changing logic has been removed
|
||
|
||
while (!_vm->playerHasControl()) {
|
||
_vm->playerGainsControl();
|
||
}
|
||
|
||
while (_vm->_mouse->isDisabled()) {
|
||
_vm->_mouse->enable();
|
||
}
|
||
|
||
_vm->_time->pause();
|
||
|
||
_ambientVolume = _vm->_ambientSounds->getVolume();
|
||
_vm->_ambientSounds->setVolume(_ambientVolume / 2);
|
||
|
||
reset();
|
||
|
||
if (!_vm->openArchive("MODE.MIX")) {
|
||
return;
|
||
}
|
||
|
||
_surfacePhoto.create(kPhotoWidth, kPhotoHeight, gameDataPixelFormat());
|
||
_surfaceViewport.create(_screen.width(), _screen.height(), screenPixelFormat());
|
||
|
||
_viewportNext = _viewport;
|
||
|
||
if (!_shapesButtons->load("ESPBUTTN.SHP")) {
|
||
return;
|
||
}
|
||
|
||
if (!_shapesPhotos->load("ESPTHUMB.SHP")) {
|
||
return;
|
||
}
|
||
|
||
_vqaPlayerMain = new VQAPlayer(_vm, &_vm->_surfaceBack, "ESPER.VQA");
|
||
if (!_vqaPlayerMain->open()) {
|
||
return;
|
||
}
|
||
_vqaPlayerMain->setLoop(2, -1, kLoopSetModeJustStart, nullptr, nullptr);
|
||
|
||
_isOpen = true;
|
||
_flash = false;
|
||
|
||
_script = new ESPERScript(_vm);
|
||
|
||
activate(true);
|
||
}
|
||
|
||
void ESPER::close() {
|
||
// CD-changing logic has been removed
|
||
delete _script;
|
||
_script = nullptr;
|
||
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxBR035_7B), 25, 0, 0, 50, 0);
|
||
|
||
unloadPhotos();
|
||
|
||
_buttons->deactivate();
|
||
_buttons->resetImages();
|
||
|
||
_shapesButtons->unload();
|
||
_shapesPhotos->unload();
|
||
|
||
_surfacePhoto.free();
|
||
_surfaceViewport.free();
|
||
|
||
delete _vqaPlayerMain;
|
||
_vqaPlayerMain = nullptr;
|
||
|
||
_vm->closeArchive("MODE.MIX");
|
||
|
||
_vm->_time->resume();
|
||
|
||
_vm->_ambientSounds->setVolume(_ambientVolume);
|
||
_vm->_scene->resume();
|
||
|
||
reset();
|
||
}
|
||
|
||
bool ESPER::isOpen() const {
|
||
return _isOpen;
|
||
}
|
||
|
||
void ESPER::handleMouseUp(int x, int y, bool mainButton) {
|
||
bool actionHandled = _buttons->handleMouseAction(x, y, false, true, false);
|
||
if (mainButton) {
|
||
_isMouseDown = false;
|
||
if (!actionHandled) {
|
||
if (_isScrolling) {
|
||
scrollingStop();
|
||
} else if (_isDrawingSelection && _mouseOverScroll == 4) {
|
||
_isDrawingSelection = false;
|
||
resetSelectionRect();
|
||
}
|
||
}
|
||
} else if (_statePhoto == kEsperPhotoStatePhotoZoomOut) {
|
||
zoomOutStop();
|
||
}
|
||
}
|
||
|
||
void ESPER::handleMouseDown(int x, int y, bool mainButton) {
|
||
bool actionHandled = _buttons->handleMouseAction(x, y, true, false, false);
|
||
|
||
if (actionHandled || _vm->_mouse->isDisabled()) {
|
||
return;
|
||
}
|
||
|
||
if (mainButton) {
|
||
if (_statePhoto != kEsperPhotoStateVideoZoomOut) {
|
||
if (_screen.contains(x, y)) {
|
||
_isMouseDown = true;
|
||
playSound(kSfxBRTARGET, 100);
|
||
}
|
||
if (_mouseOverScroll >= 0 && _mouseOverScroll <= 3 && !_isScrolling) {
|
||
scrollingStart(_mouseOverScroll);
|
||
}
|
||
tick();
|
||
}
|
||
} else {
|
||
if (_statePhoto == kEsperPhotoStateShow || _statePhoto == kEsperPhotoStateVideoShow) {
|
||
zoomOutStart();
|
||
}
|
||
}
|
||
}
|
||
|
||
void ESPER::tick() {
|
||
if (!_vm->_windowIsActive) {
|
||
return;
|
||
}
|
||
|
||
tickSound();
|
||
|
||
blit(_vm->_surfaceBack, _vm->_surfaceFront);
|
||
|
||
int mouseX, mouseY;
|
||
_vm->_mouse->getXY(&mouseX, &mouseY);
|
||
if (!_vm->_mouse->isDisabled()) {
|
||
_buttons->handleMouseAction(mouseX, mouseY, false, false, false);
|
||
}
|
||
|
||
if (!_isOpen) {
|
||
return;
|
||
}
|
||
|
||
draw(_vm->_surfaceFront);
|
||
_buttons->draw(_vm->_surfaceFront);
|
||
drawMouse(_vm->_surfaceFront);
|
||
|
||
tickSound();
|
||
_vm->_subtitles->tick(_vm->_surfaceFront);
|
||
_vm->blitToScreen(_vm->_surfaceFront);
|
||
|
||
if (_statePhoto == kEsperPhotoStateVideoShow) {
|
||
if (_regionSelectedAck) {
|
||
_regionSelectedAck = false;
|
||
_script->specialRegionSelected(_photoIdSelected, _regions[_regionSelected].regionId);
|
||
}
|
||
}
|
||
}
|
||
|
||
void ESPER::addPhoto(const char *name, int photoId, int shapeId) {
|
||
int i = findEmptyPhoto();
|
||
if (i >= 0) {
|
||
_photos[i].shapeId = shapeId;
|
||
_photos[i].isPresent = true;
|
||
_photos[i].photoId = photoId;
|
||
_photos[i].name = name;
|
||
|
||
_buttons->defineImage(i,
|
||
Common::Rect(
|
||
100 * (i % 3) + _screen.left + 3,
|
||
66 * (i / 3) + _screen.top + 3,
|
||
100 * (i % 3) + _screen.left + 100 - 3,
|
||
66 * (i / 3) + _screen.top + 66 - 3
|
||
),
|
||
_shapesPhotos->get(shapeId),
|
||
_shapesPhotos->get(shapeId),
|
||
_shapesPhotos->get(shapeId),
|
||
nullptr);
|
||
}
|
||
playSound(kSfxBR028_2A, 25);
|
||
wait(300);
|
||
tick();
|
||
}
|
||
|
||
void ESPER::defineRegion(int regionId, Common::Rect inner, Common::Rect outer, Common::Rect selection, const char *name) {
|
||
int i = findEmptyRegion();
|
||
if (i >= 0) {
|
||
_regions[i].isPresent = true;
|
||
_regions[i].regionId = regionId;
|
||
_regions[i].rectInner = inner;
|
||
_regions[i].rectOuter = outer;
|
||
_regions[i].rectSelection = selection;
|
||
_regions[i].name = name;
|
||
}
|
||
}
|
||
|
||
void ESPER::mouseDownCallback(int buttonId, void *callbackData) {
|
||
ESPER *self = ((ESPER *)callbackData);
|
||
if (self->_statePhoto != kEsperPhotoStateVideoZoomOut && buttonId == kPhotoCount + 2) {
|
||
self->zoomOutStart();
|
||
}
|
||
}
|
||
|
||
void ESPER::mouseUpCallback(int buttonId, void *callbackData) {
|
||
ESPER *self = (ESPER *)callbackData;
|
||
if (buttonId < kPhotoCount) {
|
||
self->selectPhoto(buttonId);
|
||
} else if (self->_statePhoto != kEsperPhotoStateVideoZoomOut) {
|
||
if (buttonId == kPhotoCount + 2) {
|
||
self->zoomOutStop();
|
||
} else if (buttonId == kPhotoCount + 3) {
|
||
self->goBack();
|
||
}
|
||
}
|
||
}
|
||
|
||
void ESPER::reset() {
|
||
_surfacePhoto.free();
|
||
_surfaceViewport.free();
|
||
|
||
_shapesButtons->unload();
|
||
_shapesPhotos->unload();
|
||
|
||
delete _vqaPlayerMain;
|
||
_vqaPlayerMain = nullptr;
|
||
|
||
delete _vqaPlayerPhoto;
|
||
_vqaPlayerPhoto = nullptr;
|
||
|
||
delete _script;
|
||
_script = nullptr;
|
||
|
||
_isOpen = false;
|
||
|
||
resetData();
|
||
}
|
||
|
||
void ESPER::resetData() {
|
||
delete _vqaPlayerPhoto;
|
||
_vqaPlayerPhoto = nullptr;
|
||
|
||
_shapeThumbnail = nullptr;
|
||
|
||
_viewport = Common::Rect();
|
||
_viewportNext = Common::Rect();
|
||
_selection = Common::Rect(-1, -1, -1, -1);
|
||
|
||
_regionSelectedAck = false;
|
||
|
||
_mouseOverScroll = -1;
|
||
_scrollingDirection = -1;
|
||
|
||
_selectionCrosshairX = -1;
|
||
_selectionCrosshairY = -1;
|
||
|
||
_stateMain = kEsperMainStatePhoto;
|
||
_statePhoto = kEsperPhotoStateShow;
|
||
|
||
_isMouseDown = false;
|
||
_isDrawingSelection = false;
|
||
_flash = false;
|
||
_isScrolling = false;
|
||
|
||
_timeScrollNextStart = 0u;
|
||
|
||
resetPhotos();
|
||
resetRegions();
|
||
resetViewport();
|
||
resetSelectionBlinking();
|
||
prepareZoom();
|
||
resetPhotoZooming();
|
||
resetPhotoOpening();
|
||
|
||
_soundId1 = -1;
|
||
_soundId2 = -1;
|
||
_soundId3 = -1;
|
||
}
|
||
|
||
void ESPER::resetPhotos() {
|
||
for (int i = 0; i < kPhotoCount; ++i) {
|
||
_photos[i].isPresent = false;
|
||
_photos[i].photoId = -1;
|
||
}
|
||
}
|
||
|
||
void ESPER::resetRegions() {
|
||
for (int i = 0; i < kRegionCount; ++i) {
|
||
_regions[i].isPresent = false;
|
||
_regions[i].regionId = -1;
|
||
}
|
||
}
|
||
|
||
void ESPER::resetViewport() {
|
||
_zoomHorizontal = (float)(_screen.width()) / (float)kPhotoWidth;
|
||
_zoomVertical = (float)(_screen.height()) / (float)kPhotoHeight;
|
||
_zoom = _zoomVertical;
|
||
_zoomMin = _zoom;
|
||
|
||
_timeZoomOutNextStart = 0u;
|
||
|
||
_viewportPositionX = kPhotoWidth / 2;
|
||
_viewportPositionY = kPhotoHeight / 2;
|
||
|
||
updateViewport();
|
||
|
||
_screenHalfWidth = _screen.width() / 2;
|
||
_screenHalfHeight = _screen.height() / 2;
|
||
}
|
||
|
||
void ESPER::resetSelectionRect() {
|
||
_selection = _screen;
|
||
_selectionCrosshairX = -1;
|
||
_selectionCrosshairY = -1;
|
||
}
|
||
|
||
void ESPER::resetSelectionBlinking() {
|
||
_selectionBlinkingCounter = 0;
|
||
_selectionBlinkingStyle = 0;
|
||
_timeSelectionBlinkingNextStart = 0u;
|
||
}
|
||
|
||
void ESPER::resetPhotoZooming() {
|
||
_zoomStep = 0;
|
||
_timeZoomNextDiff = 0u;
|
||
_timeZoomNextStart = 0u;
|
||
}
|
||
|
||
void ESPER::resetPhotoOpening() {
|
||
_photoOpeningWidth = _screen.left + 1;
|
||
_photoOpeningHeight = _screen.top + 1;
|
||
_timePhotoOpeningNextDiff = 0u;
|
||
_timePhotoOpeningNextStart = 0u;
|
||
}
|
||
|
||
void ESPER::updateViewport() {
|
||
float halfWidth = (1.0f / 2.0f) * ((float)kPhotoWidth * (_zoomHorizontal / _zoom));
|
||
|
||
_viewport.left = _viewportPositionX - halfWidth;
|
||
_viewport.right = _viewportPositionX + halfWidth;
|
||
|
||
if (_viewport.left < 0) {
|
||
_viewport.right -= _viewport.left;
|
||
_viewport.left = 0;
|
||
}
|
||
if (_viewport.right >= kPhotoWidth) {
|
||
_viewport.left -= _viewport.right - (kPhotoWidth - 1);
|
||
if (_viewport.left < 0) {
|
||
_viewport.left = 0;
|
||
}
|
||
_viewport.right = kPhotoWidth - 1;
|
||
}
|
||
|
||
float halfHeight = 1.0f / 2.0f * ((float)kPhotoHeight * (_zoomVertical / _zoom));
|
||
|
||
_viewport.top = _viewportPositionY - halfHeight;
|
||
_viewport.bottom = _viewportPositionY + halfHeight;
|
||
|
||
if (_viewport.top < 0) {
|
||
_viewport.bottom -= _viewport.top;
|
||
_viewport.top = 0;
|
||
}
|
||
if (_viewport.bottom >= kPhotoHeight) {
|
||
_viewport.top -= _viewport.bottom - (kPhotoHeight - 1);
|
||
if (_viewport.top < 0) {
|
||
_viewport.top = 0;
|
||
}
|
||
_viewport.bottom = kPhotoHeight - 1;
|
||
}
|
||
|
||
_viewportWidth = _viewport.right + 1 - _viewport.left;
|
||
_viewportHeight = _viewport.bottom + 1 - _viewport.top;
|
||
|
||
int centerX = (_viewport.left + _viewport.right ) / 2;
|
||
int centerY = (_viewport.top + _viewport.bottom) / 2;
|
||
|
||
float range = _zoom / _zoomHorizontal * 1.0f;
|
||
if ((_viewportPositionX > centerX + range) || (_viewportPositionX < centerX - range)) {
|
||
_viewportPositionX = centerX;
|
||
}
|
||
|
||
range = _zoom / _zoomVertical * 1.0f;
|
||
if ((_viewportPositionY > centerY + range) || (_viewportPositionY < centerY - range)) {
|
||
_viewportPositionY = centerY;
|
||
}
|
||
}
|
||
|
||
void ESPER::activate(bool withOpening) {
|
||
_vm->_mouse->disable();
|
||
|
||
_buttons->resetImages();
|
||
|
||
if (withOpening) {
|
||
setStateMain(kEsperMainStateOpening);
|
||
playSound(kSfxBR025_5A, 25);
|
||
wait(1000);
|
||
playSound(kSfxBR027_1P, 25);
|
||
wait(2000);
|
||
} else {
|
||
_buttons->deactivate();
|
||
setStateMain(kEsperMainStateClear);
|
||
}
|
||
|
||
_buttons->activate(nullptr, nullptr, mouseDownCallback, mouseUpCallback, this);
|
||
_buttons->defineImage(kPhotoCount + 3, Common::Rect(42, 403, 76, 437), nullptr, nullptr, _shapesButtons->get(0), nullptr);
|
||
|
||
playSound(kSfxBR024_4B, 25);
|
||
wait(1000);
|
||
|
||
setStateMain(kEsperMainStateList);
|
||
resetPhotos();
|
||
_script->initialize();
|
||
|
||
_vm->_mouse->enable();
|
||
}
|
||
|
||
void ESPER::setStateMain(EsperMainStates state) {
|
||
if (_isOpen) {
|
||
_stateMain = state;
|
||
}
|
||
}
|
||
|
||
void ESPER::setStatePhoto(EsperPhotoStates state) {
|
||
_statePhoto = state;
|
||
}
|
||
|
||
void ESPER::wait(uint32 timeout) {
|
||
if (!_isWaiting) {
|
||
_isWaiting = true;
|
||
// int timeEnd = timeout + _vm->_time->current();
|
||
uint32 timeStart = _vm->_time->current();
|
||
// unsigned difference is intentional
|
||
while (_vm->_gameIsRunning && (_vm->_time->current() - timeStart < timeout)) {
|
||
_vm->gameTick();
|
||
}
|
||
_isWaiting = false;
|
||
}
|
||
}
|
||
|
||
void ESPER::playSound(int soundId, int volume) {
|
||
if (_soundId1 == -1) {
|
||
_soundId1 = soundId;
|
||
_volume1 = volume;
|
||
} else if (_soundId2 == -1) {
|
||
_soundId2 = soundId;
|
||
_volume2 = volume;
|
||
} else if (_soundId3 == -1) {
|
||
_soundId3 = soundId;
|
||
_volume3 = volume;
|
||
}
|
||
}
|
||
|
||
void ESPER::draw(Graphics::Surface &surface) {
|
||
if (!_isOpen) {
|
||
return;
|
||
}
|
||
_vqaPlayerMain->update(false);
|
||
switch (_stateMain) {
|
||
case kEsperMainStateOpening:
|
||
case kEsperMainStateList:
|
||
return;
|
||
case kEsperMainStatePhotoOpening:
|
||
drawPhotoOpening(surface);
|
||
break;
|
||
case kEsperMainStateClear:
|
||
surface.fillRect(_screen, surface.format.RGBToColor(0, 0, 0));
|
||
break;
|
||
case kEsperMainStatePhoto:
|
||
if (_isScrolling) {
|
||
tickScroll();
|
||
}
|
||
switch (_statePhoto) {
|
||
case kEsperPhotoStateShow:
|
||
drawPhotoWithGrid(surface);
|
||
if (_isDrawingSelection) {
|
||
drawSelection(surface, true, 1);
|
||
}
|
||
|
||
if (_vm->_debugger->_viewUI) {
|
||
for (int i = 0; i < kRegionCount; ++i) {
|
||
if (_regions[i].isPresent) {
|
||
surface.frameRect(
|
||
Common::Rect(
|
||
viewportXToScreenX(_regions[i].rectInner.left),
|
||
viewportYToScreenY(_regions[i].rectInner.top),
|
||
viewportXToScreenX(_regions[i].rectInner.right),
|
||
viewportYToScreenY(_regions[i].rectInner.bottom)
|
||
),
|
||
surface.format.RGBToColor(248, 248, 0)
|
||
);
|
||
surface.frameRect(
|
||
Common::Rect(
|
||
viewportXToScreenX(_regions[i].rectOuter.left),
|
||
viewportYToScreenY(_regions[i].rectOuter.top),
|
||
viewportXToScreenX(_regions[i].rectOuter.right),
|
||
viewportYToScreenY(_regions[i].rectOuter.bottom)
|
||
),
|
||
surface.format.RGBToColor(248, 248, 0)
|
||
);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case kEsperPhotoStateScrolling:
|
||
scrollUpdate();
|
||
drawPhotoWithGrid(surface);
|
||
break;
|
||
case kEsperPhotoStateSelectionZooming:
|
||
drawPhotoWithGrid(surface);
|
||
if (!drawSelectionZooming(surface)) {
|
||
setStatePhoto(kEsperPhotoStateSelectionBlinking);
|
||
playSound(kSfxBR030_3A, 25);
|
||
}
|
||
break;
|
||
case kEsperPhotoStateSelectionBlinking:
|
||
drawPhotoWithGrid(surface);
|
||
if (!drawSelectionBlinking(surface)) {
|
||
setStatePhoto(kEsperPhotoStatePhotoZooming);
|
||
}
|
||
break;
|
||
case kEsperPhotoStatePhotoZooming:
|
||
drawPhotoZooming(surface);
|
||
break;
|
||
case kEsperPhotoStatePhotoSharpening:
|
||
drawPhotoSharpening(surface);
|
||
break;
|
||
case kEsperPhotoStatePhotoZoomOut:
|
||
drawPhotoZoomOut(surface);
|
||
break;
|
||
case kEsperPhotoStateVideoZooming:
|
||
drawVideoZooming(surface);
|
||
break;
|
||
case kEsperPhotoStateVideoShow:
|
||
drawVideoFrame(surface);
|
||
drawGrid(surface);
|
||
break;
|
||
case kEsperPhotoStateVideoZoomOut:
|
||
drawVideoZoomOut(surface);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
drawTextCoords(surface);
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
void ESPER::drawPhotoOpening(Graphics::Surface &surface) {
|
||
bool needMoreZooming = true;
|
||
uint32 timeNow = _vm->_time->current();
|
||
// unsigned difference is intentional
|
||
if (timeNow - _timePhotoOpeningNextStart >= _timePhotoOpeningNextDiff) {
|
||
_photoOpeningWidth = MIN(_photoOpeningWidth + 8, _screen.right - 1);
|
||
_photoOpeningHeight = MIN(_photoOpeningHeight + 7, _screen.bottom - 1);
|
||
|
||
if (_photoOpeningWidth == _screen.right - 1 && _photoOpeningHeight == _screen.bottom - 1) {
|
||
needMoreZooming = false;
|
||
}
|
||
_timePhotoOpeningNextDiff = 20u;
|
||
_timePhotoOpeningNextStart = timeNow;
|
||
}
|
||
copyImageScale(_surfacePhoto, _viewport, surface, Common::Rect(_screen.left, _screen.top, _photoOpeningWidth, _photoOpeningHeight));
|
||
|
||
surface.hLine(_screen.left, _photoOpeningHeight, _screen.right - 1, surface.format.RGBToColor(0, 248, 0));
|
||
surface.vLine(_photoOpeningWidth, _screen.top, _screen.bottom - 1, surface.format.RGBToColor(0, 248, 0));
|
||
surface.hLine(_screen.left, _photoOpeningHeight - 1, _screen.right - 1, surface.format.RGBToColor(0, 144, 0));
|
||
surface.vLine(_photoOpeningWidth - 1, _screen.top, _screen.bottom - 1, surface.format.RGBToColor(0, 144, 0));
|
||
|
||
drawGrid(surface);
|
||
|
||
if (!needMoreZooming) {
|
||
setStateMain(kEsperMainStatePhoto);
|
||
setStatePhoto(kEsperPhotoStateShow);
|
||
_vm->_mouse->enable();
|
||
}
|
||
}
|
||
|
||
bool ESPER::drawSelectionZooming(Graphics::Surface &surface) {
|
||
bool zooming = false;
|
||
bool needMoreZooming = true;
|
||
uint32 timeNow = _vm->_time->current();
|
||
// unsigned difference is intentional
|
||
if (timeNow - _timeSelectionZoomNextStart > 150u) {
|
||
zooming = true;
|
||
_selection.left += _selectionDelta.left;
|
||
_selection.top += _selectionDelta.top;
|
||
_selection.right += _selectionDelta.right;
|
||
_selection.bottom += _selectionDelta.bottom;
|
||
++_selectionZoomStep;
|
||
_timeSelectionZoomNextStart = timeNow;
|
||
if (_selectionZoomStep > kSelectionZoomSteps) {
|
||
needMoreZooming = false;
|
||
_selection.left = _selectionTarget.left;
|
||
_selection.top = _selectionTarget.top;
|
||
_selection.right = _selectionTarget.right;
|
||
_selection.bottom = _selectionTarget.bottom;
|
||
}
|
||
}
|
||
drawSelection(surface, false, 1);
|
||
if (!needMoreZooming) {
|
||
_statePhoto = kEsperPhotoStatePhotoZooming;
|
||
resetPhotoZooming();
|
||
zooming = false;
|
||
}
|
||
if (zooming) {
|
||
playSound(kSfxBR029_3A, 20);
|
||
}
|
||
return needMoreZooming;
|
||
}
|
||
|
||
bool ESPER::drawSelectionBlinking(Graphics::Surface &surface) {
|
||
bool needMoreBlinking = true;
|
||
uint32 timeNow = _vm->_time->current();
|
||
// unsigned difference is intentional
|
||
if (timeNow - _timeSelectionBlinkingNextStart > 100u) {
|
||
_timeSelectionBlinkingNextStart = timeNow;
|
||
_selectionBlinkingStyle ^= 1;
|
||
++_selectionBlinkingCounter;
|
||
if (_selectionBlinkingCounter > 10) {
|
||
needMoreBlinking = false;
|
||
_selectionBlinkingStyle = 0;
|
||
}
|
||
}
|
||
drawSelection(surface, false, _selectionBlinkingStyle);
|
||
if (!needMoreBlinking) {
|
||
resetSelectionBlinking();
|
||
}
|
||
return needMoreBlinking;
|
||
}
|
||
|
||
void ESPER::drawPhotoZooming(Graphics::Surface &surface) {
|
||
uint32 timeNow = _vm->_time->current();
|
||
// unsigned difference is intentional
|
||
if ((timeNow - _timeZoomNextStart > _timeZoomNextDiff) && (_zoomStep < _zoomSteps)) {
|
||
_flash = true;
|
||
|
||
_viewportPositionXCurrent += _viewportPositionXDelta;
|
||
_viewportPositionYCurrent += _viewportPositionYDelta;
|
||
_viewportPositionX = _viewportPositionXCurrent;
|
||
_viewportPositionY = _viewportPositionYCurrent;
|
||
|
||
_zoom += _zoomDelta;
|
||
if (_zoomDelta > 0.0f) {
|
||
if (_zoom > _zoomTarget) {
|
||
_zoom = _zoomTarget;
|
||
_zoomStep = _zoomSteps;
|
||
} else {
|
||
_blur += _zoomDelta * 2.0f;
|
||
}
|
||
} else if (_zoomDelta < 0.0f) {
|
||
if (_zoom < _zoomTarget) {
|
||
_zoom = _zoomTarget;
|
||
_zoomStep = _zoomSteps;
|
||
}
|
||
}
|
||
++_zoomStep;
|
||
if (_zoomStep >= _zoomSteps) {
|
||
_zoom = _zoomTarget;
|
||
_viewportPositionX = _viewportPositionXTarget;
|
||
_viewportPositionY = _viewportPositionYTarget;
|
||
}
|
||
updateViewport();
|
||
_timeZoomNextDiff = 300u;
|
||
_timeZoomNextStart = timeNow;
|
||
}
|
||
|
||
if (_zoomDelta >= 0.0f) {
|
||
drawPhoto(surface);
|
||
} else {
|
||
drawPhotoWithGrid(surface);
|
||
}
|
||
drawGrid(surface);
|
||
|
||
// unsigned difference is intentional
|
||
if ((timeNow - _timeZoomNextStart > _timeZoomNextDiff) && (_zoomStep >= _zoomSteps)) {
|
||
if (_regionSelectedAck) {
|
||
if (!_regions[_regionSelected].name.empty()) {
|
||
if (_zoomDelta < 0.0f) {
|
||
_blur = 1.0f;
|
||
_zoomDelta = (_zoom * 1.5f - _zoom) / (float)_zoomSteps; // 0.5f * _zoom ???
|
||
}
|
||
setStatePhoto(kEsperPhotoStateVideoZooming);
|
||
_timeZoomNextDiff += 300u;
|
||
} else {
|
||
_regionSelectedAck = false;
|
||
_selection.left = viewportXToScreenX(_regions[_regionSelected].rectInner.left);
|
||
_selection.right = viewportXToScreenX(_regions[_regionSelected].rectInner.right);
|
||
_selection.top = viewportYToScreenY(_regions[_regionSelected].rectInner.top);
|
||
_selection.bottom = viewportYToScreenY(_regions[_regionSelected].rectInner.bottom);
|
||
prepareZoom();
|
||
resetPhotoZooming();
|
||
updateSelection();
|
||
setStatePhoto(kEsperPhotoStatePhotoZooming);
|
||
}
|
||
} else {
|
||
setStatePhoto(kEsperPhotoStatePhotoSharpening);
|
||
}
|
||
resetPhotoOpening();
|
||
}
|
||
}
|
||
|
||
void ESPER::drawPhotoSharpening(Graphics::Surface &surface) {
|
||
uint32 timeNow = _vm->_time->current();
|
||
bool needMoreSharpening = true;
|
||
// unsigned difference is intentional
|
||
if (timeNow - _timePhotoOpeningNextStart >= _timePhotoOpeningNextDiff) {
|
||
_photoOpeningWidth = MIN(_photoOpeningWidth + 8, _screen.right - 1);
|
||
_photoOpeningHeight = MIN(_photoOpeningHeight + 7, _screen.bottom - 1);
|
||
|
||
if (_photoOpeningWidth == _screen.right - 1 && _photoOpeningHeight == _screen.bottom - 1) {
|
||
needMoreSharpening = false;
|
||
}
|
||
|
||
_timePhotoOpeningNextDiff = 50u;
|
||
_timePhotoOpeningNextStart = timeNow;
|
||
}
|
||
|
||
if (_regionSelectedAck && !_regions[_regionSelected].name.empty()) {
|
||
_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(_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);
|
||
surface.hLine(_screen.left, _photoOpeningHeight, _screen.right - 1, surface.format.RGBToColor(0, 248, 0));
|
||
surface.vLine(_photoOpeningWidth, _screen.top, _screen.bottom - 1, surface.format.RGBToColor(0, 248, 0));
|
||
surface.hLine(_screen.left, _photoOpeningHeight - 1, _screen.right - 1, surface.format.RGBToColor(0, 144, 0));
|
||
surface.vLine(_photoOpeningWidth - 1, _screen.top, _screen.bottom - 1, surface.format.RGBToColor(0, 144, 0));
|
||
if (!needMoreSharpening) {
|
||
if (_regionSelectedAck && !_regions[_regionSelected].name.empty()) {
|
||
setStatePhoto(kEsperPhotoStateVideoShow);
|
||
} else {
|
||
setStatePhoto(kEsperPhotoStateShow);
|
||
}
|
||
resetPhotoZooming();
|
||
resetPhotoOpening();
|
||
_vm->_mouse->enable();
|
||
}
|
||
}
|
||
|
||
void ESPER::drawPhotoZoomOut(Graphics::Surface &surface) {
|
||
uint32 timeNow = _vm->_time->current();
|
||
// unsigned difference is intentional
|
||
if (timeNow - _timeZoomOutNextStart >= 300u) {
|
||
_timeZoomOutNextStart = timeNow;
|
||
|
||
if (_zoom > _zoomMin) {
|
||
_zoom /= 1.3f;
|
||
_flash = true;
|
||
if (_zoomHorizontal <= _zoomVertical) {
|
||
if (_zoom < _zoomVertical) {
|
||
_zoom = _zoomVertical;
|
||
}
|
||
} else {
|
||
if (_zoom < _zoomHorizontal) {
|
||
_zoom = _zoomHorizontal;
|
||
}
|
||
}
|
||
updateViewport();
|
||
} else {
|
||
_statePhoto = kEsperPhotoStateShow;
|
||
}
|
||
}
|
||
drawPhotoWithGrid(surface);
|
||
}
|
||
|
||
void ESPER::drawVideoZooming(Graphics::Surface &surface) {
|
||
if (_vqaPlayerPhoto == nullptr) {
|
||
_vqaPlayerPhoto = new VQAPlayer(_vm, &_surfaceViewport, Common::String(_regions[_regionSelected].name) + ".VQA");
|
||
if (!_vqaPlayerPhoto->open()) {
|
||
setStatePhoto(kEsperPhotoStateShow);
|
||
_vm->_mouse->enable();
|
||
|
||
delete _vqaPlayerPhoto;
|
||
_vqaPlayerPhoto = nullptr;
|
||
|
||
return;
|
||
}
|
||
|
||
_timeZoomNextDiff = 0u;
|
||
_timeZoomNextStart = 0u;
|
||
}
|
||
|
||
bool flash = false;
|
||
bool advanceFrame = false;
|
||
uint32 timeNow = _vm->_time->current();
|
||
// unsigned difference is intentional
|
||
if (timeNow - _timeZoomNextStart > _timeZoomNextDiff) {
|
||
_timeZoomNextDiff = 300u;
|
||
_timeZoomNextStart = timeNow;
|
||
playSound(kSfxBR031_1P, 25);
|
||
flash = true;
|
||
advanceFrame = true;
|
||
_blur += _zoomDelta * 5.0f;
|
||
}
|
||
|
||
int frame = _vqaPlayerPhoto->update(true, advanceFrame);
|
||
if (frame == _vqaPlayerPhoto->getFrameCount() - 1) {
|
||
_vqaLastFrame = frame;
|
||
setStatePhoto(kEsperPhotoStatePhotoSharpening);
|
||
} else if (flash) {
|
||
// TODO? Temporary workaround for very noticeable blue tint in the first frame during zoom-out:
|
||
// Don't flash for the last frame of the photo (which is the starting frame when zooming out)
|
||
flashViewport();
|
||
}
|
||
|
||
copyImageBlur(_surfaceViewport, Common::Rect(0, 0, 299, 263), surface, _screen, _blur);
|
||
drawGrid(surface);
|
||
}
|
||
|
||
void ESPER::drawVideoZoomOut(Graphics::Surface &surface) {
|
||
bool flash = false;
|
||
bool advanceFrame = false;
|
||
uint32 timeNow = _vm->_time->current();
|
||
// unsigned difference is intentional
|
||
if (timeNow - _timeZoomNextStart > _timeZoomNextDiff && _vqaLastFrame > 0) {
|
||
_timeZoomNextDiff = 300u;
|
||
_timeZoomNextStart = timeNow;
|
||
playSound(kSfxBR031_1P, 25);
|
||
_vqaPlayerPhoto->seekToFrame(_vqaLastFrame);
|
||
int nextFrame = _vqaPlayerPhoto->getFrameCount() / 4;
|
||
if (nextFrame <= 0) {
|
||
nextFrame = 1;
|
||
} else if (nextFrame > 4) {
|
||
nextFrame = 4;
|
||
}
|
||
|
||
if (_vqaLastFrame < _vqaPlayerPhoto->getFrameCount() - 1) {
|
||
// TODO? Temporary workaround for persistent blue tint in the last frame:
|
||
// Don't flash for the last frame of the photo (starting frame when zooming out)
|
||
flash = true;
|
||
}
|
||
advanceFrame = true;
|
||
_vqaLastFrame -= nextFrame;
|
||
}
|
||
|
||
_vqaPlayerPhoto->update(true, advanceFrame);
|
||
if (flash) {
|
||
flashViewport();
|
||
}
|
||
copyImageBlit(_surfaceViewport, Common::Rect(0, 0, 0, 0), surface, _screen);
|
||
drawGrid(surface);
|
||
// unsigned difference is intentional
|
||
if (timeNow - _timeZoomNextStart > _timeZoomNextDiff && _vqaLastFrame <= 0) {
|
||
_vqaPlayerPhoto->close();
|
||
delete _vqaPlayerPhoto;
|
||
_vqaPlayerPhoto = nullptr;
|
||
|
||
if (_vm->isMouseButtonDown()) {
|
||
zoomOutStart();
|
||
} else {
|
||
zoomOutStop();
|
||
}
|
||
}
|
||
}
|
||
|
||
void ESPER::drawPhoto(Graphics::Surface &surface) {
|
||
copyImageBlur(_surfacePhoto, _viewport, surface, _screen, _blur);
|
||
}
|
||
|
||
void ESPER::drawGrid(Graphics::Surface &surface) {
|
||
for (int i = 0; i < 7; ++i) {
|
||
surface.drawLine(_screen.left + i * 50, _screen.top, _screen.left + i * 50, _screen.bottom - 1, surface.format.RGBToColor(32, 32, 224));
|
||
}
|
||
|
||
for (int i = 0; i < 7; ++i) {
|
||
surface.drawLine(_screen.left, _screen.top + i * 44, _screen.right - 1, _screen.top + i * 44, surface.format.RGBToColor(32, 32, 224));
|
||
}
|
||
}
|
||
|
||
void ESPER::drawPhotoWithGrid(Graphics::Surface &surface) {
|
||
copyImageScale(_surfacePhoto, _viewport, surface, _screen);
|
||
drawGrid(surface);
|
||
}
|
||
|
||
void ESPER::drawSelection(Graphics::Surface &surface, bool crosshair, int style) {
|
||
int left = CLIP(_selection.left, _screen.left, (int16)(_screen.right - 1));
|
||
int top = CLIP(_selection.top, _screen.top, (int16)(_screen.bottom - 1));
|
||
int right = CLIP(_selection.right, _screen.left, (int16)(_screen.right - 1));
|
||
int bottom = CLIP(_selection.bottom, _screen.top, (int16)(_screen.bottom - 1));
|
||
|
||
int color = surface.format.RGBToColor(0, 144, 0);
|
||
if (style) {
|
||
color = surface.format.RGBToColor(0, 248, 0);
|
||
}
|
||
|
||
// selection rectangle
|
||
Common::Rect selectedRect(MIN(left, right), MIN(top, bottom), MAX(left, right) + 1, MAX(top, bottom) + 1);
|
||
Common::Rect selectedRect2 = selectedRect;
|
||
selectedRect2.grow(-1);
|
||
surface.frameRect(selectedRect, color);
|
||
surface.frameRect(selectedRect2, color);
|
||
|
||
if (crosshair) {
|
||
if (_selectionCrosshairX == -1) {
|
||
if (_selection.left < (_screen.left + _screen.right) / 2) {
|
||
_selectionCrosshairX = _screen.left;
|
||
} else {
|
||
_selectionCrosshairX = _screen.right - 1;
|
||
}
|
||
}
|
||
if (_selectionCrosshairY == -1) {
|
||
if (_selection.top < (_screen.top + _screen.bottom) / 2) {
|
||
_selectionCrosshairY = _screen.top;
|
||
} else {
|
||
_selectionCrosshairY = _screen.bottom - 1;
|
||
}
|
||
}
|
||
|
||
// ghosting
|
||
if (_selectionCrosshairX != right) {
|
||
surface.vLine(_selectionCrosshairX, _screen.top, _screen.bottom - 1, surface.format.RGBToColor(0, 144, 0));
|
||
if (abs(_selectionCrosshairX - right) <= 1) {
|
||
_selectionCrosshairX = right;
|
||
} else {
|
||
_selectionCrosshairX = (_selectionCrosshairX + right) / 2;
|
||
}
|
||
}
|
||
if (_selectionCrosshairY != bottom) {
|
||
surface.hLine(_screen.left, _selectionCrosshairY, _screen.right - 1, surface.format.RGBToColor(0, 144, 0));
|
||
if (abs(_selectionCrosshairY - bottom) <= 1) {
|
||
_selectionCrosshairY = bottom;
|
||
} else {
|
||
_selectionCrosshairY = (_selectionCrosshairY + bottom) / 2;
|
||
}
|
||
}
|
||
|
||
surface.vLine(right, _screen.top, _screen.bottom - 1, surface.format.RGBToColor(0, 248, 0));
|
||
surface.hLine(_screen.left, bottom, _screen.right - 1, surface.format.RGBToColor(0, 248, 0));
|
||
}
|
||
}
|
||
|
||
void ESPER::drawVideoFrame(Graphics::Surface &surface) {
|
||
_vqaPlayerPhoto->update(true, false);
|
||
copyImageBlit(_surfaceViewport, Common::Rect(0, 0, 0, 0), surface, _screen);
|
||
}
|
||
|
||
void ESPER::drawTextCoords(Graphics::Surface &surface) {
|
||
const char *zm = "ZM %04.0f";
|
||
const char *ns = "NS %04d";
|
||
const char *ew = "EW %04d";
|
||
if (_vm->_language == Common::RU_RUS) {
|
||
// ПР, ВР, ГР
|
||
if (_vm->_russianCP1251) {
|
||
// Patched transalation by Siberian Studio is using Windows-1251 encoding
|
||
zm = "\xcf\xd0 %04.0f";
|
||
ns = "\xc2\xd0 %04d";
|
||
ew = "\xc3\xd0 %04d";
|
||
} else {
|
||
// Original release uses custom encoding
|
||
zm = "gh %04.0f";
|
||
ns = "dh %04d";
|
||
ew = "uh %04d";
|
||
}
|
||
}
|
||
_vm->_mainFont->drawString(&surface, Common::String::format(zm, _zoom / _zoomMin * 2.0f ), 155, 364, surface.w, surface.format.RGBToColor(0, 0, 255));
|
||
_vm->_mainFont->drawString(&surface, Common::String::format(ns, 12 * _viewport.top + 98), 260, 364, surface.w, surface.format.RGBToColor(0, 0, 255));
|
||
_vm->_mainFont->drawString(&surface, Common::String::format(ew, 12 * _viewport.left + 167), 364, 364, surface.w, surface.format.RGBToColor(0, 0, 255));
|
||
}
|
||
|
||
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, surface.format.RGBToColor(0, 248, 0));
|
||
surface.vLine(p.x, p.y + 8, p.y + 1, surface.format.RGBToColor(0, 248, 0));
|
||
surface.hLine(p.x - 8, p.y, p.x - 1, surface.format.RGBToColor(0, 248, 0));
|
||
surface.hLine(p.x + 8, p.y, p.x + 1, surface.format.RGBToColor(0, 248, 0));
|
||
_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() {
|
||
for (int y = 0; y < _surfaceViewport.h; ++y) {
|
||
for (int x = 0; x < _surfaceViewport.w; ++x) {
|
||
uint8 r, g, b;
|
||
void *ptr = _surfaceViewport.getBasePtr(x, y);
|
||
_surfaceViewport.format.colorToRGB(READ_UINT32(ptr), r, g, b);
|
||
b *= 2;
|
||
drawPixel(_surfaceViewport, ptr, _surfaceViewport.format.RGBToColor(r, g, b));
|
||
}
|
||
}
|
||
}
|
||
|
||
void ESPER::copyImageScale(Graphics::Surface &src, Common::Rect srcRect, Graphics::Surface &dst, Common::Rect dstRect) {
|
||
if (_flash) {
|
||
playSound(kSfxBR031_1P, 25);
|
||
}
|
||
|
||
int srcDstWidthRatio = srcRect.width() / dstRect.width();
|
||
int srcDstWidthRest = srcRect.width() % dstRect.width();
|
||
int srcDstHeightRatio = srcRect.height() / dstRect.height();
|
||
int srcDstHeightRest = srcRect.height() % dstRect.height();
|
||
|
||
if (srcRect.width() > dstRect.width() && srcRect.height() > dstRect.height()) {
|
||
// reduce
|
||
int srcY = srcRect.top;
|
||
int srcYCounter = 0;
|
||
for (int dstY = dstRect.top; dstY < dstRect.bottom; ++dstY) {
|
||
int srcX = srcRect.left;
|
||
int srcXCounter = 0;
|
||
for (int dstX = dstRect.left; dstX < dstRect.right; ++dstX) {
|
||
srcX = CLIP(srcX, 0, src.w - 1);
|
||
srcY = CLIP(srcY, 0, src.h - 1);
|
||
|
||
dstX = CLIP(dstX, 0, dst.w - 1);
|
||
dstY = CLIP(dstY, 0, dst.h - 1);
|
||
|
||
uint8 r, g, b;
|
||
src.format.colorToRGB(READ_UINT32(src.getBasePtr(srcX, srcY)), r, g, b);
|
||
if (_flash) {
|
||
// add blue-ish tint
|
||
b *= 2;
|
||
}
|
||
drawPixel(dst, dst.getBasePtr(dstX, dstY), dst.format.RGBToColor(r, g, b));
|
||
|
||
srcX += srcDstWidthRatio;
|
||
srcXCounter += srcDstWidthRest;
|
||
if (srcXCounter >= dstRect.width()) {
|
||
srcXCounter -= dstRect.width();
|
||
++srcX;
|
||
}
|
||
}
|
||
|
||
srcY += srcDstHeightRatio;
|
||
srcYCounter += srcDstHeightRest;
|
||
if (srcYCounter >= dstRect.height()) {
|
||
srcYCounter -= dstRect.height();
|
||
++srcY;
|
||
}
|
||
}
|
||
} else {
|
||
// enlarge
|
||
int srcY = srcRect.top;
|
||
int srcYCounter = 0;
|
||
for (int dstY = dstRect.top; dstY < dstRect.bottom; ++dstY) {
|
||
int srcX = srcRect.left;
|
||
int srcXCounter = 0;
|
||
for (int dstX = dstRect.left; dstX < dstRect.right; ++dstX) {
|
||
srcXCounter += srcRect.width();
|
||
if (srcXCounter >= dstRect.width()) {
|
||
srcXCounter -= dstRect.width();
|
||
++srcX;
|
||
}
|
||
|
||
srcX = CLIP(srcX, 0, src.w - 1);
|
||
srcY = CLIP(srcY, 0, src.h - 1);
|
||
|
||
dstX = CLIP(dstX, 0, dst.w - 1);
|
||
dstY = CLIP(dstY, 0, dst.h - 1);
|
||
|
||
uint8 r, g, b;
|
||
src.format.colorToRGB(READ_UINT32(src.getBasePtr(srcX, srcY)), r, g, b);
|
||
if (_flash) {
|
||
// add blue-ish tint
|
||
b *= 2;
|
||
}
|
||
drawPixel(dst, dst.getBasePtr(dstX, dstY), dst.format.RGBToColor(r, g, b));
|
||
}
|
||
|
||
srcYCounter += srcRect.height();
|
||
if (srcYCounter >= dstRect.height()) {
|
||
srcYCounter -= dstRect.height();
|
||
++srcY;
|
||
}
|
||
}
|
||
}
|
||
_flash = false;
|
||
}
|
||
|
||
void ESPER::copyImageBlur(Graphics::Surface &src, Common::Rect srcRect, Graphics::Surface &dst, Common::Rect dstRect, float blur) {
|
||
if (_flash) {
|
||
playSound(kSfxBR031_1P, 25);
|
||
}
|
||
|
||
int srcDstWidthRatio = srcRect.width() / dstRect.width();
|
||
int srcDstWidthRest = srcRect.width() % dstRect.width();
|
||
int srcDstHeightRatio = srcRect.height() / dstRect.height();
|
||
int srcDstHeightRest = srcRect.height() % dstRect.height();
|
||
|
||
int skipStep = (blur - (int)blur) * 1000.0f;
|
||
if (srcRect.width() > dstRect.width() && srcRect.height() > dstRect.height()) {
|
||
// reduce
|
||
int srcY = srcRect.top;
|
||
int dstY = dstRect.top;
|
||
int srcYCounter = 0;
|
||
int skipYMaxCounter = 0;
|
||
while (dstY < dstRect.bottom) {
|
||
skipYMaxCounter += skipStep;
|
||
int skipYMax = blur;
|
||
if (skipYMaxCounter >= 1000) {
|
||
skipYMaxCounter -= 1000;
|
||
++skipYMax;
|
||
}
|
||
int skipY = 0;
|
||
while (dstY < dstRect.bottom && skipY < skipYMax) {
|
||
int srcX = srcRect.left;
|
||
int dstX = dstRect.left;
|
||
int srcXCounter = 0;
|
||
int skipXMaxCounter = 0;
|
||
while (dstX < dstRect.right) {
|
||
skipXMaxCounter += skipStep;
|
||
int skipXMax = blur;
|
||
if (skipXMaxCounter >= 1000) {
|
||
skipXMaxCounter -= 1000;
|
||
++skipXMax;
|
||
}
|
||
int skipX = 0;
|
||
while (dstX < dstRect.right && skipX < skipXMax) {
|
||
|
||
srcX = CLIP(srcX, 0, src.w - 1);
|
||
srcY = CLIP(srcY, 0, src.h - 1);
|
||
|
||
dstX = CLIP(dstX, 0, dst.w - 1);
|
||
dstY = CLIP(dstY, 0, dst.h - 1);
|
||
|
||
uint8 r, g, b;
|
||
src.format.colorToRGB(READ_UINT32(src.getBasePtr(srcX, srcY)), r, g, b);
|
||
if (_flash) {
|
||
// add blue-ish tint
|
||
b *= 2;
|
||
}
|
||
drawPixel(dst, dst.getBasePtr(dstX, dstY), dst.format.RGBToColor(r, g, b));
|
||
|
||
++dstX;
|
||
++skipX;
|
||
}
|
||
srcXCounter += srcDstWidthRest;
|
||
srcX += srcDstWidthRatio * skipX;
|
||
if (srcXCounter >= dstRect.width()) {
|
||
srcXCounter -= dstRect.width();
|
||
srcX += skipX;
|
||
}
|
||
}
|
||
|
||
++dstY;
|
||
++skipY;
|
||
}
|
||
|
||
srcYCounter += srcDstHeightRest;
|
||
srcY += srcDstHeightRatio * skipY;
|
||
if (srcYCounter >= dstRect.height()) {
|
||
srcYCounter -= dstRect.height();
|
||
srcY += skipY;
|
||
}
|
||
}
|
||
} else {
|
||
// enlarge
|
||
int srcY = srcRect.top;
|
||
int dstY = dstRect.top;
|
||
int srcYCounter = srcRect.height(); // TODO: look at this again because in original source this is 0, but then first line is doubled
|
||
int skipYMaxCounter = 0;
|
||
while (dstY < dstRect.bottom) {
|
||
skipYMaxCounter += skipStep;
|
||
int skipYMax = blur;
|
||
if (skipYMaxCounter >= 1000) {
|
||
skipYMaxCounter -= 1000;
|
||
++skipYMax;
|
||
}
|
||
int skipY = 0;
|
||
while (dstY < dstRect.bottom && skipY < skipYMax) {
|
||
int srcX = srcRect.left;
|
||
int dstX = dstRect.left;
|
||
int srcXCounter = 0;
|
||
int skipXMaxCounter = 0;
|
||
while (dstX < dstRect.right) {
|
||
skipXMaxCounter += skipStep;
|
||
int skipXMax = blur;
|
||
if (skipXMaxCounter >= 1000) {
|
||
skipXMaxCounter -= 1000;
|
||
++skipXMax;
|
||
}
|
||
int skipX = 0;
|
||
while (dstX < dstRect.right && skipX < skipXMax) {
|
||
srcXCounter += srcRect.width();
|
||
if (srcXCounter >= dstRect.width()) {
|
||
srcXCounter -= dstRect.width();
|
||
++srcX; // bug in original game? Advancing by 1 instead of skipX as for Y
|
||
}
|
||
|
||
srcX = CLIP(srcX, 0, src.w - 1);
|
||
srcY = CLIP(srcY, 0, src.h - 1);
|
||
|
||
dstX = CLIP(dstX, 0, dst.w - 1);
|
||
dstY = CLIP(dstY, 0, dst.h - 1);
|
||
|
||
uint8 r, g, b;
|
||
src.format.colorToRGB(READ_UINT32(src.getBasePtr(srcX, srcY)), r, g, b);
|
||
if (_flash) {
|
||
// add blue-ish tint
|
||
b *= 2;
|
||
}
|
||
drawPixel(dst, dst.getBasePtr(dstX, dstY), dst.format.RGBToColor(r, g, b));
|
||
|
||
++dstX;
|
||
++skipX;
|
||
}
|
||
}
|
||
|
||
++dstY;
|
||
++skipY;
|
||
}
|
||
|
||
srcYCounter += srcRect.height();
|
||
if (srcYCounter >= dstRect.height()) {
|
||
srcYCounter -= dstRect.height();
|
||
srcY += skipY;
|
||
}
|
||
}
|
||
}
|
||
_flash = false;
|
||
}
|
||
|
||
void ESPER::copyImageBlit(Graphics::Surface &src, Common::Rect srcRect, Graphics::Surface &dst, Common::Rect dstRect) {
|
||
for (int y = 0; y < dstRect.height(); ++y) {
|
||
for (int x = 0; x < dstRect.width(); ++x) {
|
||
uint8 r, g, b;
|
||
src.format.colorToRGB(READ_UINT32(src.getBasePtr(CLIP(srcRect.left + x, 0, src.w - 1), CLIP(srcRect.top + y, 0, src.h - 1))), r, g, b);
|
||
drawPixel(dst, dst.getBasePtr(CLIP(dstRect.left + x, 0, dst.w - 1), CLIP(dstRect.top + y, 0, dst.h - 1)), dst.format.RGBToColor(r, g, b));
|
||
}
|
||
}
|
||
}
|
||
|
||
void ESPER::tickSound() {
|
||
if (_soundId1 != -1) {
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(_soundId1), _volume1, 0, 0, 50, 0);
|
||
_soundId1 = -1;
|
||
}
|
||
if (_soundId2 != -1) {
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(_soundId2), _volume2, 0, 0, 50, 0);
|
||
_soundId2 = -1;
|
||
}
|
||
if (_soundId3 != -1) {
|
||
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(_soundId3), _volume3, 0, 0, 50, 0);
|
||
_soundId3 = -1;
|
||
}
|
||
}
|
||
|
||
void ESPER::tickScroll() {
|
||
uint32 timeNow = _vm->_time->current();
|
||
// unsigned difference is intentional
|
||
if (timeNow - _timeScrollNextStart <= 300u) {
|
||
return;
|
||
}
|
||
_timeScrollNextStart = timeNow;
|
||
|
||
if (_scrollingDirection == 0) {
|
||
scrollUp();
|
||
} else if (_scrollingDirection == 1) {
|
||
scrollRight();
|
||
} else if (_scrollingDirection == 2) {
|
||
scrollDown();
|
||
} else if (_scrollingDirection == 3) {
|
||
scrollLeft();
|
||
}
|
||
}
|
||
|
||
int ESPER::findEmptyPhoto() {
|
||
for (int i = 0; i < kPhotoCount; ++i) {
|
||
if (!_photos[i].isPresent) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
void ESPER::selectPhoto(int photoId) {
|
||
_vm->_mouse->disable();
|
||
_photoIdSelected = _photos[photoId].photoId;
|
||
unloadPhotos();
|
||
_script->photoSelected(_photoIdSelected);
|
||
|
||
Common::ScopedPtr<Common::SeekableReadStream> s(_vm->getResourceStream(_photos[photoId].name));
|
||
|
||
uint 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();
|
||
uint photoCompressedSize = s->size() - s->pos();
|
||
uint8 *photoCompressed = (uint8 *)_surfacePhoto.getPixels() + photoSize - photoCompressedSize;
|
||
s->read(photoCompressed, photoCompressedSize);
|
||
|
||
decompress_lcw(photoCompressed, photoCompressedSize, (uint8 *)_surfacePhoto.getPixels(), photoSize);
|
||
#ifdef SCUMM_BIG_ENDIAN
|
||
// As the compression is working with 8-bit data, on big-endian architectures we have to switch order of bytes in uncompressed data
|
||
uint8 *rawData = (uint8 *)_surfacePhoto.getPixels();
|
||
for (size_t i = 0; i < photoSize - 1; i += 2) {
|
||
SWAP(rawData[i], rawData[i + 1]);
|
||
}
|
||
#endif
|
||
|
||
// apply palette
|
||
for (uint j = 0; j < width * height; ++j) {
|
||
// _surfacePhoto[j] = Palette[_surfacePhoto[j]];
|
||
}
|
||
|
||
_shapeThumbnail = _shapesPhotos->get(_photos[photoId].shapeId);
|
||
_buttons->resetImages();
|
||
_buttons->defineImage(kPhotoCount + 2, Common::Rect(480, 350, 578, 413), _shapeThumbnail, _shapeThumbnail, _shapeThumbnail, nullptr);
|
||
_buttons->defineImage(kPhotoCount + 3, Common::Rect(42, 403, 76, 437), nullptr, nullptr, _shapesButtons->get(0), nullptr);
|
||
|
||
resetPhotoOpening();
|
||
resetViewport();
|
||
setStateMain(kEsperMainStatePhotoOpening);
|
||
setStatePhoto(kEsperPhotoStateOpening);
|
||
playSound(kSfxBR032_7B, 25);
|
||
playSound(kSfxBR033_4B, 25);
|
||
}
|
||
|
||
void ESPER::unloadPhotos() {
|
||
for (int i = 0; i < kPhotoCount; ++i) {
|
||
if (_photos[i].isPresent) {
|
||
_photos[i].isPresent = false;
|
||
_buttons->resetImage(i);
|
||
}
|
||
}
|
||
}
|
||
|
||
int ESPER::findEmptyRegion() {
|
||
for (int i = 0; i < kRegionCount; ++i) {
|
||
if (!_regions[i].isPresent) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
int ESPER::findRegion(Common::Rect where) {
|
||
for (int i = 0; i < kRegionCount; ++i) {
|
||
if (_regions[i].isPresent && _regions[i].rectOuter.contains(where) && where.contains(_regions[i].rectInner)) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
void ESPER::zoomingStart() {
|
||
prepareZoom();
|
||
setStatePhoto(kEsperPhotoStateSelectionZooming);
|
||
}
|
||
|
||
void ESPER::zoomOutStart() {
|
||
if (_statePhoto == kEsperPhotoStateVideoShow) {
|
||
resetPhotoZooming();
|
||
setStatePhoto(kEsperPhotoStateVideoZoomOut);
|
||
} else {
|
||
zoomOutStop();
|
||
if (_zoomMin < _zoom) {
|
||
_isZoomingOut = true;
|
||
setStatePhoto(kEsperPhotoStatePhotoZoomOut);
|
||
}
|
||
}
|
||
}
|
||
|
||
void ESPER::zoomOutStop() {
|
||
_isZoomingOut = false;
|
||
_statePhoto = kEsperPhotoStateShow;
|
||
}
|
||
|
||
void ESPER::scrollingStart(int direction) {
|
||
scrollingStop();
|
||
if ((direction != 3 || _viewport.left > 0)
|
||
&& (direction != 0 || _viewport.top > 0)
|
||
&& (direction != 1 || _viewport.right != kPhotoWidth - 1)
|
||
&& (direction != 2 || _viewport.bottom != kPhotoHeight - 1)) {
|
||
_isScrolling = true;
|
||
_scrollingDirection = direction;
|
||
}
|
||
}
|
||
|
||
void ESPER::scrollingStop() {
|
||
_isScrolling = false;
|
||
_scrollingDirection = -1;
|
||
}
|
||
|
||
void ESPER::scrollUpdate() {
|
||
if ((_viewport.left == _viewportNext.left) && (_viewportNext.top == _viewport.top)) {
|
||
setStatePhoto(kEsperPhotoStateShow);
|
||
return;
|
||
}
|
||
|
||
if (_viewport.left != _viewportNext.left) {
|
||
_viewport.left = _viewportNext.left;
|
||
_viewport.right = _viewportNext.right;
|
||
|
||
_viewportPositionX = (_viewportNext.left + _viewportNext.right) / 2;
|
||
}
|
||
|
||
if (_viewport.top != _viewportNext.top) {
|
||
_viewport.top = _viewportNext.top;
|
||
_viewport.bottom = _viewportNext.bottom;
|
||
|
||
_viewportPositionY = (_viewportNext.top + _viewportNext.bottom) / 2;
|
||
}
|
||
}
|
||
|
||
void ESPER::scrollLeft() {this->_flash = 1;
|
||
_flash = true;
|
||
setStatePhoto(kEsperPhotoStateScrolling);
|
||
|
||
_viewportNext.left = _viewport.left - 40;
|
||
_viewportNext.right = _viewport.right - 40;
|
||
if (_viewportNext.left < 0) {
|
||
_viewportNext.right -= _viewportNext.left;
|
||
_viewportNext.left = 0;
|
||
scrollingStop();
|
||
}
|
||
_viewportNext.top = _viewport.top;
|
||
_viewportNext.bottom = _viewport.bottom;
|
||
}
|
||
|
||
void ESPER::scrollUp() {
|
||
_flash = true;
|
||
setStatePhoto(kEsperPhotoStateScrolling);
|
||
|
||
_viewportNext.top = _viewport.top - 40;
|
||
_viewportNext.bottom = _viewport.bottom - 40;
|
||
if (_viewportNext.top < 0) {
|
||
_viewportNext.bottom -= _viewportNext.top;
|
||
_viewportNext.top = 0;
|
||
scrollingStop();
|
||
}
|
||
_viewportNext.left = _viewport.left;
|
||
_viewportNext.right = _viewport.right;
|
||
}
|
||
|
||
void ESPER::scrollRight() {
|
||
if (_viewport.right < kPhotoWidth - 1) {
|
||
_flash = true;
|
||
setStatePhoto(kEsperPhotoStateScrolling);
|
||
|
||
_viewportNext.left = _viewport.left + 40;
|
||
_viewportNext.right = _viewport.right + 40;
|
||
_viewportNext.top = _viewport.top;
|
||
_viewportNext.bottom = _viewport.bottom;
|
||
|
||
if (_viewportNext.right > kPhotoWidth - 1) {
|
||
_viewportNext.left -= _viewportNext.right - (kPhotoWidth - 1);
|
||
_viewportNext.right = kPhotoWidth - 1;
|
||
scrollingStop();
|
||
}
|
||
}
|
||
}
|
||
|
||
void ESPER::scrollDown() {
|
||
if (_viewport.bottom < kPhotoHeight - 1) {
|
||
_flash = true;
|
||
setStatePhoto(kEsperPhotoStateScrolling);
|
||
|
||
_viewportNext.top = _viewport.top + 40;
|
||
_viewportNext.bottom = _viewport.bottom + 40;
|
||
_viewportNext.left = _viewport.left;
|
||
_viewportNext.right = _viewport.right;
|
||
|
||
if (_viewportNext.bottom > kPhotoHeight - 1) {
|
||
_viewportNext.top -= _viewportNext.bottom - (kPhotoHeight - 1);
|
||
_viewportNext.bottom = kPhotoHeight - 1;
|
||
scrollingStop();
|
||
}
|
||
}
|
||
}
|
||
|
||
void ESPER::goBack() {
|
||
// CD-changing logic has been removed
|
||
|
||
if (_stateMain == kEsperMainStateList) {
|
||
close();
|
||
} else {
|
||
resetData();
|
||
activate(false);
|
||
}
|
||
}
|
||
|
||
void ESPER::prepareZoom() {
|
||
_selectionZoomStep = 0;
|
||
_timeSelectionZoomNextStart = 0u;
|
||
|
||
_selectionTarget = _selection;
|
||
resetSelectionRect();
|
||
_selectionDelta.left = (_selectionTarget.left - _selection.left) / kSelectionZoomSteps;
|
||
_selectionDelta.top = (_selectionTarget.top - _selection.top) / kSelectionZoomSteps;
|
||
_selectionDelta.right = (_selectionTarget.right - _selection.right) / kSelectionZoomSteps;
|
||
_selectionDelta.bottom = (_selectionTarget.bottom - _selection.bottom) / kSelectionZoomSteps;
|
||
|
||
Common::Rect rect = _selectionTarget;
|
||
if (_regionSelectedAck) {
|
||
rect.left = viewportXToScreenX(_regions[_regionSelected].rectSelection.left);
|
||
rect.top = viewportYToScreenY(_regions[_regionSelected].rectSelection.top);
|
||
rect.right = viewportXToScreenX(_regions[_regionSelected].rectSelection.right);
|
||
rect.bottom = viewportYToScreenY(_regions[_regionSelected].rectSelection.bottom);
|
||
}
|
||
|
||
_zoomSteps = 10;
|
||
float ratio = (rect.width() + 1.0f) / (float)_screen.width();
|
||
if (ratio == 0.0f) {
|
||
_zoomTarget = ratio;
|
||
_zoomDelta = 0.0f;
|
||
} else {
|
||
_zoomTarget = CLIP(_zoom / ratio, _zoomMin, 2.0f);
|
||
_zoomSteps = CLIP((int)(_zoomTarget / _zoom) - 1, 0, 5) + 5;
|
||
_zoomDelta = (_zoomTarget - _zoom) / (float)_zoomSteps;
|
||
}
|
||
|
||
_blur = 1.0f;
|
||
|
||
_viewportPositionXTarget = _viewport.left + ((rect.left + rect.right) / 2 - _screen.left) * _viewport.width() / _screen.width();
|
||
_viewportPositionYTarget = _viewport.top + ((rect.top + rect.bottom) / 2 - _screen.top ) * _viewport.height() / _screen.height();
|
||
_viewportPositionXDelta = (_viewportPositionXTarget - _viewportPositionX) / (float)_zoomSteps;
|
||
_viewportPositionYDelta = (_viewportPositionYTarget - _viewportPositionY) / (float)_zoomSteps;
|
||
_viewportPositionXCurrent = _viewportPositionX;
|
||
_viewportPositionYCurrent = _viewportPositionY;
|
||
}
|
||
|
||
void ESPER::updateSelection() {
|
||
int selectionWidth = abs(_selection.right + 1 - _selection.left);
|
||
int selectionHeight = abs(_selection.bottom + 1 - _selection.top);
|
||
|
||
int photoSelectedWidth = _viewport.width() * selectionWidth / _screen.width();
|
||
if (photoSelectedWidth < _screenHalfWidth) {
|
||
// minimal width of selection
|
||
selectionWidth = _screen.width() * _screenHalfWidth / _viewport.width();
|
||
}
|
||
|
||
photoSelectedWidth = _viewport.height() * selectionHeight / _screen.height();
|
||
if (photoSelectedWidth < _screenHalfHeight) {
|
||
// minimal height of selection
|
||
selectionHeight = _screen.height() * _screenHalfHeight / _viewport.height();
|
||
}
|
||
|
||
// correct aspect ratio
|
||
if (selectionWidth / (float)_screen.width() <= selectionHeight / (float)_screen.height()) {
|
||
while (selectionWidth / (float)_screen.width() <= selectionHeight / (float)_screen.height()) {
|
||
++selectionWidth;
|
||
}
|
||
} else {
|
||
while (selectionHeight / (float)_screen.height() <= selectionWidth / (float)_screen.width()) {
|
||
++selectionHeight;
|
||
}
|
||
}
|
||
|
||
if (selectionWidth > _screen.width()) {
|
||
selectionWidth = _screen.width();
|
||
}
|
||
if (selectionHeight > _screen.height()) {
|
||
selectionHeight = _screen.height();
|
||
}
|
||
|
||
int left = _viewport.right - (_screen.right - 1 - _selection.left) * _viewport.width() / _screen.width();
|
||
int right = _viewport.left + (_selection.right - _screen.left ) * _viewport.width() / _screen.width();
|
||
int top = _viewport.bottom - (_screen.bottom - 1 - _selection.top ) * _viewport.height() / _screen.height();
|
||
int bottom = _viewport.top + (_selection.bottom - _screen.top ) * _viewport.height() / _screen.height();
|
||
|
||
bool stop = false;
|
||
bool alternate = false;
|
||
|
||
while (selectionWidth > abs(_selection.right + 1 - _selection.left)) {
|
||
if (alternate) {
|
||
--_selection.left;
|
||
if (_selection.left < 0) {
|
||
left = _viewport.right - (_screen.right - 1 + 100 - _selection.left) * _viewport.width() / _screen.width();
|
||
if (left < 0) {
|
||
left = 0;
|
||
++_selection.left;
|
||
if (stop) {
|
||
break;
|
||
}
|
||
stop = true;
|
||
alternate = false;
|
||
}
|
||
}
|
||
} else {
|
||
++_selection.right;
|
||
if (_selection.right > _screen.right - 1) {
|
||
right = _viewport.left + (_selection.right - _screen.left) * _viewport.width() / _screen.width();
|
||
if (right > kPhotoWidth - 1) {
|
||
right = kPhotoWidth - 1;
|
||
--_selection.right;
|
||
if (stop) {
|
||
break;
|
||
}
|
||
stop = true;
|
||
alternate = true;
|
||
}
|
||
}
|
||
}
|
||
if (!stop) {
|
||
alternate = !alternate;
|
||
}
|
||
}
|
||
|
||
alternate = false;
|
||
stop = false;
|
||
while (selectionHeight > abs(_selection.bottom + 1 - _selection.top)) {
|
||
if (alternate) {
|
||
--_selection.top;
|
||
if (_selection.top < 0) {
|
||
top = _viewport.bottom - (_screen.bottom - 1 - _selection.top) * _viewport.height() / _screen.height();
|
||
if (top < 0) {
|
||
top = 0;
|
||
++_selection.top;
|
||
if (stop) {
|
||
break;
|
||
}
|
||
stop = true;
|
||
alternate = false;
|
||
}
|
||
}
|
||
} else {
|
||
++_selection.bottom;
|
||
if (_selection.bottom > _screen.bottom - 1) {
|
||
bottom = _viewport.top + (_selection.bottom - _screen.top) * _viewport.height() / _screen.height();
|
||
if (bottom > kPhotoHeight - 1) {
|
||
bottom = kPhotoHeight - 1;
|
||
--_selection.bottom;
|
||
if (stop) {
|
||
break;
|
||
}
|
||
alternate = true;
|
||
stop = true;
|
||
}
|
||
}
|
||
}
|
||
if (!stop) {
|
||
alternate = !alternate;
|
||
}
|
||
}
|
||
|
||
if (left > right) {
|
||
SWAP(left, right);
|
||
}
|
||
|
||
if (top > bottom) {
|
||
SWAP(top, bottom);
|
||
}
|
||
|
||
_regionSelected = findRegion(Common::Rect(left, top, right, bottom));
|
||
if (_regionSelected >= 0) {
|
||
_regionSelectedAck = true;
|
||
setStatePhoto(kEsperPhotoStatePhotoZooming);
|
||
}
|
||
}
|
||
|
||
int ESPER::viewportXToScreenX(int x) {
|
||
return _screen.width() * (x - _viewport.left) / _viewport.width() + _screen.left;
|
||
}
|
||
|
||
int ESPER::viewportYToScreenY(int y) {
|
||
return _screen.height() * (y - _viewport.top) / _viewport.height() + _screen.top;
|
||
}
|
||
|
||
} // End of namespace BladeRunner
|