[Scummvm-git-logs] scummvm master -> 612104336fd7844b39049cc0a48dfa77895cd6da

djsrv dservilla at gmail.com
Thu Jun 18 00:39:32 UTC 2020


This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
b248a78732 DIRECTOR: LINGO: Merge Sprite/Frame/Score Script
8db0405d31 DIRECTOR: Load D4 cast scripts
af62c56624 DIRECTOR: Consider sprites with CastScripts active
612104336f DIRECTOR: LINGO: Rework event handling


Commit: b248a7873248fc2c54adde0669e1f072dbfa07e0
    https://github.com/scummvm/scummvm/commit/b248a7873248fc2c54adde0669e1f072dbfa07e0
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-17T20:38:49-04:00

Commit Message:
DIRECTOR: LINGO: Merge Sprite/Frame/Score Script

Changed paths:
    engines/director/lingo/lingo-events.cpp
    engines/director/lingo/lingo-patcher.cpp
    engines/director/lingo/lingo-the.cpp
    engines/director/lingo/lingo.cpp
    engines/director/score-loading.cpp
    engines/director/types.h
    engines/director/util.cpp


diff --git a/engines/director/lingo/lingo-events.cpp b/engines/director/lingo/lingo-events.cpp
index a2a9a3cbcd..8ab93ca4fd 100644
--- a/engines/director/lingo/lingo-events.cpp
+++ b/engines/director/lingo/lingo-events.cpp
@@ -88,7 +88,7 @@ ScriptType Lingo::event2script(LEvent ev) {
 		//case kEventStartMovie: // We are precompiling it now
 		//	return kMovieScript;
 		case kEventEnterFrame:
-			return kFrameScript;
+			return kScoreScript;
 		default:
 			return kNoneScript;
 		}
@@ -161,10 +161,10 @@ void Lingo::registerInputEvent(LEvent event) {
 	if (_vm->getVersion() > 3) {
 		if (true) {
 			// TODO: Check whether occurring over a sprite
-			_eventQueue.push(LingoEvent(event, kSpriteScript, sprite->_scriptId));
+			_eventQueue.push(LingoEvent(event, kScoreScript, sprite->_scriptId));
 		}
 		_eventQueue.push(LingoEvent(event, kCastScript, sprite->_castId));
-		_eventQueue.push(LingoEvent(event, kFrameScript, currentFrame->_actionId));
+		_eventQueue.push(LingoEvent(event, kScoreScript, currentFrame->_actionId));
 		// TODO: Is the kFrameScript call above correct?
 	} else if (event == kEventMouseDown || event == kEventMouseUp) {
 		// If sprite is immediate, its script is run on mouseDown, otherwise on mouseUp
@@ -175,14 +175,14 @@ void Lingo::registerInputEvent(LEvent event) {
 			queueEventNone = true;
 		}
 	
-		// Frame script overrides sprite script
+		// Score (sprite) script overrides cast script
 		if (sprite->_scriptId) {
 			if (queueEventNone)
-				_eventQueue.push(LingoEvent(kEventNone, kFrameScript, sprite->_scriptId, spriteId));
+				_eventQueue.push(LingoEvent(kEventNone, kScoreScript, sprite->_scriptId, spriteId));
 		} else {
 			if (queueEventNone)
-				_eventQueue.push(LingoEvent(kEventNone, kSpriteScript, sprite->_castId));
-			_eventQueue.push(LingoEvent(event, kSpriteScript, sprite->_castId));
+				_eventQueue.push(LingoEvent(kEventNone, kCastScript, sprite->_castId));
+			_eventQueue.push(LingoEvent(event, kCastScript, sprite->_castId));
 		}
 	}
 
@@ -235,7 +235,7 @@ void Lingo::registerFrameEvent(LEvent event) {
 		assert(score->_frames[score->getCurrentFrame()] != nullptr);
 		entity = score->_frames[score->getCurrentFrame()]->_actionId;
 	}
-	_eventQueue.push(LingoEvent(event, kFrameScript, entity));
+	_eventQueue.push(LingoEvent(event, kScoreScript, entity));
 
 	runMovieScript(event);
 }
diff --git a/engines/director/lingo/lingo-patcher.cpp b/engines/director/lingo/lingo-patcher.cpp
index b55bc7d907..88362a9b1c 100644
--- a/engines/director/lingo/lingo-patcher.cpp
+++ b/engines/director/lingo/lingo-patcher.cpp
@@ -40,11 +40,11 @@ struct ScriptPatch {
 	const char *replace;
 } const scriptPatches[] = {
 	// Garbage at end of script
-	{"warlock", kPlatformMacintosh, "WARLOCKSHIP/WARLOCKSHIP/UpForeECall", kFrameScript, 12,
+	{"warlock", kPlatformMacintosh, "WARLOCKSHIP/WARLOCKSHIP/UpForeECall", kScoreScript, 12,
 			2, "SS Warlock:DATA:WARLOCKSHIP:Up.GCGunner", ""},
-	{"warlock", kPlatformMacintosh, "WARLOCKSHIP/WARLOCKSHIP/UpForeECall", kFrameScript, 12,
+	{"warlock", kPlatformMacintosh, "WARLOCKSHIP/WARLOCKSHIP/UpForeECall", kScoreScript, 12,
 			3, "Channels 17 to 18", ""},
-	{"warlock", kPlatformMacintosh, "WARLOCKSHIP/WARLOCKSHIP/UpForeECall", kFrameScript, 12,
+	{"warlock", kPlatformMacintosh, "WARLOCKSHIP/WARLOCKSHIP/UpForeECall", kScoreScript, 12,
 			4, "Frames 150 to 160", ""},
 
 	// Unbalanced 'end if' at the end of the script
@@ -52,11 +52,11 @@ struct ScriptPatch {
 			5, "end if", ""},
 
 	// Garbage at end of script
-	{"warlock", kPlatformWindows, "WRLCKSHP/UpForeECall", kFrameScript, 12,
+	{"warlock", kPlatformWindows, "WRLCKSHP/UpForeECall", kScoreScript, 12,
 			2, "SS Warlock:DATA:WARLOCKSHIP:Up.GCGunner", ""},
-	{"warlock", kPlatformWindows, "WRLCKSHP/UpForeECall", kFrameScript, 12,
+	{"warlock", kPlatformWindows, "WRLCKSHP/UpForeECall", kScoreScript, 12,
 			3, "Channels 17 to 18", ""},
-	{"warlock", kPlatformWindows, "WRLCKSHP/UpForeECall", kFrameScript, 12,
+	{"warlock", kPlatformWindows, "WRLCKSHP/UpForeECall", kScoreScript, 12,
 			4, "Frames 150 to 160", ""},
 
 	// Unbalanced 'end if' at the end of the script
@@ -65,7 +65,7 @@ struct ScriptPatch {
 
 
 	// Unbalanced 'end if' at the end of the script
-	{"jman", kPlatformWindows, "mmm/TSA RR 06", kFrameScript, 26,
+	{"jman", kPlatformWindows, "mmm/TSA RR 06", kScoreScript, 26,
 			17, "end if", ""},
 
 	{nullptr, kPlatformUnknown, nullptr, kNoneScript, 0, 0, nullptr, nullptr}
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index a5aace3e5f..68837cc305 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -1088,7 +1088,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
 			return;
 		}
 		// FIXME: What if the cast member is in a different archive than the current one?
-		addCode(d.u.s->c_str(), _archiveIndex, kSpriteScript, id);
+		addCode(d.u.s->c_str(), _archiveIndex, kCastScript, id);
 
 		castInfo->script = d.asString();
 		break;
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 23a6f497d0..a1a1f6c321 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -370,10 +370,10 @@ ScriptContext *Lingo::addCode(const char *code, int archiveIndex, ScriptType typ
 	currentFunc.u.defn = _currentAssembly;
 	// guess the name. don't actually bind it to the event, there's a seperate
 	// triggering mechanism for that.
-	if (type == kFrameScript) {
-		currentFunc.name = new Common::String("enterFrame");
-	} else if (type == kSpriteScript) {
-		currentFunc.name = new Common::String("mouseUp");
+	if (type == kScoreScript) {
+		currentFunc.name = new Common::String("[score script]");
+	} else if (type == kCastScript) {
+		currentFunc.name = new Common::String("[cast script");
 	} else {
 		currentFunc.name = new Common::String("[unknown]");
 	}
@@ -1023,9 +1023,9 @@ void Lingo::executeImmediateScripts(Frame *frame) {
 			// From D5 only explicit event handlers are processed
 			// Before that you could specify commands which will be executed on mouse up
 			if (_vm->getVersion() < 5)
-				g_lingo->processEvent(kEventNone, kFrameScript, frame->_sprites[i]->_scriptId, i);
+				g_lingo->processEvent(kEventNone, kScoreScript, frame->_sprites[i]->_scriptId, i);
 			else
-				g_lingo->processEvent(kEventMouseUp, kFrameScript, frame->_sprites[i]->_scriptId, i);
+				g_lingo->processEvent(kEventMouseUp, kScoreScript, frame->_sprites[i]->_scriptId, i);
 		}
 	}
 }
diff --git a/engines/director/score-loading.cpp b/engines/director/score-loading.cpp
index 4151984369..18f7acd2fa 100644
--- a/engines/director/score-loading.cpp
+++ b/engines/director/score-loading.cpp
@@ -44,8 +44,6 @@ namespace Director {
 
 const char *scriptTypes[] = {
 	"MovieScript",
-	"SpriteScript",
-	"FrameScript",
 	"CastScript",
 	"GlobalScript",
 	"ScoreScript"
@@ -1002,7 +1000,7 @@ void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) {
 	if (ConfMan.getBool("dump_scripts"))
 		for (j = _actions.begin(); j != _actions.end(); ++j) {
 			if (!j->_value.empty())
-				dumpScript(j->_value.c_str(), kFrameScript, j->_key);
+				dumpScript(j->_value.c_str(), kScoreScript, j->_key);
 		}
 
 	for (j = _actions.begin(); j != _actions.end(); ++j) {
@@ -1011,7 +1009,7 @@ void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) {
 			// continue;
 		}
 		if (!j->_value.empty()) {
-			_lingo->addCode(j->_value.c_str(), _lingoArchive, kFrameScript, j->_key);
+			_lingo->addCode(j->_value.c_str(), _lingoArchive, kScoreScript, j->_key);
 
 			processImmediateFrameScript(j->_value, j->_key);
 		}
@@ -1125,10 +1123,10 @@ void Score::loadCastInfo(Common::SeekableSubReadStreamEndian &stream, uint16 id)
 	ci->script = castStrings[0];
 
 	if (!ci->script.empty() && ConfMan.getBool("dump_scripts"))
-		dumpScript(ci->script.c_str(), kSpriteScript, id);
+		dumpScript(ci->script.c_str(), kCastScript, id);
 
 	if (!ci->script.empty())
-		_lingo->addCode(ci->script.c_str(), _lingoArchive, kSpriteScript, id);
+		_lingo->addCode(ci->script.c_str(), _lingoArchive, kCastScript, id);
 
 	ci->name = getString(castStrings[1]);
 	ci->directory = getString(castStrings[2]);
diff --git a/engines/director/types.h b/engines/director/types.h
index 34367fabb1..5b332fd6d0 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -44,12 +44,10 @@ enum CastType {
 enum ScriptType {
 	kNoneScript = -1,
 	kMovieScript = 0,
-	kSpriteScript = 1,
-	kFrameScript = 2,
-	kCastScript = 3,
-	kGlobalScript = 4,
-	kScoreScript = 5,
-	kMaxScriptType = 5	// Sync with score.cpp:45, array scriptTypes[]
+	kCastScript = 1,
+	kGlobalScript = 2,
+	kScoreScript = 3,
+	kMaxScriptType = 3	// Sync with score.cpp:45, array scriptTypes[]
 };
 
 enum ShapeType {
diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index 619a17fcbb..c79c51602c 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -522,15 +522,9 @@ Common::String dumpScriptName(const char *prefix, int type, int id, const char *
 	case kNoneScript:
 	default:
 		error("dumpScriptName(): Incorrect call (type %d)", type);
-	case kFrameScript:
-		typeName = "frame";
-		break;
 	case kMovieScript:
 		typeName = "movie";
 		break;
-	case kSpriteScript:
-		typeName = "sprite";
-		break;
 	case kCastScript:
 		typeName = "cast";
 		break;


Commit: 8db0405d31b1ee74087b42cb2dac1bf1df80d667
    https://github.com/scummvm/scummvm/commit/8db0405d31b1ee74087b42cb2dac1bf1df80d667
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-17T20:38:49-04:00

Commit Message:
DIRECTOR: Load D4 cast scripts

Changed paths:
    engines/director/score-loading.cpp


diff --git a/engines/director/score-loading.cpp b/engines/director/score-loading.cpp
index 18f7acd2fa..15247b3ae7 100644
--- a/engines/director/score-loading.cpp
+++ b/engines/director/score-loading.cpp
@@ -880,15 +880,16 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
 			}
 		} else {
 			if (!ci->script.empty()) {
+				ScriptType scriptType = kCastScript;
+				// the script type here could be wrong!
 				if (member->_type == kCastLingoScript) {
-					// the script type here could be wrong!
-					if (ConfMan.getBool("dump_scripts"))
-						dumpScript(ci->script.c_str(), ((ScriptCast *)member)->_scriptType, id);
-
-					_lingo->addCode(ci->script.c_str(), _lingoArchive, ((ScriptCast *)member)->_scriptType, id);
-				} else {
-					warning("Score::loadCastData(): Wrong cast type: %d", member->_type);
+					scriptType = ((ScriptCast *)member)->_scriptType;
 				}
+
+				if (ConfMan.getBool("dump_scripts"))
+					dumpScript(ci->script.c_str(), scriptType, id);
+
+				_lingo->addCode(ci->script.c_str(), _lingoArchive, scriptType, id);
 			}
 		}
 


Commit: af62c56624d214d6772a3172df99c8d1f245c1ad
    https://github.com/scummvm/scummvm/commit/af62c56624d214d6772a3172df99c8d1f245c1ad
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-17T20:38:49-04:00

Commit Message:
DIRECTOR: Consider sprites with CastScripts active

Changed paths:
    engines/director/sprite.cpp


diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 01a0f8eb6d..a06d225b9e 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -22,6 +22,7 @@
 
 #include "director/director.h"
 #include "director/cast.h"
+#include "director/lingo/lingo.h"
 #include "director/sprite.h"
 
 #include "director/score.h"
@@ -108,7 +109,14 @@ bool Sprite::isDirty() {
 }
 
 bool Sprite::isActive() {
-	return _moveable || _puppet || _scriptId;
+	if (_moveable || _puppet || _scriptId)
+		return true;
+	
+	if (g_lingo->getScriptContext(kArchMain, kCastScript, _castId)
+			|| g_lingo->getScriptContext(kArchShared, kCastScript, _castId))
+		return true;
+
+	return false;
 }
 
 void Sprite::setClean() {


Commit: 612104336fd7844b39049cc0a48dfa77895cd6da
    https://github.com/scummvm/scummvm/commit/612104336fd7844b39049cc0a48dfa77895cd6da
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-17T20:38:49-04:00

Commit Message:
DIRECTOR: LINGO: Rework event handling

Setup for proper event delegation. It probably needs adjustments but
it should be mostly correct for D4.

Changed paths:
    engines/director/events.cpp
    engines/director/lingo/lingo-builtins.cpp
    engines/director/lingo/lingo-bytecode.cpp
    engines/director/lingo/lingo-codegen.cpp
    engines/director/lingo/lingo-events.cpp
    engines/director/lingo/lingo.cpp
    engines/director/lingo/lingo.h
    engines/director/score.cpp


diff --git a/engines/director/events.cpp b/engines/director/events.cpp
index 557ef9dc6a..9d3e84f1c1 100644
--- a/engines/director/events.cpp
+++ b/engines/director/events.cpp
@@ -108,7 +108,7 @@ void DirectorEngine::processEvents(bool bufferLingoEvents) {
 				sc->_lastClickTime = sc->_lastEventTime;
 
 				debugC(3, kDebugEvents, "event: Button Down @(%d, %d), sprite id: %d", pos.x, pos.y, spriteId);
-				_lingo->registerEvent(kEventMouseDown);
+				_lingo->registerEvent(kEventMouseDown, spriteId);
 
 				if (sc->getSpriteById(spriteId)->_moveable)
 					g_director->setDraggedSprite(spriteId);
@@ -136,7 +136,7 @@ void DirectorEngine::processEvents(bool bufferLingoEvents) {
 						cast->_hilite = !cast->_hilite;
 				}
 
-				_lingo->registerEvent(kEventMouseUp);
+				_lingo->registerEvent(kEventMouseUp, spriteId);
 				sc->_currentMouseDownSpriteId = 0;
 				break;
 
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index dfef2c5cdb..30f18c855c 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -520,7 +520,7 @@ void LB::b_value(int nargs) {
 	Common::String code = "scummvm_returnNumber " + expr;
 	// Compile the code to an anonymous function and call it
 	ScriptContext *sc = g_lingo->addCode(code.c_str(), kArchNone, kNoneScript, 0);
-	Symbol sym = sc->functions[0];
+	Symbol sym = sc->eventHandlers[kEventNone];
 	LC::call(sym, 0);
 	delete sc;
 }
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index d2dc160b25..f15c92101d 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -741,7 +741,6 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
 
 	_assemblyArchive = archiveIndex;
 	_assemblyContext = new ScriptContext;
-	_currentEntityId = id;
 	_archives[_assemblyArchive].scriptContexts[type][id] = _assemblyContext;
 
 	if (stream.size() < 0x5c) {
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index 1b61c5f84f..76b6c284ed 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -98,8 +98,9 @@ Symbol Lingo::define(Common::String &name, int nargs, ScriptData *code, Common::
 
 		if (!_eventHandlerTypeIds.contains(name)) {
 			_archives[_assemblyArchive].functionHandlers[name] = sym;
+			_assemblyContext->functionHandlers[name] = sym;
 		} else {
-			_archives[_assemblyArchive].eventHandlers[ENTITY_INDEX(_eventHandlerTypeIds[name], _currentEntityId)] = sym;
+			_assemblyContext->eventHandlers[_eventHandlerTypeIds[name]] = sym;
 		}
 	}
 
@@ -107,9 +108,8 @@ Symbol Lingo::define(Common::String &name, int nargs, ScriptData *code, Common::
 }
 
 Symbol Lingo::codeDefine(Common::String &name, int start, int nargs, Object *factory, int end, bool removeCode) {
-	debugC(1, kDebugCompile, "codeDefine(\"%s\"(len: %d), %d, %d, \"%s\", %d) entity: %d",
-			name.c_str(), _currentAssembly->size() - 1, start, nargs, (factory ? factory->name->c_str() : ""),
-			end, _currentEntityId);
+	debugC(1, kDebugCompile, "codeDefine(\"%s\"(len: %d), %d, %d, \"%s\", %d)",
+			name.c_str(), _currentAssembly->size() - 1, start, nargs, (factory ? factory->name->c_str() : ""), end);
 
 	if (end == -1)
 		end = _currentAssembly->size();
diff --git a/engines/director/lingo/lingo-events.cpp b/engines/director/lingo/lingo-events.cpp
index 8ab93ca4fd..afaa93c32c 100644
--- a/engines/director/lingo/lingo-events.cpp
+++ b/engines/director/lingo/lingo-events.cpp
@@ -114,26 +114,26 @@ void Lingo::primaryEventHandler(LEvent event) {
 	 * the message by including the dontPassEventCommand in the script
 	 * [D4 docs page 77]
 	 */
-	debugC(3, kDebugLingoExec, "calling primary event handler (%s)", _eventHandlerTypes[event]);
+	/* 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:
-		executeScript(kGlobalScript, event, 0);
+		debugC(3, kDebugLingoExec, "calling primary event handler (%s)", _eventHandlerTypes[event]);
+		executeScript(kGlobalScript, event);
 		break;
 	default:
-		/* 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]
-		 */
-		warning("primaryEventHandler() on event other than mouseDown, mouseUp, keyUp, keyDown, timeout");
+		break;
 	}
 }
 
-void Lingo::registerInputEvent(LEvent event) {
+void Lingo::registerSpriteEvent(LEvent event, 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.
@@ -147,64 +147,41 @@ void Lingo::registerInputEvent(LEvent event) {
 	Score *score = _vm->getCurrentScore();
 	Frame *currentFrame = score->_frames[score->getCurrentFrame()];
 	assert(currentFrame != nullptr);
-	uint16 spriteId = score->_currentMouseDownSpriteId;
 	Sprite *sprite = score->getSpriteById(spriteId);
 
-	primaryEventHandler(event);
-
-	if (_dontPassEvent) {
-		_dontPassEvent = false;
-
-		return;
-	}
-
-	if (_vm->getVersion() > 3) {
-		if (true) {
-			// TODO: Check whether occurring over a sprite
-			_eventQueue.push(LingoEvent(event, kScoreScript, sprite->_scriptId));
-		}
-		_eventQueue.push(LingoEvent(event, kCastScript, sprite->_castId));
-		_eventQueue.push(LingoEvent(event, kScoreScript, currentFrame->_actionId));
-		// TODO: Is the kFrameScript call above correct?
-	} else if (event == kEventMouseDown || event == kEventMouseUp) {
-		// If sprite is immediate, its script is run on mouseDown, otherwise on mouseUp
-		bool queueEventNone = false;
-		if (event == kEventMouseDown && sprite->_immediate) {
-			queueEventNone = true;
-		} else if (event == kEventMouseUp && !sprite->_immediate) {
-			queueEventNone = true;
-		}
-	
-		// Score (sprite) script overrides cast script
-		if (sprite->_scriptId) {
-			if (queueEventNone)
-				_eventQueue.push(LingoEvent(kEventNone, kScoreScript, sprite->_scriptId, spriteId));
+	// Sprite (score) script
+	if (sprite->_scriptId) {
+		if (_vm->getVersion() <= 3) {
+			// In D3 the event lingo is not contained in a handler
+			// 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;
+			}
 		} else {
-			if (queueEventNone)
-				_eventQueue.push(LingoEvent(kEventNone, kCastScript, sprite->_castId));
-			_eventQueue.push(LingoEvent(event, kCastScript, sprite->_castId));
+			ScriptContext *script = getScriptContext(kArchMain, kScoreScript, sprite->_scriptId);
+			if (script && script->eventHandlers.contains(event)) {
+				_eventQueue.push(LingoEvent(event, kArchMain, kScoreScript, sprite->_scriptId, spriteId));
+				return;
+			}
 		}
 	}
 
-	runMovieScript(event);
-}
-
-void Lingo::runMovieScript(LEvent event) {
-	/* 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]
-	 */
-
-	if (_dontPassEvent)
+	// Cast script
+	int archiveIndex = kArchMain;
+	ScriptContext *script = getScriptContext(archiveIndex, kCastScript, sprite->_castId);
+	if (!script) {
+		archiveIndex = kArchShared;
+		script = getScriptContext(archiveIndex, kCastScript, sprite->_castId);
+	}
+	if (script && script->eventHandlers.contains(event)) {
+		_eventQueue.push(LingoEvent(event, archiveIndex, kCastScript, sprite->_castId, spriteId));
 		return;
-
-	for (ScriptContextHash::iterator it = _archives[_archiveIndex].scriptContexts[kMovieScript].begin();
-			it != _archives[_archiveIndex].scriptContexts[kMovieScript].end(); ++it) {
-		if (_archives[_archiveIndex].eventHandlers.contains(ENTITY_INDEX(event, it->_key))) {
-			_eventQueue.push(LingoEvent(event, kMovieScript, it->_key));
-			break;
-		}
 	}
+
+	// Delegate to the frame
+	registerFrameEvent(event);	
 }
 
 void Lingo::registerFrameEvent(LEvent event) {
@@ -214,66 +191,72 @@ void Lingo::registerFrameEvent(LEvent event) {
 	 * message goes to movie scripts.
 	 * [p.81 of D4 docs]
 	 */
-	// TODO: Same for D2-3 or not?
+
 	Score *score = _vm->getCurrentScore();
 
-	if (event == kEventTimeout) {
-		primaryEventHandler(event);
-	}
+	// if (event == kEventPrepareFrame || event == kEventIdle) {
+	// 	entity = score->getCurrentFrame();
+	// } else {
 
-	if (_dontPassEvent) {
-		_dontPassEvent = false;
+	assert(score->_frames[score->getCurrentFrame()] != nullptr);
+	int scriptId = score->_frames[score->getCurrentFrame()]->_actionId;
 
+	if (scriptId) {
+		_eventQueue.push(LingoEvent(event, kArchMain, kScoreScript, scriptId));
 		return;
 	}
 
-	int entity;
+	// Delegate to the movie
+	registerMovieEvent(event);
+}
 
-	if (event == kEventPrepareFrame || event == kEventIdle) {
-		entity = score->getCurrentFrame();
-	} else {
-		assert(score->_frames[score->getCurrentFrame()] != nullptr);
-		entity = score->_frames[score->getCurrentFrame()]->_actionId;
-	}
-	_eventQueue.push(LingoEvent(event, kScoreScript, entity));
+void Lingo::registerMovieEvent(LEvent event) {
+	/* 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]
+	 */
 
-	runMovieScript(event);
-}
+	if (event == kEventNone)
+		return;
 
-void Lingo::registerGenericEvent(LEvent event) {
-	// Movie Script
-	if (event == kEventStart || event == kEventStartUp || event == kEventPrepareMovie ||
-			event == kEventStartMovie || event == kEventStopMovie)
-		; // we're OK
-	else
-		warning("STUB: processGenericEvent called for unprocessed event, additional logic probably needed");
+	// FIXME: shared cast movie scripts could come before main movie ones
+	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));
+			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));
+			return;
+		}
+	}
 
-	runMovieScript(event);
+	debugC(9, kDebugEvents, "Lingo::registerEvent(%s): no handler", _eventHandlerTypes[event]);
 }
 
-void Lingo::registerSpriteEvent(LEvent event) {
-	Score *score = _vm->getCurrentScore();
-	Frame *currentFrame = score->_frames[score->getCurrentFrame()];
-	if (event == kEventBeginSprite) {
-		// TODO: Check if this is also possibly a kSpriteScript?
-		for (uint16 i = 0; i <= score->_numChannelsDisplayed; i++)
-			if (currentFrame->_sprites[i]->_enabled)
-				_eventQueue.push(LingoEvent(event, kCastScript, currentFrame->_sprites[i]->_scriptId));
+void Lingo::registerEvent(LEvent event, int spriteId) {
+	primaryEventHandler(event);
 
-	} else {
-		warning("STUB: processSpriteEvent called for something else than kEventBeginSprite, additional logic probably needed");
+	if (_dontPassEvent) {
+		_dontPassEvent = false;
+		return;
 	}
 
-}
-
-void Lingo::registerEvent(LEvent event) {
 	switch (event) {
 		case kEventKeyUp:
 		case kEventKeyDown:
 		case kEventMouseUp:
 		case kEventMouseDown:
-			registerInputEvent(event);
-			break;
+		case kEventBeginSprite:
+			if (spriteId) {
+				registerSpriteEvent(event, spriteId);
+				break;
+			}
+			// fall through
 
 		case kEventIdle:
 		case kEventEnterFrame:
@@ -288,21 +271,16 @@ void Lingo::registerEvent(LEvent event) {
 		case kEventStopMovie:
 		case kEventTimeout:
 		case kEventPrepareMovie:
-			registerGenericEvent(event);
-			break;
-		case kEventBeginSprite:
-			registerSpriteEvent(event);
+			registerMovieEvent(event);
 			break;
 
 		default:
 			warning("registerEvent: Unhandled event %s", _eventHandlerTypes[event]);
 	}
-
-	_dontPassEvent = false;
 }
 
-void Lingo::processEvent(LEvent event) {
-	registerEvent(event);
+void Lingo::processEvent(LEvent event, int spriteId) {
+	registerEvent(event, spriteId);
 	processEvents();
 }
 
@@ -313,34 +291,24 @@ void Lingo::processEvents() {
 		if (_vm->getCurrentScore()->_stopPlay && el.event != kEventStopMovie)
 			continue;
 
-		processEvent(el.event, el.st, el.entityId, el.channelId);
+		processEvent(el.event, el.archiveIndex, el.st, el.scriptId, el.channelId);
 	}
 }
 
-void Lingo::processEvent(LEvent event, ScriptType st, int entityId, int channelId) {
-	if (entityId < 0)
-		return;
-
-	if (_dontPassEvent)
-		return;
-
-	_currentEntityId = entityId;
+void Lingo::processEvent(LEvent event, int archiveIndex, ScriptType st, int scriptId, int channelId) {
 	_currentChannelId = channelId;
 
 	if (!_eventHandlerTypes.contains(event))
-		error("processEvent: Unknown event %d for entity %d", event, entityId);
-
-	if (_archives[kArchMain].eventHandlers.contains(ENTITY_INDEX(event, entityId)) ||
-			_archives[kArchShared].eventHandlers.contains(ENTITY_INDEX(event, entityId))) {
-		// handler
-		debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d): executing event handler", _eventHandlerTypes[event], scriptType2str(st), entityId);
-		executeHandler(_eventHandlerTypes[event]);
-	} else if (_vm->getVersion() < 4 && event == kEventNone && getScriptContext(_archiveIndex, st, entityId)) {
-		// script (D3)
-		debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d): executing event script", _eventHandlerTypes[event], scriptType2str(st), entityId);
-		executeScript(st, entityId, 0);
+		error("processEvent: Unknown event %d", event);
+
+	ScriptContext *script = getScriptContext(archiveIndex, st, scriptId);
+
+	if (script && script->eventHandlers.contains(event)) {
+		debugC(1, kDebugEvents, "Lingo::processEvent(%s, %d, %s, %d): executing event handler", _eventHandlerTypes[event], archiveIndex, scriptType2str(st), scriptId);
+		LC::call(script->eventHandlers[event], 0);
+		execute(_pc);
 	} else {
-		debugC(9, kDebugEvents, "Lingo::processEvent(%s, %s, %d): no handler", _eventHandlerTypes[event], scriptType2str(st), entityId);
+		debugC(9, kDebugEvents, "Lingo::processEvent(%s, %d, %s, %d): no handler", _eventHandlerTypes[event], archiveIndex, scriptType2str(st), scriptId);
 	}
 }
 
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index a1a1f6c321..5ce1a4131a 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -132,7 +132,6 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
 	_currentAssembly = nullptr;
 	_assemblyContext = nullptr;
 
-	_currentEntityId = 0;
 	_currentChannelId = -1;
 	_pc = 0;
 	_abort = false;
@@ -215,16 +214,6 @@ Symbol Lingo::getHandler(const Common::String &name) {
 
 		return result;
 	}
-
-	uint32 entityIndex = ENTITY_INDEX(_eventHandlerTypeIds[name], _currentEntityId);
-	// local scripts
-	if (_archives[kArchMain].eventHandlers.contains(entityIndex))
-		return _archives[kArchMain].eventHandlers[entityIndex];
-
-	// shared scripts
-	if (_archives[kArchShared].eventHandlers.contains(entityIndex))
-		return _archives[kArchShared].eventHandlers[entityIndex];
-
 	return result;
 }
 
@@ -279,7 +268,6 @@ ScriptContext *Lingo::addCode(const char *code, int archiveIndex, ScriptType typ
 	_assemblyArchive = archiveIndex;
 	ScriptContext *sc = _assemblyContext = new ScriptContext;
 	_currentAssembly = new ScriptData;
-	_currentEntityId = id;
 	if (archiveIndex >= 0)
 		_archives[_assemblyArchive].scriptContexts[type][id] = _assemblyContext;
 
@@ -408,7 +396,7 @@ ScriptContext *Lingo::addCode(const char *code, int archiveIndex, ScriptType typ
 
 	currentFunc.argNames = argNames;
 	currentFunc.varNames = varNames;
-	_assemblyContext->functions.push_back(currentFunc);
+	_assemblyContext->eventHandlers[kEventNone] = currentFunc;
 	_assemblyContext = nullptr;
 	_currentAssembly = nullptr;
 	return sc;
@@ -577,21 +565,17 @@ void Lingo::execute(uint pc) {
 	_abort = false;
 }
 
-void Lingo::executeScript(ScriptType type, uint16 id, uint16 function) {
+void Lingo::executeScript(ScriptType type, uint16 id) {
 	ScriptContext *sc = getScriptContext(_archiveIndex, type, id);
 
 	if (!sc) {
 		debugC(3, kDebugLingoExec, "Request to execute non-existant script type %d id %d", type, id);
 		return;
 	}
-	if (function >= sc->functions.size()) {
-		debugC(3, kDebugLingoExec, "Request to execute non-existant function %d in script type %d id %d", function, type, id);
-		return;
-	}
 
-	debugC(1, kDebugLingoExec, "Executing script type: %s, id: %d, function: %d", scriptType2str(type), id, function);
+	debugC(1, kDebugLingoExec, "Executing script type: %s, id: %d", scriptType2str(type), id);
 
-	Symbol sym = sc->functions[function];
+	Symbol sym = sc->eventHandlers[kEventNone];
 	LC::call(sym, 0);
 	execute(_pc);
 }
@@ -613,7 +597,8 @@ void Lingo::restartLingo(bool keepSharedCast) {
 		LingoArchive *arch = &_archives[a];
 		for (int i = 0; i <= kMaxScriptType; i++) {
 			for (ScriptContextHash::iterator it = arch->scriptContexts[i].begin(); it != arch->scriptContexts[i].end(); ++it) {
-				it->_value->functions.clear();
+				it->_value->eventHandlers.clear();
+				it->_value->functionHandlers.clear();
 				delete it->_value;
 			}
 
@@ -621,7 +606,6 @@ void Lingo::restartLingo(bool keepSharedCast) {
 		}
 
 		arch->names.clear();
-		arch->eventHandlers.clear();
 		arch->functionHandlers.clear();
 	}
 
@@ -1003,7 +987,7 @@ void Lingo::runTests() {
 
 			if (!debugChannelSet(-1, kDebugCompileOnly)) {
 				if (!_hadError)
-					executeScript(kMovieScript, counter, 0);
+					executeScript(kMovieScript, counter);
 				else
 					debug(">> Skipping execution");
 			}
@@ -1023,9 +1007,9 @@ void Lingo::executeImmediateScripts(Frame *frame) {
 			// From D5 only explicit event handlers are processed
 			// Before that you could specify commands which will be executed on mouse up
 			if (_vm->getVersion() < 5)
-				g_lingo->processEvent(kEventNone, kScoreScript, frame->_sprites[i]->_scriptId, i);
+				g_lingo->processEvent(kEventNone, kArchMain, kScoreScript, frame->_sprites[i]->_scriptId, i);
 			else
-				g_lingo->processEvent(kEventMouseUp, kScoreScript, frame->_sprites[i]->_scriptId, i);
+				g_lingo->processEvent(kEventMouseUp, kArchMain, kScoreScript, frame->_sprites[i]->_scriptId, i);
 		}
 	}
 }
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 0cc68c991a..4fae571de7 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -204,11 +204,6 @@ struct Builtin {
 	Builtin(void (*func1)(void), int nargs1) : func(func1), nargs(nargs1) {}
 };
 
-struct ScriptContext {
-	Common::Array<Symbol> functions;
-	Common::Array<Datum> constants;
-};
-
 typedef Common::HashMap<int32, ScriptContext *> ScriptContextHash;
 typedef Common::Array<Datum> StackData;
 typedef Common::HashMap<Common::String, Symbol, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SymbolHash;
@@ -218,6 +213,13 @@ typedef Common::HashMap<Common::String, Builtin *, Common::IgnoreCase_Hash, Comm
 typedef Common::HashMap<Common::String, TheEntity *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> TheEntityHash;
 typedef Common::HashMap<Common::String, TheEntityField *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> TheEntityFieldHash;
 
+struct ScriptContext {
+	Common::Array<Symbol> functions; // used only by bytecode
+	Common::HashMap<uint32, Symbol> eventHandlers;
+	SymbolHash functionHandlers;
+	Common::Array<Datum> constants;
+};
+
 enum ObjectType {
 	kNoneObj = 0,
 	kFactoryObj = 1 << 0,
@@ -278,14 +280,16 @@ struct CFrame {	/* proc/func call stack frame */
 
 struct LingoEvent {
 	LEvent event;
+	int archiveIndex;
 	ScriptType st;
-	int entityId;
+	int scriptId;
 	int channelId;
 
-	LingoEvent (LEvent e, ScriptType s, int ei, int ci = -1) {
+	LingoEvent (LEvent e, int ai, ScriptType s, int si, int ci = -1) {
 		event = e;
+		archiveIndex = ai;
 		st = s;
-		entityId = ei;
+		scriptId = si;
 		channelId = ci;
 	}
 };
@@ -294,7 +298,6 @@ struct LingoEvent {
 struct LingoArchive {
 	ScriptContextHash scriptContexts[kMaxScriptType + 1];
 	Common::Array<Common::String> names;
-	Common::HashMap<uint32, Symbol> eventHandlers;
 	Common::HashMap<uint32, Common::String> primaryEventHandlers;
 	SymbolHash functionHandlers;
 };
@@ -316,7 +319,7 @@ public:
 	void addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIndex, ScriptType type, uint16 id, Common::String &archName);
 	void addNamesV4(Common::SeekableSubReadStreamEndian &stream, int archiveIndex);
 	void executeHandler(const Common::String &name);
-	void executeScript(ScriptType type, uint16 id, uint16 function);
+	void executeScript(ScriptType type, uint16 id);
 	void printStack(const char *s, uint pc);
 	void printCallStack(uint pc);
 	Common::String decodeInstruction(ScriptData *sd, uint pc, uint *newPC = NULL);
@@ -347,12 +350,10 @@ private:
 	void initEventHandlerTypes();
 	void setPrimaryEventHandler(LEvent event, const Common::String &code);
 	void primaryEventHandler(LEvent event);
-	void registerInputEvent(LEvent event);
+	void registerSpriteEvent(LEvent event, int spriteId);
 	void registerFrameEvent(LEvent event);
-	void registerGenericEvent(LEvent event);
-	void runMovieScript(LEvent event);
-	void registerSpriteEvent(LEvent event);
-	void processEvent(LEvent event, ScriptType st, int entityId, int channelId = -1);
+	void registerMovieEvent(LEvent event);
+	void processEvent(LEvent event, int archiveIndex, ScriptType st, int entityId, int channelId = -1);
 
 	Common::Queue<LingoEvent> _eventQueue;
 
@@ -363,9 +364,9 @@ public:
 	Symbol getHandler(const Common::String &name);
 
 	int getEventCount();
-	void processEvent(LEvent event);
+	void processEvent(LEvent event, int spriteId = 0);
 	void processEvents();
-	void registerEvent(LEvent event);
+	void registerEvent(LEvent event, int spriteId = 0);
 
 public:
 	void execute(uint pc);
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index a3ed671ad2..cbc89f11e3 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -106,7 +106,7 @@ Score::Score(DirectorEngine *vm) {
 
 	// FIXME: TODO: Check whether the original truely does it
 	if (_vm->getVersion() <= 3) {
-		_lingo->executeScript(kMovieScript, 0, 0);
+		_lingo->executeScript(kMovieScript, 0);
 	}
 	_movieScriptCount = 0;
 	_labels = nullptr;
@@ -484,9 +484,9 @@ void Score::update() {
 	_lingo->executeImmediateScripts(_frames[_currentFrame]);
 
 	if (_vm->getVersion() >= 6) {
-		_lingo->processEvent(kEventBeginSprite);
+		// _lingo->processEvent(kEventBeginSprite);
 		// TODO Director 6 step: send beginSprite event to any sprites whose span begin in the upcoming frame
-		_lingo->processEvent(kEventPrepareFrame);
+		// _lingo->processEvent(kEventPrepareFrame);
 		// TODO: Director 6 step: send prepareFrame event to all sprites and the script channel in upcoming frame
 	}
 




More information about the Scummvm-git-logs mailing list