diff options
| -rw-r--r-- | engines/zvision/events.cpp | 92 | ||||
| -rw-r--r-- | engines/zvision/render_manager.cpp | 62 | ||||
| -rw-r--r-- | engines/zvision/render_manager.h | 10 | 
3 files changed, 157 insertions, 7 deletions
| diff --git a/engines/zvision/events.cpp b/engines/zvision/events.cpp index 79ef0bd6b0..68fa81ede3 100644 --- a/engines/zvision/events.cpp +++ b/engines/zvision/events.cpp @@ -26,6 +26,8 @@  #include "zvision/console.h"  #include "common/events.h"  #include "engines/util.h" +#include "common/system.h" +#include "common/rational.h"  #include "zvision/cursor_manager.h"  #include "zvision/render_manager.h" @@ -95,7 +97,7 @@ void ZVision::onMouseDown(const Common::Point &pos) {  void ZVision::onMouseUp(const Common::Point &pos) {  	_cursorManager->cursorDown(false); -	Common::Point imageCoord(_renderManager->convertToImageCoords(pos)); +	Common::Point imageCoord(_renderManager->screenSpaceToImageSpace(pos));  	for (Common::List<MouseEvent>::iterator iter = _mouseEvents.begin(); iter != _mouseEvents.end(); iter++) {  		if (iter->withinHotspot(imageCoord)) { @@ -105,17 +107,93 @@ void ZVision::onMouseUp(const Common::Point &pos) {  }  void ZVision::onMouseMove(const Common::Point &pos) { -	Common::Point imageCoord(_renderManager->convertToImageCoords(pos)); +	Common::Point imageCoord(_renderManager->screenSpaceToImageSpace(pos));  	bool isWithinAHotspot = false; -	for (Common::List<MouseEvent>::iterator iter = _mouseEvents.begin(); iter != _mouseEvents.end(); iter++) { -		if (iter->withinHotspot(imageCoord)) { -			_cursorManager->changeCursor(iter->getHoverCursor()); -			isWithinAHotspot = true; +	if (_workingWindow.contains(pos)) { +		for (Common::List<MouseEvent>::iterator iter = _mouseEvents.begin(); iter != _mouseEvents.end(); iter++) { +			if (iter->withinHotspot(imageCoord)) { +				_cursorManager->changeCursor(iter->getHoverCursor()); +				isWithinAHotspot = true; +			}  		}  	} - +	// Graph of the function governing rotation velocity: +	// +	//                                     |--------------- working window -----------------| +	//               ^                     |--------| +	//               |                          | +	// +Max velocity |                        rotation screen edge offset                    _____________________ +	//               |                                                                      / +	//               |                                                                     / +	//               |                                                                    / +	//               |                                                                   / +	//               |                                                                  / +	//               |                                                                 / +	//               |                                                                / +	//               |                                                               / +	//               |                                                              / +	// Zero velocity |______________________________ ______________________________/____________________________________> +	//               | Position ->                  / +	//               |                             / +	//               |                            / +	//               |                           / +	//               |                          / +	//               |                         / +	//               |                        / +	//               |                       / +	//               |                      / +	// -Max velocity |_____________________/ +	//               | +	//               | +	//               ^ + +	// NOTE: RenderManger uses the inverse of velocity (ms/pixel instead of pixels/ms) because it allows you to accumulate whole +	// pixels 'steps' instead of rounding pixels every frame + +	if (_workingWindow.contains(pos)) { +		RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState(); +		if (renderState == RenderTable::PANORAMA) { +			if (pos.x >= _workingWindow.left && pos.x < _workingWindow.left + ROTATION_SCREEN_EDGE_OFFSET) { +				// Linear function of distance to the left edge (y = -mx + b) +				// We use fixed point math to get better accuracy +				Common::Rational velocity = (Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.x - _workingWindow.left)) - MAX_ROTATION_SPEED; +				_renderManager->setBackgroundVelocity(velocity.toInt()); +				_cursorManager->setLeftCursor(); +				isWithinAHotspot = true; +			} else if (pos.x <= _workingWindow.right && pos.x > _workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET) { +				// Linear function of distance to the right edge (y = mx) +				// We use fixed point math to get better accuracy +				Common::Rational velocity = Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.x - _workingWindow.right + ROTATION_SCREEN_EDGE_OFFSET); +				_renderManager->setBackgroundVelocity(velocity.toInt()); +				_cursorManager->setRightCursor(); +				isWithinAHotspot = true; +			} else { +				_renderManager->setBackgroundVelocity(0); +			} +		} else if (renderState == RenderTable::TILT) { +			if (pos.y >= _workingWindow.top && pos.y < _workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET) { +				// Linear function of distance to top edge +				// We use fixed point math to get better accuracy +				Common::Rational velocity = (Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.top)) - MAX_ROTATION_SPEED; +				_renderManager->setBackgroundVelocity(velocity.toInt()); +				_cursorManager->setUpCursor(); +				isWithinAHotspot = true; +			} else if (pos.y <= _workingWindow.bottom && pos.y > _workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET) { +				// Linear function of distance to the bottom edge (y = mx) +				// We use fixed point math to get better accuracy +				Common::Rational velocity = Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.bottom + ROTATION_SCREEN_EDGE_OFFSET); +				_renderManager->setBackgroundVelocity(velocity.toInt()); +				_cursorManager->setDownCursor(); +				isWithinAHotspot = true; +			} else { +				_renderManager->setBackgroundVelocity(0); +			} +		} +	} else { +		_renderManager->setBackgroundVelocity(0); +	}  	if (!isWithinAHotspot) {  		_cursorManager->revertToIdle(); diff --git a/engines/zvision/render_manager.cpp b/engines/zvision/render_manager.cpp index 7855dc3903..b8dcd0dd87 100644 --- a/engines/zvision/render_manager.cpp +++ b/engines/zvision/render_manager.cpp @@ -40,6 +40,10 @@ RenderManager::RenderManager(OSystem *system, const Common::Rect workingWindow)  	  _workingHeight(workingWindow.height()),  	  _workingWindow(workingWindow),  	  _currentBackground(0), +	  _backgroundWidth(0), +	  _backgroundHeight(0), +	  _backgroundInverseVelocity(0), +	  _accumulatedVelocityMilliseconds(0),  	  _renderTable(workingWindow.width(), workingWindow.height()) {  } @@ -56,6 +60,24 @@ void RenderManager::renderSubRectToScreen(uint16 *buffer, uint32 imageWidth, uin  		uint32 temp = imageHeight;  		imageHeight = imageWidth;  		imageWidth = temp; +void RenderManager::update(uint deltaTimeInMillis) { +	// An inverse velocity of 0 would be infinitely fast, so we'll let 0 mean no velocity. +	if (_backgroundInverseVelocity == 0) +		return; + +	_accumulatedVelocityMilliseconds += deltaTimeInMillis; + +	int absVelocity = abs(_backgroundInverseVelocity); + +	uint numberOfSteps = 0; +	while (_accumulatedVelocityMilliseconds >= absVelocity) { +		_accumulatedVelocityMilliseconds -= absVelocity; +		numberOfSteps++; +	} + +	// Choose the direction of movement using the sign of the velocity +	moveBackground(_backgroundInverseVelocity < 0 ? -numberOfSteps : numberOfSteps); +}  	}  	// If subRect is empty, use the entire image @@ -178,6 +200,46 @@ void RenderManager::setBackgroundImage(const Common::String &fileName) {  	_currentBackground = file;  	renderImageToScreen(*_currentBackground, 0, 0, Common::Rect(), true); +void RenderManager::setBackgroundPosition(int offset) { +	if (_renderTable.getRenderState() == RenderTable::TILT) { +		_backgroundOffset = Common::Point(0, offset); +	} else { +		_backgroundOffset = Common::Point(offset, 0); +	} +} + +void RenderManager::setBackgroundVelocity(int velocity) { +	// setBackgroundVelocity(0) will be called quite often, so make sure +	// _backgroundInverseVelocity isn't already 0 to prevent an extraneous assignment +	if (velocity == 0) { +		if (_backgroundInverseVelocity != 0) { +			_backgroundInverseVelocity = 0; +		} +	} else { +		_backgroundInverseVelocity = 1000 / velocity; +	} +} + +void RenderManager::moveBackground(int offset) { +	if (_renderTable.getRenderState() == RenderTable::TILT) { +		_backgroundOffset += Common::Point(0, offset); +	} else { +		_backgroundOffset += Common::Point(offset, 0); +	} + +	// Make sure the offset is within image bounds +	if (_backgroundOffset.x < 0) +		_backgroundOffset.x += _backgroundWidth; +	if (_backgroundOffset.x > _backgroundWidth) +		_backgroundOffset.x -= _backgroundWidth; +	if (_backgroundOffset.y < 0) +		_backgroundOffset.y += _backgroundHeight; +	if (_backgroundOffset.y > _backgroundHeight) +		_backgroundOffset.y -= _backgroundHeight; + +	_currentBackground->seek(0); +	// Purposely make the subRectangle empty. renderImageToScreen will then set the width and height automatically. +	renderImageToScreen(*_currentBackground, 0, 0, Common::Rect(_backgroundOffset.x, _backgroundOffset.y, _backgroundOffset.x, _backgroundOffset.y), true);  }  } // End of namespace ZVision diff --git a/engines/zvision/render_manager.h b/engines/zvision/render_manager.h index 8731675ef6..7d44a37726 100644 --- a/engines/zvision/render_manager.h +++ b/engines/zvision/render_manager.h @@ -55,12 +55,18 @@ private:  	Common::SeekableReadStream *_currentBackground;  	Common::Point _backgroundOffset; +	uint16 _backgroundWidth; +	uint16 _backgroundHeight; + +	int _backgroundInverseVelocity; +	uint _accumulatedVelocityMilliseconds;  	Video::VideoDecoder *_currentVideo;  	byte *_scaledVideoFrameBuffer;  public:  	void initialize(); +	void update(uint deltaTimeInMillis);  	/**  	 * Blits the image or a portion of the image to the screen. Actual screen updates won't happen until the end of the frame. @@ -92,6 +98,10 @@ public:  	 */  	void setBackgroundImage(const Common::String &fileName); +	void setBackgroundPosition(int offset); + +	void setBackgroundVelocity(int velocity); +  	const Common::Point screenSpaceToImageSpace(const Common::Point &point);  	RenderTable *getRenderTable(); | 
