diff options
| -rw-r--r-- | engines/bladerunner/bladerunner.cpp | 35 | ||||
| -rw-r--r-- | engines/bladerunner/bladerunner.h | 6 | ||||
| -rw-r--r-- | engines/bladerunner/module.mk | 2 | ||||
| -rw-r--r-- | engines/bladerunner/scene.cpp | 4 | ||||
| -rw-r--r-- | engines/bladerunner/script/script.cpp | 12 | ||||
| -rw-r--r-- | engines/bladerunner/spinner.cpp | 291 | ||||
| -rw-r--r-- | engines/bladerunner/spinner.h | 77 | ||||
| -rw-r--r-- | engines/bladerunner/ui_image_picker.cpp | 265 | ||||
| -rw-r--r-- | engines/bladerunner/ui_image_picker.h | 92 | 
9 files changed, 768 insertions, 16 deletions
| diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp index 83a07bbd69..348d5f7c1f 100644 --- a/engines/bladerunner/bladerunner.cpp +++ b/engines/bladerunner/bladerunner.cpp @@ -49,6 +49,7 @@  #include "bladerunner/shape.h"  #include "bladerunner/slice_animations.h"  #include "bladerunner/slice_renderer.h" +#include "bladerunner/spinner.h"  #include "bladerunner/text_resource.h"  #include "bladerunner/vqa_decoder.h"  #include "bladerunner/waypoints.h" @@ -286,6 +287,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {  	// TODO: KIA  	// TODO: Spinner Interface +	_spinner = new Spinner(this);  	// TODO: Elevators @@ -534,6 +536,10 @@ bool BladeRunnerEngine::init2() {  	return true;  } +Common::Point BladeRunnerEngine::getMousePos() { +	return _eventMan->getMousePos(); +} +  void BladeRunnerEngine::gameLoop() {  	_gameIsRunning = true;  	do { @@ -581,7 +587,13 @@ void BladeRunnerEngine::gameTick() {  		// TODO: Autosave  		// TODO: Kia -		// TODO: Spinner + +		if (_spinner->isOpen()) { +			_spinner->tick(); +			_ambientSounds->tick(); +			return; +		} +  		// TODO: Esper  		// TODO: VK  		// TODO: Elevators @@ -636,7 +648,7 @@ void BladeRunnerEngine::gameTick() {  			// TODO: Draw dialogue menu -			Common::Point p = _eventMan->getMousePos(); +			Common::Point p = getMousePos();  			_mouse->tick(p.x, p.y);  			_mouse->draw(_surfaceGame, p.x, p.y); @@ -797,17 +809,32 @@ void BladeRunnerEngine::handleEvents() {  		switch (event.type) {  		case Common::EVENT_LBUTTONDOWN:  		case Common::EVENT_RBUTTONDOWN: -			handleMouseClick(event.mouse.x, event.mouse.y); +		case Common::EVENT_LBUTTONUP: +		case Common::EVENT_RBUTTONUP: { +			bool buttonLeft = event.type == Common::EVENT_LBUTTONDOWN || event.type == Common::EVENT_LBUTTONUP; +			bool buttonDown = event.type == Common::EVENT_LBUTTONDOWN || event.type == Common::EVENT_RBUTTONDOWN; + +			handleMouseAction(event.mouse.x, event.mouse.y, buttonLeft, buttonDown); +		}  		default:  			;  		}  	}  } -void BladeRunnerEngine::handleMouseClick(int x, int y) { +void BladeRunnerEngine::handleMouseAction(int x, int y, bool buttonLeft, bool buttonDown) {  	if (!playerHasControl() || _mouse->isDisabled())  		return; +	if (_spinner->isOpen()) { +		if (buttonDown) { +			_spinner->handleMouseDown(x, y); +		} else { +			_spinner->handleMouseUp(x, y); +		} +		return; +	} +  	Vector3 mousePosition = _mouse->getXYZ(x, y);  	int isClickable; diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h index b2e3df08ea..8fd43df211 100644 --- a/engines/bladerunner/bladerunner.h +++ b/engines/bladerunner/bladerunner.h @@ -69,6 +69,7 @@ class Settings;  class Shape;  class SliceAnimations;  class SliceRenderer; +class Spinner;  class TextResource;  class View;  class Waypoints; @@ -105,6 +106,7 @@ public:  	Settings         *_settings;  	SliceAnimations  *_sliceAnimations;  	SliceRenderer    *_sliceRenderer; +	Spinner          *_spinner;  	SuspectsDatabase *_suspectsDatabase;  	View             *_view;  	Waypoints        *_waypoints; @@ -164,11 +166,13 @@ public:  	bool loadSplash();  	bool init2(); +	Common::Point getMousePos(); +  	void gameLoop();  	void gameTick();  	void actorsUpdate();  	void handleEvents(); -	void handleMouseClick(int x, int y); +	void handleMouseAction(int x, int y, bool buttonLeft, bool buttonDown);  	void handleMouseClickExit(int x, int y, int exitIndex);  	void handleMouseClickRegion(int x, int y, int regionIndex);  	void handleMouseClickItem(int x, int y, int itemId); diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk index 3569efab12..9a43ef4457 100644 --- a/engines/bladerunner/module.mk +++ b/engines/bladerunner/module.mk @@ -167,8 +167,10 @@ MODULE_OBJS = \  	shape.o \  	slice_animations.o \  	slice_renderer.o \ +	spinner.o \  	suspects_database.o \  	text_resource.o \ +	ui_image_picker.o \  	view.o \  	vqa_decoder.o \  	vqa_player.o \ diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp index 4af2c15d08..1e5297a4bf 100644 --- a/engines/bladerunner/scene.cpp +++ b/engines/bladerunner/scene.cpp @@ -33,6 +33,7 @@  #include "bladerunner/scene_objects.h"  #include "bladerunner/script/scene.h"  #include "bladerunner/slice_renderer.h" +#include "bladerunner/spinner.h"  #include "common/str.h" @@ -306,8 +307,7 @@ void Scene::loopEnded(int frame, int loopId) {  			_playerWalkedIn = true;  		}  		if (_specialLoopMode == 3) { -			//TODO: -			//spinner::open(Spinner); +			_vm->_spinner->setIsOpen();  		}  		_specialLoopMode = -1;  		_specialLoop = -1; diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp index 9fcfb252c6..ba78a42b4c 100644 --- a/engines/bladerunner/script/script.cpp +++ b/engines/bladerunner/script/script.cpp @@ -43,6 +43,7 @@  #include "bladerunner/scene_objects.h"  #include "bladerunner/slice_animations.h"  #include "bladerunner/slice_renderer.h" +#include "bladerunner/spinner.h"  #include "bladerunner/text_resource.h"  #include "bladerunner/vector.h"  #include "bladerunner/waypoints.h" @@ -1071,22 +1072,15 @@ bool ScriptBase::SDB_Add_Other_Clue(int suspectId, int clueId) {  }  void ScriptBase::Spinner_Set_Selectable_Destination_Flag(int a1, int a2) { -	//TODO -	warning("Spinner_Set_Selectable_Destination_Flag(%d, %d)", a1, a2); +	_vm->_spinner->setSelectableDestinationFlag(a1, a2);  }  // ScriptBase::Spinner_Query_Selectable_Destination_Flag  int ScriptBase::Spinner_Interface_Choose_Dest(int a1, int a2) { -	//TODO -	warning("Spinner_Interface_Choose_Dest(%d, %d)", a1, a2); -	return -1; +	return _vm->_spinner->interfaceChooseDest(a1, a2);  } -// ScriptBase::Spinner_Set_Selectable_Destination_Flag -// ScriptBase::Spinner_Query_Selectable_Destination_Flag -// ScriptBase::Spinner_Interface_Choose_Dest -  void ScriptBase::ESPER_Flag_To_Activate() {  	//TODO  	warning("ESPER_Flag_To_Activate()"); diff --git a/engines/bladerunner/spinner.cpp b/engines/bladerunner/spinner.cpp new file mode 100644 index 0000000000..6c30a62bac --- /dev/null +++ b/engines/bladerunner/spinner.cpp @@ -0,0 +1,291 @@ +/* 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/spinner.h" + +#include "bladerunner/bladerunner.h" + +#include "bladerunner/scene.h" +#include "bladerunner/shape.h" +#include "bladerunner/mouse.h" +#include "bladerunner/vqa_player.h" +#include "bladerunner/text_resource.h" +#include "bladerunner/ui_image_picker.h" + +#include "common/rect.h" +#include "common/system.h" + +namespace BladeRunner { + +Spinner::Spinner(BladeRunnerEngine *vm) : _vm(vm) { +	reset(); +	_imagePicker = new UIImagePicker(vm, SPINNER_DESTINATIONS); +} + +Spinner::~Spinner() { +	delete _imagePicker; +	reset(); +} + +void Spinner::setSelectableDestinationFlag(int destination, bool selectable) { +	_isDestinationSelectable[destination] = selectable; +} + +bool Spinner::querySelectableDestinationFlag(int destination) const { +	return _isDestinationSelectable[destination]; +} + +SpinnerDestination SpinnerDestinationsNear[] = { +	{ 0, 0x0D2, 0x107, 0x107, 0x14C }, +	{ 1, 0x133, 0x14A, 0x169, 0x17D }, +	{ 2, 0x152, 0x089, 0x16A, 0x0A9 }, +	{ 3, 0x0F8, 0x087, 0x121, 0x0A8 }, +	{ 4, 0x160, 0x0DE, 0x17B, 0x0EE }, +	{ -1, -1, -1, -1, -1 } +}; + +SpinnerDestination SpinnerDestinationsMedium[] = { +	{ 0, 0x0FC, 0x0F2, 0x117, 0x11B }, +	{ 1, 0x12D, 0x111, 0x148, 0x130 }, +	{ 2, 0x13F, 0x0B6, 0x150, 0x0C8 }, +	{ 3, 0x10D, 0x0B5, 0x125, 0x0C8 }, +	{ 4, 0x145, 0x0E3, 0x159, 0x0F0 }, +	{ 5, 0x103, 0x04A, 0x17C, 0x077 }, +	{ 6, 0x0CB, 0x07C, 0x0E0, 0x088 }, +	{ 7, 0x0C8, 0x093, 0x0DE, 0x0AA }, +	{ -1, -1, -1, -1, -1 } +}; + +SpinnerDestination SpinnerDestinationsFar[] = { +	{ 0, 0x0DC, 0x0E3, 0x0F6, 0x106 }, +	{ 1, 0x104, 0x0FC, 0x11E, 0x117 }, +	{ 2, 0x11E, 0x0B2, 0x12E, 0x0C4 }, +	{ 3, 0x0F4, 0x0B2, 0x107, 0x0C3 }, +	{ 4, 0x120, 0x0D8, 0x132, 0x0E4 }, +	{ 5, 0x0F9, 0x04D, 0x161, 0x07C }, +	{ 6, 0x0BE, 0x07F, 0x0D0, 0x08A }, +	{ 7, 0x0B9, 0x095, 0x0CE, 0x0AA }, +	{ 8, 0x18E, 0x0F9, 0x1A3, 0x10C }, +	{ 9, 0x186, 0x0DA, 0x1A3, 0x0EC }, +	{ -1, -1, -1, -1, -1 } +}; + +static void spinner_mouseInCallback(int, void*); +static void spinner_mouseOutCallback(int, void*); +static void spinner_mouseDownCallback(int, void*); +static void spinner_mouseUpCallback(int, void*); + +int Spinner::interfaceChooseDest(int loopId, int loopFlag) { +	_selectedDestination = 0; +	if (!_vm->openArchive("MODE.MIX")) +		return 0; + +	if (loopId < 0) { +		_isOpen = true; +	} else { +		_vm->playerLosesControl(); +		_vm->_scene->loopStartSpecial(3, loopId, loopFlag); +		while (!_isOpen) { +			_vm->gameTick(); +		} +		_vm->playerGainsControl(); +	} + +	_vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceInterface); +	if (!_vqaPlayer->open("SPINNER.VQA")) { +		return 0; +	} + +	_vm->_mouse->setCursor(0); + +	// Determine which map we need to show to include the active destinations +	uint8 mapmask = 0; +	uint8 mapmaskv[SPINNER_DESTINATIONS] = { 1, 1, 1, 1, 1, 3, 3, 3, 7, 7 }; +	for (int i = 0; i != SPINNER_DESTINATIONS; ++i) { +		if (_isDestinationSelectable[i]) +			mapmask |= mapmaskv[i]; +	} + +	_destinations = nullptr; +	int firstShapeId = 0; +	int shapeCount = 0; +	int spinnerLoopId = 4; + +	mapmask = 1; + +	if (mapmask & 4) { +		_destinations = SpinnerDestinationsFar; +		firstShapeId = 26; +		shapeCount = 20; +		spinnerLoopId = 4; +	} else if (mapmask & 2) { +		_destinations = SpinnerDestinationsMedium; +		firstShapeId = 10; +		shapeCount = 16; +		spinnerLoopId = 2; +	} else if (mapmask & 1) { +		_destinations = SpinnerDestinationsNear; +		firstShapeId = 0; +		shapeCount = 10; +		spinnerLoopId = 0; +	} else { +		return -1; +	} + +	_vqaPlayer->setLoop(spinnerLoopId,     -1, 2, nullptr, nullptr); +	_vqaPlayer->setLoop(spinnerLoopId + 1, -1, 0, nullptr, nullptr); + +	for (int j = 0; j != shapeCount; ++j) { +		_shapes.push_back(new Shape(_vm)); +		_shapes[j]->readFromContainer("SPINNER.SHP", firstShapeId + j); +	} + +	_imagePicker->resetImages(); + +	for (SpinnerDestination *dest = _destinations; dest->id != -1; ++dest) { +		if (!_isDestinationSelectable[dest->id]) +			continue; + +		const char *tooltip = _vm->_textSpinnerDestinations->getText(dest->id); + +		_imagePicker->defineImage( +			dest->id, +			dest->left, +			dest->top, +			dest->right, +			dest->bottom, +			_shapes[dest->id], +			_shapes[dest->id + _shapes.size() / 2], +			_shapes[dest->id + _shapes.size() / 2], +			tooltip +		); +	} + +	_imagePicker->setCallbacks( +		spinner_mouseInCallback, +		spinner_mouseOutCallback, +		spinner_mouseDownCallback, +		spinner_mouseUpCallback, +		this +	); + +	// TODO: Freeze game time +	_selectedDestination = -1; +	do { +		_vm->gameTick(); +	} while (_selectedDestination == -1); + +	// TODO: Unfreeze game time +	_isOpen = false; +	// TODO: _vm->_scene->resume(); + +	for (int i = 0; i != (int)_shapes.size(); ++i) +		delete _shapes[i]; +	_shapes.clear(); + +	return _selectedDestination; +} + +static void spinner_mouseInCallback(int, void*) { +} + +static void spinner_mouseOutCallback(int, void*) { +} + +static void spinner_mouseDownCallback(int, void*) { +} + +static void spinner_mouseUpCallback(int image, void *data) { +	if (image >= 0 && image < 10) { +		Spinner *spinner = (Spinner *)data; +		spinner->setSelectedDestination(image); +	} +} + +void Spinner::setIsOpen() { +	_isOpen = true; +} + +bool Spinner::isOpen() const { +	return _isOpen; +} + +int Spinner::handleMouseUp(int x, int y) { +	_imagePicker->handleMouseAction(x, y, false, true, 0); +	return false; +} + +int Spinner::handleMouseDown(int x, int y) { +	_imagePicker->handleMouseAction(x, y, true, false, 0); +	return false; +} + +void Spinner::tick() { +	if (!_vm->_gameIsRunning) +		return; + +	int frame = _vqaPlayer->update(); +	assert(frame >= -1); + +	// vqaPlayer renders to _surfaceInterface +	_vm->_surfaceGame.copyRectToSurface(_vm->_surfaceInterface, 0, 0, Common::Rect(640, 480)); + +	_imagePicker->draw(_vm->_surfaceInterface); + +	Common::Point p = _vm->getMousePos(); +	_imagePicker->handleMouseAction(p.x, p.y, false, false, false); +	if (_imagePicker->hasHoveredImage()) { +		_vm->_mouse->setCursor(1); +	} else { +		_vm->_mouse->setCursor(0); +	} +	_vm->_mouse->draw(_vm->_surfaceGame, p.x, p.y); + +	_vm->_system->copyRectToScreen(_vm->_surfaceGame.getPixels(), _vm->_surfaceGame.pitch, 0, 0, 640, 480); +	_vm->_system->updateScreen(); +	_vm->_system->delayMillis(10); +} + +void Spinner::setSelectedDestination(int destination) { +	_selectedDestination = destination; +} + +void Spinner::reset() { +	for (int i = 0; i != SPINNER_DESTINATIONS; ++i) { +		_isDestinationSelectable[i] = 0; +	} + +	_isOpen = false; +	_destinations = nullptr; +	_selectedDestination = -1; +	_imagePicker = nullptr; + +	for (int i = 0; i != (int)_shapes.size(); ++i) +		delete _shapes[i]; +	_shapes.clear(); +} + +void Spinner::resume() { +	// TODO +} + +} // End of namespace BladeRunner diff --git a/engines/bladerunner/spinner.h b/engines/bladerunner/spinner.h new file mode 100644 index 0000000000..19021fac1a --- /dev/null +++ b/engines/bladerunner/spinner.h @@ -0,0 +1,77 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BLADERUNNER_SPINNER_H +#define BLADERUNNER_SPINNER_H + +#include "common/array.h" + +namespace BladeRunner { + +class BladeRunnerEngine; +class Shape; +class VQAPlayer; +class UIImagePicker; + +#define SPINNER_DESTINATIONS 10 + +struct SpinnerDestination { +	int id; +	int left; +	int top; +	int right; +	int bottom; +}; + +class Spinner { +	BladeRunnerEngine     *_vm; +	bool                   _isDestinationSelectable[SPINNER_DESTINATIONS]; +	bool                   _isOpen; +	VQAPlayer             *_vqaPlayer; +	SpinnerDestination    *_destinations; +	int                    _selectedDestination; +	Common::Array<Shape*>  _shapes; +	UIImagePicker         *_imagePicker; + +public: +	Spinner(BladeRunnerEngine *vm); +	~Spinner(); + +	void setSelectableDestinationFlag(int destination, bool selectable); +	bool querySelectableDestinationFlag(int destination) const; + +	int interfaceChooseDest(int vqaLoopId, int loopFlag); + +	void setIsOpen(); +	bool isOpen() const; + +	int handleMouseUp(int x, int y); +	int handleMouseDown(int x, int y); +	void tick(); +	void setSelectedDestination(int destination); +	void reset(); +	void resume(); +}; + +} // End of namespace BladeRunner + +#endif diff --git a/engines/bladerunner/ui_image_picker.cpp b/engines/bladerunner/ui_image_picker.cpp new file mode 100644 index 0000000000..654129754c --- /dev/null +++ b/engines/bladerunner/ui_image_picker.cpp @@ -0,0 +1,265 @@ +/* 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_image_picker.h" + +#include "bladerunner/bladerunner.h" + +#include "bladerunner/shape.h" + +#include "common/rect.h" +#include "graphics/surface.h" + +namespace BladeRunner { + +struct UIImagePickerImage { +	int          active; +	Common::Rect rect; +	Shape       *shapeUp; +	Shape       *shapeHovered; +	Shape       *shapeDown; +	const char  *tooltip; +}; + +UIImagePicker::UIImagePicker(BladeRunnerEngine *vm, int imageCount) : _vm(vm) { +	reset(); +	_images = new UIImagePickerImage[imageCount]; +	_imageCount = imageCount; +	resetImages(); +} + +UIImagePicker::~UIImagePicker() { +	delete[] _images; +	_images = nullptr; +	reset(); +} + +void UIImagePicker::resetImages() { +	for (int i = 0; i != _imageCount; i++) { +		resetImage(i); +	} +} + +bool UIImagePicker::defineImage(int i, int left, int top, int right, int bottom, Shape *shapeUp, Shape *shapeHovered, Shape *shapeDown, const char *tooltip) { +	if (i < 0 || i >= _imageCount || _images[i].active) +		return false; + +	UIImagePickerImage &img = _images[i]; + +	img.rect.left = left; +	img.rect.top = top; +	img.rect.right = right + 1; +	img.rect.bottom = bottom + 1; +	img.shapeUp = shapeUp; +	img.shapeHovered = shapeHovered; +	img.shapeDown = shapeDown; +	img.active = true; +	img.tooltip = tooltip; + +	return true; +} + +bool UIImagePicker::setImageTop(int i, int top) { +	if (i < 0 || i >= _imageCount || !_images[i].active) +		return false; + +	UIImagePickerImage &img = _images[i]; + +	img.rect.moveTo(img.rect.left, top); + +	return true; +} + +bool UIImagePicker::setImageLeft(int i, int left) { +	if (i < 0 || i >= _imageCount || !_images[i].active) +		return false; + +	UIImagePickerImage &img = _images[i]; + +	img.rect.moveTo(left, img.rect.top); + +	return true; +} + +bool UIImagePicker::setImageShapeUp(int i, Shape *shapeUp) { +	if (i < 0 || i >= _imageCount || !_images[i].active) +		return false; + +	_images[i].shapeUp = shapeUp; + +	return true; +} + +bool UIImagePicker::setImageShapeHovered(int i, Shape *shapeHovered) { +	if (i < 0 || i >= _imageCount || !_images[i].active) +		return false; + +	_images[i].shapeHovered = shapeHovered; + +	return true; +} + +bool UIImagePicker::setImageShapeDown(int i, Shape *shapeDown) { +	if (i < 0 || i >= _imageCount || !_images[i].active) +		return false; + +	_images[i].shapeDown = shapeDown; + +	return true; +} + +bool UIImagePicker::setImageTooltip(int i, const char *tooltip) { +	if (i < 0 || i >= _imageCount || !_images[i].active) +		return false; + +	_images[i].tooltip = tooltip; + +	return true; +} + +bool UIImagePicker::resetActiveImage(int i) { +	if (i < 0 || i >= _imageCount || !_images[i].active) +		return false; + +	resetImage(i); +	return true; +} + +void UIImagePicker::setCallbacks(UIImagePickerCallback *mouseInCallback, +                                 UIImagePickerCallback *mouseOutCallback, +                                 UIImagePickerCallback *mouseDownCallback, +                                 UIImagePickerCallback *mouseUpCallback, +                                 void *callbackData) +{ +	_isButtonDown = false; +	_mouseInCallback   = mouseInCallback; +	_mouseOutCallback  = mouseOutCallback; +	_mouseDownCallback = mouseDownCallback; +	_mouseUpCallback   = mouseUpCallback; +	_callbackData      = callbackData; +	_hoverStartTimestamp = 0; +	_isVisible = true; +	_hoveredImageIndex = -1; +	_pressedImageIndex = -1; +} + +void UIImagePicker::resetCallbacks() {} + +// TODO +void UIImagePicker::drawTooltip() {} + +void UIImagePicker::draw(Graphics::Surface &surface) { +	if (!_isVisible) +		return; + +	for (int i = 0; i != _imageCount; ++i) { +		UIImagePickerImage &img = _images[i]; +		if (!img.active) +			continue; + +		// TODO: Check interaction with Mouse::isDisabled +		if (i == _hoveredImageIndex && i == _pressedImageIndex && _isButtonDown) { +			if (img.shapeDown) { +				img.shapeDown->draw(surface, img.rect.left, img.rect.top); +			} +		} else if (i == _hoveredImageIndex && !_isButtonDown) { +			if (img.shapeHovered) { +				img.shapeHovered->draw(surface, img.rect.left, img.rect.top); +			} +		} else { +			if (img.shapeUp) { +				img.shapeUp->draw(surface, img.rect.left, img.rect.top); +			} +		} +	} +} + +void UIImagePicker::handleMouseAction(int x, int y, bool down, bool up, bool ignore) { +	if (!_isVisible || ignore) { +		return; +	} + +	int hoveredImageIndex = -1; +	for (int i = 0; i != _imageCount; ++i) { +		if (_images[i].rect.contains(x, y)) { +			hoveredImageIndex = i; +			break; +		} +	} + +	// If mouse moved to a new image +	if (hoveredImageIndex != _hoveredImageIndex) { +		if (!_isButtonDown) { +			if (hoveredImageIndex == -1) { +				if (_mouseOutCallback) +					_mouseOutCallback(hoveredImageIndex, _callbackData); +			} else { +				if (_mouseInCallback) +					_mouseInCallback(hoveredImageIndex, _callbackData); +			} +		} +		_hoveredImageIndex = hoveredImageIndex; +	} + +	// If mouse button changed to pressed +	if (down && !_isButtonDown) { +		_isButtonDown = true; +		_pressedImageIndex = _hoveredImageIndex; +		if (_mouseDownCallback) +			_mouseDownCallback(_hoveredImageIndex, _callbackData); +	} + +	// If mouse button changed to released +	if (up) { +		if (_isButtonDown) { +			if (_hoveredImageIndex == _pressedImageIndex && _pressedImageIndex != -1) { +				if (_mouseUpCallback) +					_mouseUpCallback(_hoveredImageIndex, _callbackData); +			} +		} +		_isButtonDown = false; +		_pressedImageIndex = -1; +	} +} + +void UIImagePicker::resetImage(int i) { +	assert(i >= 0 && i < _imageCount); +	UIImagePickerImage &img = _images[i]; + +	img.active = false; +	img.rect.left = -1; +	img.rect.top = -1; +	img.rect.right = -1; +	img.rect.bottom = -1; +	img.shapeUp = nullptr; +	img.shapeHovered = nullptr; +	img.shapeDown = nullptr; +	img.tooltip = nullptr; +} + +bool UIImagePicker::hasHoveredImage() { +	return _hoveredImageIndex >= 0; +} + +void UIImagePicker::reset() {} + +} // End of namespace BladeRunner diff --git a/engines/bladerunner/ui_image_picker.h b/engines/bladerunner/ui_image_picker.h new file mode 100644 index 0000000000..c55aa48a64 --- /dev/null +++ b/engines/bladerunner/ui_image_picker.h @@ -0,0 +1,92 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BLADERUNNER_UI_IMAGE_PICKER_H +#define BLADERUNNER_UI_IMAGE_PICKER_H + +namespace Graphics { +struct Surface; +} + +namespace BladeRunner { + +class BladeRunnerEngine; +class Shape; +struct UIImagePickerImage; + +typedef void UIImagePickerCallback(int, void*); + +class UIImagePicker { +	BladeRunnerEngine *_vm; + +	int _isVisible; +	int _imageCount; +	int _hoveredImageIndex; +	int _pressedImageIndex; +	int _hoverStartTimestamp; +	int _isButtonDown; +	UIImagePickerImage *_images; + +	UIImagePickerCallback *_mouseInCallback; +	UIImagePickerCallback *_mouseOutCallback; +	UIImagePickerCallback *_mouseDownCallback; +	UIImagePickerCallback *_mouseUpCallback; +	void *_callbackData; + +public: +	UIImagePicker(BladeRunnerEngine *vm, int imageCount); +	~UIImagePicker(); + +	void resetImages(); +	bool defineImage(int i, int left, int top, int right, int bottom, Shape *shapeUp, Shape *shapeHovered, Shape *shapeDown, const char *tooltip); + +	bool setImageTop(int i, int top); +	bool setImageLeft(int i, int left); +	bool setImageShapeUp(int i, Shape *shapeUp); +	bool setImageShapeHovered(int i, Shape *shapeHovered); +	bool setImageShapeDown(int i, Shape *shapeDown); +	bool setImageTooltip(int i, const char *tooltip); + +	bool resetActiveImage(int i); + +	void setCallbacks(UIImagePickerCallback *mouseInCallback, +	                  UIImagePickerCallback *mouseOutCallback, +	                  UIImagePickerCallback *mouseDownCallback, +	                  UIImagePickerCallback *mouseUpCallback, +	                  void *callbackData); + +	void resetCallbacks(); + +	void drawTooltip(); +	void draw(Graphics::Surface &surface); + +	void handleMouseAction(int x, int y, bool down, bool up, bool ignore = false); + +	void resetImage(int i); +	bool hasHoveredImage(); + +	void reset(); +}; + +} // End of namespace BladeRunner + +#endif | 
