[Scummvm-git-logs] scummvm master -> 5b4b78123b6574d3cb49f8ada41dfb0a6d7b74da

fracturehill 76959842+fracturehill at users.noreply.github.com
Sat Apr 17 12:37:02 UTC 2021


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

Summary:
c88b02a3c7 NANCY: Add sticky cursor when moving viewport
29cf663f45 NANCY: Fix primary video flicker when moving with keyboard
54d6de7b57 NANCY: Make text rendering pixel-perfect
43c4c62f40 NANCY: Cursor fixes
5b4b78123b NANCY: Primary video fixes


Commit: c88b02a3c79520bb7829146ca36818c753d21ff4
    https://github.com/scummvm/scummvm/commit/c88b02a3c79520bb7829146ca36818c753d21ff4
Author: fracturehill (strahy at outlook.com)
Date: 2021-04-17T14:57:21+03:00

Commit Message:
NANCY: Add sticky cursor when moving viewport

The cursor now sticks to the same position when moving the viewport, making movement easier and mimicking the original engine's behavior.

Changed paths:
    engines/nancy/ui/viewport.cpp
    engines/nancy/ui/viewport.h


diff --git a/engines/nancy/ui/viewport.cpp b/engines/nancy/ui/viewport.cpp
index b592ff07a6..326f32bbe2 100644
--- a/engines/nancy/ui/viewport.cpp
+++ b/engines/nancy/ui/viewport.cpp
@@ -20,6 +20,8 @@
  *
  */
 
+#include "common/system.h"
+
 #include "engines/nancy/nancy.h"
 #include "engines/nancy/graphics.h"
 #include "engines/nancy/cursor.h"
@@ -61,11 +63,17 @@ void Viewport::handleInput(NancyInput &input) {
 	Time playTime = g_nancy->getTotalPlayTime();
 	byte direction = 0;
 
+	// Make cursor sticky when scrolling the viewport
+	if (input.input & (NancyInput::kLeftMouseButton | NancyInput::kRightMouseButton) && _stickyCursorPos.x > -1) {
+		g_system->warpMouse(_stickyCursorPos.x, _stickyCursorPos.y);
+		input.mousePos = _stickyCursorPos;
+	}
+
 	if (_screenPosition.contains(input.mousePos)) {
 		g_nancy->_cursorManager->setCursorType(CursorManager::kNormal);
 	}
 
-	// Do not handle hotspots marked as incative and ignore diagonals if intersecting hotspots are not active
+	// Do not handle hotspots marked as inactive and ignore diagonals if intersecting hotspots are not active
 	if (_upHotspot.contains(input.mousePos) && (_edgesMask & kUp) == 0) {
 		if (_upHotspot.findIntersectingRect(_leftHotspot).contains(input.mousePos)) {
 			if ((_edgesMask & kLeft) == 0) {
@@ -118,6 +126,15 @@ void Viewport::handleInput(NancyInput &input) {
 		}
 	}
 
+	// Set sticky cursor
+	if (input.input & (NancyInput::kLeftMouseButton | NancyInput::kRightMouseButton) && direction) {
+		if (_stickyCursorPos.x <= -1) {
+			_stickyCursorPos = input.mousePos;
+		}
+	} else {
+		_stickyCursorPos.x = -1;
+	}
+
 	if (direction) {
 		g_nancy->_cursorManager->setCursorType(CursorManager::kMove);
 
diff --git a/engines/nancy/ui/viewport.h b/engines/nancy/ui/viewport.h
index 20bf6722e2..5566e4e730 100644
--- a/engines/nancy/ui/viewport.h
+++ b/engines/nancy/ui/viewport.h
@@ -46,7 +46,8 @@ public:
 		_movementLastFrame(0),
 		_edgesMask(0),
 		_currentFrame(0),
-		_videoFormat(0) {}
+		_videoFormat(0),
+		_stickyCursorPos(-1, -1) {}
 		
 	virtual ~Viewport() { _decoder.close(); _fullFrame.free(); }
 
@@ -94,6 +95,7 @@ public:
 	Graphics::ManagedSurface _fullFrame;
 	Common::Rect _format1Bounds;
 	Common::Rect _format2Bounds;
+	Common::Point _stickyCursorPos;
 };
 
 } // End of namespace UI


Commit: 29cf663f4570cff0fe0e9cbb18796e637fd173cc
    https://github.com/scummvm/scummvm/commit/29cf663f4570cff0fe0e9cbb18796e637fd173cc
Author: fracturehill (strahy at outlook.com)
Date: 2021-04-17T14:57:21+03:00

Commit Message:
NANCY: Fix primary video flicker when moving with keyboard

Removed the flicker that occurs when the player presses one of the movement keys during dialogue scenes.

Changed paths:
    engines/nancy/ui/viewport.cpp


diff --git a/engines/nancy/ui/viewport.cpp b/engines/nancy/ui/viewport.cpp
index 326f32bbe2..47a34c7515 100644
--- a/engines/nancy/ui/viewport.cpp
+++ b/engines/nancy/ui/viewport.cpp
@@ -240,11 +240,17 @@ void Viewport::setFrame(uint frameNr) {
 }
 
 void Viewport::setNextFrame() {
-	setFrame(getCurFrame() + 1 >= getFrameCount() ? 0 : getCurFrame() + 1);
+	uint newFrame = getCurFrame() + 1 >= getFrameCount() ? 0 : getCurFrame() + 1;
+	if (newFrame != _currentFrame) {
+		setFrame(newFrame);
+	}
 }
 
 void Viewport::setPreviousFrame() {
-	setFrame((int)getCurFrame() - 1 < 0 ? getFrameCount() - 1 : getCurFrame() - 1);
+	uint newFrame = (int)getCurFrame() - 1 < 0 ? getFrameCount() - 1 : getCurFrame() - 1;
+	if (newFrame != _currentFrame) {
+		setFrame(newFrame);
+	}
 }
 
 void Viewport::setVerticalScroll(uint scroll) {
@@ -267,11 +273,15 @@ void Viewport::setVerticalScroll(uint scroll) {
 }
 
 void Viewport::scrollUp(uint delta) {
-	setVerticalScroll(_drawSurface.getOffsetFromOwner().y < (int16)delta ? 0 : _drawSurface.getOffsetFromOwner().y - delta);
+	if (_drawSurface.getOffsetFromOwner().y != 0) {
+		setVerticalScroll(_drawSurface.getOffsetFromOwner().y < (int16)delta ? 0 : _drawSurface.getOffsetFromOwner().y - delta);
+	}
 }
 
 void Viewport::scrollDown(uint delta) {
-	setVerticalScroll(_drawSurface.getOffsetFromOwner().y + delta > getMaxScroll() ? getMaxScroll() : _drawSurface.getOffsetFromOwner().y + delta);
+	if (_drawSurface.getOffsetFromOwner().y != getMaxScroll()) {
+		setVerticalScroll(_drawSurface.getOffsetFromOwner().y + delta > getMaxScroll() ? getMaxScroll() : _drawSurface.getOffsetFromOwner().y + delta);
+	}
 }
 
 Common::Rect Viewport::getBoundsByFormat(uint format) const {


Commit: 54d6de7b57044402ba038ca62487726b9e1f1b8a
    https://github.com/scummvm/scummvm/commit/54d6de7b57044402ba038ca62487726b9e1f1b8a
Author: fracturehill (strahy at outlook.com)
Date: 2021-04-17T15:09:18+03:00

Commit Message:
NANCY: Make text rendering pixel-perfect

Made changes to the Textbox and Font classes so the text rendering in nancy1 looks exactly the same as it does in the original engine.

Changed paths:
    engines/nancy/font.cpp
    engines/nancy/font.h
    engines/nancy/ui/textbox.cpp
    engines/nancy/ui/textbox.h


diff --git a/engines/nancy/font.cpp b/engines/nancy/font.cpp
index ea8f1abff9..5585fe01f6 100644
--- a/engines/nancy/font.cpp
+++ b/engines/nancy/font.cpp
@@ -118,6 +118,27 @@ void Font::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 col
 	}
 }
 
+void Font::wordWrap(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines, int initWidth) const {
+	Common::String temp;
+	for (const char *c = str.begin(); c != str.end(); ++c) {
+		temp += *c;
+		int size = getStringWidth(temp) + (lines.size() == 0 ? initWidth : 0);
+		if (size >= maxWidth) {
+			do {
+				temp.deleteLastChar();
+				--c;
+			} while (temp.size() && temp.lastChar() != ' ');
+
+			lines.push_back(temp);
+			temp.clear();
+		}
+	}
+
+	if (temp.size()) {
+		lines.push_back(temp);
+	}
+}
+
 Common::Rect Font::getCharacterSourceRect(char chr) const {
 	using namespace Common;
 	uint offset = 0;
diff --git a/engines/nancy/font.h b/engines/nancy/font.h
index 41d2ed867f..2237d0d06e 100644
--- a/engines/nancy/font.h
+++ b/engines/nancy/font.h
@@ -49,11 +49,14 @@ public:
 
 	void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
 
+	// Custom word wrapping function to fix an edge case with overflowing whitespaces
+	void wordWrap(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines, int initWidth = 0) const;
+
 private:
 	Common::Rect getCharacterSourceRect(char chr) const;
 
 	Common::String _description; // 0xA
-	Common::Point _colorCoordsOffset; // y is def at 0x34, x is just a guess
+	Common::Point _colorCoordsOffset; // 0x32
 
 	uint16 _spaceWidth;              // 0x38
 
diff --git a/engines/nancy/ui/textbox.cpp b/engines/nancy/ui/textbox.cpp
index c0f43e57b7..b289e08a98 100644
--- a/engines/nancy/ui/textbox.cpp
+++ b/engines/nancy/ui/textbox.cpp
@@ -73,10 +73,10 @@ void Textbox::init() {
 	scrollbarDefaultPos.y = chunk->readUint16LE();
 	uint16 scrollbarMaxScroll = chunk->readUint16LE();
 
-	_firstLineOffset = chunk->readUint16LE();
+	_firstLineOffset = chunk->readUint16LE() + 1;
 	_lineHeight = chunk->readUint16LE();
-	// Not sure why but to get exact results we subtract 1
 	_borderWidth = chunk->readUint16LE() - 1;
+	_maxWidthDifference = chunk->readUint16LE();
 
 	chunk->seek(0x1FE, SEEK_SET);
 	_fontID = chunk->readUint16LE();
@@ -141,7 +141,7 @@ void Textbox::drawTextbox() {
 
 	const Font *font = g_nancy->_graphicsManager->getFont(_fontID);
 
-	uint maxWidth = _fullSurface.w - _borderWidth * 2;
+	uint maxWidth = _fullSurface.w - _maxWidthDifference - _borderWidth - 2;
 	uint lineDist = _lineHeight + _lineHeight / 4;
 
 	for (uint lineID = 0; lineID < _textLines.size(); ++lineID) {
@@ -211,7 +211,7 @@ void Textbox::drawTextbox() {
 			Array<Common::String> wrappedLines;
 
 			// Do word wrapping on the rest of the text
-			font->wordWrapText(currentSubLine, maxWidth, wrappedLines, horizontalOffset);
+			font->wordWrap(currentSubLine, maxWidth, wrappedLines, horizontalOffset);
 
 			if (hasHotspot) {
 				hotspot.left = _borderWidth;
@@ -229,6 +229,12 @@ void Textbox::drawTextbox() {
 				++_numLines;
 			}
 
+			// Simulate a bug in the original engine where player text longer than
+			// a single line gets a double newline afterwards
+			if (wrappedLines.size() > 1 && hasHotspot) {
+				++_numLines;
+			}
+
 			horizontalOffset = 0;
 		}
 
@@ -295,7 +301,7 @@ void Textbox::onScrollbarMove() {
 
 uint16 Textbox::getInnerHeight() const {
 	uint lineDist = _lineHeight + _lineHeight / 4;
-	return _numLines * lineDist + _firstLineOffset + lineDist / 2;
+	return _numLines * lineDist + _firstLineOffset + lineDist / 2 - 1;
 }
 
 } // End of namespace UI
diff --git a/engines/nancy/ui/textbox.h b/engines/nancy/ui/textbox.h
index 4487fa3e25..e7244eee8c 100644
--- a/engines/nancy/ui/textbox.h
+++ b/engines/nancy/ui/textbox.h
@@ -72,6 +72,7 @@ private:
 	uint16 _firstLineOffset;
 	uint16 _lineHeight;
 	uint16 _borderWidth;
+	uint16 _maxWidthDifference;
 	uint16 _numLines;
 	uint16 _fontID;
 


Commit: 43c4c62f40dd9e5569062dc9b4c4bbb364d62a34
    https://github.com/scummvm/scummvm/commit/43c4c62f40dd9e5569062dc9b4c4bbb364d62a34
Author: fracturehill (strahy at outlook.com)
Date: 2021-04-17T15:20:59+03:00

Commit Message:
NANCY: Cursor fixes

When exiting a scene while holding an item, the cursor shown is now the fourth version of the item cursor, just as it is in the original engine. When entering a scene through the map while holding an item, the cursor no longer gets reset to the default one.

Changed paths:
    engines/nancy/action/leverpuzzle.cpp
    engines/nancy/action/orderingpuzzle.cpp
    engines/nancy/action/passwordpuzzle.cpp
    engines/nancy/action/recordtypes.h
    engines/nancy/action/rotatinglockpuzzle.cpp
    engines/nancy/action/sliderpuzzle.cpp
    engines/nancy/action/telephone.cpp
    engines/nancy/cursor.cpp
    engines/nancy/cursor.h
    engines/nancy/state/scene.cpp


diff --git a/engines/nancy/action/leverpuzzle.cpp b/engines/nancy/action/leverpuzzle.cpp
index ff5e854e70..7406f0480f 100644
--- a/engines/nancy/action/leverpuzzle.cpp
+++ b/engines/nancy/action/leverpuzzle.cpp
@@ -162,7 +162,7 @@ void LeverPuzzle::handleInput(NancyInput &input) {
 	}
 
 	if (NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
-		g_nancy->_cursorManager->setCursorType(CursorManager::kExitArrow);
+		g_nancy->_cursorManager->setCursorType(CursorManager::kExit);
 
 		if (input.input & NancyInput::kLeftMouseButtonUp) {
 			_state = kActionTrigger;
diff --git a/engines/nancy/action/orderingpuzzle.cpp b/engines/nancy/action/orderingpuzzle.cpp
index c5ea10d7ee..b8e32300eb 100644
--- a/engines/nancy/action/orderingpuzzle.cpp
+++ b/engines/nancy/action/orderingpuzzle.cpp
@@ -163,7 +163,7 @@ void OrderingPuzzle::handleInput(NancyInput &input) {
 	}
 
 	if (NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
-		g_nancy->_cursorManager->setCursorType(CursorManager::kExitArrow);
+		g_nancy->_cursorManager->setCursorType(CursorManager::kExit);
 
 		if (input.input & NancyInput::kLeftMouseButtonUp) {
 			_state = kActionTrigger;
diff --git a/engines/nancy/action/passwordpuzzle.cpp b/engines/nancy/action/passwordpuzzle.cpp
index 65edb00fd2..af20159964 100644
--- a/engines/nancy/action/passwordpuzzle.cpp
+++ b/engines/nancy/action/passwordpuzzle.cpp
@@ -168,7 +168,7 @@ void PasswordPuzzle::handleInput(NancyInput &input) {
 	}
 
 	if (NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
-		g_nancy->_cursorManager->setCursorType(CursorManager::kExitArrow);
+		g_nancy->_cursorManager->setCursorType(CursorManager::kExit);
 
 		if (input.input & NancyInput::kLeftMouseButtonUp) {
 			_state = kActionTrigger;
diff --git a/engines/nancy/action/recordtypes.h b/engines/nancy/action/recordtypes.h
index 62a6a174b8..219d610677 100644
--- a/engines/nancy/action/recordtypes.h
+++ b/engines/nancy/action/recordtypes.h
@@ -72,7 +72,7 @@ protected:
 };
 
 class Hot1FrExitSceneChange : public Hot1FrSceneChange {
-	virtual CursorManager::CursorType getHoverCursor() const override { return CursorManager::kExitArrow; }
+	virtual CursorManager::CursorType getHoverCursor() const override { return CursorManager::kExit; }
 
 protected:
 	virtual Common::String getRecordTypeName() const override { return "Hot1FrExitSceneChange"; }
@@ -190,7 +190,7 @@ public:
 	virtual void readData(Common::SeekableReadStream &stream) override;
 	virtual void execute() override;
 
-	virtual CursorManager::CursorType getHoverCursor() const override { return CursorManager::kExitArrow; }
+	virtual CursorManager::CursorType getHoverCursor() const override { return CursorManager::kExit; }
 
 protected:
 	virtual Common::String getRecordTypeName() const override { return "MapCall"; }
diff --git a/engines/nancy/action/rotatinglockpuzzle.cpp b/engines/nancy/action/rotatinglockpuzzle.cpp
index 8bb6b8ff7a..b951293d91 100644
--- a/engines/nancy/action/rotatinglockpuzzle.cpp
+++ b/engines/nancy/action/rotatinglockpuzzle.cpp
@@ -172,7 +172,7 @@ void RotatingLockPuzzle::handleInput(NancyInput &input) {
 	}
 
 	if (NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
-		g_nancy->_cursorManager->setCursorType(CursorManager::kExitArrow);
+		g_nancy->_cursorManager->setCursorType(CursorManager::kExit);
 
 		if (input.input & NancyInput::kLeftMouseButtonUp) {
 			_state = kActionTrigger;
diff --git a/engines/nancy/action/sliderpuzzle.cpp b/engines/nancy/action/sliderpuzzle.cpp
index 1aed740409..120d62fbb8 100644
--- a/engines/nancy/action/sliderpuzzle.cpp
+++ b/engines/nancy/action/sliderpuzzle.cpp
@@ -191,7 +191,7 @@ void SliderPuzzle::handleInput(NancyInput &input) {
 	}
 
 	if (NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
-		g_nancy->_cursorManager->setCursorType(CursorManager::kExitArrow);
+		g_nancy->_cursorManager->setCursorType(CursorManager::kExit);
 
 		if (input.input & NancyInput::kLeftMouseButtonUp) {
 			_state = kActionTrigger;
diff --git a/engines/nancy/action/telephone.cpp b/engines/nancy/action/telephone.cpp
index df5febc81e..769702c8ac 100644
--- a/engines/nancy/action/telephone.cpp
+++ b/engines/nancy/action/telephone.cpp
@@ -269,7 +269,7 @@ void Telephone::handleInput(NancyInput &input) {
 	}
 
 	if (NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
-		g_nancy->_cursorManager->setCursorType(CursorManager::kExitArrow);
+		g_nancy->_cursorManager->setCursorType(CursorManager::kExit);
 
 		if (input.input & NancyInput::kLeftMouseButtonUp) {
 			g_nancy->_sound->loadSound(_hangUpSound);
diff --git a/engines/nancy/cursor.cpp b/engines/nancy/cursor.cpp
index f302170bc4..17dc936fed 100644
--- a/engines/nancy/cursor.cpp
+++ b/engines/nancy/cursor.cpp
@@ -70,20 +70,16 @@ void CursorManager::setCursor(CursorType type, int16 itemID) {
 		_curItemID = itemID;
 	}
 
-	uint16 newID = 0;
 	bool hasItem = false;
 
 	switch (type) {
 	case kNormalArrow:
-		newID = 4;
+		_curCursorID = 4;
 		break;
 	case kHotspotArrow:
-		newID = 6;
+		_curCursorID = 6;
 		break;
-	case kExitArrow:
-		newID = 3;
-		break;
-	default: {
+	default:
 		if (itemID == -1) {
 			// No item held, set to eyeglass
 			itemID = 0;
@@ -93,13 +89,12 @@ void CursorManager::setCursor(CursorType type, int16 itemID) {
 			hasItem = true;
 		}
 
-		newID = itemID * 4 + type;
-	}
+		_curCursorID = itemID * 4 + type;
 	}
 
 	Graphics::ManagedSurface *surf;
-	Common::Rect bounds = _cursors[newID].bounds;
-	Common::Point hotspot = _cursors[newID].hotspot;
+	Common::Rect bounds = _cursors[_curCursorID].bounds;
+	Common::Point hotspot = _cursors[_curCursorID].hotspot;
 
 	if (hasItem) {
 		surf = &_invCursorsSurface;
diff --git a/engines/nancy/cursor.h b/engines/nancy/cursor.h
index 3ad8a3e4bd..80bbab041b 100644
--- a/engines/nancy/cursor.h
+++ b/engines/nancy/cursor.h
@@ -33,12 +33,13 @@ class NancyEngine;
 
 class CursorManager {
 public:
-	enum CursorType { kNormal = 0, kHotspot = 1, kMove = 2, kNormalArrow, kHotspotArrow, kExitArrow };
+	enum CursorType { kNormal = 0, kHotspot = 1, kMove = 2, kExit = 3, kNormalArrow, kHotspotArrow };
 
 	CursorManager() :
 		_isInitialized(false),
 		_curItemID(-1),
-		_curCursorType(kNormal) {}
+		_curCursorType(kNormal),
+		_curCursorID(0) {}
 
 	void init();
 
@@ -63,6 +64,7 @@ private:
 
 	CursorType _curCursorType;
 	int16 _curItemID;
+	uint _curCursorID;
 	bool _isInitialized;
 };
 
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index bbabdd1f76..3353c17736 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -135,6 +135,10 @@ void Scene::onStateEnter() {
 
 		g_nancy->_graphicsManager->redrawAll();
 
+		if (getHeldItem() != -1) {
+			g_nancy->_cursorManager->setCursorItemID(getHeldItem());
+		}
+
 		// Run once to clear out the previous scene when coming from Map
 		process();
 


Commit: 5b4b78123b6574d3cb49f8ada41dfb0a6d7b74da
    https://github.com/scummvm/scummvm/commit/5b4b78123b6574d3cb49f8ada41dfb0a6d7b74da
Author: fracturehill (strahy at outlook.com)
Date: 2021-04-17T15:21:55+03:00

Commit Message:
NANCY: Primary video fixes

Primary video now affects the mouse the same way it does in the original game: the cursor gets moved to a set location when starting a conversation, and is blocked from moving above a certain threshold. Also removed the static pointer from PlayPrimaryVideoChan0.

Changed paths:
    engines/nancy/action/primaryvideo.cpp
    engines/nancy/action/primaryvideo.h
    engines/nancy/cursor.h
    engines/nancy/nancy.cpp
    engines/nancy/state/scene.cpp
    engines/nancy/state/scene.h


diff --git a/engines/nancy/action/primaryvideo.cpp b/engines/nancy/action/primaryvideo.cpp
index f4fc2408ae..861cb58174 100644
--- a/engines/nancy/action/primaryvideo.cpp
+++ b/engines/nancy/action/primaryvideo.cpp
@@ -20,11 +20,13 @@
  *
  */
 
+#include "common/system.h"
 #include "common/random.h"
 #include "common/config-manager.h"
 
 #include "engines/nancy/nancy.h"
 #include "engines/nancy/sound.h"
+#include "engines/nancy/input.h"
 #include "engines/nancy/util.h"
 
 #include "engines/nancy/action/primaryvideo.h"
@@ -35,8 +37,6 @@
 namespace Nancy {
 namespace Action {
 
-PlayPrimaryVideoChan0 *PlayPrimaryVideoChan0::_activePrimaryVideo = nullptr;
-
 void PlayPrimaryVideoChan0::ConditionFlag::read(Common::SeekableReadStream &stream) {
 	type = (ConditionType)stream.readByte();
 	flag.label = stream.readSint16LE();
@@ -108,8 +108,8 @@ bool PlayPrimaryVideoChan0::ConditionFlags::isSatisfied() const {
 PlayPrimaryVideoChan0::~PlayPrimaryVideoChan0() {
 	_decoder.close();
 
-	if (_activePrimaryVideo == this) {
-		_activePrimaryVideo = nullptr;
+	if (NancySceneState.getActivePrimaryVideo() == this) {
+		NancySceneState.setActivePrimaryVideo(nullptr);
 	}
 
 	NancySceneState.setShouldClearTextbox(true);
@@ -218,12 +218,13 @@ void PlayPrimaryVideoChan0::readData(Common::SeekableReadStream &stream) {
 }
 
 void PlayPrimaryVideoChan0::execute() {
-	if (_activePrimaryVideo != this && _activePrimaryVideo != nullptr) {
+	PlayPrimaryVideoChan0 *activeVideo = NancySceneState.getActivePrimaryVideo();
+	if (activeVideo != this && activeVideo != nullptr) {
 		return;
 	}
 
 	switch (_state) {
-	case kBegin:
+	case kBegin: {
 		init();
 		registerGraphics();
 		g_nancy->_sound->loadSound(_sound);
@@ -232,8 +233,27 @@ void PlayPrimaryVideoChan0::execute() {
 			g_nancy->_sound->playSound(_sound);
 		}
 
+		// Remove held item and re-add it to inventory
+		int heldItem = NancySceneState.getHeldItem();
+		if (heldItem != -1) {
+			NancySceneState.addItemToInventory(heldItem);
+			NancySceneState.setHeldItem(-1);
+		}
+
+		// Move the mouse to the default position defined in CURS
+		const Common::Point initialMousePos = g_nancy->_cursorManager->getPrimaryVideoInitialPos();
+		const Common::Point cursorHotspot = g_nancy->_cursorManager->getCurrentCursorHotspot();
+		Common::Point adjustedMousePos = g_nancy->_input->getInput().mousePos;
+		adjustedMousePos.x -= cursorHotspot.x;
+		adjustedMousePos.y -= cursorHotspot.y - 1;
+		if (g_nancy->_cursorManager->getPrimaryVideoInactiveZone().bottom > adjustedMousePos.y) {
+			g_system->warpMouse(initialMousePos.x + cursorHotspot.x, initialMousePos.y + cursorHotspot.y);
+			g_nancy->_cursorManager->setCursorType(CursorManager::kNormalArrow);
+		}
+
 		_state = kRun;
-		_activePrimaryVideo = this;
+		NancySceneState.setActivePrimaryVideo(this);
+	}
 		// fall through
 	case kRun:
 		if (!_hasDrawnTextbox) {
@@ -327,6 +347,18 @@ void PlayPrimaryVideoChan0::execute() {
 	}
 }
 
+void PlayPrimaryVideoChan0::handleInput(NancyInput &input) {
+	const Common::Rect &inactiveZone = g_nancy->_cursorManager->getPrimaryVideoInactiveZone();
+	const Common::Point cursorHotspot = g_nancy->_cursorManager->getCurrentCursorHotspot();
+	Common::Point adjustedMousePos = input.mousePos;
+	adjustedMousePos.y -= cursorHotspot.y;
+
+	if (inactiveZone.bottom > adjustedMousePos.y) {
+		input.mousePos.y = inactiveZone.bottom + cursorHotspot.y;
+		g_system->warpMouse(input.mousePos.x, input.mousePos.y);
+	}
+}
+
 void PlayPrimaryVideoChan0::addConditionalResponses() {
 	for (const auto &res : nancy1ConditionalResponses) {
 		if (res.characterID == _conditionalResponseCharacterID) {
diff --git a/engines/nancy/action/primaryvideo.h b/engines/nancy/action/primaryvideo.h
index 7398715615..13d794ec3d 100644
--- a/engines/nancy/action/primaryvideo.h
+++ b/engines/nancy/action/primaryvideo.h
@@ -79,6 +79,7 @@ public:
 
 	virtual void readData(Common::SeekableReadStream &stream) override;
 	virtual void execute() override;
+	virtual void handleInput(NancyInput &input) override;
 
 	// Functions for handling the built-in dialogue responses found in the executable
 	void addConditionalResponses();
@@ -106,9 +107,6 @@ public:
 	bool _hasDrawnTextbox = false;
 	int16 _pickedResponse = -1;
 
-	// Used to avoid clashes between multiple instances in the same scene
-	static PlayPrimaryVideoChan0 *_activePrimaryVideo;
-
 protected:
 	virtual Common::String getRecordTypeName() const override { return "PlayPrimaryVideoChan0"; }
 	virtual bool isViewportRelative() const override { return true; }
diff --git a/engines/nancy/cursor.h b/engines/nancy/cursor.h
index 80bbab041b..29fab7d365 100644
--- a/engines/nancy/cursor.h
+++ b/engines/nancy/cursor.h
@@ -48,6 +48,10 @@ public:
 	void setCursorItemID(int16 itemID);
 	void showCursor(bool shouldShow);
 
+	const Common::Point &getCurrentCursorHotspot() { return _cursors[_curCursorID].hotspot;}
+	const Common::Rect &getPrimaryVideoInactiveZone() { return _primaryVideoInactiveZone; }
+	const Common::Point &getPrimaryVideoInitialPos() { return _primaryVideoInitialPos; }
+
 private:
 	struct Cursor {
 		Common::Rect bounds;
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index ce23f44632..acebb13e6a 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -115,7 +115,7 @@ bool NancyEngine::canLoadGameStateCurrently()  {
 
 bool NancyEngine::canSaveGameStateCurrently() {
 	// TODO also disable during secondary movie
-	return Action::PlayPrimaryVideoChan0::_activePrimaryVideo == nullptr;
+	return State::Scene::hasInstance() && NancySceneState.getActivePrimaryVideo() == nullptr;
 }
 
 bool NancyEngine::canSaveAutosaveCurrently() {
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 3353c17736..7b2cbf0b21 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -94,7 +94,8 @@ Scene::Scene() :
 		_menuButton(nullptr),
 		_helpButton(nullptr),
 		_actionManager(),
-		_difficulty(0) {}
+		_difficulty(0),
+		_activePrimaryVideo(nullptr) {}
 
 Scene::~Scene()  {
 	delete _helpButton;
@@ -442,6 +443,14 @@ void Scene::init() {
 	g_nancy->_graphicsManager->redrawAll();
 }
 
+void Scene::setActivePrimaryVideo(Action::PlayPrimaryVideoChan0 *activeVideo) {
+	_activePrimaryVideo = activeVideo;
+}
+
+Action::PlayPrimaryVideoChan0 *Scene::getActivePrimaryVideo() {
+	return _activePrimaryVideo;
+}
+
 void Scene::load() {
 	clearSceneData();
 
@@ -561,11 +570,11 @@ void Scene::run() {
 	// Update the UI elements and handle input
 	NancyInput input = g_nancy->_input->getInput();
 	_viewport.handleInput(input);
+	_actionManager.handleInput(input);
 	_menuButton->handleInput(input);
 	_helpButton->handleInput(input);
 	_textbox.handleInput(input);
 	_inventoryBox.handleInput(input);
-	_actionManager.handleInput(input);
 
 	if (_menuButton->_isClicked) {
 		_menuButton->_isClicked = false;
diff --git a/engines/nancy/state/scene.h b/engines/nancy/state/scene.h
index 7e33c96a12..c4c36db9ff 100644
--- a/engines/nancy/state/scene.h
+++ b/engines/nancy/state/scene.h
@@ -50,6 +50,7 @@ struct SceneChangeDescription;
 
 namespace Action {
 class SliderPuzzle;
+class PlayPrimaryVideoChan0;
 }
 
 namespace UI {
@@ -164,6 +165,9 @@ public:
 	SceneInfo &getSceneInfo() { return _sceneState.currentScene; }
 	const SceneSummary &getSceneSummary() const { return _sceneState.summary; }
 
+	void setActivePrimaryVideo(Action::PlayPrimaryVideoChan0 *activeVideo);
+	Action::PlayPrimaryVideoChan0 *getActivePrimaryVideo();
+
 private:
 	void init();
 	void load();
@@ -244,6 +248,7 @@ private:
 	Common::Array<uint16> _mapAccessSceneIDs;
 
 	Action::ActionManager _actionManager;
+	Action::PlayPrimaryVideoChan0 *_activePrimaryVideo;
 
 	State _state;
 




More information about the Scummvm-git-logs mailing list