[Scummvm-cvs-logs] scummvm master -> 7186eab65f47c7370925d1a72598ccd8e0656076

dreammaster dreammaster at scummvm.org
Fri Jun 19 03:49:31 CEST 2015


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
7186eab65f SHERLOCK: RT: Implement loading for the text window widget


Commit: 7186eab65f47c7370925d1a72598ccd8e0656076
    https://github.com/scummvm/scummvm/commit/7186eab65f47c7370925d1a72598ccd8e0656076
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-06-18T21:48:27-04:00

Commit Message:
SHERLOCK: RT: Implement loading for the text window widget

Changed paths:
    engines/sherlock/tattoo/tattoo_user_interface.cpp
    engines/sherlock/tattoo/tattoo_user_interface.h
    engines/sherlock/tattoo/widget_base.cpp
    engines/sherlock/tattoo/widget_base.h
    engines/sherlock/tattoo/widget_text.cpp
    engines/sherlock/tattoo/widget_text.h



diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
index 29a5704..4dd8513 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.cpp
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -172,6 +172,8 @@ void TattooUserInterface::printObjectDesc(const Common::String &str, bool firstT
 			events._oldButtons = 0;
 		}
 	} else {
+		events._pressed = events._released = events._rightReleased = false;;
+
 		// Show text dialog
 		_textWidget.load(str);
 
@@ -186,6 +188,11 @@ void TattooUserInterface::doJournal() {
 	// TODO
 }
 
+void TattooUserInterface::reset() {
+	UserInterface::reset();
+	_lookPos = Common::Point(SHERLOCK_SCREEN_WIDTH / 2, SHERLOCK_SCREEN_HEIGHT / 2);
+}
+
 void TattooUserInterface::handleInput() {
 	TattooEngine &vm = *(TattooEngine *)_vm;
 	Events &events = *_vm->_events;
@@ -527,7 +534,43 @@ void TattooUserInterface::doStandardControl() {
 }
 
 void TattooUserInterface::doLookControl() {
-	warning("TODO: ui control (look)");
+	Events &events = *_vm->_events;
+	TattooScene &scene = *(TattooScene *)_vm->_scene;
+	Sound &sound = *_vm->_sound;
+
+	// See if a mouse button was released or a key pressed, and we want to initiate an action
+	// TODO: Not sure about _soundOn.. should be check for speaking voice for text being complete
+	if (events._released || events._rightReleased || _keyState.keycode || (sound._voices && !sound._soundOn)) {
+		// See if we were looking at an inventory object
+		if (!_invLookFlag) {
+			// See if there is any more text to display
+			if (!_textWidget._remainingText.empty()) {
+				printObjectDesc(_textWidget._remainingText, false);
+			} else {
+				// Otherwise restore the background and go back into STD_MODE
+				freeMenu();
+				_key = -1;
+				_menuMode = scene._labTableScene ? LAB_MODE : STD_MODE;
+
+				events.setCursor(ARROW);
+				events._pressed = events._released = events._rightReleased = false;
+				events._oldButtons = 0;
+			}
+		} else {
+			// We were looking at a Inventory object
+			// Erase the text window, and then redraw the inventory window
+			_textWidget.banishWindow();
+
+			warning("TODO: re-show inventory");
+
+			_invLookFlag = false;
+			_key = -1;
+
+			events.setCursor(ARROW);
+			events._pressed = events._released = events._rightReleased = false;
+			events._oldButtons = 0;
+		}
+	}
 }
 
 void TattooUserInterface::doFileControl() {
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.h b/engines/sherlock/tattoo/tattoo_user_interface.h
index 0f71803..0ccdc67 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.h
+++ b/engines/sherlock/tattoo/tattoo_user_interface.h
@@ -136,6 +136,7 @@ public:
 	bool _personFound;
 	int _activeObj;
 	Common::KeyState _keyState;
+	Common::Point _lookPos;
 public:
 	TattooUserInterface(SherlockEngine *vm);
 	virtual ~TattooUserInterface() {}
@@ -188,6 +189,11 @@ public:
 	void pickUpObject(int objNum);
 public:
 	/**
+	 * Resets the user interface
+	 */
+	virtual void reset();
+
+	/**
 	 * Main input handler for the user interface
 	 */
 	virtual void handleInput();
diff --git a/engines/sherlock/tattoo/widget_base.cpp b/engines/sherlock/tattoo/widget_base.cpp
index 49ad409..16f02a1 100644
--- a/engines/sherlock/tattoo/widget_base.cpp
+++ b/engines/sherlock/tattoo/widget_base.cpp
@@ -22,12 +22,14 @@
 
 #include "sherlock/tattoo/widget_base.h"
 #include "sherlock/tattoo/tattoo.h"
+#include "sherlock/tattoo/tattoo_talk.h"
 
 namespace Sherlock {
 
 namespace Tattoo {
 
 WidgetBase::WidgetBase(SherlockEngine *vm) : _vm(vm) {
+	_images = nullptr;
 }
 
 void WidgetBase::summonWindow() {
@@ -39,6 +41,83 @@ void WidgetBase::banishWindow() {
 	_surface.free();
 }
 
+Common::String WidgetBase::splitLines(const Common::String &str, Common::StringArray &lines, int maxWidth, uint maxLines) {
+	Talk &talk = *_vm->_talk;
+	const char *strP = str.c_str();
+
+	// Loop counting up lines
+	lines.clear();
+	while (lines.size() < maxLines) {
+		int width = 0;
+		const char *spaceP = nullptr;
+		const char *lineStartP = strP;
+
+		// Find how many characters will fit on the next line
+		while (width < maxWidth && *strP && (*strP < 170 || *strP == 225)) {
+			width += _surface.charWidth(*strP);
+
+			// Keep track of the last space
+			if (*strP == ' ')
+				spaceP = strP;
+			++strP;
+		}
+
+		// If the line was too wide to fit on a single line, go back to the last space 
+		// if there was one, or otherwise simply break the line at this point
+		if (width >= maxWidth && spaceP != nullptr)
+			strP = spaceP;
+
+		// Add the line to the output array
+		lines.push_back(Common::String(lineStartP, strP));
+
+		// Move the string ahead to the next line
+		if (*strP == ' ' || *strP == 13)
+			++strP;
+	} while (*strP && (*strP < talk._opcodes[OP_SWITCH_SPEAKER] || *strP == 225));
+
+	// Return any remaining text left over
+	return *strP ? Common::String(strP) : Common::String();
+}
+
+void WidgetBase::checkMenuPosition() {
+	if (_bounds.left < 0)
+		_bounds.moveTo(0, _bounds.top);
+	if (_bounds.top < 0)
+		_bounds.moveTo(_bounds.left, 0);
+	if (_bounds.right > SHERLOCK_SCREEN_WIDTH)
+		_bounds.moveTo(SHERLOCK_SCREEN_WIDTH - _bounds.width(), _bounds.top);
+	if (_bounds.bottom > SHERLOCK_SCREEN_HEIGHT)
+		_bounds.moveTo(_bounds.left, SHERLOCK_SCREEN_HEIGHT - _bounds.height());
+}
+
+void WidgetBase::makeInfoArea() {
+	// Draw the four corners of the Info Box
+	_surface.transBlitFrom((*_images)[0], Common::Point(0, 0));
+	_surface.transBlitFrom((*_images)[1], Common::Point(_bounds.width() - (*_images)[1]._width, 0));
+	_surface.transBlitFrom((*_images)[2], Common::Point(0, _bounds.height() - (*_images)[2]._height));
+	_surface.transBlitFrom((*_images)[3], Common::Point(_bounds.width() - (*_images)[3]._width, _bounds.height()));
+
+	// Draw the top of the Info Box
+	_surface.hLine((*_images)[0]._width, 0, _bounds.width() - (*_images)[1]._width, INFO_TOP);
+	_surface.hLine((*_images)[0]._width, 1, _bounds.width() - (*_images)[1]._width, INFO_MIDDLE);
+	_surface.hLine((*_images)[0]._width, 2, _bounds.width() - (*_images)[1]._width, INFO_BOTTOM);
+
+	// Draw the bottom of the Info Box
+	_surface.hLine((*_images)[0]._width, _bounds.height()- 3, _bounds.width() - (*_images)[1]._width, INFO_TOP);
+	_surface.hLine((*_images)[0]._width, _bounds.height()- 2, _bounds.width() - (*_images)[1]._width, INFO_MIDDLE);
+	_surface.hLine((*_images)[0]._width, _bounds.height()- 1, _bounds.width() - (*_images)[1]._width, INFO_BOTTOM);
+
+	// Draw the left Side of the Info Box
+	_surface.vLine(0, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_TOP);
+	_surface.vLine(1, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_MIDDLE);
+	_surface.vLine(2, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_BOTTOM);
+
+	// Draw the right Side of the Info Box
+	_surface.vLine(_bounds.width() - 3, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_TOP);
+	_surface.vLine(_bounds.width() - 2, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_MIDDLE);
+	_surface.vLine(_bounds.width() - 1, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_BOTTOM);
+}
+
 } // End of namespace Tattoo
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/widget_base.h b/engines/sherlock/tattoo/widget_base.h
index 2a9988b..38b6d04 100644
--- a/engines/sherlock/tattoo/widget_base.h
+++ b/engines/sherlock/tattoo/widget_base.h
@@ -31,6 +31,7 @@
 namespace Sherlock {
 
 class SherlockEngine;
+class ImageFile;
 
 namespace Tattoo {
 
@@ -39,6 +40,19 @@ protected:
 	SherlockEngine *_vm;
 	Common::Rect _bounds, _oldBounds;
 	Surface _surface;
+	ImageFile *_images;
+
+	/**
+	 * Used by descendent classes to split up long text for display across multiple lines
+	 */
+	Common::String splitLines(const Common::String &str, Common::StringArray &lines, int maxWidth, uint maxLines);
+
+	/**
+	 * Ensure that menu is drawn entirely on-screen
+	 */
+	void checkMenuPosition();
+
+	void makeInfoArea();
 public:
 	WidgetBase(SherlockEngine *vm);
 	virtual ~WidgetBase() {}
diff --git a/engines/sherlock/tattoo/widget_text.cpp b/engines/sherlock/tattoo/widget_text.cpp
index 928dbbf..2c4fef0 100644
--- a/engines/sherlock/tattoo/widget_text.cpp
+++ b/engines/sherlock/tattoo/widget_text.cpp
@@ -32,7 +32,58 @@ WidgetText::WidgetText(SherlockEngine *vm) : WidgetBase(vm) {
 }
 
 void WidgetText::load(const Common::String &str) {
-	// TODO
+	Screen &screen = *_vm->_screen;
+	Talk &talk = *_vm->_talk;
+	TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+	Common::StringArray lines;
+
+	// If bounds for a window have not yet been calculated, figure them out
+	if (_surface.empty()) {
+		int width = SHERLOCK_SCREEN_WIDTH / 3;
+		int height;
+
+		for (;;) {
+			_remainingText = splitLines(str, lines, width - _surface.widestChar() * 2, 100);
+			height = (screen.fontHeight() + 1) * lines.size() + 9;
+
+			if ((width - _surface.widestChar() * 2 > height * 3 / 2) || (width - _surface.widestChar() * 2
+					> SHERLOCK_SCREEN_WIDTH * 3 / 4))
+				break;
+
+			width += (width / 4);
+		}
+
+		// See if it's only a single line long
+		if (height == _surface.fontHeight() + 10) {
+			width = _surface.widestChar() * 2 + 6;
+			
+			const char *strP = str.c_str();
+			while (*strP && (*strP < talk._opcodes[OP_SWITCH_SPEAKER] || *strP == 225))
+				width += _surface.charWidth(*strP++);
+		}
+
+		_bounds.setWidth(width);
+		_bounds.setHeight(height);
+		_bounds.translate(ui._lookPos.x - width / 2, ui._lookPos.y - height / 2);
+		checkMenuPosition();
+	} else {
+		// Split up the string into lines in preparation for drawing
+		_remainingText = splitLines(str, lines, _bounds.width() - _surface.widestChar() * 2, 
+			(_bounds.height() - _surface.fontHeight() / 2) / (_surface.fontHeight() + 1));
+	}
+
+	// Allocate a surface for the window
+	_surface.create(_bounds.width(), _bounds.height());
+
+	// Form the background for the new window
+	_surface.fillRect(Common::Rect(0, 0, _surface.w(), _surface.h()), TRANSPARENCY);
+	makeInfoArea();
+
+	int yp = 5;
+	for (int lineNum = 0; yp < (_bounds.height() - _surface.fontHeight() / 2); ++lineNum) {
+		_surface.writeString(lines[lineNum], Common::Point(_surface.widestChar(), yp), INFO_TOP);
+		yp += _surface.fontHeight() + 1;
+	}
 }
 
 } // End of namespace Tattoo
diff --git a/engines/sherlock/tattoo/widget_text.h b/engines/sherlock/tattoo/widget_text.h
index 9765e1b..2608d75 100644
--- a/engines/sherlock/tattoo/widget_text.h
+++ b/engines/sherlock/tattoo/widget_text.h
@@ -34,6 +34,8 @@ namespace Tattoo {
 
 class WidgetText: public WidgetBase {
 public:
+	Common::String _remainingText;
+public:
 	WidgetText(SherlockEngine *vm);
 	virtual ~WidgetText() {}
 






More information about the Scummvm-git-logs mailing list