[Scummvm-git-logs] scummvm master -> 74863cb32ffc155ae43cd794c8256b087543fdb2

elasota noreply at scummvm.org
Sat Jul 2 06:20:41 UTC 2022


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:
74863cb32f MTROPOLIS: Discharge message queue after low-level scene transition actions


Commit: 74863cb32ffc155ae43cd794c8256b087543fdb2
    https://github.com/scummvm/scummvm/commit/74863cb32ffc155ae43cd794c8256b087543fdb2
Author: elasota (ejlasota at gmail.com)
Date: 2022-07-02T02:20:26-04:00

Commit Message:
MTROPOLIS: Discharge message queue after low-level scene transition actions

Changed paths:
    engines/mtropolis/runtime.cpp
    engines/mtropolis/runtime.h


diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index 8a9376bcd46..29b0603a3fc 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -3212,18 +3212,20 @@ MessageDispatch::MessageDispatch(const Common::SharedPtr<MessageProperties> &msg
 
 		PropagationStack topEntry;
 		topEntry.index = 0;
-		topEntry.propagationStage = PropagationStack::kStageSendCommand;
+		topEntry.propagationStage = PropagationStack::kStageCheckAndSendCommand;
 		topEntry.ptr.structural = root;
 
 		_propagationStack.push_back(topEntry);
 	} else {
 		PropagationStack topEntry;
 		topEntry.index = 0;
-		topEntry.propagationStage = PropagationStack::kStageSendToStructuralSelf;
+		topEntry.propagationStage = PropagationStack::kStageCheckAndSendToStructural;
 		topEntry.ptr.structural = root;
 
 		_propagationStack.push_back(topEntry);
 	}
+
+	_root = root->getSelfReference();
 }
 
 MessageDispatch::MessageDispatch(const Common::SharedPtr<MessageProperties> &msgProps, Modifier *root, bool cascade, bool relay, bool couldBeCommand)
@@ -3234,13 +3236,15 @@ MessageDispatch::MessageDispatch(const Common::SharedPtr<MessageProperties> &msg
 	} else {
 		PropagationStack topEntry;
 		topEntry.index = 0;
-		topEntry.propagationStage = PropagationStack::kStageSendToModifier;
+		topEntry.propagationStage = PropagationStack::kStageCheckAndSendToModifier;
 		topEntry.ptr.modifier = root;
 
 		_isCommand = (couldBeCommand && EventIDs::isCommand(msgProps->getEvent().eventType));
 
 		_propagationStack.push_back(topEntry);
 	}
+
+	_root = root->getSelfReference();
 }
 
 bool MessageDispatch::isTerminated() const {
@@ -3255,6 +3259,21 @@ VThreadState MessageDispatch::continuePropagating(Runtime *runtime) {
 		PropagationStack &stackTop = _propagationStack.back();
 
 		switch (stackTop.propagationStage) {
+		case PropagationStack::kStageCheckAndSendCommand:
+			if (_root.expired())
+				return kVThreadReturn;
+			stackTop.propagationStage = PropagationStack::kStageSendCommand;
+			break;
+		case PropagationStack::kStageCheckAndSendToStructural:
+			if (_root.expired())
+				return kVThreadReturn;
+			stackTop.propagationStage = PropagationStack::kStageSendToStructuralSelf;
+			break;
+		case PropagationStack::kStageCheckAndSendToModifier:
+			if (_root.expired())
+				return kVThreadReturn;
+			stackTop.propagationStage = PropagationStack::kStageSendToModifier;
+			break;
 		case PropagationStack::kStageSendToModifier: {
 				Modifier *modifier = stackTop.ptr.modifier;
 				_propagationStack.pop_back();
@@ -3786,15 +3805,7 @@ bool Runtime::runFrame() {
 			continue;
 		}
 
-		if (_messageQueue.size() > 0) {
-			Common::SharedPtr<MessageDispatch> msg = _messageQueue[0];
-			_messageQueue.remove_at(0);
-
-			sendMessageOnVThread(msg);
-			continue;
-		}
-
-		// Teardowns must only occur during idle conditions where there are no queued message and no VThread tasks
+		// Teardowns must only occur during idle conditions where there are no VThread tasks
 		if (_pendingTeardowns.size() > 0) {
 			for (Common::Array<Teardown>::const_iterator it = _pendingTeardowns.begin(), itEnd = _pendingTeardowns.end(); it != itEnd; ++it) {
 				executeTeardown(*it);
@@ -3812,6 +3823,27 @@ bool Runtime::runFrame() {
 			continue;
 		}
 
+		// This has to be in this specific spot: Queued messages that occur from scene transitions are normally discharged
+		// after the "Scene Started" event, but before scene transition.
+		// 
+		// Obsidian depends on this behavior in several scripts, most notably setting up conditional ambience correctly.
+		// For example, in Inspiration chapter, on exiting the plane into the statue:
+		// Shared scene fires Parent Enabled which triggers "GEN_SND_Start_Ambience on PE" which sends GEN_SND_Start_Ambience
+		// but not immediately, so it goes into the queue.
+		// After the main scene loads, it fires Scene Started and which in turn triggers "NAV_setup_navigation on SS" which
+		// sends NAV_setup_navigation immediately, which sets the current nav node variable.
+		// Then, the queued GEN_SND_Start_Ambience can read the nav node variable to set up ambience correctly.
+		//
+		// If messages are discharged before low-level scene transitions, then the music plays in the lower level of the
+		// statue on disembarking because the nav node variable is set to the wrong value.
+		if (_messageQueue.size() > 0) {
+			Common::SharedPtr<MessageDispatch> msg = _messageQueue[0];
+			_messageQueue.remove_at(0);
+
+			sendMessageOnVThread(msg);
+			continue;
+		}
+
 		if (_pendingSceneTransitions.size() > 0) {
 			HighLevelSceneTransition transition = _pendingSceneTransitions[0];
 			_pendingSceneTransitions.remove_at(0);
diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h
index 2394f0665cd..e8a1716c0cd 100644
--- a/engines/mtropolis/runtime.h
+++ b/engines/mtropolis/runtime.h
@@ -1311,6 +1311,10 @@ private:
 			kStageSendToStructuralModifiers,
 			kStageSendToStructuralChildren,
 
+			kStageCheckAndSendToModifier,
+			kStageCheckAndSendToStructural,
+			kStageCheckAndSendCommand,
+
 			kStageSendCommand,
 		};
 
@@ -1321,6 +1325,9 @@ private:
 
 	Common::Array<PropagationStack> _propagationStack;
 	Common::SharedPtr<MessageProperties> _msg;
+
+	Common::WeakPtr<RuntimeObject> _root;
+
 	bool _cascade; // Traverses structure tree
 	bool _relay;   // Fire on multiple modifiers
 	bool _terminated;




More information about the Scummvm-git-logs mailing list