[Scummvm-git-logs] scummvm master -> 1679f1018984eadc65c569613b56c9d3bf25b1ba
djsrv
dservilla at gmail.com
Fri Jun 26 17:23:05 UTC 2020
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
1679f10189 DIRECTOR: LINGO: Implement event passing
Commit: 1679f1018984eadc65c569613b56c9d3bf25b1ba
https://github.com/scummvm/scummvm/commit/1679f1018984eadc65c569613b56c9d3bf25b1ba
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-26T13:22:15-04:00
Commit Message:
DIRECTOR: LINGO: Implement event passing
Changed paths:
engines/director/lingo/lingo-builtins.cpp
engines/director/lingo/lingo-events.cpp
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 5c7a6b5802..c320961647 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1095,7 +1095,7 @@ void LB::b_continue(int nargs) {
}
void LB::b_dontPassEvent(int nargs) {
- g_lingo->_dontPassEvent = true;
+ g_lingo->_passEvent = false;
warning("dontPassEvent raised");
}
@@ -1181,9 +1181,8 @@ void LB::b_halt(int nargs) {
}
void LB::b_pass(int nargs) {
- g_lingo->printSTUBWithArglist("b_pass", nargs);
-
- g_lingo->dropStack(nargs);
+ g_lingo->_passEvent = true;
+ warning("pass raised");
}
void LB::b_pause(int nargs) {
diff --git a/engines/director/lingo/lingo-events.cpp b/engines/director/lingo/lingo-events.cpp
index 187e7d95a8..59b089f3f7 100644
--- a/engines/director/lingo/lingo-events.cpp
+++ b/engines/director/lingo/lingo-events.cpp
@@ -107,33 +107,7 @@ void Lingo::setPrimaryEventHandler(LEvent event, const Common::String &code) {
addCode(code.c_str(), kArchMain, kGlobalScript, event);
}
-void Lingo::primaryEventHandler(LEvent event) {
- /* When an event occurs the message [...] is first sent to a
- * primary event handler: [... if exists it is executed] and the
- * event is passed on to other objects unless you explicitly stop
- * the message by including the dontPassEventCommand in the script
- * [D4 docs page 77]
- */
- /* N.B.: No primary event handlers for events other than
- * keyup, keydown, mouseup, mousedown, timeout
- * [see: www.columbia.edu/itc/visualarts/r4110/s2001/handouts
- * /03_03_Event_Hierarchy.pdf]
- */
- switch (event) {
- case kEventMouseDown:
- case kEventMouseUp:
- case kEventKeyUp:
- case kEventKeyDown:
- case kEventTimeout:
- debugC(3, kDebugLingoExec, "calling primary event handler (%s)", _eventHandlerTypes[event]);
- executeScript(kGlobalScript, event);
- break;
- default:
- break;
- }
-}
-
-void Lingo::registerSpriteEvent(LEvent event, int spriteId) {
+void Lingo::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.
@@ -156,14 +130,12 @@ void Lingo::registerSpriteEvent(LEvent event, int spriteId) {
// If sprite is immediate, its script is run on mouseDown, otherwise on mouseUp
if ((event == kEventMouseDown && sprite->_immediate)
|| (event == kEventMouseUp && !sprite->_immediate)) {
- _eventQueue.push(LingoEvent(kEventNone, kArchMain, kScoreScript, sprite->_scriptId, spriteId));
- return;
+ _eventQueue.push(LingoEvent(kEventNone, eventId, kArchMain, kScoreScript, sprite->_scriptId, false, spriteId));
}
} else {
ScriptContext *script = getScriptContext(kArchMain, kScoreScript, sprite->_scriptId);
if (script && script->_eventHandlers.contains(event)) {
- _eventQueue.push(LingoEvent(event, kArchMain, kScoreScript, sprite->_scriptId, spriteId));
- return;
+ _eventQueue.push(LingoEvent(event, eventId, kArchMain, kScoreScript, sprite->_scriptId, false, spriteId));
}
}
}
@@ -176,15 +148,11 @@ void Lingo::registerSpriteEvent(LEvent event, int spriteId) {
script = getScriptContext(archiveIndex, kCastScript, sprite->_castId);
}
if (script && script->_eventHandlers.contains(event)) {
- _eventQueue.push(LingoEvent(event, archiveIndex, kCastScript, sprite->_castId, spriteId));
- return;
+ _eventQueue.push(LingoEvent(event, eventId, archiveIndex, kCastScript, sprite->_castId, false, spriteId));
}
-
- // Delegate to the frame
- registerFrameEvent(event);
}
-void Lingo::registerFrameEvent(LEvent event) {
+void Lingo::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
@@ -202,15 +170,11 @@ void Lingo::registerFrameEvent(LEvent event) {
int scriptId = score->_frames[score->getCurrentFrame()]->_actionId;
if (scriptId) {
- _eventQueue.push(LingoEvent(event, kArchMain, kScoreScript, scriptId));
- return;
+ _eventQueue.push(LingoEvent(event, eventId, kArchMain, kScoreScript, scriptId, false));
}
-
- // Delegate to the movie
- registerMovieEvent(event);
}
-void Lingo::registerMovieEvent(LEvent event) {
+void Lingo::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]
@@ -223,59 +187,89 @@ void Lingo::registerMovieEvent(LEvent event) {
for (ScriptContextHash::iterator it = _archives[kArchMain].scriptContexts[kMovieScript].begin();
it != _archives[kArchMain].scriptContexts[kMovieScript].end(); ++it) {
if (it->_value->_eventHandlers.contains(event)) {
- _eventQueue.push(LingoEvent(event, kArchMain, kMovieScript, it->_key));
+ _eventQueue.push(LingoEvent(event, eventId, kArchMain, kMovieScript, it->_key, false));
return;
}
}
for (ScriptContextHash::iterator it = _archives[kArchShared].scriptContexts[kMovieScript].begin();
it != _archives[kArchShared].scriptContexts[kMovieScript].end(); ++it) {
if (it->_value->_eventHandlers.contains(event)) {
- _eventQueue.push(LingoEvent(event, kArchShared, kMovieScript, it->_key));
+ _eventQueue.push(LingoEvent(event, eventId, kArchShared, kMovieScript, it->_key, false));
return;
}
}
-
- debugC(9, kDebugEvents, "Lingo::registerEvent(%s): no handler", _eventHandlerTypes[event]);
}
void Lingo::registerEvent(LEvent event, int spriteId) {
- primaryEventHandler(event);
+ int eventId = _nextEventId++;
+ if (_nextEventId < 0)
+ _nextEventId = 0;
- if (_dontPassEvent) {
- _dontPassEvent = false;
- return;
+ int oldQueueSize = _eventQueue.size();
+
+ /* When an event occurs the message [...] is first sent to a
+ * primary event handler: [... if exists it is executed] and the
+ * event is passed on to other objects unless you explicitly stop
+ * the message by including the dontPassEvent command in the script
+ * [D4 docs page 77]
+ */
+ /* N.B.: No primary event handlers for events other than
+ * keyup, keydown, mouseup, mousedown, timeout
+ * [see: www.columbia.edu/itc/visualarts/r4110/s2001/handouts
+ * /03_03_Event_Hierarchy.pdf]
+ */
+ switch (event) {
+ case kEventMouseDown:
+ case kEventMouseUp:
+ case kEventKeyUp:
+ case kEventKeyDown:
+ case kEventTimeout:
+ if (getScriptContext(kArchMain, kGlobalScript, event)) {
+ _eventQueue.push(LingoEvent(kEventNone, eventId, kArchMain, kGlobalScript, event, true));
+ }
+ break;
+ default:
+ break;
}
+ /* Now queue any objects that responds to this event, in order of precedence.
+ * (Sprite -> Cast Member -> Frame -> Movie)
+ * Once one of these objects handles the event, any event handlers queued
+ * for the same event will be ignored unless the pass command was called.
+ */
switch (event) {
- case kEventKeyUp:
- case kEventKeyDown:
- case kEventMouseUp:
- case kEventMouseDown:
- case kEventBeginSprite:
- if (spriteId) {
- registerSpriteEvent(event, spriteId);
- break;
- }
- // fall through
+ case kEventKeyUp:
+ case kEventKeyDown:
+ case kEventMouseUp:
+ case kEventMouseDown:
+ case kEventBeginSprite:
+ if (spriteId) {
+ queueSpriteEvent(event, eventId, spriteId);
+ }
+ // fall through
+
+ case kEventIdle:
+ case kEventEnterFrame:
+ case kEventExitFrame:
+ case kEventNone:
+ queueFrameEvent(event, eventId);
+ // fall through
+
+ case kEventStart:
+ case kEventStartUp:
+ case kEventStartMovie:
+ case kEventStopMovie:
+ case kEventTimeout:
+ case kEventPrepareMovie:
+ queueMovieEvent(event, eventId);
+ break;
- case kEventIdle:
- case kEventEnterFrame:
- case kEventExitFrame:
- case kEventNone:
- registerFrameEvent(event);
- break;
-
- case kEventStart:
- case kEventStartUp:
- case kEventStartMovie:
- case kEventStopMovie:
- case kEventTimeout:
- case kEventPrepareMovie:
- registerMovieEvent(event);
- break;
+ default:
+ warning("registerEvent: Unhandled event %s", _eventHandlerTypes[event]);
+ }
- default:
- warning("registerEvent: Unhandled event %s", _eventHandlerTypes[event]);
+ if (oldQueueSize == _eventQueue.size()) {
+ debugC(9, kDebugEvents, "Lingo::registerEvent(%s): no event handler", _eventHandlerTypes[event]);
}
}
@@ -285,13 +279,20 @@ void Lingo::processEvent(LEvent event, int spriteId) {
}
void Lingo::processEvents() {
+ int lastEventId = -1;
+
while (!_eventQueue.empty()) {
LingoEvent el = _eventQueue.pop();
if (_vm->getCurrentScore()->_stopPlay && el.event != kEventStopMovie)
continue;
- processEvent(el.event, el.archiveIndex, el.st, el.scriptId, el.channelId);
+ if (lastEventId == el.eventId && !_passEvent)
+ continue;
+
+ _passEvent = el.passByDefault;
+ processEvent(el.event, el.archiveIndex, el.scriptType, el.scriptId, el.channelId);
+ lastEventId = el.eventId;
}
}
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 7e41fc81df..dcb0752422 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -155,10 +155,11 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
_localvars = NULL;
- _dontPassEvent = false;
-
_archiveIndex = kArchMain;
+ // events
+ _nextEventId = 0;
+ _passEvent = false;
_perFrameHook = Datum();
initEventHandlerTypes();
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index fc69d149bb..89231416ee 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -332,16 +332,20 @@ struct CFrame { /* proc/func call stack frame */
struct LingoEvent {
LEvent event;
+ int eventId;
int archiveIndex;
- ScriptType st;
+ ScriptType scriptType;
int scriptId;
+ bool passByDefault;
int channelId;
- LingoEvent (LEvent e, int ai, ScriptType s, int si, int ci = -1) {
+ LingoEvent (LEvent e, int ei, int ai, ScriptType st, int si, bool pass, int ci = -1) {
event = e;
+ eventId = ei;
archiveIndex = ai;
- st = s;
+ scriptType = st;
scriptId = si;
+ passByDefault = pass;
channelId = ci;
}
};
@@ -403,12 +407,12 @@ private:
private:
void initEventHandlerTypes();
void setPrimaryEventHandler(LEvent event, const Common::String &code);
- void primaryEventHandler(LEvent event);
- void registerSpriteEvent(LEvent event, int spriteId);
- void registerFrameEvent(LEvent event);
- void registerMovieEvent(LEvent event);
+ void queueSpriteEvent(LEvent event, int eventId, int spriteId);
+ void queueFrameEvent(LEvent event, int eventId);
+ void queueMovieEvent(LEvent event, int eventId);
void processEvent(LEvent event, int archiveIndex, ScriptType st, int entityId, int channelId = -1);
+ int _nextEventId;
Common::Queue<LingoEvent> _eventQueue;
public:
@@ -541,7 +545,6 @@ public:
Common::HashMap<Common::String, VarType, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> *_methodVarsStash;
public:
- uint16 _currentEntityId;
int _currentChannelId;
ScriptContext *_currentScriptContext;
ScriptData *_currentScript;
@@ -606,8 +609,8 @@ public:
int _floatPrecision;
- bool _dontPassEvent;
-
+ // events
+ bool _passEvent;
Datum _perFrameHook;
public:
More information about the Scummvm-git-logs
mailing list