[Scummvm-git-logs] scummvm master -> 11ab98f89aabd732bd376b6b0e2ccf95a8c061a7
bluegr
noreply at scummvm.org
Thu Jun 18 21:06:13 UTC 2026
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
960486d2ba NANCY: Implement animations when placing pieces in multibuildpuzzle
11ab98f89a NANCY: Fix label when using the ring at the slot machine in Nancy 10
Commit: 960486d2bac39060b53ca1657d59a4c8c0ac5914
https://github.com/scummvm/scummvm/commit/960486d2bac39060b53ca1657d59a4c8c0ac5914
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-06-19T00:05:59+03:00
Commit Message:
NANCY: Implement animations when placing pieces in multibuildpuzzle
Functionality introduced in Nancy 10. Now, the mixing animation is
shown when placing ingredients in the bowl in the cake mixing puzzle
Changed paths:
engines/nancy/action/puzzle/multibuildpuzzle.cpp
engines/nancy/action/puzzle/multibuildpuzzle.h
diff --git a/engines/nancy/action/puzzle/multibuildpuzzle.cpp b/engines/nancy/action/puzzle/multibuildpuzzle.cpp
index 4655799b4da..a50e4b2ef64 100644
--- a/engines/nancy/action/puzzle/multibuildpuzzle.cpp
+++ b/engines/nancy/action/puzzle/multibuildpuzzle.cpp
@@ -46,6 +46,21 @@ void MultiBuildPuzzle::init() {
_closeupImage.setTransparentColor(_drawSurface.getTransparentColor());
}
+ if (_hasAnimImage) {
+ _animRender._drawSurface.create(_animRect.width(), _animRect.height(),
+ g_nancy->_graphics->getInputPixelFormat());
+ _animRender.setTransparent(true);
+ _animRender._drawSurface.clear(g_nancy->_graphics->getTransColor());
+ _animRender.moveTo(_animRect);
+ _animRender.setZOrder((uint16)(_z + 80 + 10));
+ _animRender.setVisible(true);
+
+ g_nancy->_resource->loadImage(_animImageName, _animImage);
+ _animImage.setTransparentColor(g_nancy->_graphics->getTransColor());
+
+ _animSurfaceReady = true;
+ }
+
for (uint i = 0; i < _pieces.size(); ++i) {
Piece &p = _pieces[i];
@@ -85,6 +100,9 @@ void MultiBuildPuzzle::registerGraphics() {
if (!_isInitialized)
return;
+ if (_animSurfaceReady)
+ _animRender.registerGraphics();
+
for (uint i = 0; i < _pieces.size(); ++i)
_pieces[i].registerGraphics();
}
@@ -119,8 +137,7 @@ void MultiBuildPuzzle::readData(Common::SeekableReadStream &stream) {
_checkOverlapOnDrop = stream.readByte() != 0;
if (isNancy10) {
- // Completion-animation block: image name + sprite-sheet rect + 4 layout
- // shorts (cols, framesPerStep, spacing, totalRows). TODO: not wired up.
+ // Anim block: name + rect + 4 layout shorts (cols/framesPerStep/spacing/totalRows)
Common::String animName;
readFilename(stream, animName);
_animImageName = Common::Path(animName);
@@ -225,6 +242,56 @@ void MultiBuildPuzzle::execute() {
_state = kActionTrigger;
}
break;
+
+ case kAnimStep: {
+ if (!_hasAnimImage) {
+ if (g_system->getMillis() >= _timerEnd)
+ _solveState = kIdle;
+ break;
+ }
+
+ _animActive = true;
+
+ if (_dropSound.name != "NO SOUND" &&
+ !g_nancy->_sound->isSoundPlaying(_dropSound)) {
+ g_nancy->_sound->playSound(_dropSound);
+ }
+
+ if (_animLayout[1] > 0 &&
+ _animFrameCounter / _animLayout[1] >= _animLayout[0]) {
+ _animFrameCounter = 0;
+ _animRowCounter++;
+ }
+
+ if (_animRowCounter < _animLayout[3] && _animLayout[1] > 0) {
+ // pdW/pdH match the raw inclusive `right - left` (our exclusive width - 1)
+ int pdW = _animRect.width() - 1;
+ int pdH = _animRect.height() - 1;
+ int spacing = _animLayout[2];
+ int col = _animFrameCounter % _animLayout[1];
+ int row = _animFrameCounter / _animLayout[1];
+ int srcL = (pdW + spacing) * col + 1;
+ int srcT = (pdH + spacing) * row + 1;
+ _animSrcRect = Common::Rect(srcL, srcT, srcL + pdW, srcT + pdH);
+ _animFrameCounter++;
+ renderAnimFrame();
+ _animFrameWaitEnd = g_system->getMillis() + 100;
+ _solveState = kAnimWaitFrame;
+ } else {
+ _animRowCounter = 0;
+ _animFrameCounter = 0;
+ _animEnded = true;
+ _animActive = false;
+ clearAnimFrame();
+ _solveState = kIdle;
+ }
+ break;
+ }
+
+ case kAnimWaitFrame:
+ if (g_system->getMillis() >= _animFrameWaitEnd)
+ _solveState = kAnimStep;
+ break;
}
break;
@@ -484,7 +551,14 @@ void MultiBuildPuzzle::handleInput(NancyInput &input) {
if (_autoSolveOnDrop || _pieces.size() > 79)
checkIfSolved();
- if (_solveState == kIdle) {
+ if (validDrop && _hasAnimImage && _solveState != kAnimStep &&
+ _solveState != kAnimWaitFrame) {
+ _animFrameCounter = 0;
+ _animRowCounter = 0;
+ _animActive = true;
+ _animEnded = false;
+ _solveState = kAnimStep;
+ } else if (_solveState == kIdle) {
_solveState = kWaitTimer;
_timerEnd = g_system->getMillis() + 300;
}
@@ -636,13 +710,6 @@ bool MultiBuildPuzzle::updateSolveFlags() {
if (total < _requiredPieces)
return false;
- if (_cancelScene._flag.label != kFlagNoLabel)
- NancySceneState.setEventFlag(_cancelScene._flag);
-
- // Preemptively clear the solve flag; the exact-match check below re-sets it.
- if (_solveScene._flag.label != kFlagNoLabel)
- NancySceneState.setEventFlag(_solveScene._flag.label, _solveScene._flag.flag ? 0 : 1);
-
for (uint i = 0; i < _numPieces; ++i) {
if (_pieces[i].placeCount > 0 && _pieces[i].mustNotPlace > 0)
return false;
@@ -650,8 +717,8 @@ bool MultiBuildPuzzle::updateSolveFlags() {
return false;
}
- if (_solveScene._flag.label != kFlagNoLabel)
- NancySceneState.setEventFlag(_solveScene._flag);
+ // Cancel flag is owned by kActionTrigger so it doesn't retrigger per drop
+ NancySceneState.setEventFlag(_solveScene._flag);
return true;
}
@@ -710,6 +777,22 @@ void MultiBuildPuzzle::checkIfSolved() {
_solveState = kWaitSolveSound;
}
+void MultiBuildPuzzle::renderAnimFrame() {
+ if (!_animSurfaceReady || _animImage.empty())
+ return;
+
+ _animRender._drawSurface.clear(g_nancy->_graphics->getTransColor());
+ _animRender._drawSurface.blitFrom(_animImage, _animSrcRect, Common::Point(0, 0));
+ _animRender.setNeedsRedraw(true);
+}
+
+void MultiBuildPuzzle::clearAnimFrame() {
+ if (!_animSurfaceReady)
+ return;
+ _animRender._drawSurface.clear(g_nancy->_graphics->getTransColor());
+ _animRender.setNeedsRedraw(true);
+}
+
void MultiBuildPuzzle::updatePieceRender(int pieceIdx) {
Piece &p = _pieces[pieceIdx];
bool isSelected = (!_isDragging && pieceIdx == _selectedPiece);
diff --git a/engines/nancy/action/puzzle/multibuildpuzzle.h b/engines/nancy/action/puzzle/multibuildpuzzle.h
index c47b1382355..66f8a9d6317 100644
--- a/engines/nancy/action/puzzle/multibuildpuzzle.h
+++ b/engines/nancy/action/puzzle/multibuildpuzzle.h
@@ -138,11 +138,31 @@ protected:
kIdle = 0,
kWaitTimer = 1,
kWaitSolveSound = 4,
- kPlaySolveSound = 5
+ kPlaySolveSound = 5,
+ kAnimStep = 6, // Blit current frame, advance counters
+ kAnimWaitFrame = 7 // ~100 ms hold between frames
};
SolveState _solveState = kIdle;
uint32 _timerEnd = 0;
+ // Nancy 10 mixing animation
+ struct AnimRender : RenderObject {
+ AnimRender() : RenderObject(0) {}
+ bool isViewportRelative() const override { return true; }
+ };
+
+ Graphics::ManagedSurface _animImage;
+ AnimRender _animRender;
+ uint16 _animFrameCounter = 0;
+ uint16 _animRowCounter = 0;
+ uint32 _animFrameWaitEnd = 0;
+ Common::Rect _animSrcRect;
+ bool _animActive = false;
+ bool _animEnded = false;
+ bool _animSurfaceReady = false;
+ void renderAnimFrame();
+ void clearAnimFrame();
+
int16 _pickedUpWidth = 0;
int16 _pickedUpHeight = 0;
Commit: 11ab98f89aabd732bd376b6b0e2ccf95a8c061a7
https://github.com/scummvm/scummvm/commit/11ab98f89aabd732bd376b6b0e2ccf95a8c061a7
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-06-19T00:06:01+03:00
Commit Message:
NANCY: Fix label when using the ring at the slot machine in Nancy 10
Also, restore an old comment as to how and why we deviate from the
original in Overlay::execute()
Changed paths:
engines/nancy/action/overlay.cpp
diff --git a/engines/nancy/action/overlay.cpp b/engines/nancy/action/overlay.cpp
index dcf30656ceb..55a6da14b21 100644
--- a/engines/nancy/action/overlay.cpp
+++ b/engines/nancy/action/overlay.cpp
@@ -360,7 +360,14 @@ void Overlay::execute() {
break;
}
case kActionTrigger:
- setVisible(false);
+ if (g_nancy->getGameType() <= kGameTypeNancy9) {
+ // This isn't done by the original engine, but it's here
+ // to fix Nancy1's safe lock light not turning off. Removing
+ // it for Nancy 10, to fix the animated label showing correctly,
+ // when using the ring at the slot machine.
+ setVisible(false);
+ }
+
g_nancy->_sound->stopSound(_sound);
_flagsOnTrigger.execute();
More information about the Scummvm-git-logs
mailing list