DIRECTOR: Move event handling to movie

This commit is contained in:
djsrv 2020-07-23 18:49:21 -04:00
parent a86b95a4f3
commit f23ef93766
12 changed files with 221 additions and 185 deletions

View File

@ -102,14 +102,9 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam
SearchMan.addSubDirectoryMatching(gameDataDir, "win_data", 0, 2); // L-ZONE
_colorDepth = 8; // 256-color
_key = 0;
_keyCode = 0;
_keyFlags = 0;
_machineType = 9; // Macintosh IIci
_playbackPaused = false;
_skipFrameAdvance = false;
_currentDraggedChannel = nullptr;
}
DirectorEngine::~DirectorEngine() {
@ -130,6 +125,10 @@ Common::String DirectorEngine::getCurrentPath() const { return _currentStage->ge
static void buildbotErrorHandler(const char *msg) { }
void DirectorEngine::setCurrentMovie(Movie *movie) {
_currentStage = movie->getStage();
}
Common::Error DirectorEngine::run() {
debug("Starting v%d Director game", getVersion());
@ -196,6 +195,8 @@ Common::Error DirectorEngine::run() {
bool loop = true;
while (loop) {
processEvents();
_currentStage = _mainStage;
loop = _currentStage->step();

View File

@ -172,6 +172,7 @@ public:
Stage *getMainStage() const { return _mainStage; }
Stage *getCurrentStage() const { return _currentStage; }
Movie *getCurrentMovie() const;
void setCurrentMovie(Movie *movie);
Common::String getCurrentPath() const;
// graphics.cpp
@ -192,7 +193,7 @@ public:
Archive *createArchive();
// events.cpp
void processEvents(bool bufferLingoEvents = false);
void processEvents();
uint32 getMacTicks();
void waitForClick();
@ -203,9 +204,6 @@ public:
public:
int _colorDepth;
unsigned char _key;
int _keyCode;
byte _keyFlags;
Common::HashMap<int, int> _macKeyCodes;
int _machineType;
bool _playbackPaused;
@ -233,9 +231,6 @@ private:
Graphics::MacPatterns _director3QuickDrawPatterns;
Common::HashMap<int, PaletteV4 *> _director4Palettes;
Channel *_currentDraggedChannel;
Common::Point _draggingSpritePos;
};
extern DirectorEngine *g_director;

View File

@ -56,21 +56,15 @@ bool processQuitEvent(bool click) {
uint32 DirectorEngine::getMacTicks() { return g_system->getMillis() * 60 / 1000.; }
void DirectorEngine::processEvents(bool bufferLingoEvents) {
void DirectorEngine::processEvents() {
debugC(3, kDebugEvents, "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
debugC(3, kDebugEvents, "@@@@ Processing events");
debugC(3, kDebugEvents, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
Common::Event event;
uint endTime = g_system->getMillis() + 10;
Movie *m = getCurrentMovie();
Score *sc = m->getScore();
if (sc->getCurrentFrame() >= sc->_frames.size()) {
warning("processEvents: request to access frame %d of %d", sc->getCurrentFrame(), sc->_frames.size() - 1);
return;
}
uint16 spriteId = 0;
Common::Point pos;
while (g_system->getMillis() < endTime) {
while (g_system->getEventManager()->pollEvent(event)) {
if (_wm->processEvent(event))
@ -78,118 +72,138 @@ void DirectorEngine::processEvents(bool bufferLingoEvents) {
switch (event.type) {
case Common::EVENT_QUIT:
sc->_playState = kPlayStopped;
_mainStage->getCurrentMovie()->getScore()->_playState = kPlayStopped;
break;
case Common::EVENT_MOUSEMOVE:
pos = _currentStage->getMousePos();
m->_lastEventTime = g_director->getMacTicks();
m->_lastRollTime = m->_lastEventTime;
sc->renderCursor(sc->getSpriteIDFromPos(pos));
if (_currentDraggedChannel) {
if (_currentDraggedChannel->_sprite->_moveable) {
pos = getCurrentStage()->getMousePos();
_currentDraggedChannel->addDelta(pos - _draggingSpritePos);
_draggingSpritePos = pos;
} else {
_currentDraggedChannel = nullptr;
}
}
break;
case Common::EVENT_LBUTTONDOWN:
pos = _currentStage->getMousePos();
// D3 doesn't have both mouse up and down.
// But we still want to know if the mouse is down for press effects.
spriteId = sc->getSpriteIDFromPos(pos, true);
m->_currentMouseDownSpriteId = spriteId;
m->_currentClickOnSpriteId = spriteId;
if (spriteId > 0 && sc->_channels[spriteId]->_sprite->shouldHilite())
g_director->getCurrentStage()->invertChannel(sc->_channels[spriteId]);
m->_lastEventTime = g_director->getMacTicks();
m->_lastClickTime = m->_lastEventTime;
m->_lastClickPos = pos;
debugC(3, kDebugEvents, "event: Button Down @(%d, %d), sprite id: %d", pos.x, pos.y, spriteId);
_lingo->registerEvent(kEventMouseDown, spriteId);
if (sc->_channels[spriteId]->_sprite->_moveable) {
_draggingSpritePos = _currentStage->getMousePos();
_currentDraggedChannel = sc->_channels[spriteId];
}
break;
case Common::EVENT_LBUTTONUP:
pos = _currentStage->getMousePos();
spriteId = sc->getSpriteIDFromPos(pos, true);
if (!sc->getChannelById(m->_currentMouseDownSpriteId)->getBbox().contains(pos))
m->_currentMouseDownSpriteId = 0;
if (spriteId > 0 && sc->_channels[spriteId]->_sprite->shouldHilite())
g_director->getCurrentStage()->invertChannel(sc->_channels[spriteId]);
if (!(g_director->_wm->_mode & Graphics::kWMModeButtonDialogStyle))
m->_currentMouseDownSpriteId = spriteId;
debugC(3, kDebugEvents, "event: Button Up @(%d, %d), sprite id: %d", pos.x, pos.y, spriteId);
_currentDraggedChannel = nullptr;
{
CastMember *cast = g_director->getCurrentMovie()->getCastMember(sc->getSpriteById(spriteId)->_castId);
if (cast && cast->_type == kCastButton)
cast->_hilite = !cast->_hilite;
}
_lingo->registerEvent(kEventMouseUp, spriteId);
sc->renderCursor(sc->getSpriteIDFromPos(pos));
m->_currentMouseDownSpriteId = 0;
break;
case Common::EVENT_KEYDOWN:
_keyCode = _macKeyCodes.contains(event.kbd.keycode) ? _macKeyCodes[event.kbd.keycode] : 0;
_key = (unsigned char)(event.kbd.ascii & 0xff);
_keyFlags = event.kbd.flags;
debugC(1, kDebugEvents, "processEvents(): keycode: %d", _keyCode);
m->_lastEventTime = g_director->getMacTicks();
m->_lastKeyTime = m->_lastEventTime;
_lingo->registerEvent(kEventKeyDown);
break;
case Common::EVENT_KEYUP:
_keyFlags = event.kbd.flags;
break;
default:
break;
}
}
if (!bufferLingoEvents)
_lingo->processEvents();
g_system->delayMillis(10);
if (getVersion() >= 3 && sc->getCurrentFrame() > 0 && sc->_playState != kPlayStopped && _lingo->getEventCount() == 0)
_lingo->registerEvent(kEventIdle);
if (!bufferLingoEvents)
_lingo->processEvents();
}
}
bool Stage::processEvent(Common::Event &event) {
if (MacWindow::processEvent(event))
return true;
if (_currentMovie && _currentMovie->processEvent(event))
return true;
return false;
}
bool Movie::processEvent(Common::Event &event) {
_vm->setCurrentMovie(this);
Score *sc = getScore();
if (sc->getCurrentFrame() >= sc->_frames.size()) {
warning("processEvents: request to access frame %d of %d", sc->getCurrentFrame(), sc->_frames.size() - 1);
return false;
}
uint16 spriteId = 0;
Common::Point pos;
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
pos = _stage->getMousePos();
_lastEventTime = g_director->getMacTicks();
_lastRollTime = _lastEventTime;
sc->renderCursor(sc->getSpriteIDFromPos(pos));
if (_currentDraggedChannel) {
if (_currentDraggedChannel->_sprite->_moveable) {
pos = _stage->getMousePos();
_currentDraggedChannel->addDelta(pos - _draggingSpritePos);
_draggingSpritePos = pos;
} else {
_currentDraggedChannel = nullptr;
}
}
return true;
case Common::EVENT_LBUTTONDOWN:
pos = _stage->getMousePos();
// D3 doesn't have both mouse up and down.
// But we still want to know if the mouse is down for press effects.
spriteId = sc->getSpriteIDFromPos(pos, true);
_currentMouseDownSpriteId = spriteId;
_currentClickOnSpriteId = spriteId;
if (spriteId > 0 && sc->_channels[spriteId]->_sprite->shouldHilite())
g_director->getCurrentStage()->invertChannel(sc->_channels[spriteId]);
_lastEventTime = g_director->getMacTicks();
_lastClickTime = _lastEventTime;
_lastClickPos = pos;
debugC(3, kDebugEvents, "event: Button Down @(%d, %d), movie '%s', sprite id: %d", pos.x, pos.y, _macName.c_str(), spriteId);
registerEvent(kEventMouseDown, spriteId);
if (sc->_channels[spriteId]->_sprite->_moveable) {
_draggingSpritePos = _stage->getMousePos();
_currentDraggedChannel = sc->_channels[spriteId];
}
return true;
case Common::EVENT_LBUTTONUP:
pos = _stage->getMousePos();
spriteId = sc->getSpriteIDFromPos(pos, true);
if (!sc->getChannelById(_currentMouseDownSpriteId)->getBbox().contains(pos))
_currentMouseDownSpriteId = 0;
if (spriteId > 0 && sc->_channels[spriteId]->_sprite->shouldHilite())
g_director->getCurrentStage()->invertChannel(sc->_channels[spriteId]);
if (!(g_director->_wm->_mode & Graphics::kWMModeButtonDialogStyle))
_currentMouseDownSpriteId = spriteId;
debugC(3, kDebugEvents, "event: Button Up @(%d, %d), movie '%s', sprite id: %d", pos.x, pos.y, _macName.c_str(), spriteId);
_currentDraggedChannel = nullptr;
{
CastMember *cast = g_director->getCurrentMovie()->getCastMember(sc->getSpriteById(spriteId)->_castId);
if (cast && cast->_type == kCastButton)
cast->_hilite = !cast->_hilite;
}
registerEvent(kEventMouseUp, spriteId);
sc->renderCursor(sc->getSpriteIDFromPos(pos));
_currentMouseDownSpriteId = 0;
return true;
case Common::EVENT_KEYDOWN:
_keyCode = _vm->_macKeyCodes.contains(event.kbd.keycode) ? _vm->_macKeyCodes[event.kbd.keycode] : 0;
_key = (unsigned char)(event.kbd.ascii & 0xff);
_keyFlags = event.kbd.flags;
debugC(1, kDebugEvents, "processEvents(): movie '%s', keycode: %d", _macName.c_str(), _keyCode);
_lastEventTime = g_director->getMacTicks();
_lastKeyTime = _lastEventTime;
registerEvent(kEventKeyDown);
break;
case Common::EVENT_KEYUP:
_keyFlags = event.kbd.flags;
return true;
default:
break;
}
return false;
}
void DirectorEngine::waitForClick() {
setCursor(kCursorMouseUp);

View File

@ -101,18 +101,18 @@ ScriptType Lingo::event2script(LEvent ev) {
return kNoneScript;
}
int Lingo::getEventCount() {
int Movie::getEventCount() {
return _eventQueue.size();
}
void Lingo::setPrimaryEventHandler(LEvent event, const Common::String &code) {
debugC(3, kDebugLingoExec, "setting primary event handler (%s)", _eventHandlerTypes[event]);
LingoArchive *mainArchive = g_director->getCurrentMovie()->getMainLingoArch();
void Movie::setPrimaryEventHandler(LEvent event, const Common::String &code) {
debugC(3, kDebugLingoExec, "setting primary event handler (%s)", _lingo->_eventHandlerTypes[event]);
LingoArchive *mainArchive = getMainLingoArch();
mainArchive->primaryEventHandlers[event] = code;
mainArchive->addCode(code.c_str(), kGlobalScript, event);
}
void Lingo::queueSpriteEvent(LEvent event, int eventId, int spriteId) {
void Movie::queueSpriteEvent(LEvent event, int eventId, int spriteId) {
/* When the mouseDown or mouseUp occurs over a sprite, the message
* goes first to the sprite script, then to the script of the cast
* member, to the frame script and finally to the movie scripts.
@ -151,7 +151,7 @@ void Lingo::queueSpriteEvent(LEvent event, int eventId, int spriteId) {
}
}
void Lingo::queueFrameEvent(LEvent event, int eventId) {
void Movie::queueFrameEvent(LEvent event, int eventId) {
/* [in D4] the enterFrame, exitFrame, idle and timeout messages
* are sent to a frame script and then a movie script. If the
* current frame has no frame script when the event occurs, the
@ -182,7 +182,7 @@ void Lingo::queueFrameEvent(LEvent event, int eventId) {
}
}
void Lingo::queueMovieEvent(LEvent event, int eventId) {
void Movie::queueMovieEvent(LEvent event, int eventId) {
/* If more than one movie script handles the same message, Lingo
* searches the movie scripts according to their order in the cast
* window [p.81 of D4 docs]
@ -210,7 +210,7 @@ void Lingo::queueMovieEvent(LEvent event, int eventId) {
}
}
void Lingo::registerEvent(LEvent event, int spriteId) {
void Movie::registerEvent(LEvent event, int spriteId) {
int eventId = _nextEventId++;
if (_nextEventId < 0)
_nextEventId = 0;
@ -265,7 +265,7 @@ void Lingo::registerEvent(LEvent event, int spriteId) {
break;
default:
warning("registerEvent: Unhandled event %s", _eventHandlerTypes[event]);
warning("registerEvent: Unhandled event %s", _lingo->_eventHandlerTypes[event]);
}
} else {
/* In D4+, queue any objects that responds to this event, in order of precedence.
@ -299,27 +299,33 @@ void Lingo::registerEvent(LEvent event, int spriteId) {
break;
default:
warning("registerEvent: Unhandled event %s", _eventHandlerTypes[event]);
warning("registerEvent: Unhandled event %s", _lingo->_eventHandlerTypes[event]);
}
}
if (oldQueueSize == _eventQueue.size()) {
debugC(9, kDebugEvents, "Lingo::registerEvent(%s): no event handler", _eventHandlerTypes[event]);
debugC(9, kDebugEvents, "Lingo::registerEvent(%s): no event handler", _lingo->_eventHandlerTypes[event]);
}
}
void Lingo::processEvent(LEvent event, int spriteId) {
void Movie::processEvent(LEvent event, int spriteId) {
registerEvent(event, spriteId);
processEvents();
_vm->setCurrentMovie(this);
_lingo->processEvents();
}
void Lingo::processEvents() {
int lastEventId = -1;
Movie *movie = _vm->getCurrentMovie();
Score *sc = movie->getScore();
while (!_eventQueue.empty()) {
LingoEvent el = _eventQueue.pop();
if (_vm->getVersion() >= 3 && sc->getCurrentFrame() > 0 && sc->_playState != kPlayStopped && movie->_eventQueue.empty())
movie->registerEvent(kEventIdle);
if (_vm->getCurrentMovie()->getScore()->_playState == kPlayStopped && el.event != kEventStopMovie)
while (!movie->_eventQueue.empty()) {
LingoEvent el = movie->_eventQueue.pop();
if (sc->_playState == kPlayStopped && el.event != kEventStopMovie)
continue;
if (lastEventId == el.eventId && !_passEvent)

View File

@ -398,11 +398,11 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheCommandDown:
d.type = INT;
d.u.i = (g_director->_keyFlags & Common::KBD_META) ? 1 : 0;
d.u.i = (_vm->getCurrentMovie()->_keyFlags & Common::KBD_META) ? 1 : 0;
break;
case kTheControlDown:
d.type = INT;
d.u.i = (g_director->_keyFlags & Common::KBD_CTRL) ? 1 : 0;
d.u.i = (_vm->getCurrentMovie()->_keyFlags & Common::KBD_CTRL) ? 1 : 0;
break;
case kTheDate:
d = getTheDate(field);
@ -454,11 +454,11 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheKey:
d.type = STRING;
d.u.s = new Common::String(_vm->_key);
d.u.s = new Common::String(_vm->getCurrentMovie()->_key);
break;
case kTheKeyCode:
d.type = INT;
d.u.i = _vm->_keyCode;
d.u.i = _vm->getCurrentMovie()->_keyCode;
break;
case kTheKeyDownScript:
d.type = STRING;
@ -636,7 +636,7 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheOptionDown:
d.type = INT;
d.u.i = (g_director->_keyFlags & Common::KBD_ALT) ? 1 : 0;
d.u.i = (_vm->getCurrentMovie()->_keyFlags & Common::KBD_ALT) ? 1 : 0;
break;
case kThePauseState:
getTheEntitySTUB(kThePauseState);
@ -692,7 +692,7 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheShiftDown:
d.type = INT;
d.u.i = (g_director->_keyFlags & Common::KBD_SHIFT) ? 1 : 0;
d.u.i = (_vm->getCurrentMovie()->_keyFlags & Common::KBD_SHIFT) ? 1 : 0;
break;
case kTheSoundEnabled:
getTheEntitySTUB(kTheSoundEnabled);
@ -883,10 +883,10 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
setTheEntitySTUB(kTheItemDelimiter);
break;
case kTheKeyDownScript:
setPrimaryEventHandler(kEventKeyDown, d.asString());
_vm->getCurrentMovie()->setPrimaryEventHandler(kEventKeyDown, d.asString());
break;
case kTheKeyUpScript:
setPrimaryEventHandler(kEventKeyUp, d.asString());
_vm->getCurrentMovie()->setPrimaryEventHandler(kEventKeyUp, d.asString());
break;
case kTheMenu:
setTheEntitySTUB(kTheMenu);
@ -895,10 +895,10 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
setTheEntitySTUB(kTheMenuItem);
break;
case kTheMouseDownScript:
setPrimaryEventHandler(kEventMouseDown, d.asString());
_vm->getCurrentMovie()->setPrimaryEventHandler(kEventMouseDown, d.asString());
break;
case kTheMouseUpScript:
setPrimaryEventHandler(kEventMouseUp, d.asString());
_vm->getCurrentMovie()->setPrimaryEventHandler(kEventMouseUp, d.asString());
break;
case kThePerFrameHook:
_perFrameHook = d;
@ -982,7 +982,7 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
setTheEntitySTUB(kTheTimeoutPlay);
break;
case kTheTimeoutScript:
setPrimaryEventHandler(kEventTimeout, d.asString());
_vm->getCurrentMovie()->setPrimaryEventHandler(kEventTimeout, d.asString());
break;
case kTheTimer:
setTheEntitySTUB(kTheTimer);

View File

@ -169,7 +169,6 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
_localvars = NULL;
// events
_nextEventId = 0;
_passEvent = false;
_perFrameHook = Datum();

View File

@ -268,23 +268,13 @@ private:
// lingo-events.cpp
private:
void initEventHandlerTypes();
void setPrimaryEventHandler(LEvent event, const Common::String &code);
void queueSpriteEvent(LEvent event, int eventId, int spriteId);
void queueFrameEvent(LEvent event, int eventId);
void queueMovieEvent(LEvent event, int eventId);
void processEvent(LEvent event, ScriptType st, int entityId, int channelId = -1);
int _nextEventId;
Common::Queue<LingoEvent> _eventQueue;
public:
ScriptType event2script(LEvent ev);
Symbol getHandler(const Common::String &name);
int getEventCount();
void processEvent(LEvent event, int spriteId = 0);
void processEvents();
void registerEvent(LEvent event, int spriteId = 0);
public:
void execute(uint pc);

View File

@ -52,6 +52,13 @@ Movie::Movie(Stage *stage) {
_lastClickTime = _lastEventTime;
_lastRollTime = _lastEventTime;
_lastTimerReset = _lastEventTime;
_nextEventId = 0;
_key = 0;
_keyCode = 0;
_keyFlags = 0;
_currentDraggedChannel = nullptr;
_allowOutdatedLingo = false;

View File

@ -24,6 +24,7 @@
#define DIRECTOR_MOVIE_H
namespace Common {
struct Event;
class ReadStreamEndian;
class SeekableSubReadStreamEndian;
}
@ -37,6 +38,7 @@ class CastMember;
class DirectorEngine;
class Lingo;
struct LingoArchive;
struct LingoEvent;
class ScriptContext;
class Stage;
struct Symbol;
@ -110,9 +112,22 @@ public:
ScriptContext *getScriptContext(ScriptType type, uint16 id);
Symbol getHandler(const Common::String &name);
// events.cpp
bool processEvent(Common::Event &event);
// lingo/lingo-events.cpp
void setPrimaryEventHandler(LEvent event, const Common::String &code);
int getEventCount();
void processEvent(LEvent event, int spriteId = 0);
void registerEvent(LEvent event, int spriteId = 0);
private:
void loadFileInfo(Common::SeekableSubReadStreamEndian &stream);
void queueSpriteEvent(LEvent event, int eventId, int spriteId);
void queueFrameEvent(LEvent event, int eventId);
void queueMovieEvent(LEvent event, int eventId);
public:
Archive *_movieArchive;
Common::Rect _movieRect;
@ -129,6 +144,13 @@ public:
Cast *_sharedCast;
bool _allowOutdatedLingo;
int _nextEventId;
Common::Queue<LingoEvent> _eventQueue;
unsigned char _key;
int _keyCode;
byte _keyFlags;
private:
Stage *_stage;
DirectorEngine *_vm;
@ -143,6 +165,9 @@ private:
Common::String _changedBy;
Common::String _script;
Common::String _directory;
Channel *_currentDraggedChannel;
Common::Point _draggingSpritePos;
};
} // End of namespace Director

View File

@ -152,7 +152,7 @@ void Stage::loadEXE(const Common::String movie) {
_currentMovie = new Movie(this);
_currentMovie->getMainLingoArch()->addCode(script, kMovieScript, 0);
g_lingo->processEvent(kEventStartUp);
_currentMovie->processEvent(kEventStartUp);
delete _currentMovie;
_currentMovie = nullptr;

View File

@ -232,24 +232,14 @@ void Score::startPlay() {
_channels.push_back(new Channel(_frames[1]->_sprites[i]));
if (_vm->getVersion() >= 3)
_lingo->processEvent(kEventStartMovie);
_movie->processEvent(kEventStartMovie);
}
void Score::step() {
if (_currentFrame >= _frames.size()) {
if (debugChannelSet(-1, kDebugNoLoop)) {
_playState = kPlayStopped;
return;
}
_currentFrame = 0;
}
_lingo->processEvents();
update();
if (_currentFrame < _frames.size())
_vm->processEvents();
if (debugChannelSet(-1, kDebugFewFramesOnly) || debugChannelSet(-1, kDebugScreenshot)) {
warning("Score::startLoop(): ran frame %0d", _framesRan);
_framesRan++;
@ -267,7 +257,7 @@ void Score::step() {
void Score::stopPlay() {
if (_vm->getVersion() >= 3)
_lingo->processEvent(kEventStopMovie);
_movie->processEvent(kEventStopMovie);
_lingo->executePerFrameHook(-1, 0);
}
@ -300,11 +290,11 @@ void Score::update() {
if (_vm->_skipFrameAdvance) {
uint16 nextFrameCache = _nextFrame;
if (_vm->getVersion() >= 4)
_lingo->processEvent(kEventExitFrame);
_movie->processEvent(kEventExitFrame);
_nextFrame = nextFrameCache;
} else {
if (_vm->getVersion() >= 4)
_lingo->processEvent(kEventExitFrame);
_movie->processEvent(kEventExitFrame);
}
// If there is a transition, the perFrameHook is called
@ -325,8 +315,14 @@ void Score::update() {
_vm->_skipFrameAdvance = false;
if (_currentFrame >= _frames.size())
return;
if (_currentFrame >= _frames.size()) {
if (debugChannelSet(-1, kDebugNoLoop)) {
_playState = kPlayStopped;
return;
}
_currentFrame = 0;
}
Common::SortedArray<Label *>::iterator i;
if (_labels != NULL) {
@ -342,9 +338,9 @@ void Score::update() {
_lingo->executeImmediateScripts(_frames[_currentFrame]);
if (_vm->getVersion() >= 6) {
// _lingo->processEvent(kEventBeginSprite);
// _movie->processEvent(kEventBeginSprite);
// TODO Director 6 step: send beginSprite event to any sprites whose span begin in the upcoming frame
// _lingo->processEvent(kEventPrepareFrame);
// _movie->processEvent(kEventPrepareFrame);
// TODO: Director 6 step: send prepareFrame event to all sprites and the script channel in upcoming frame
}
@ -354,12 +350,12 @@ void Score::update() {
// Enter and exit from previous frame
if (!_vm->_playbackPaused) {
_lingo->processEvent(kEventEnterFrame); // Triggers the frame script in D2-3, explicit enterFrame handlers in D4+
_movie->processEvent(kEventEnterFrame); // Triggers the frame script in D2-3, explicit enterFrame handlers in D4+
if (_vm->getVersion() == 3) {
// Movie version of enterFrame, for D3 only. The Lingo Dictionary claims
// "This handler executes before anything else when the playback head moves."
// but this is incorrect. The frame script is executed first.
_lingo->processEvent(kEventStepMovie);
_movie->processEvent(kEventStepMovie);
}
}
// TODO Director 6 - another order

View File

@ -121,6 +121,9 @@ class Stage : public Graphics::MacWindow, public Object<Stage> {
bool step();
// events.cpp
virtual bool processEvent(Common::Event &event);
// tests.cpp
Common::HashMap<Common::String, Movie *> *scanMovies(const Common::String &folder);
void testFontScaling();