[Scummvm-git-logs] scummvm master -> 2f9287e379f7f9e5112dab8bdda655a899a909ee
sev-
noreply at scummvm.org
Mon Aug 3 10:59:50 UTC 2026
This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
a1e8a5a6c9 DIRECTOR: Add _flags to Filmloop Cast Member
4504b70170 DIRECTOR: Add load() to MovieCastMembers
20dc32b0c0 DIRECTOR: Play the linked movie in movie cast members
8aa7d70ca5 DIRECTOR: Run movie cast members as parallel movies
2088479998 DIRECTOR: Stop embedded movies from rendering the host window
449cabdd2f DIRECTOR: Isolate embedded movie Lingo state
8a2165044e DIRECTOR: Honor scriptsEnabled on movie cast members
2f9287e379 DIRECTOR: Simplify filmloop flag read and movie cast mouse routing
Commit: a1e8a5a6c9593f40e4fbe790ce79e00f54d271f5
https://github.com/scummvm/scummvm/commit/a1e8a5a6c9593f40e4fbe790ce79e00f54d271f5
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-08-03T12:59:43+02:00
Commit Message:
DIRECTOR: Add _flags to Filmloop Cast Member
Remove uint32 _flags from movie cast members and
add _flags to filmloops, because movie cast used
_flags (uinitialised garbage) to set _enableScripts
but the reading was done by a local var in Filmloops
constructor. There was no way to read _flags
from movie cast member's constructor
Changed paths:
engines/director/castmember/filmloop.cpp
engines/director/castmember/filmloop.h
engines/director/castmember/movie.h
diff --git a/engines/director/castmember/filmloop.cpp b/engines/director/castmember/filmloop.cpp
index 052952b8a40..403735cda22 100644
--- a/engines/director/castmember/filmloop.cpp
+++ b/engines/director/castmember/filmloop.cpp
@@ -49,10 +49,12 @@ FilmLoopCastMember::FilmLoopCastMember(Cast *cast, uint16 castId, Common::Seekab
_center = false;
_index = -1;
_score = nullptr;
+ _flags = 0;
if (cast->_version >= kFileVer400) {
_initialRect = Movie::readRect(stream);
uint32 flags = stream.readUint32BE();
+ _flags = flags;
uint16 unk1 = stream.readUint16BE();
_looping = flags & 32 ? 0 : 1;
_enableSound = flags & 8 ? 1 : 0;
@@ -75,6 +77,7 @@ FilmLoopCastMember::FilmLoopCastMember(Cast *cast, uint16 castId, FilmLoopCastMe
if (cast == source._cast)
_children = source._children;
+ _flags = source._flags;
_enableSound = source._enableSound;
_crop = source._crop;
_center = source._center;
diff --git a/engines/director/castmember/filmloop.h b/engines/director/castmember/filmloop.h
index 1bb2ed2ba70..f847a6e2831 100644
--- a/engines/director/castmember/filmloop.h
+++ b/engines/director/castmember/filmloop.h
@@ -68,6 +68,8 @@ public:
void writeSCVWResource(Common::SeekableWriteStream *writeStream, uint32 offset);
uint32 getSCVWResourceSize();
+ // raw CASt flag word; MovieCastMember reads its enableScripts bit (0x10)
+ uint32 _flags;
bool _enableSound;
bool _looping;
bool _crop;
diff --git a/engines/director/castmember/movie.h b/engines/director/castmember/movie.h
index fe67a708209..0bf1681741f 100644
--- a/engines/director/castmember/movie.h
+++ b/engines/director/castmember/movie.h
@@ -42,7 +42,6 @@ public:
Common::String formatInfo() override;
- uint32 _flags;
bool _enableScripts;
};
Commit: 4504b70170a3a713561ca5af07a03fe826323354
https://github.com/scummvm/scummvm/commit/4504b70170a3a713561ca5af07a03fe826323354
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-08-03T12:59:43+02:00
Commit Message:
DIRECTOR: Add load() to MovieCastMembers
Movie cast members inherited filmloop's load(), which looks for an
embedded SCVW child. A movie cast member has no children; its content
lives in an external movie referenced by the cast info. Resolve that
path via getLinkedPath()/findMoviePath(), open the archive, and load
it as an owned Movie, pointing the inherited _score at its score.
Changed paths:
engines/director/castmember/movie.cpp
engines/director/castmember/movie.h
diff --git a/engines/director/castmember/movie.cpp b/engines/director/castmember/movie.cpp
index da768a21b4a..72f30cdd2c0 100644
--- a/engines/director/castmember/movie.cpp
+++ b/engines/director/castmember/movie.cpp
@@ -24,7 +24,7 @@
#include "director/sprite.h"
#include "director/castmember/movie.h"
-
+#include "director/cast.h"
#include "director/lingo/lingo-the.h"
namespace Director {
@@ -34,6 +34,7 @@ MovieCastMember::MovieCastMember(Cast *cast, uint16 castId, Common::SeekableRead
_type = kCastMovie;
_enableScripts = _flags & 0x10;
+ _linkedMovie = nullptr;
if (debugChannelSet(2, kDebugLoading))
_initialRect.debugPrint(2, "MovieCastMember(): rect:");
@@ -50,6 +51,10 @@ MovieCastMember::MovieCastMember(Cast *cast, uint16 castId, MovieCastMember &sou
_enableScripts = source._enableScripts;
}
+MovieCastMember::~MovieCastMember() {
+ delete _linkedMovie;
+}
+
Common::Array<Channel> *MovieCastMember::getSubChannels(Common::Rect &bbox, uint frame) {
if (_needsReload) {
_loaded = false;
@@ -63,12 +68,38 @@ void MovieCastMember::load() {
if (_loaded)
return;
- FilmLoopCastMember::load();
+ Common::String rawMoviePath = _cast->getLinkedPath(_castId);
+ if(rawMoviePath.empty()) {
+ warning("MovieCastMember::load() No filename for linked movie in _castId %d", _castId);
+ _loaded = true;
+ return;
+ }
+
+ Common::Path moviePath = findMoviePath(rawMoviePath);
+ if(moviePath.empty()) {
+ warning("MovieCastMember::load(): Linked movie %s not found", rawMoviePath.c_str());
+ _loaded = true;
+ return;
+ }
+
+ Common::SharedPtr<Archive> archive = g_director->openArchive(moviePath);
+ if (!archive) {
+ warning("MovieCastMember::load(): Failed to load archive at %s", moviePath.toString().c_str());
+ _loaded = true;
+ return;
+ }
+
+ _linkedMovie = new Movie(_cast->getMovie()->getWindow());
+ _linkedMovie->setArchive(archive);
+ _linkedMovie->loadArchive();
+ _score = _linkedMovie->getScore();
_loaded = true;
- _needsReload = false;
+ return;
}
+
+
bool MovieCastMember::hasField(int field) {
switch (field) {
case kTheCenter:
diff --git a/engines/director/castmember/movie.h b/engines/director/castmember/movie.h
index 0bf1681741f..106613b7a1e 100644
--- a/engines/director/castmember/movie.h
+++ b/engines/director/castmember/movie.h
@@ -23,6 +23,7 @@
#define DIRECTOR_CASTMEMBER_MOVIE_H
#include "director/castmember/filmloop.h"
+#include "director/movie.h"
namespace Director {
@@ -31,6 +32,8 @@ public:
MovieCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version);
MovieCastMember(Cast *cast, uint16 castId, MovieCastMember &source);
+ ~MovieCastMember();
+
CastMember *duplicate(Cast *cast, uint16 castId) override { return (CastMember *)(new MovieCastMember(cast, castId, *this)); }
Common::Array<Channel> *getSubChannels(Common::Rect &bbox, uint frame) override;
@@ -43,6 +46,7 @@ public:
Common::String formatInfo() override;
bool _enableScripts;
+ Movie *_linkedMovie;
};
} // End of namespace Director
Commit: 20dc32b0c0d995b8186a72f003500ada4dd59649
https://github.com/scummvm/scummvm/commit/20dc32b0c0d995b8186a72f003500ada4dd59649
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-08-03T12:59:43+02:00
Commit Message:
DIRECTOR: Play the linked movie in movie cast members
A movie cast member points at an external Director movie, named by the
directory and fileName entries in its cast info. It inherited the film
loop loader, which only looks for an embedded SCVW child, so nothing
was ever loaded and the member drew nothing.
Resolve the path with getLinkedPath()/findMoviePath(), open the archive
and load it as a Movie owned by the cast member, then point the
inherited _score at its score so the existing film loop render path
serves its frames. Sprites are resolved against the linked movie's own
cast rather than the host's.
The linked movie borrows the host's window, so loadArchive() would
otherwise resize the stage and the screen to the linked movie's rect,
recentre it and overwrite its colour. Add Movie::_isEmbedded to skip
the parts of loadArchive() that take ownership of the stage.
In D4 film loops freeze while an explicit jump holds the playhead on
one frame, but a movie that loops naturally on a single frame still
advances them, so only freeze for the jump case.
Changed paths:
engines/director/castmember/movie.cpp
engines/director/castmember/movie.h
engines/director/movie.cpp
engines/director/movie.h
engines/director/score.cpp
engines/director/score.h
diff --git a/engines/director/castmember/movie.cpp b/engines/director/castmember/movie.cpp
index 72f30cdd2c0..f411b8ce44f 100644
--- a/engines/director/castmember/movie.cpp
+++ b/engines/director/castmember/movie.cpp
@@ -26,6 +26,8 @@
#include "director/castmember/movie.h"
#include "director/cast.h"
#include "director/lingo/lingo-the.h"
+#include "director/frame.h"
+#include "director/score.h"
namespace Director {
@@ -49,6 +51,11 @@ MovieCastMember::MovieCastMember(Cast *cast, uint16 castId, MovieCastMember &sou
_type = kCastMovie;
_enableScripts = source._enableScripts;
+
+ // the copy loads its own linked movie (this member owns it)
+ _linkedMovie = nullptr;
+ _score = nullptr;
+ _loaded = false;
}
MovieCastMember::~MovieCastMember() {
@@ -68,37 +75,75 @@ void MovieCastMember::load() {
if (_loaded)
return;
+ // A reload rebuilds the linked movie
+ delete _linkedMovie;
+ _linkedMovie = nullptr;
+ _score = nullptr;
+
+ _loaded = true;
+ _needsReload = false;
+
Common::String rawMoviePath = _cast->getLinkedPath(_castId);
- if(rawMoviePath.empty()) {
- warning("MovieCastMember::load() No filename for linked movie in _castId %d", _castId);
- _loaded = true;
+ if (rawMoviePath.empty()) {
+ warning("MovieCastMember::load(): No filename for linked movie in castId %d", _castId);
return;
}
Common::Path moviePath = findMoviePath(rawMoviePath);
- if(moviePath.empty()) {
+ if (moviePath.empty()) {
warning("MovieCastMember::load(): Linked movie %s not found", rawMoviePath.c_str());
- _loaded = true;
return;
}
Common::SharedPtr<Archive> archive = g_director->openArchive(moviePath);
if (!archive) {
warning("MovieCastMember::load(): Failed to load archive at %s", moviePath.toString().c_str());
- _loaded = true;
return;
}
+ // The linked movie borrows the host's window, so it must not take over
+ // the stage (resize, recolour, reset palette) like a normal movie does.
_linkedMovie = new Movie(_cast->getMovie()->getWindow());
+ _linkedMovie->_isEmbedded = true;
_linkedMovie->setArchive(archive);
_linkedMovie->loadArchive();
_score = _linkedMovie->getScore();
- _loaded = true;
- return;
+ // resolve the sprites against the linked movie's own cast
+ for (auto &frame : _score->_scoreCache) {
+ for (auto &sprite : frame->_sprites) {
+ if (sprite && !sprite->_castId.isNull())
+ sprite->setCast(sprite->_castId, false);
+ }
+ }
}
-
+void MovieCastMember::update() {
+ if (!_loaded)
+ load();
+ if (!_linkedMovie)
+ return;
+
+ Score *score = _linkedMovie->getScore();
+ switch (score->_playState) {
+ case kPlayNotStarted:
+ score->_playState = kPlayLoaded;
+ break;
+ case kPlayLoaded:
+ // startPlay() without kEventStartMovie: movie scripts do not
+ // run inside movie cast members
+ score->_haveInteractivity = false;
+ score->startPlay();
+ score->_haveInteractivity = true;
+ break;
+ case kPlayStarted:
+ // lockstep advance is host-driven in incrementFilmLoops();
+ // frame-script dispatch lands here (via the Score seam) later
+ break;
+ default:
+ break;
+ }
+}
bool MovieCastMember::hasField(int field) {
switch (field) {
diff --git a/engines/director/castmember/movie.h b/engines/director/castmember/movie.h
index 106613b7a1e..8a8508f4f68 100644
--- a/engines/director/castmember/movie.h
+++ b/engines/director/castmember/movie.h
@@ -43,6 +43,8 @@ public:
Datum getField(int field) override;
void setField(int field, const Datum &value) override;
+ void update();
+
Common::String formatInfo() override;
bool _enableScripts;
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index d6a82ab2e1a..3e2d18fd7d8 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -289,14 +289,16 @@ bool Movie::loadArchive() {
} else {
_defaultPalette = CastMemberID(kClutSystemMac, -1);
}
- g_director->_lastPalette = CastMemberID();
+ if (!_isEmbedded)
+ g_director->_lastPalette = CastMemberID();
bool recenter = false;
// For the stage, always resize to the movie rect.
// For MIAWs, only resize if the window hasn't been explicitly sized by Lingo
// (i.e. still at the 1x1 default from createWindow).
+ // An embedded movie borrows the host's window and must never resize it.
bool windowSizeIsDefault = (_window->getSurface()->w <= 1 && _window->getSurface()->h <= 1);
- if (_window == _vm->getStage() || windowSizeIsDefault) {
+ if (!_isEmbedded && (_window == _vm->getStage() || windowSizeIsDefault)) {
if (_window->getSurface()->w != _movieRect.width() || _window->getSurface()->h != _movieRect.height()) {
_window->resizeInner(_movieRect.width(), _movieRect.height());
recenter = true;
@@ -304,7 +306,7 @@ bool Movie::loadArchive() {
}
// TODO: Add more options for desktop dimensions
- if (_window == _vm->getStage()) {
+ if (!_isEmbedded && _window == _vm->getStage()) {
uint16 windowWidth = g_director->desktopEnabled() ? g_director->_wmWidth : _movieRect.width();
uint16 windowHeight = g_director->desktopEnabled() ? g_director->_wmHeight : _movieRect.height();
if (_vm->_wm->_screenDims.width() != windowWidth || _vm->_wm->_screenDims.height() != windowHeight) {
@@ -318,7 +320,8 @@ bool Movie::loadArchive() {
if (recenter && g_director->desktopEnabled())
_window->center(g_director->_centerStage);
- _window->setStageColor(_stageColor, true);
+ if (!_isEmbedded)
+ _window->setStageColor(_stageColor, true);
// Score
if (!(r = _movieArchive->getMovieResourceIfPresent(MKTAG('V', 'W', 'S', 'C')))) {
diff --git a/engines/director/movie.h b/engines/director/movie.h
index 94aa12b4348..4d0bf1868d3 100644
--- a/engines/director/movie.h
+++ b/engines/director/movie.h
@@ -213,6 +213,11 @@ public:
// shouldn't be recorded as movie event, which may cause undesirable change in the lingo script
bool _inGuiMessageBox = false;
+ // Set for a movie loaded inside a cast member. It shares the host's
+ // window but never owns the stage, so loadArchive() must not resize
+ // or recolour it.
+ bool _isEmbedded = false;
+
private:
Window *_window;
DirectorEngine *_vm;
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index d079528a851..5016d3937e4 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -48,6 +48,7 @@
#include "director/window.h"
#include "director/castmember/castmember.h"
#include "director/castmember/filmloop.h"
+#include "director/castmember/movie.h"
#include "director/castmember/transition.h"
#include "director/debugger/debugtools.h"
@@ -451,6 +452,10 @@ void Score::updateCurrentFrame() {
nextFrameNumberToLoad = (_curFrameNumber+1);
}
+ // whether this frame is held by an explicit jump (go the frame), which
+ // film loops treat differently from a natural single-frame loop
+ _frameHeldByJump = (_nextFrame != 0);
+
_nextFrame = 0;
_window->_skipFrameAdvance = false;
@@ -911,20 +916,25 @@ bool Score::renderTransition(uint16 frameId, RenderMode mode) {
return false;
}
+// increment filmloops or movie cast members
void Score::incrementFilmLoops() {
// Film loops do not advance while the movie is paused
if (_window->_playbackPaused)
return;
- // In D4, film loops also freeze while the playhead loops in a single
- // frame, e.g. via go the frame. D5 and later animate in that case
- if (_vm->getVersion() < 500 && _curFrameNumber == _filmLoopsLastFrame)
+ // In D4, film loops freeze only while an explicit jump (go the frame)
+ // holds the playhead on one frame; a movie that loops naturally on a
+ // single frame still advances them. D5 and later always animate.
+ if (_vm->getVersion() < 500 && _curFrameNumber == _filmLoopsLastFrame && _frameHeldByJump)
return;
_filmLoopsLastFrame = _curFrameNumber;
for (auto &it : _channels) {
- if (it->_sprite->_cast && (it->_sprite->_cast->_type == kCastFilmLoop || it->_sprite->_cast->_type == kCastMovie)) {
+ if (!it->_sprite->_cast) continue;
+ CastType type = it->_sprite->_cast->_type;
+ if (type == kCastFilmLoop || type == kCastMovie) {
FilmLoopCastMember *fl = ((FilmLoopCastMember *)it->_sprite->_cast);
+
if (fl->_score && !fl->_score->_scoreCache.empty()) {
if (fl->_looping) {
it->_filmLoopFrame += 1;
@@ -935,6 +945,12 @@ void Score::incrementFilmLoops() {
} else {
warning("Score::incrementFilmLoops(): invalid film loop in castId %s", it->_sprite->_castId.asString().c_str());
}
+
+ if (type == kCastMovie) {
+ MovieCastMember *mv = ((MovieCastMember *)it->_sprite->_cast);
+ mv->update();
+ }
+
}
}
}
diff --git a/engines/director/score.h b/engines/director/score.h
index ca88dd10f0c..413ac7efb8d 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -253,6 +253,10 @@ private:
// score frame number at the last film loop advance
uint32 _filmLoopsLastFrame = 0;
+ // true when the current frame is held by an explicit jump (e.g. go the
+ // frame) rather than natural playback; in D4 this freezes film loops.
+ bool _frameHeldByJump = false;
+
int _previousBuildBotBuild = -1;
bool _firstRun = true;
};
Commit: 8aa7d70ca5165ca3bee8421cfc6d17de2f2e68e5
https://github.com/scummvm/scummvm/commit/8aa7d70ca5165ca3bee8421cfc6d17de2f2e68e5
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-08-03T12:59:43+02:00
Commit Message:
DIRECTOR: Run movie cast members as parallel movies
A movie cast member's linked movie is now stepped like a real movie
rather than a film loop, so it runs its own score: its frame scripts,
go() navigation, globals and mouse handlers all work. This is what the
mini-map in Star Trek: TNG Interactive Technical Manual needs, where a
linked movie runs in parallel and syncs with the panorama via globals.
- MovieCastMember::update() starts and steps the linked movie's score,
and getSubChannels() composites its live channels into the sprite's
bbox, so script-driven changes (e.g. go()) are reflected.
- Movie::_isEmbedded marks a movie loaded inside a cast member. Such a
movie shares the host's window but never owns the stage, so
loadArchive() does not resize or recolour it, renderFrame() only
refreshes its channels, and its channels neither create widgets nor
hilite (which would draw at the embedded movie's native origin).
- The window's current movie is retargeted at the linked movie around
its step, so its go()/globals/event context resolves against itself.
- Movie::_parentMovie lets an embedded movie share its host's scope:
getHandler() and getCastMemberIDByNameAndType() fall back to the host.
- Clicks that land on a movie cast member are routed into its linked
movie, translated into its coordinate space, and drained each step so
a per-frame go() in its exitFrame does not starve them.
- In D4 a movie cast member keeps running while the host holds its
playhead on one frame; only film loops freeze in that case.
Changed paths:
engines/director/castmember/movie.cpp
engines/director/castmember/movie.h
engines/director/channel.cpp
engines/director/lingo/lingo-events.cpp
engines/director/movie.cpp
engines/director/movie.h
engines/director/score.cpp
engines/director/sprite.cpp
engines/director/window.h
diff --git a/engines/director/castmember/movie.cpp b/engines/director/castmember/movie.cpp
index f411b8ce44f..7ed4d0134d1 100644
--- a/engines/director/castmember/movie.cpp
+++ b/engines/director/castmember/movie.cpp
@@ -25,9 +25,11 @@
#include "director/castmember/movie.h"
#include "director/cast.h"
+#include "director/channel.h"
#include "director/lingo/lingo-the.h"
#include "director/frame.h"
#include "director/score.h"
+#include "director/window.h"
namespace Director {
@@ -68,7 +70,47 @@ Common::Array<Channel> *MovieCastMember::getSubChannels(Common::Rect &bbox, uint
load();
}
- return FilmLoopCastMember::getSubChannels(bbox, frame);
+ // Composite the embedded score's live channels (frame ignored) so
+ // script-driven changes show, unlike a film loop's fixed frames.
+ Common::Rect widgetRect(bbox.width() ? bbox.width() : _initialRect.width(),
+ bbox.height() ? bbox.height() : _initialRect.height());
+
+ _subchannels.clear();
+
+ if (!_score || _score->_channels.empty())
+ return &_subchannels;
+
+ bool needToScale = (bbox.width() != _initialRect.width() || bbox.height() != _initialRect.height());
+ float scaleX = needToScale ? (float)bbox.width() / _initialRect.width() : 1.0f;
+ float scaleY = needToScale ? (float)bbox.height() / _initialRect.height() : 1.0f;
+
+ // channel 0 is the score's own frame channel; sprites start at 1
+ for (uint i = 1; i < _score->_channels.size(); ++i) {
+ Sprite *chanSprite = _score->_channels[i]->_sprite;
+ if (!chanSprite || chanSprite->_castId.isNull())
+ continue;
+
+ Sprite src = *chanSprite;
+
+ if (needToScale) {
+ src._startPoint.x = (src._startPoint.x - _initialRect.left) * scaleX + bbox.left;
+ src._startPoint.y = (src._startPoint.y - _initialRect.top) * scaleY + bbox.top;
+ src._width = widgetRect.width();
+ src._height = widgetRect.height();
+ src._stretch = true;
+ } else {
+ src._startPoint.x = (src._startPoint.x - _initialRect.left) + bbox.left;
+ src._startPoint.y = (src._startPoint.y - _initialRect.top) + bbox.top;
+ }
+
+ Channel chan(nullptr, &src);
+ _subchannels.push_back(chan);
+ }
+
+ for (auto &iter : _subchannels)
+ iter.replaceWidget();
+
+ return &_subchannels;
}
void MovieCastMember::load() {
@@ -105,6 +147,7 @@ void MovieCastMember::load() {
// the stage (resize, recolour, reset palette) like a normal movie does.
_linkedMovie = new Movie(_cast->getMovie()->getWindow());
_linkedMovie->_isEmbedded = true;
+ _linkedMovie->_parentMovie = _cast->getMovie();
_linkedMovie->setArchive(archive);
_linkedMovie->loadArchive();
_score = _linkedMovie->getScore();
@@ -119,30 +162,50 @@ void MovieCastMember::load() {
}
void MovieCastMember::update() {
- if (!_loaded)
- load();
- if (!_linkedMovie)
- return;
-
- Score *score = _linkedMovie->getScore();
- switch (score->_playState) {
- case kPlayNotStarted:
- score->_playState = kPlayLoaded;
- break;
- case kPlayLoaded:
- // startPlay() without kEventStartMovie: movie scripts do not
- // run inside movie cast members
- score->_haveInteractivity = false;
- score->startPlay();
- score->_haveInteractivity = true;
- break;
- case kPlayStarted:
- // lockstep advance is host-driven in incrementFilmLoops();
- // frame-script dispatch lands here (via the Score seam) later
- break;
- default:
- break;
- }
+ if (!_loaded)
+ load();
+ if (!_linkedMovie)
+ return;
+
+ // Step the linked score once per host frame. Its renderFrame() is
+ // short-circuited (see Score::renderFrame) to refresh channels without
+ // drawing to the host window; the host composites them via getSubChannels().
+ Score *score = _linkedMovie->getScore();
+
+ // Scripts resolve context via getCurrentMovie(), so point the shared
+ // window at the linked movie for the step, then restore. This lets its
+ // go()/globals/events act on itself.
+ Window *window = _linkedMovie->getWindow();
+ Movie *hostMovie = window->getCurrentMovie();
+ window->setCurrentMovie(_linkedMovie);
+
+ if (score->_playState != kPlayStarted)
+ score->startPlay();
+
+ // A per-frame go() in exitFrame leaves hasJump/frozen state set, so
+ // step() never drains routed input. Drain here so the embedded movie's
+ // mouse handlers (e.g. mouseUp) fire.
+ if (!_linkedMovie->_inputEventQueue.empty())
+ g_lingo->processEvents(_linkedMovie->_inputEventQueue, true);
+
+ score->step();
+
+ window->setCurrentMovie(hostMovie);
+}
+
+void MovieCastMember::routeInputEvent(LEvent event, Common::Point hostPos, const Common::Rect &bbox) {
+ if (!_linkedMovie)
+ return;
+
+ // Invert getSubChannels()'s scaling to map the click into the linked
+ // movie's coordinate space.
+ Common::Point p = hostPos;
+ if (bbox.width() && bbox.height()) {
+ p.x = (hostPos.x - bbox.left) * _initialRect.width() / bbox.width() + _initialRect.left;
+ p.y = (hostPos.y - bbox.top) * _initialRect.height() / bbox.height() + _initialRect.top;
+ }
+
+ _linkedMovie->queueInputEvent(event, 0, p);
}
bool MovieCastMember::hasField(int field) {
diff --git a/engines/director/castmember/movie.h b/engines/director/castmember/movie.h
index 8a8508f4f68..ad1646e2394 100644
--- a/engines/director/castmember/movie.h
+++ b/engines/director/castmember/movie.h
@@ -45,6 +45,10 @@ public:
void update();
+ // Map a host-stage mouse position into the linked movie's space and
+ // queue the event for its scripts to handle on the next step.
+ void routeInputEvent(LEvent event, Common::Point hostPos, const Common::Rect &bbox);
+
Common::String formatInfo() override;
bool _enableScripts;
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 64aec4398e6..ada056cfea8 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -728,6 +728,17 @@ bool Channel::canKeepWidget(Sprite *currentSprite, Sprite *nextSprite) {
// currently, when we are setting hilite, we delete the widget and the re-create it
// so we may optimize this if this operation takes much time
void Channel::replaceWidget(CastMemberID previousCastId, bool force) {
+ // An embedded movie is composited via getSubChannels(); its own channels
+ // must not create widgets, or the shared window would draw them at the
+ // embedded movie's native position.
+ if (_score && _score->getMovie() && _score->getMovie()->_isEmbedded) {
+ if (_widget) {
+ delete _widget;
+ _widget = nullptr;
+ }
+ return;
+ }
+
// if the castmember is the same, and we are not modifying anything which cannot be handle by channel. Then we don't replace the widget
if (!force && canKeepWidget(previousCastId)) {
debug(5, "Channel::replaceWidget(): skip deleting %s", _sprite->_castId.asString().c_str());
diff --git a/engines/director/lingo/lingo-events.cpp b/engines/director/lingo/lingo-events.cpp
index afe0a50a36c..9214a52d558 100644
--- a/engines/director/lingo/lingo-events.cpp
+++ b/engines/director/lingo/lingo-events.cpp
@@ -32,6 +32,7 @@
#include "director/movie.h"
#include "director/score.h"
#include "director/sprite.h"
+#include "director/castmember/movie.h"
#include "director/types.h"
#include "director/window.h"
@@ -162,7 +163,10 @@ void Movie::resolveScriptEvent(LingoEvent &event) {
}
if (event.channelId > 0) {
- if (_score->_channels[event.channelId]->_sprite->shouldHilite()) {
+ // An embedded movie (a movie cast member) is composited into
+ // the host stage via getSubChannels(); hiliting its own
+ // channels would draw at the embedded movie's native origin.
+ if (!_isEmbedded && _score->_channels[event.channelId]->_sprite->shouldHilite()) {
_currentHiliteChannelId = event.channelId;
g_director->_wm->_hilitingWidget = true;
g_director->getCurrentWindow()->setDirty(true);
@@ -672,6 +676,17 @@ void Movie::queueInputEvent(LEvent event, int targetId, Common::Point pos) {
bool Movie::processInputEvent(LEvent event, int targetId, Common::Point pos) {
+ // Route a click on a movie cast member into its linked movie so that
+ // movie's own scripts (mouseUp, the clickOn) handle it.
+ if (event == kEventMouseUp || event == kEventMouseDown) {
+ uint16 spriteId = _score->getMouseSpriteIDFromPos(pos);
+ if (spriteId) {
+ Channel *ch = _score->getChannelById(spriteId);
+ if (ch && ch->_sprite->_cast && ch->_sprite->_cast->_type == kCastMovie)
+ ((MovieCastMember *)ch->_sprite->_cast)->routeInputEvent(event, pos, ch->getBbox());
+ }
+ }
+
queueInputEvent(event, targetId, pos);
if ((!_lingo->_state->callstack.empty()) || (_lingo->_currentInputEvent.type != VOIDSYM)) {
// We're in the middle of executing something else, queue input event for later
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index 3e2d18fd7d8..f3d966f10c2 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -747,6 +747,11 @@ CastMemberID Movie::getCastMemberIDByNameAndType(const Common::String &name, int
} else {
warning("Movie::getCastMemberIDByNameAndType: Unknown castLib %d", castLib);
}
+ // An embedded movie shares its host's cast, so a member it lacks may
+ // live in the host movie.
+ if (result.member == -1 && _parentMovie)
+ return _parentMovie->getCastMemberIDByNameAndType(name, castLib, type);
+
if (result.member == -1) {
warning("Movie::getCastMemberIDByNameAndType: No match found for member name %s and lib %d", name.c_str(), castLib);
}
@@ -831,6 +836,11 @@ Symbol Movie::getHandler(const Common::String &name, uint16 castLibHint) {
if (_sharedCast && _sharedCast->_lingoArchive->functionHandlers.contains(name))
return _sharedCast->_lingoArchive->functionHandlers[name];
+ // An embedded movie shares its host's handler scope, so a handler it
+ // lacks may live in the host movie.
+ if (_parentMovie)
+ return _parentMovie->getHandler(name, castLibHint);
+
return Symbol();
}
diff --git a/engines/director/movie.h b/engines/director/movie.h
index 4d0bf1868d3..8bdb260a111 100644
--- a/engines/director/movie.h
+++ b/engines/director/movie.h
@@ -218,6 +218,10 @@ public:
// or recolour it.
bool _isEmbedded = false;
+ // For an embedded movie, the movie that hosts it. Its scripts share the
+ // host's handler scope, so getHandler() falls back to the parent.
+ Movie *_parentMovie = nullptr;
+
private:
Window *_window;
DirectorEngine *_vm;
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 5016d3937e4..17e5069047c 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -854,6 +854,13 @@ void Score::update() {
}
void Score::renderFrame(uint16 frameId, RenderMode mode, bool sound1Changed, bool sound2Changed) {
+ // An embedded movie only refreshes its own channels for the host to
+ // composite via getSubChannels(); it must never touch the shared window.
+ if (_movie->_isEmbedded) {
+ updateSprites(mode);
+ return;
+ }
+
uint32 start = g_system->getMillis(false);
// Force cursor update if a new movie's started.
if (_window->_newMovieStarted)
@@ -922,19 +929,24 @@ void Score::incrementFilmLoops() {
if (_window->_playbackPaused)
return;
- // In D4, film loops freeze only while an explicit jump (go the frame)
- // holds the playhead on one frame; a movie that loops naturally on a
- // single frame still advances them. D5 and later always animate.
- if (_vm->getVersion() < 500 && _curFrameNumber == _filmLoopsLastFrame && _frameHeldByJump)
- return;
- _filmLoopsLastFrame = _curFrameNumber;
+ // In D4, film loops freeze while an explicit jump holds the playhead on
+ // one frame (a natural single-frame loop still advances them); D5+ always
+ // animate. Movie cast members are independent and always keep running.
+ bool filmLoopsFrozen = (_vm->getVersion() < 500 && _curFrameNumber == _filmLoopsLastFrame && _frameHeldByJump);
+ if (!filmLoopsFrozen)
+ _filmLoopsLastFrame = _curFrameNumber;
for (auto &it : _channels) {
- if (!it->_sprite->_cast) continue;
+ if (!it->_sprite->_cast)
+ continue;
CastType type = it->_sprite->_cast->_type;
- if (type == kCastFilmLoop || type == kCastMovie) {
- FilmLoopCastMember *fl = ((FilmLoopCastMember *)it->_sprite->_cast);
+ if (type == kCastMovie) {
+ // A movie cast member steps its own embedded score like a normal
+ // movie, not the film loop flipbook.
+ ((MovieCastMember *)it->_sprite->_cast)->update();
+ } else if (type == kCastFilmLoop && !filmLoopsFrozen) {
+ FilmLoopCastMember *fl = ((FilmLoopCastMember *)it->_sprite->_cast);
if (fl->_score && !fl->_score->_scoreCache.empty()) {
if (fl->_looping) {
it->_filmLoopFrame += 1;
@@ -945,12 +957,6 @@ void Score::incrementFilmLoops() {
} else {
warning("Score::incrementFilmLoops(): invalid film loop in castId %s", it->_sprite->_castId.asString().c_str());
}
-
- if (type == kCastMovie) {
- MovieCastMember *mv = ((MovieCastMember *)it->_sprite->_cast);
- mv->update();
- }
-
}
}
}
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 65d66c9399d..13665f40e41 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -354,6 +354,11 @@ bool Sprite::respondsToMouse() {
if (_cast && _cast->_type == kCastButton)
return true;
+ // A movie cast member is interactive: its embedded movie may have mouse
+ // handlers, so clicks must be routed into it.
+ if (_cast && _cast->_type == kCastMovie)
+ return true;
+
// TODO: Check if we need to check against individual events like below
if (g_director->getVersion() >= 600) {
if (_behaviors.size() > 0)
diff --git a/engines/director/window.h b/engines/director/window.h
index 57a38c8c529..b7e7389aade 100644
--- a/engines/director/window.h
+++ b/engines/director/window.h
@@ -134,6 +134,9 @@ public:
DirectorEngine *getVM() const { return _vm; }
Graphics::MacWindow *getMacWindow() const { return _window; }
Movie *getCurrentMovie() const { return _currentMovie; }
+ // Temporarily retarget the current movie when stepping an embedded movie
+ // so getCurrentMovie()-based context (go, globals, events) points at it.
+ void setCurrentMovie(Movie *movie) { _currentMovie = movie; }
Common::String getCurrentPath() const { return _currentPath; }
DirectorSound *getSoundManager() const { return _soundManager; }
Commit: 2088479998ffd9d0853a4398f60fa2143065ab13
https://github.com/scummvm/scummvm/commit/2088479998ffd9d0853a4398f60fa2143065ab13
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-08-03T12:59:43+02:00
Commit Message:
DIRECTOR: Stop embedded movies from rendering the host window
A movie cast member's linked movie could paint the shared window from
its own updateStage (Window::render), drawing its channels at the
embedded movie's native origin instead of only through the host's
getSubChannels() composite. Suppress Window::render() while an embedded
movie is current.
This also makes the previous mouseDown hilite guard unnecessary, so
drop it: the hilite is only visible through a render, which no longer
happens for an embedded movie.
Changed paths:
engines/director/lingo/lingo-events.cpp
engines/director/window.cpp
diff --git a/engines/director/lingo/lingo-events.cpp b/engines/director/lingo/lingo-events.cpp
index 9214a52d558..cc462d2c6b6 100644
--- a/engines/director/lingo/lingo-events.cpp
+++ b/engines/director/lingo/lingo-events.cpp
@@ -163,10 +163,7 @@ void Movie::resolveScriptEvent(LingoEvent &event) {
}
if (event.channelId > 0) {
- // An embedded movie (a movie cast member) is composited into
- // the host stage via getSubChannels(); hiliting its own
- // channels would draw at the embedded movie's native origin.
- if (!_isEmbedded && _score->_channels[event.channelId]->_sprite->shouldHilite()) {
+ if (_score->_channels[event.channelId]->_sprite->shouldHilite()) {
_currentHiliteChannelId = event.channelId;
g_director->_wm->_hilitingWidget = true;
g_director->getCurrentWindow()->setDirty(true);
diff --git a/engines/director/window.cpp b/engines/director/window.cpp
index b9964b79489..76fc57aa2e2 100644
--- a/engines/director/window.cpp
+++ b/engines/director/window.cpp
@@ -233,6 +233,12 @@ bool Window::render(bool forceRedraw, Graphics::ManagedSurface *blitTo) {
if (!_currentMovie)
return false;
+ // An embedded movie is composited via getSubChannels(); it must never
+ // render the shared window itself (e.g. from its own updateStage), which
+ // would draw its channels at the embedded movie's native origin.
+ if (_currentMovie->_isEmbedded)
+ return false;
+
if (!blitTo)
blitTo = _window->getSurface();
Commit: 449cabdd2f6367ca13adfdae8b13c5334eb1fbca
https://github.com/scummvm/scummvm/commit/449cabdd2f6367ca13adfdae8b13c5334eb1fbca
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-08-03T12:59:43+02:00
Commit Message:
DIRECTOR: Isolate embedded movie Lingo state
The embedded movie shared the host window's single LingoState (its call
stack and frozen-state stack). The mini-map runs a per-frame go() in its
exitFrame, which freezes that shared state; because the host and the
embedded movie share it, the host's own frame scripts were then blocked
and stopped running. This showed up as the panorama's description text no
longer drawing and as routed input events never draining.
Give the embedded movie its own LingoState and frozen stack, swapped onto
the window around its step (Window::swapLingoState) and switched via
switchStateFromWindow(). Global variables stay shared on g_lingo, which is
how the host and the linked movie communicate; only the execution state is
isolated.
Changed paths:
engines/director/castmember/movie.cpp
engines/director/castmember/movie.h
engines/director/window.h
diff --git a/engines/director/castmember/movie.cpp b/engines/director/castmember/movie.cpp
index 7ed4d0134d1..9190cd10fe3 100644
--- a/engines/director/castmember/movie.cpp
+++ b/engines/director/castmember/movie.cpp
@@ -30,6 +30,7 @@
#include "director/frame.h"
#include "director/score.h"
#include "director/window.h"
+#include "director/lingo/lingo.h"
namespace Director {
@@ -62,6 +63,9 @@ MovieCastMember::MovieCastMember(Cast *cast, uint16 castId, MovieCastMember &sou
MovieCastMember::~MovieCastMember() {
delete _linkedMovie;
+ delete _embeddedLingoState;
+ for (auto &it : _embeddedFrozenStates)
+ delete it;
}
Common::Array<Channel> *MovieCastMember::getSubChannels(Common::Rect &bbox, uint frame) {
@@ -179,6 +183,13 @@ void MovieCastMember::update() {
Movie *hostMovie = window->getCurrentMovie();
window->setCurrentMovie(_linkedMovie);
+ // Give the linked movie its own Lingo state for the step, so its
+ // go()/freeze does not block the host's scripts.
+ if (!_embeddedLingoState)
+ _embeddedLingoState = new LingoState;
+ window->swapLingoState(_embeddedLingoState, _embeddedFrozenStates);
+ g_lingo->switchStateFromWindow();
+
if (score->_playState != kPlayStarted)
score->startPlay();
@@ -190,7 +201,9 @@ void MovieCastMember::update() {
score->step();
+ window->swapLingoState(_embeddedLingoState, _embeddedFrozenStates);
window->setCurrentMovie(hostMovie);
+ g_lingo->switchStateFromWindow();
}
void MovieCastMember::routeInputEvent(LEvent event, Common::Point hostPos, const Common::Rect &bbox) {
diff --git a/engines/director/castmember/movie.h b/engines/director/castmember/movie.h
index ad1646e2394..4539ae3524d 100644
--- a/engines/director/castmember/movie.h
+++ b/engines/director/castmember/movie.h
@@ -27,6 +27,8 @@
namespace Director {
+struct LingoState;
+
class MovieCastMember : public FilmLoopCastMember {
public:
MovieCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version);
@@ -53,6 +55,11 @@ public:
bool _enableScripts;
Movie *_linkedMovie;
+
+ // The linked movie's own Lingo state, swapped onto the shared window
+ // while it steps to isolate its go()/freeze from the host.
+ LingoState *_embeddedLingoState = nullptr;
+ Common::Array<LingoState *> _embeddedFrozenStates;
};
} // End of namespace Director
diff --git a/engines/director/window.h b/engines/director/window.h
index b7e7389aade..8953fe1a463 100644
--- a/engines/director/window.h
+++ b/engines/director/window.h
@@ -185,6 +185,14 @@ public:
LingoState *getLastFrozenLingoState() { return _frozenLingoStates.empty() ? nullptr : _frozenLingoStates[_frozenLingoStates.size() - 1]; }
void moveLingoState(Window *target);
+ // Swap the window's Lingo state (current + frozen stack) with an external
+ // one, so an embedded movie runs isolated and its go()/freeze does not
+ // block the host's scripts.
+ void swapLingoState(LingoState *&state, Common::Array<LingoState *> &frozen) {
+ SWAP(_lingoState, state);
+ SWAP(_frozenLingoStates, frozen);
+ }
+
Common::String formatWindowInfo();
static void inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::ManagedSurface *blitTo = nullptr);
Commit: 8a2165044e501fef1765fc2497832cd1e791d12b
https://github.com/scummvm/scummvm/commit/8a2165044e501fef1765fc2497832cd1e791d12b
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-08-03T12:59:43+02:00
Commit Message:
DIRECTOR: Honor scriptsEnabled on movie cast members
scriptsEnabled (CASt bit 0x10) was decoded but never enforced, so a
movie cast member always ran its linked movie's Lingo. Gate it: set the
linked score's _haveInteractivity to _enableScripts, which Score::step()
and update() already respect. With scripts off the movie is a passive
flipbook (frames and channels update, no Lingo); update() skips the
Lingo-state swap and input draining, and the sprite is non-interactive so
clicks are not routed.
Changed paths:
engines/director/castmember/movie.cpp
engines/director/sprite.cpp
diff --git a/engines/director/castmember/movie.cpp b/engines/director/castmember/movie.cpp
index 9190cd10fe3..ddf0e9840f9 100644
--- a/engines/director/castmember/movie.cpp
+++ b/engines/director/castmember/movie.cpp
@@ -156,6 +156,10 @@ void MovieCastMember::load() {
_linkedMovie->loadArchive();
_score = _linkedMovie->getScore();
+ // scriptsEnabled off makes the linked movie a passive flipbook: its score
+ // advances and its channels refresh, but it runs no Lingo of its own.
+ _score->_haveInteractivity = _enableScripts;
+
// resolve the sprites against the linked movie's own cast
for (auto &frame : _score->_scoreCache) {
for (auto &sprite : frame->_sprites) {
@@ -183,12 +187,15 @@ void MovieCastMember::update() {
Movie *hostMovie = window->getCurrentMovie();
window->setCurrentMovie(_linkedMovie);
- // Give the linked movie its own Lingo state for the step, so its
- // go()/freeze does not block the host's scripts.
- if (!_embeddedLingoState)
- _embeddedLingoState = new LingoState;
- window->swapLingoState(_embeddedLingoState, _embeddedFrozenStates);
- g_lingo->switchStateFromWindow();
+ // With scripts enabled, give the linked movie its own Lingo state for the
+ // step so its go()/freeze does not block the host's scripts. With scripts
+ // disabled it runs no Lingo, so the swap and input routing do not apply.
+ if (_enableScripts) {
+ if (!_embeddedLingoState)
+ _embeddedLingoState = new LingoState;
+ window->swapLingoState(_embeddedLingoState, _embeddedFrozenStates);
+ g_lingo->switchStateFromWindow();
+ }
if (score->_playState != kPlayStarted)
score->startPlay();
@@ -196,14 +203,16 @@ void MovieCastMember::update() {
// A per-frame go() in exitFrame leaves hasJump/frozen state set, so
// step() never drains routed input. Drain here so the embedded movie's
// mouse handlers (e.g. mouseUp) fire.
- if (!_linkedMovie->_inputEventQueue.empty())
+ if (_enableScripts && !_linkedMovie->_inputEventQueue.empty())
g_lingo->processEvents(_linkedMovie->_inputEventQueue, true);
score->step();
- window->swapLingoState(_embeddedLingoState, _embeddedFrozenStates);
+ if (_enableScripts) {
+ window->swapLingoState(_embeddedLingoState, _embeddedFrozenStates);
+ g_lingo->switchStateFromWindow();
+ }
window->setCurrentMovie(hostMovie);
- g_lingo->switchStateFromWindow();
}
void MovieCastMember::routeInputEvent(LEvent event, Common::Point hostPos, const Common::Rect &bbox) {
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 13665f40e41..5aa96c6fa79 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -28,6 +28,7 @@
#include "director/sprite.h"
#include "director/castmember/castmember.h"
#include "director/castmember/digitalvideo.h"
+#include "director/castmember/movie.h"
#include "director/castmember/shape.h"
#include "director/castmember/text.h"
@@ -354,10 +355,10 @@ bool Sprite::respondsToMouse() {
if (_cast && _cast->_type == kCastButton)
return true;
- // A movie cast member is interactive: its embedded movie may have mouse
- // handlers, so clicks must be routed into it.
+ // A movie cast member is interactive only when its scripts are enabled:
+ // its embedded movie may then have mouse handlers to route clicks into.
if (_cast && _cast->_type == kCastMovie)
- return true;
+ return ((MovieCastMember *)_cast)->_enableScripts;
// TODO: Check if we need to check against individual events like below
if (g_director->getVersion() >= 600) {
Commit: 2f9287e379f7f9e5112dab8bdda655a899a909ee
https://github.com/scummvm/scummvm/commit/2f9287e379f7f9e5112dab8bdda655a899a909ee
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-08-03T12:59:43+02:00
Commit Message:
DIRECTOR: Simplify filmloop flag read and movie cast mouse routing
FilmLoopCastMember reads the flag word straight into _flags instead of
through a local variable. Movie::processInputEvent routes every mouse
event (not just up/down) to a movie cast member's linked movie.
Changed paths:
engines/director/castmember/filmloop.cpp
engines/director/lingo/lingo-events.cpp
diff --git a/engines/director/castmember/filmloop.cpp b/engines/director/castmember/filmloop.cpp
index 403735cda22..3b700f6a6fd 100644
--- a/engines/director/castmember/filmloop.cpp
+++ b/engines/director/castmember/filmloop.cpp
@@ -53,15 +53,14 @@ FilmLoopCastMember::FilmLoopCastMember(Cast *cast, uint16 castId, Common::Seekab
if (cast->_version >= kFileVer400) {
_initialRect = Movie::readRect(stream);
- uint32 flags = stream.readUint32BE();
- _flags = flags;
+ _flags = stream.readUint32BE();
uint16 unk1 = stream.readUint16BE();
- _looping = flags & 32 ? 0 : 1;
- _enableSound = flags & 8 ? 1 : 0;
- _crop = flags & 2 ? 0 : 1;
- _center = flags & 1 ? 1 : 0;
+ _looping = _flags & 32 ? 0 : 1;
+ _enableSound = _flags & 8 ? 1 : 0;
+ _crop = _flags & 2 ? 0 : 1;
+ _center = _flags & 1 ? 1 : 0;
- debugC(5, kDebugLoading, "FilmLoopCastMember::FilmLoopCastMember(): flags: %d, unk1: %d, looping: %d, enableSound: %d, crop: %d, center: %d", flags, unk1, _looping, _enableSound, _crop, _center);
+ debugC(5, kDebugLoading, "FilmLoopCastMember::FilmLoopCastMember(): flags: %d, unk1: %d, looping: %d, enableSound: %d, crop: %d, center: %d", _flags, unk1, _looping, _enableSound, _crop, _center);
}
}
diff --git a/engines/director/lingo/lingo-events.cpp b/engines/director/lingo/lingo-events.cpp
index cc462d2c6b6..28bd6531dc5 100644
--- a/engines/director/lingo/lingo-events.cpp
+++ b/engines/director/lingo/lingo-events.cpp
@@ -673,9 +673,9 @@ void Movie::queueInputEvent(LEvent event, int targetId, Common::Point pos) {
bool Movie::processInputEvent(LEvent event, int targetId, Common::Point pos) {
- // Route a click on a movie cast member into its linked movie so that
+ // Route a mouse event on a movie cast member into its linked movie so that
// movie's own scripts (mouseUp, the clickOn) handle it.
- if (event == kEventMouseUp || event == kEventMouseDown) {
+ if (event >= kEventMouseUp && event <= kEventMouseWithin) {
uint16 spriteId = _score->getMouseSpriteIDFromPos(pos);
if (spriteId) {
Channel *ch = _score->getChannelById(spriteId);
More information about the Scummvm-git-logs
mailing list