[Scummvm-git-logs] scummvm master -> 04e95b249ba01cca85e278b2969a92e41fa7da91
tnm23
noreply at scummvm.org
Mon Aug 25 21:58:05 UTC 2025
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
1afbbf9439 MATH: Make sequence of vector2d & vector3d member declarations more consistent for better readability & comparison.
eb63ac4144 ZVISION: Improved functionality of draggable lever controls.
1cf6c413ce ZVISION: More improvement of draggable lever controls.
04e95b249b ZVISION: Add workaround for lever animation alignment bug in Nemesis orrery.
Commit: 1afbbf9439a18c44a67dbf7e3f0aa4e9630a1d35
https://github.com/scummvm/scummvm/commit/1afbbf9439a18c44a67dbf7e3f0aa4e9630a1d35
Author: Thomas N McEwan (46427621+tnm23 at users.noreply.github.com)
Date: 2025-08-25T22:55:34+01:00
Commit Message:
MATH: Make sequence of vector2d & vector3d member declarations more consistent for better readability & comparison.
Changed paths:
math/vector2d.h
math/vector3d.h
diff --git a/math/vector2d.h b/math/vector2d.h
index ef680d2b150..5e1e89294bd 100644
--- a/math/vector2d.h
+++ b/math/vector2d.h
@@ -27,6 +27,8 @@
namespace Math {
+typedef Matrix<2, 1> Vector2d;
+
template<>
class Matrix<2, 1> : public MatrixType<2, 1> {
public:
@@ -46,8 +48,6 @@ public:
Vector3d toVector3d() const;
};
-typedef Matrix<2, 1> Vector2d;
-
}
#endif
diff --git a/math/vector3d.h b/math/vector3d.h
index 9f531bd563c..8fbbb5a5791 100644
--- a/math/vector3d.h
+++ b/math/vector3d.h
@@ -36,6 +36,11 @@ typedef Matrix<3, 1> Vector3d;
template<>
class Matrix<3, 1> : public MatrixType<3, 1> {
public:
+ Matrix();
+ Matrix(float lx, float ly, float lz);
+ Matrix(const MatrixBase<3, 1> &m);
+ Matrix(const float *data);
+
float& x() { return value(0); }
float x() const { return value(0); }
float& y() { return value(1); }
@@ -43,11 +48,6 @@ public:
float& z() { return value(2); }
float z() const { return value(2); }
- Matrix();
- Matrix(float lx, float ly, float lz);
- Matrix(const MatrixBase<3, 1> &m);
- Matrix(const float *data);
-
/**
* Set the value of the vector using three floats
* @param lx X Value
Commit: eb63ac414400eec7d09383b751b3cb405dcf2a6f
https://github.com/scummvm/scummvm/commit/eb63ac414400eec7d09383b751b3cb405dcf2a6f
Author: Thomas N McEwan (46427621+tnm23 at users.noreply.github.com)
Date: 2025-08-25T22:55:34+01:00
Commit Message:
ZVISION: Improved functionality of draggable lever controls.
Now based on vector dot product instead of angle matching.
Trigger sensitivity now corresponds to animation step distance.
Much smoother movement; could possibly be improved further.
Changed paths:
engines/zvision/scripting/controls/lever_control.cpp
engines/zvision/scripting/controls/lever_control.h
diff --git a/engines/zvision/scripting/controls/lever_control.cpp b/engines/zvision/scripting/controls/lever_control.cpp
index 4ddb711cb4e..3fb05291fc6 100644
--- a/engines/zvision/scripting/controls/lever_control.cpp
+++ b/engines/zvision/scripting/controls/lever_control.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "common/debug.h"
#include "common/file.h"
#include "common/scummsys.h"
#include "common/stream.h"
@@ -84,6 +85,7 @@ LeverControl::~LeverControl() {
}
void LeverControl::parseLevFile(const Common::Path &fileName) {
+ debugC(2, kDebugControl, "LeverControl::parseLevFile(%s)", fileName.toString().c_str());
Common::File file;
if (!file.open(fileName)) {
warning("LEV file %s could could be opened", fileName.toString().c_str());
@@ -160,7 +162,7 @@ void LeverControl::parseLevFile(const Common::Path &fileName) {
uint angle;
uint toFrame;
if (sscanf(token.c_str(), "%u,%u", &toFrame, &angle) == 2)
- _frameInfo[frameNumber].directions.push_back(Direction(angle, toFrame));
+ _frameInfo[frameNumber].paths.push_back(PathSegment(angle, toFrame));
} else if (token.hasPrefix("p")) {
// Format: P(<from> to <to>)
tokenizer.nextToken();
@@ -177,6 +179,19 @@ void LeverControl::parseLevFile(const Common::Path &fileName) {
// Don't read lines in this place because last will not be parsed.
}
+ // Cycle through all unit direction vectors in path segments & determine step distance
+ debugC(3, kDebugControl, "Setting step distances");
+ for(uint frame=0; frame < _frameCount; frame++) {
+ debugC(3, kDebugControl, "Frame %d", frame);
+ for(auto &iter : _frameInfo[frame].paths) {
+ uint destFrame = iter.toFrame;
+ Common::Point deltaPos = _frameInfo[destFrame].hotspot.origin() - _frameInfo[frame].hotspot.origin();
+ Math::Vector2d deltaPosVector((float)deltaPos.x, (float)deltaPos.y);
+ iter.distance *= deltaPosVector.getMagnitude();
+ debugC(3, kDebugControl, "\tdeltaPos = %d,%d, Distance %f", deltaPos.x, deltaPos.y, iter.distance);
+ }
+ }
+ debugC(2, kDebugControl, "LeverControl::~parseLevFile()");
}
bool LeverControl::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
@@ -186,7 +201,7 @@ bool LeverControl::onMouseDown(const Common::Point &screenSpacePos, const Common
if (_frameInfo[_currentFrame].hotspot.contains(backgroundImageSpacePos)) {
setVenus();
_mouseIsCaptured = true;
- _lastMousePos = backgroundImageSpacePos;
+ _gripOffset = backgroundImageSpacePos - _frameInfo[_currentFrame].hotspot.origin();
}
return false;
}
@@ -203,6 +218,7 @@ bool LeverControl::onMouseUp(const Common::Point &screenSpacePos, const Common::
_returnRoutesCurrentProgress = _frameInfo[_currentFrame].returnRoute.begin();
_returnRoutesCurrentFrame = _currentFrame;
}
+ _gripOffset = Common::Point(0,0);
return false;
}
@@ -213,21 +229,18 @@ bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common
bool cursorWasChanged = false;
if (_mouseIsCaptured) {
- // Make sure the square distance between the last point and the current point is greater than 16
- // This is a heuristic. This determines how responsive the lever is to mouse movement.
- if (_lastMousePos.sqrDist(backgroundImageSpacePos) >= 16) {
- int angle = calculateVectorAngle(_lastMousePos, backgroundImageSpacePos);
- _lastMousePos = backgroundImageSpacePos;
-
- for (Common::List<Direction>::iterator iter = _frameInfo[_currentFrame].directions.begin(); iter != _frameInfo[_currentFrame].directions.end(); ++iter) {
- if (angle >= (int)iter->angle - ANGLE_DELTA && angle <= (int)iter->angle + ANGLE_DELTA) {
- _currentFrame = iter->toFrame;
- renderFrame(_currentFrame);
- _engine->getScriptManager()->setStateValue(_key, _currentFrame);
- break;
- }
- }
+ Common::Point deltaPos = (backgroundImageSpacePos - _gripOffset) - _frameInfo[_currentFrame].hotspot.origin();
+
+
+ debugC(1, kDebugControl, "LeverControl::onMouseMove()");
+ debugC(1, kDebugControl, "\tscreenPos = %d,%d, imagePos = %d,%d, deltaPos = %d,%d", screenSpacePos.x, screenSpacePos.y, backgroundImageSpacePos.x, backgroundImageSpacePos.y, deltaPos.x, deltaPos.y);
+
+ _currentFrame = nextFrame(deltaPos);
+ if(_lastRenderedFrame != _currentFrame) {
+ renderFrame(_currentFrame);
+ _engine->getScriptManager()->setStateValue(_key, _currentFrame);
}
+
_engine->getCursorManager()->changeCursor(_cursor);
cursorWasChanged = true;
} else if (_frameInfo[_currentFrame].hotspot.contains(backgroundImageSpacePos)) {
@@ -238,14 +251,25 @@ bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common
return cursorWasChanged;
}
+uint LeverControl::nextFrame(Common::Point &deltaPos) {
+ Math::Vector2d movement((float)deltaPos.x, (float)deltaPos.y);
+ for (auto &iter : _frameInfo[_currentFrame].paths) {
+ debugC(1, kDebugControl, "\tPossible step = %f,%f, angle = %d, distance %f", iter.direction.getX(), iter.direction.getY(), (uint)Math::rad2deg(iter.angle), iter.distance);
+ if (movement.dotProduct(iter.direction) >= iter.distance/2) {
+ return iter.toFrame;
+ }
+ }
+ return _currentFrame;
+}
+
bool LeverControl::process(uint32 deltaTimeInMillis) {
if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
if (_isReturning) {
_accumulatedTime += deltaTimeInMillis;
- while (_accumulatedTime >= ANIMATION_FRAME_TIME) {
- _accumulatedTime -= ANIMATION_FRAME_TIME;
+ while (_accumulatedTime >= _returnFramePeriod) {
+ _accumulatedTime -= _returnFramePeriod;
if (_returnRoutesCurrentFrame == *_returnRoutesCurrentProgress) {
_returnRoutesCurrentProgress++;
}
@@ -270,95 +294,6 @@ bool LeverControl::process(uint32 deltaTimeInMillis) {
return false;
}
-int LeverControl::calculateVectorAngle(const Common::Point &pointOne, const Common::Point &pointTwo) {
- // Check for the easy angles first
- if (pointOne.x == pointTwo.x && pointOne.y == pointTwo.y)
- return -1; // This should never happen
- else if (pointOne.x == pointTwo.x) {
- if (pointTwo.y < pointOne.y)
- return 90;
- else
- return 270;
- } else if (pointOne.y == pointTwo.y) {
- if (pointTwo.x > pointOne.x)
- return 0;
- else
- return 180;
- } else {
- // Calculate the angle with trig
- int16 xDist = pointTwo.x - pointOne.x;
- int16 yDist = pointTwo.y - pointOne.y;
-
- // Calculate the angle using arctan
- // Then convert to degrees. (180 / 3.14159 = 57.2958)
- int angle = int(atan((float)yDist / (float)abs(xDist)) * 57);
-
- // Calculate what quadrant pointTwo is in
- uint quadrant = ((yDist > 0 ? 1 : 0) << 1) | (xDist < 0 ? 1 : 0);
-
- // Explanation of quadrants:
- //
- // yDist > 0 | xDist < 0 | Quadrant number
- // 0 | 0 | 0
- // 0 | 1 | 1
- // 1 | 0 | 2
- // 1 | 1 | 3
- //
- // Note: I know this doesn't line up with traditional mathematical quadrants
- // but doing it this way allows you can use a switch and is a bit cleaner IMO.
- //
- // The graph below shows the 4 quadrants pointTwo can end up in as well
- // as what the angle as calculated above refers to.
- // Note: The calculated angle in quadrants 0 and 3 is negative
- // due to arctan(-x) = -theta
- //
- // Origin => (pointOne.x, pointOne.y)
- // * => (pointTwo.x, pointTwo.y)
- //
- // 90 |
- // ^ |
- // * | * |
- // \ | / |
- // \ | / |
- // \ | / |
- // Quadrant 1 \ | / Quadrant 0 |
- // \ | / |
- // \ | / |
- // angle ( \|/ ) -angle |
- // 180 <----------------------------------------> 0 |
- // -angle ( /|\ ) angle |
- // / | \ |
- // / | \ |
- // Quadrant 3 / | \ Quadrant 2 |
- // / | \ |
- // / | \ |
- // / | \ |
- // * | * |
- // ^ |
- // 270 |
-
- // Convert the local angles to unit circle angles
- switch (quadrant) {
- case 0:
- angle = -angle;
- break;
- case 1:
- angle = angle + 180;
- break;
- case 2:
- angle = 360 - angle;
- break;
- case 3:
- angle = 180 + angle;
- break;
- default:
- break;
- }
-
- return angle;
- }
-}
-
void LeverControl::renderFrame(uint frameNumber) {
if (frameNumber == 0) {
_lastRenderedFrame = frameNumber;
diff --git a/engines/zvision/scripting/controls/lever_control.h b/engines/zvision/scripting/controls/lever_control.h
index 33a7bca087e..2e0583b91ed 100644
--- a/engines/zvision/scripting/controls/lever_control.h
+++ b/engines/zvision/scripting/controls/lever_control.h
@@ -25,6 +25,7 @@
#include "common/list.h"
#include "common/path.h"
#include "common/rect.h"
+#include "math/vector2d.h"
#include "zvision/scripting/control.h"
namespace Video {
@@ -41,24 +42,21 @@ public:
private:
- struct Direction {
- Direction(uint a, uint t) : angle(a), toFrame(t) {}
+ struct PathSegment {
+ PathSegment(uint a, uint t) : angle(Math::deg2rad<float>(a)), toFrame(t), direction(cos(angle), -sin(angle)) {}
- uint angle;
+ float angle; // Radians
uint toFrame;
+ Math::Vector2d direction; // NB unit vector upon initialisation
+ float distance = 1.0f;
};
struct FrameInfo {
Common::Rect hotspot;
- Common::List<Direction> directions;
+ Common::List<PathSegment> paths;
Common::List<uint> returnRoute;
};
- enum {
- ANGLE_DELTA = 30, // How far off a mouse angle can be and still be considered valid. This is in both directions, so the total buffer zone is (2 * ANGLE_DELTA)
- ANIMATION_FRAME_TIME = 30 // In millis
- };
-
private:
Video::VideoDecoder *_animation;
@@ -74,9 +72,10 @@ private:
uint _lastRenderedFrame;
bool _mouseIsCaptured;
bool _isReturning;
- Common::Point _lastMousePos;
+ Common::Point _gripOffset;
Common::List<uint>::iterator _returnRoutesCurrentProgress;
uint _returnRoutesCurrentFrame;
+ const uint8 _returnFramePeriod = 60; // milliseconds
uint32 _accumulatedTime;
public:
@@ -87,32 +86,9 @@ public:
private:
void parseLevFile(const Common::Path &fileName);
- /**
- * Calculates the angle a vector makes with the negative y-axis
- *
- * 90
- * pointTwo * ^
- * \ |
- * \ |
- * \ |
- * \ |
- * angle ( \|pointOne
- * 180 <-----------*-----------> 0
- * |
- * |
- * |
- * |
- * |
- * ^
- * 270
- *
- * @param pointOne The origin of the vector
- * @param pointTwo The end of the vector
- * @return The angle the vector makes with the negative y-axis
- */
- static int calculateVectorAngle(const Common::Point &pointOne, const Common::Point &pointTwo);
void renderFrame(uint frameNumber);
void getLevParams(const Common::String &inputStr, Common::String ¶meter, Common::String &values);
+ uint nextFrame(Common::Point &deltaPos);
};
} // End of namespace ZVision
Commit: 1cf6c413ce9aeed88e42f77431a1e2ddf3e8f905
https://github.com/scummvm/scummvm/commit/1cf6c413ce9aeed88e42f77431a1e2ddf3e8f905
Author: Thomas N McEwan (46427621+tnm23 at users.noreply.github.com)
Date: 2025-08-25T22:55:34+01:00
Commit Message:
ZVISION: More improvement of draggable lever controls.
Allow more than one animation frame per cycle to cope with fast mouse movements.
Changed paths:
engines/zvision/scripting/controls/lever_control.cpp
engines/zvision/scripting/controls/lever_control.h
diff --git a/engines/zvision/scripting/controls/lever_control.cpp b/engines/zvision/scripting/controls/lever_control.cpp
index 3fb05291fc6..17086e5e353 100644
--- a/engines/zvision/scripting/controls/lever_control.cpp
+++ b/engines/zvision/scripting/controls/lever_control.cpp
@@ -181,9 +181,9 @@ void LeverControl::parseLevFile(const Common::Path &fileName) {
}
// Cycle through all unit direction vectors in path segments & determine step distance
debugC(3, kDebugControl, "Setting step distances");
- for(uint frame=0; frame < _frameCount; frame++) {
+ for (uint frame=0; frame < _frameCount; frame++) {
debugC(3, kDebugControl, "Frame %d", frame);
- for(auto &iter : _frameInfo[frame].paths) {
+ for (auto &iter : _frameInfo[frame].paths) {
uint destFrame = iter.toFrame;
Common::Point deltaPos = _frameInfo[destFrame].hotspot.origin() - _frameInfo[frame].hotspot.origin();
Math::Vector2d deltaPosVector((float)deltaPos.x, (float)deltaPos.y);
@@ -229,17 +229,20 @@ bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common
bool cursorWasChanged = false;
if (_mouseIsCaptured) {
- Common::Point deltaPos = (backgroundImageSpacePos - _gripOffset) - _frameInfo[_currentFrame].hotspot.origin();
-
-
- debugC(1, kDebugControl, "LeverControl::onMouseMove()");
- debugC(1, kDebugControl, "\tscreenPos = %d,%d, imagePos = %d,%d, deltaPos = %d,%d", screenSpacePos.x, screenSpacePos.y, backgroundImageSpacePos.x, backgroundImageSpacePos.y, deltaPos.x, deltaPos.y);
+ uint nextFrame = _currentFrame;
+ do {
+ Common::Point gripOrigin = _frameInfo[_currentFrame].hotspot.origin() + _gripOffset;
+ debugC(1, kDebugControl, "LeverControl::onMouseMove() screenPos = %d,%d, imagePos = %d,%d, gripOrigin = %d,%d", screenSpacePos.x, screenSpacePos.y, backgroundImageSpacePos.x, backgroundImageSpacePos.y, gripOrigin.x, gripOrigin.y);
+ Common::Point deltaPos = backgroundImageSpacePos - gripOrigin;
+ nextFrame = getNextFrame(deltaPos);
+ if (nextFrame != _currentFrame) {
+ _currentFrame = nextFrame;
+ _engine->getScriptManager()->setStateValue(_key, _currentFrame);
+ }
+ } while (nextFrame != _currentFrame);
- _currentFrame = nextFrame(deltaPos);
- if(_lastRenderedFrame != _currentFrame) {
+ if (_lastRenderedFrame != _currentFrame)
renderFrame(_currentFrame);
- _engine->getScriptManager()->setStateValue(_key, _currentFrame);
- }
_engine->getCursorManager()->changeCursor(_cursor);
cursorWasChanged = true;
@@ -247,11 +250,10 @@ bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common
_engine->getCursorManager()->changeCursor(_cursor);
cursorWasChanged = true;
}
-
return cursorWasChanged;
}
-uint LeverControl::nextFrame(Common::Point &deltaPos) {
+uint LeverControl::getNextFrame(Common::Point &deltaPos) {
Math::Vector2d movement((float)deltaPos.x, (float)deltaPos.y);
for (auto &iter : _frameInfo[_currentFrame].paths) {
debugC(1, kDebugControl, "\tPossible step = %f,%f, angle = %d, distance %f", iter.direction.getX(), iter.direction.getY(), (uint)Math::rad2deg(iter.angle), iter.distance);
@@ -295,14 +297,9 @@ bool LeverControl::process(uint32 deltaTimeInMillis) {
}
void LeverControl::renderFrame(uint frameNumber) {
- if (frameNumber == 0) {
- _lastRenderedFrame = frameNumber;
- } else if (frameNumber < _lastRenderedFrame && _mirrored) {
- _lastRenderedFrame = frameNumber;
+ _lastRenderedFrame = frameNumber;
+ if (frameNumber != 0 && frameNumber < _lastRenderedFrame && _mirrored)
frameNumber = (_frameCount * 2) - frameNumber - 1;
- } else {
- _lastRenderedFrame = frameNumber;
- }
const Graphics::Surface *frameData;
diff --git a/engines/zvision/scripting/controls/lever_control.h b/engines/zvision/scripting/controls/lever_control.h
index 2e0583b91ed..a3ad3f31ba7 100644
--- a/engines/zvision/scripting/controls/lever_control.h
+++ b/engines/zvision/scripting/controls/lever_control.h
@@ -88,7 +88,7 @@ private:
void parseLevFile(const Common::Path &fileName);
void renderFrame(uint frameNumber);
void getLevParams(const Common::String &inputStr, Common::String ¶meter, Common::String &values);
- uint nextFrame(Common::Point &deltaPos);
+ uint getNextFrame(Common::Point &deltaPos);
};
} // End of namespace ZVision
Commit: 04e95b249ba01cca85e278b2969a92e41fa7da91
https://github.com/scummvm/scummvm/commit/04e95b249ba01cca85e278b2969a92e41fa7da91
Author: Thomas N McEwan (46427621+tnm23 at users.noreply.github.com)
Date: 2025-08-25T22:55:34+01:00
Commit Message:
ZVISION: Add workaround for lever animation alignment bug in Nemesis orrery.
Changed paths:
engines/zvision/scripting/controls/lever_control.cpp
diff --git a/engines/zvision/scripting/controls/lever_control.cpp b/engines/zvision/scripting/controls/lever_control.cpp
index 17086e5e353..8e558042af4 100644
--- a/engines/zvision/scripting/controls/lever_control.cpp
+++ b/engines/zvision/scripting/controls/lever_control.cpp
@@ -96,12 +96,15 @@ void LeverControl::parseLevFile(const Common::Path &fileName) {
Common::String param;
Common::String values;
+ int id = 0;
+
while (!file.eos()) {
line = file.readLine();
getLevParams(line, param, values);
if (param.matchString("animation_id", true)) {
- // Not used
+ sscanf(values.c_str(), "%d", &id);
+ debugC(2, kDebugControl, "Lever animation ID: %d", id);
} else if (param.matchString("filename", true)) {
_animation = _engine->loadAnimation(Common::Path(values));
} else if (param.matchString("skipcolor", true)) {
@@ -179,6 +182,19 @@ void LeverControl::parseLevFile(const Common::Path &fileName) {
// Don't read lines in this place because last will not be parsed.
}
+ // WORKAROUND for a script bug in Zork: Nemesis, room tz2e (orrery)
+ // Animation coordinates for left hand lever do not properly align with background image
+ switch (id) {
+ case 2926:
+ _animationCoords.bottom -= 4;
+ _animationCoords.right += 1;
+ _animationCoords.left -= 1;
+ _animationCoords.top += 1;
+ break;
+ default:
+ break;
+ }
+
// Cycle through all unit direction vectors in path segments & determine step distance
debugC(3, kDebugControl, "Setting step distances");
for (uint frame=0; frame < _frameCount; frame++) {
More information about the Scummvm-git-logs
mailing list