[Scummvm-git-logs] scummvm master -> 2fcbe697717e3ffc132b4bd32682deb2f5bc9846

elasota noreply at scummvm.org
Wed Jul 27 05:42:42 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:
2fcbe69771 MTROPOLIS: Forcibly disable behavior children when the behavior is switched off


Commit: 2fcbe697717e3ffc132b4bd32682deb2f5bc9846
    https://github.com/scummvm/scummvm/commit/2fcbe697717e3ffc132b4bd32682deb2f5bc9846
Author: elasota (ejlasota at gmail.com)
Date: 2022-07-27T01:41:51-04:00

Commit Message:
MTROPOLIS: Forcibly disable behavior children when the behavior is switched off

Changed paths:
    engines/mtropolis/modifiers.cpp
    engines/mtropolis/modifiers.h
    engines/mtropolis/plugin/obsidian.cpp
    engines/mtropolis/plugin/obsidian.h
    engines/mtropolis/plugin/standard.cpp
    engines/mtropolis/plugin/standard.h
    engines/mtropolis/runtime.cpp
    engines/mtropolis/runtime.h


diff --git a/engines/mtropolis/modifiers.cpp b/engines/mtropolis/modifiers.cpp
index 2f540eccd1f..793641c1fe9 100644
--- a/engines/mtropolis/modifiers.cpp
+++ b/engines/mtropolis/modifiers.cpp
@@ -120,6 +120,18 @@ bool BehaviorModifier::respondsToEvent(const Event &evt) const {
 VThreadState BehaviorModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
 	if (_switchable) {
 		if (_disableWhen.respondsTo(msg->getEvent())) {
+			// These are executed in reverse order.  The disable event is propagated to children, then the disable task
+			// runs to forcibly disable any children.
+			//
+			// This works a bit weirdly in practice with child behaviors since ultimately we want them to be disabled and
+			// fire their Parent Disabled task but we don't actually do it on disable.  We instead rely on it being kind of
+			// the logical outcome of how this works:
+			//
+			// If the behavior is enabled, then Parent Disabled will propagate through the behavior, followed by the children
+			// actually being disabled.
+			DisableTaskData *disableTask = runtime->getVThread().pushTask("BehaviorModifier::disableTask", this, &BehaviorModifier::disableTask);
+			disableTask->runtime = runtime;
+
 			SwitchTaskData *taskData = runtime->getVThread().pushTask("BehaviorModifier::switchTask", this, &BehaviorModifier::switchTask);
 			taskData->targetState = false;
 			taskData->eventID = EventIDs::kParentDisabled;
@@ -136,6 +148,14 @@ VThreadState BehaviorModifier::consumeMessage(Runtime *runtime, const Common::Sh
 	return kVThreadReturn;
 }
 
+void BehaviorModifier::disable(Runtime *runtime) {
+	if (_switchable && _isEnabled)
+		_isEnabled = false;
+
+	for (const Common::SharedPtr<Modifier> &child : _children)
+		child->disable(runtime);
+}
+
 VThreadState BehaviorModifier::switchTask(const SwitchTaskData &taskData) {
 	if (_isEnabled != taskData.targetState) {
 		_isEnabled = taskData.targetState;
@@ -166,6 +186,11 @@ VThreadState BehaviorModifier::propagateTask(const PropagateTaskData &taskData)
 	return kVThreadReturn;
 }
 
+VThreadState BehaviorModifier::disableTask(const DisableTaskData &taskData) {
+	disable(taskData.runtime);
+	return kVThreadReturn;
+}
+
 Common::SharedPtr<Modifier> BehaviorModifier::shallowClone() const {
 	return Common::SharedPtr<Modifier>(new BehaviorModifier(*this));
 }
@@ -559,23 +584,27 @@ VThreadState SoundEffectModifier::consumeMessage(Runtime *runtime, const Common:
 			_player.reset();
 		}
 	} else if (_executeWhen.respondsTo(msg->getEvent())) {
-		if (_soundType == kSoundTypeAudioAsset) {
-			if (!_cachedAudio)
-				loadAndCacheAudio(runtime);
-
-			if (_cachedAudio) {
-				if (_player) {
-					_player->stop();
-					_player.reset();
-				}
+		disable(runtime);
+	}
+
+	return kVThreadReturn;
+}
 
-				size_t numSamples = _cachedAudio->getNumSamples(*_metadata);
-				_player.reset(new AudioPlayer(runtime->getAudioMixer(), 255, 0, _metadata, _cachedAudio, false, 0, 0, numSamples));
+void SoundEffectModifier::disable(Runtime *runtime) {
+	if (_soundType == kSoundTypeAudioAsset) {
+		if (!_cachedAudio)
+			loadAndCacheAudio(runtime);
+
+		if (_cachedAudio) {
+			if (_player) {
+				_player->stop();
+				_player.reset();
 			}
+
+			size_t numSamples = _cachedAudio->getNumSamples(*_metadata);
+			_player.reset(new AudioPlayer(runtime->getAudioMixer(), 255, 0, _metadata, _cachedAudio, false, 0, 0, numSamples));
 		}
 	}
-
-	return kVThreadReturn;
 }
 
 void SoundEffectModifier::loadAndCacheAudio(Runtime *runtime) {
@@ -659,16 +688,19 @@ VThreadState PathMotionModifierV2::consumeMessage(Runtime *runtime, const Common
 		return kVThreadReturn;
 	}
 	if (_terminateWhen.respondsTo(msg->getEvent())) {
-#ifdef MTROPOLIS_DEBUG_ENABLE
-		if (Debugger *debugger = runtime->debugGetDebugger())
-			debugger->notify(kDebugSeverityWarning, "Path motion modifier was supposed to terminate, but this isn't implemented yet");
-#endif
+		disable(runtime);
 		return kVThreadReturn;
 	}
 
 	return kVThreadReturn;
 }
 
+void PathMotionModifierV2::disable(Runtime *runtime) {
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	if (Debugger *debugger = runtime->debugGetDebugger())
+		debugger->notify(kDebugSeverityWarning, "Path motion modifier was supposed to terminate, but this isn't implemented yet");
+#endif
+}
 
 Common::SharedPtr<Modifier> PathMotionModifierV2::shallowClone() const {
 	Common::SharedPtr<PathMotionModifierV2> clone(new PathMotionModifierV2(*this));
@@ -741,15 +773,19 @@ VThreadState DragMotionModifier::consumeMessage(Runtime *runtime, const Common::
 		return kVThreadReturn;
 	}
 	if (_disableWhen.respondsTo(msg->getEvent())) {
-		Structural *owner = this->findStructuralOwner();
-		if (owner->isElement() && static_cast<Element *>(owner)->isVisual())
-			static_cast<VisualElement *>(owner)->setDragMotionProperties(nullptr);
+		disable(runtime);
 		return kVThreadReturn;
 	}
 
 	return kVThreadReturn;
 }
 
+void DragMotionModifier::disable(Runtime *runtime) {
+	Structural *owner = this->findStructuralOwner();
+	if (owner->isElement() && static_cast<Element *>(owner)->isVisual())
+		static_cast<VisualElement *>(owner)->setDragMotionProperties(nullptr);
+}
+
 VectorMotionModifier::~VectorMotionModifier() {
 	if (_scheduledEvent) {
 		_scheduledEvent->cancel();
@@ -816,16 +852,20 @@ VThreadState VectorMotionModifier::consumeMessage(Runtime *runtime, const Common
 		}
 	}
 	if (_disableWhen.respondsTo(msg->getEvent())) {
-		if (_scheduledEvent) {
-			_scheduledEvent->cancel();
-			_scheduledEvent.reset();
-		}
+		disable(runtime);
 		return kVThreadReturn;
 	}
 
 	return kVThreadReturn;
 }
 
+void VectorMotionModifier::disable(Runtime *runtime) {
+	if (_scheduledEvent) {
+		_scheduledEvent->cancel();
+		_scheduledEvent.reset();
+	}
+}
+
 void VectorMotionModifier::trigger(Runtime *runtime) {
 	uint64 currentTime = runtime->getPlayTime();
 	_scheduledEvent = runtime->getScheduler().scheduleMethod<VectorMotionModifier, &VectorMotionModifier::trigger>(currentTime + 1, this);
@@ -948,11 +988,15 @@ VThreadState SceneTransitionModifier::consumeMessage(Runtime *runtime, const Com
 		runtime->setSceneTransitionEffect(true, &effect);
 	}
 	if (_disableWhen.respondsTo(msg->getEvent()))
-		runtime->setSceneTransitionEffect(true, nullptr);
+		disable(runtime);
 
 	return kVThreadReturn;
 }
 
+void SceneTransitionModifier::disable(Runtime *runtime) {
+	runtime->setSceneTransitionEffect(true, nullptr);
+}
+
 Common::SharedPtr<Modifier> SceneTransitionModifier::shallowClone() const {
 	return Common::SharedPtr<Modifier>(new SceneTransitionModifier(*this));
 }
@@ -1058,18 +1102,21 @@ VThreadState ElementTransitionModifier::consumeMessage(Runtime *runtime, const C
 	}
 
 	if (_disableWhen.respondsTo(msg->getEvent())) {
-		if (_scheduledEvent) {
-			_scheduledEvent->cancel();
-
-			completeTransition(runtime);
-		}
-
+		disable(runtime);
 		return kVThreadReturn;
 	}
 
 	return Modifier::consumeMessage(runtime, msg);
 }
 
+void ElementTransitionModifier::disable(Runtime *runtime) {
+	if (_scheduledEvent) {
+		_scheduledEvent->cancel();
+
+		completeTransition(runtime);
+	}
+}
+
 Common::SharedPtr<Modifier> ElementTransitionModifier::shallowClone() const {
 	Common::SharedPtr<ElementTransitionModifier> clone(new ElementTransitionModifier(*this));
 	clone->_scheduledEvent.reset();
@@ -1241,11 +1288,10 @@ bool TimerMessengerModifier::respondsToEvent(const Event &evt) const {
 VThreadState TimerMessengerModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
 	// If this terminates AND starts then just cancel out and terminate
 	if (_terminateWhen.respondsTo(msg->getEvent())) {
-		if (_scheduledEvent) {
-			_scheduledEvent->cancel();
-			_scheduledEvent.reset();
-		}
-	} else if (_executeWhen.respondsTo(msg->getEvent())) {
+		disable(runtime);
+		return kVThreadReturn;
+	}
+	if (_executeWhen.respondsTo(msg->getEvent())) {
 		// 0-time events are not allowed
 		uint32 realMilliseconds = _milliseconds;
 		if (realMilliseconds == 0)
@@ -1262,11 +1308,20 @@ VThreadState TimerMessengerModifier::consumeMessage(Runtime *runtime, const Comm
 		_incomingData = msg->getValue();
 		if (_incomingData.getType() == DynamicValueTypes::kList)
 			_incomingData.setList(_incomingData.getList()->clone());
+
+		return kVThreadReturn;
 	}
 
 	return kVThreadReturn;
 }
 
+void TimerMessengerModifier::disable(Runtime *runtime) {
+	if (_scheduledEvent) {
+		_scheduledEvent->cancel();
+		_scheduledEvent.reset();
+	}
+}
+
 void TimerMessengerModifier::linkInternalReferences(ObjectLinkingScope *outerScope) {
 	_sendSpec.linkInternalReferences(outerScope);
 }
@@ -1346,13 +1401,19 @@ VThreadState BoundaryDetectionMessengerModifier::consumeMessage(Runtime *runtime
 		if (_incomingData.getType() == DynamicValueTypes::kList)
 			_incomingData.setList(_incomingData.getList()->clone());
 	}
-	if (_disableWhen.respondsTo(msg->getEvent()) && _isActive) {
+	if (_disableWhen.respondsTo(msg->getEvent())) {
+		disable(runtime);
+	}
+
+	return kVThreadReturn;
+}
+
+void BoundaryDetectionMessengerModifier::disable(Runtime *runtime) {
+	if (_isActive) {
 		_runtime->removeBoundaryDetector(this);
 		_isActive = false;
 		_runtime = nullptr;
 	}
-
-	return kVThreadReturn;
 }
 
 void BoundaryDetectionMessengerModifier::linkInternalReferences(ObjectLinkingScope *outerScope) {
@@ -1454,16 +1515,20 @@ VThreadState CollisionDetectionMessengerModifier::consumeMessage(Runtime *runtim
 		}
 	}
 	if (_disableWhen.respondsTo(msg->getEvent())) {
-		if (_isActive) {
-			_isActive = false;
-			_runtime->removeCollider(this);
-			_incomingData = DynamicValue();
-		}
+		disable(runtime);
 	}
 
 	return kVThreadReturn;
 }
 
+void CollisionDetectionMessengerModifier::disable(Runtime *runtime) {
+	if (_isActive) {
+		_isActive = false;
+		_runtime->removeCollider(this);
+		_incomingData = DynamicValue();
+	}
+}
+
 void CollisionDetectionMessengerModifier::linkInternalReferences(ObjectLinkingScope *scope) {
 	_sendSpec.linkInternalReferences(scope);
 }
@@ -1586,12 +1651,16 @@ VThreadState KeyboardMessengerModifier::consumeMessage(Runtime *runtime, const C
  	if (Event::create(EventIDs::kParentEnabled, 0).respondsTo(msg->getEvent())) {
 		_isEnabled = true;
 	} else if (Event::create(EventIDs::kParentDisabled, 0).respondsTo(msg->getEvent())) {
-		_isEnabled = false;
+		disable(runtime);
 	}
 
 	return kVThreadReturn;
 }
 
+void KeyboardMessengerModifier::disable(Runtime *runtime) {
+	_isEnabled = false;
+}
+
 Common::SharedPtr<Modifier> KeyboardMessengerModifier::shallowClone() const {
 	Common::SharedPtr<KeyboardMessengerModifier> cloned(new KeyboardMessengerModifier(*this));
 	cloned->_isEnabled = false;
@@ -1789,13 +1858,16 @@ VThreadState TextStyleModifier::consumeMessage(Runtime *runtime, const Common::S
 
 		return kVThreadReturn;
 	} else if (_removeWhen.respondsTo(msg->getEvent())) {
-		// Doesn't actually do anything
+		disable(runtime);
 		return kVThreadReturn;
 	}
 
 	return Modifier::consumeMessage(runtime, msg);
 }
 
+void TextStyleModifier::disable(Runtime *runtime) {
+	// Doesn't actually do anything
+}
 
 Common::SharedPtr<Modifier> TextStyleModifier::shallowClone() const {
 	return Common::SharedPtr<Modifier>(new TextStyleModifier(*this));
@@ -1861,13 +1933,30 @@ VThreadState GraphicModifier::consumeMessage(Runtime *runtime, const Common::Sha
 		visual->setRenderProperties(_renderProps, this->getSelfReference().staticCast<GraphicModifier>());
 	}
 	if (_removeWhen.respondsTo(msg->getEvent())) {
-		if (visual->getPrimaryGraphicModifier().lock().get() == this)
-			static_cast<VisualElement *>(element)->setRenderProperties(VisualElementRenderProperties(), Common::WeakPtr<GraphicModifier>());
+		disable(runtime);
 	}
 
 	return kVThreadReturn;
 }
 
+void GraphicModifier::disable(Runtime *runtime) {
+	Structural *owner = findStructuralOwner();
+	if (!owner)
+		return;
+
+	if (!owner->isElement())
+		return;
+
+	Element *element = static_cast<Element *>(owner);
+	if (!element->isVisual())
+		return;
+
+	VisualElement *visual = static_cast<VisualElement *>(element);
+
+	if (visual->getPrimaryGraphicModifier().lock().get() == this)
+		static_cast<VisualElement *>(element)->setRenderProperties(VisualElementRenderProperties(), Common::WeakPtr<GraphicModifier>());
+}
+
 Common::SharedPtr<Modifier> GraphicModifier::shallowClone() const {
 	return Common::SharedPtr<Modifier>(new GraphicModifier(*this));
 }
@@ -1894,6 +1983,10 @@ bool CompoundVariableModifier::load(ModifierLoaderContext &context, const Data::
 	return true;
 }
 
+void CompoundVariableModifier::disable(Runtime *runtime) {
+	// Do nothing I guess, no variables can be disdabled
+}
+
 Common::SharedPtr<ModifierSaveLoad> CompoundVariableModifier::getSaveLoad() {
 	return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
 }
diff --git a/engines/mtropolis/modifiers.h b/engines/mtropolis/modifiers.h
index 168cc14ce2a..77d129354bf 100644
--- a/engines/mtropolis/modifiers.h
+++ b/engines/mtropolis/modifiers.h
@@ -52,6 +52,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Behavior Modifier"; }
@@ -75,8 +76,15 @@ private:
 		Runtime *runtime;
 	};
 
+	struct DisableTaskData {
+		DisableTaskData() : runtime(nullptr) {}
+
+		Runtime *runtime;
+	};
+
 	VThreadState switchTask(const SwitchTaskData &taskData);
 	VThreadState propagateTask(const PropagateTaskData &taskData);
+	VThreadState disableTask(const DisableTaskData &taskData);
 
 	Common::SharedPtr<Modifier> shallowClone() const override;
 	const char *getDefaultName() const override;
@@ -98,6 +106,8 @@ public:
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
 
+	void disable(Runtime *runtime) override {}
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Miniscript Modifier"; }
 	SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
@@ -122,6 +132,8 @@ public:
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
 
+	void disable(Runtime *runtime) override {}
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Save And Restore Modifier"; }
 	SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
@@ -147,6 +159,8 @@ public:
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
 
+	void disable(Runtime *runtime) override {}
+
 	void linkInternalReferences(ObjectLinkingScope *outerScope) override;
 	void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
 
@@ -167,6 +181,8 @@ class SetModifier : public Modifier {
 public:
 	bool load(ModifierLoaderContext &context, const Data::SetModifier &data);
 
+	void disable(Runtime *runtime) override {}
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Set Modifier"; }
 #endif
@@ -187,6 +203,8 @@ public:
 
 	bool isAlias() const override;
 
+	void disable(Runtime *runtime) override {}
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Alias Modifier"; }
 	SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
@@ -206,6 +224,8 @@ public:
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
 
+	void disable(Runtime *runtime) override {}
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Change Scene Modifier"; }
 	SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
@@ -237,6 +257,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Sound Effect Modifier"; }
@@ -272,6 +293,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Path Motion Modifier"; }
@@ -313,6 +335,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Drag Motion Modifier"; }
@@ -337,6 +360,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Vector Modifier"; }
@@ -371,6 +395,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Scene Transition Modifier"; }
@@ -398,6 +423,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 	enum TransitionType {
 		kTransitionTypeRectangularIris,
@@ -445,6 +471,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override {}
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "If Messenger Modifier"; }
@@ -482,6 +509,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 	void linkInternalReferences(ObjectLinkingScope *outerScope) override;
 	void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
@@ -516,6 +544,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 	void linkInternalReferences(ObjectLinkingScope *outerScope) override;
 	void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
@@ -565,6 +594,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 	void linkInternalReferences(ObjectLinkingScope *scope) override;
 	void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
@@ -615,6 +645,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 	bool checkKeyEventTrigger(Runtime *runtime, Common::EventType evtType, bool repeat, const Common::KeyState &keyEvt, Common::String &outChar) const;
 	void dispatchMessage(Runtime *runtime, const Common::String &charStr);
@@ -672,6 +703,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Text Style Modifier"; }
@@ -698,6 +730,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Graphic Modifier"; }
@@ -723,6 +756,8 @@ class CompoundVariableModifier : public Modifier, public IModifierContainer {
 public:
 	bool load(ModifierLoaderContext &context, const Data::CompoundVariableModifier &data);
 
+	void disable(Runtime *runtime) override;
+
 	Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
 
 	IModifierContainer *getChildContainer() override;
diff --git a/engines/mtropolis/plugin/obsidian.cpp b/engines/mtropolis/plugin/obsidian.cpp
index 50795842d98..06d7e402342 100644
--- a/engines/mtropolis/plugin/obsidian.cpp
+++ b/engines/mtropolis/plugin/obsidian.cpp
@@ -94,15 +94,19 @@ VThreadState MovementModifier::consumeMessage(Runtime *runtime, const Common::Sh
 		}
 	}
 	if (_disableWhen.respondsTo(msg->getEvent())) {
-		if (_moveEvent) {
-			_moveEvent->cancel();
-			_moveEvent.reset();
-		}
+		disable(runtime);
 	}
 
 	return kVThreadReturn;
 }
 
+void MovementModifier::disable(Runtime *runtime) {
+	if (_moveEvent) {
+		_moveEvent->cancel();
+		_moveEvent.reset();
+	}
+}
+
 MiniscriptInstructionOutcome MovementModifier::writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) {
 	if (attrib == "type") {
 		DynamicValueWriteBoolHelper::create(&_type, result);
@@ -213,12 +217,18 @@ VThreadState RectShiftModifier::consumeMessage(Runtime *runtime, const Common::S
 		_isActive = true;
 	}
 	if (_disableWhen.respondsTo(msg->getEvent()) && _isActive) {
+		disable(runtime);
+	}
+
+	return kVThreadReturn;
+}
+
+void RectShiftModifier::disable(Runtime *runtime) {
+	if (_isActive) {
 		_isActive = false;
 		_runtime->removePostEffect(this);
 		_runtime = nullptr;
 	}
-
-	return kVThreadReturn;
 }
 
 bool RectShiftModifier::load(const PlugInModifierLoaderContext &context, const Data::Obsidian::RectShiftModifier &data) {
@@ -798,32 +808,44 @@ bool XorModModifier::respondsToEvent(const Event &evt) const {
 }
 
 VThreadState XorModModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
-	Structural *owner = findStructuralOwner();
-	if (!owner)
-		return kVThreadError;
+	if (_enableWhen.respondsTo(msg->getEvent())) {
+		Structural *owner = findStructuralOwner();
+		if (!owner)
+			return kVThreadError;
 
-	if (!owner->isElement())
-		return kVThreadReturn;
+		if (!owner->isElement())
+			return kVThreadReturn;
 
-	Element *element = static_cast<Element *>(owner);
-	if (!element->isVisual())
-		return kVThreadReturn;
+		Element *element = static_cast<Element *>(owner);
+		if (!element->isVisual())
+			return kVThreadReturn;
 
-	VisualElement *visual = static_cast<VisualElement *>(element);
+		VisualElement *visual = static_cast<VisualElement *>(element);
 
-	VisualElementRenderProperties renderProps = visual->getRenderProperties();
-	renderProps.setInkMode(VisualElementRenderProperties::kInkModeXor);
+		VisualElementRenderProperties renderProps = visual->getRenderProperties();
+		renderProps.setInkMode(VisualElementRenderProperties::kInkModeXor);
 
-	if (_shapeID == 0)
-		renderProps.setShape(VisualElementRenderProperties::kShapeRect);
-	else
-		renderProps.setShape(static_cast<VisualElementRenderProperties::Shape>(VisualElementRenderProperties::kShapeObsidianCanvasPuzzleTri1 + _shapeID - 1));
+		if (_shapeID == 0)
+			renderProps.setShape(VisualElementRenderProperties::kShapeRect);
+		else
+			renderProps.setShape(static_cast<VisualElementRenderProperties::Shape>(VisualElementRenderProperties::kShapeObsidianCanvasPuzzleTri1 + _shapeID - 1));
 
-	visual->setRenderProperties(renderProps, Common::WeakPtr<GraphicModifier>());
+		visual->setRenderProperties(renderProps, Common::WeakPtr<GraphicModifier>());
+
+		return kVThreadReturn;
+	}
+	if (_disableWhen.respondsTo(msg->getEvent())) {
+		disable(runtime);
+		return kVThreadReturn;
+	}
 
 	return kVThreadReturn;
 }
 
+void XorModModifier::disable(Runtime *runtime) {
+	// This is a special-purpose modifier and is never disabled
+}
+
 Common::SharedPtr<Modifier> XorModModifier::shallowClone() const {
 	return Common::SharedPtr<Modifier>(new XorModModifier(*this));
 }
diff --git a/engines/mtropolis/plugin/obsidian.h b/engines/mtropolis/plugin/obsidian.h
index 6e261cf0eb1..6e03ffaeb52 100644
--- a/engines/mtropolis/plugin/obsidian.h
+++ b/engines/mtropolis/plugin/obsidian.h
@@ -46,6 +46,8 @@ public:
 
 	MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
 
+	void disable(Runtime *runtime) override;
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Movement Modifier"; }
 	void debugInspect(IDebugInspectionReport *report) const override;
@@ -81,6 +83,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 	bool load(const PlugInModifierLoaderContext &context, const Data::Obsidian::RectShiftModifier &data);
 
@@ -115,6 +118,8 @@ public:
 	bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
 	MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
 
+	void disable(Runtime *runtime) override {}
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "TextWork Modifier"; }
 	SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
@@ -144,6 +149,8 @@ public:
 	bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
 	MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
 
+	void disable(Runtime *runtime) override {}
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Dictionary Modifier"; }
 	SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
@@ -173,6 +180,8 @@ public:
 	bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
 	MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
 
+	void disable(Runtime *runtime) override {}
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "WordMixer Modifier"; }
 	SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
@@ -201,6 +210,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Xor Mod Modifier"; }
@@ -226,6 +236,8 @@ public:
 	bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
 	MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
 
+	void disable(Runtime *runtime) override {}
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Xor Check Modifier"; }
 	SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
diff --git a/engines/mtropolis/plugin/standard.cpp b/engines/mtropolis/plugin/standard.cpp
index dca08eb54bb..b50598d7733 100644
--- a/engines/mtropolis/plugin/standard.cpp
+++ b/engines/mtropolis/plugin/standard.cpp
@@ -1574,11 +1574,16 @@ VThreadState CursorModifier::consumeMessage(Runtime *runtime, const Common::Shar
 		runtime->setModifierCursorOverride(_cursorID);
 	}
 	if (_removeWhen.respondsTo(msg->getEvent())) {
+		// This doesn't call "disable" because the behavior is actually different.
+		// Disabling a cursor modifier doesn't seem to remove it.
 		runtime->clearModifierCursorOverride();
 	}
 	return kVThreadReturn;
 }
 
+void CursorModifier::disable(Runtime *runtime) {
+}
+
 bool CursorModifier::load(const PlugInModifierLoaderContext &context, const Data::Standard::CursorModifier &data) {
 	if (!_applyWhen.load(data.applyWhen) || !_removeWhen.load(data.removeWhen))
 		return false;
@@ -1646,11 +1651,15 @@ VThreadState STransCtModifier::consumeMessage(Runtime *runtime, const Common::Sh
 		}
 	}
 	if (_disableWhen.respondsTo(msg->getEvent()))
-		runtime->setSceneTransitionEffect(false, nullptr);
+		disable(runtime);
 
 	return kVThreadReturn;
 }
 
+void STransCtModifier::disable(Runtime *runtime) {
+	runtime->setSceneTransitionEffect(false, nullptr);
+}
+
 bool STransCtModifier::readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) {
 	if (attrib == "rate") {
 		if (_duration <= (kMaxDuration / 100))
@@ -1848,18 +1857,22 @@ VThreadState MediaCueMessengerModifier::consumeMessage(Runtime *runtime, const C
 		}
 	}
 	if (_disableWhen.respondsTo(msg->getEvent())) {
-		if (_isActive) {
-			Structural *owner = findStructuralOwner();
-			if (owner && owner->isElement())
-				static_cast<Element *>(owner)->removeMediaCue(&_mediaCue);
-
-			_isActive = false;
-		}
+		disable(runtime);
 	}
 
 	return kVThreadReturn;
 }
 
+void MediaCueMessengerModifier::disable(Runtime *runtime) {
+	if (_isActive) {
+		Structural *owner = findStructuralOwner();
+		if (owner && owner->isElement())
+			static_cast<Element *>(owner)->removeMediaCue(&_mediaCue);
+
+		_isActive = false;
+	}
+}
+
 Common::SharedPtr<Modifier> MediaCueMessengerModifier::shallowClone() const {
 	Common::SharedPtr<MediaCueMessengerModifier> clone(new MediaCueMessengerModifier(*this));
 	clone->_isActive = false;
@@ -2351,19 +2364,23 @@ VThreadState MidiModifier::consumeMessage(Runtime *runtime, const Common::Shared
 		}
 	}
 	if (_terminateWhen.respondsTo(msg->getEvent())) {
-		if (_filePlayer) {
-			_plugIn->getMidi()->deleteFilePlayer(_filePlayer);
-			_filePlayer = nullptr;
-		}
-		if (_notePlayer) {
-			_plugIn->getMidi()->deleteNotePlayer(_notePlayer);
-			_notePlayer = nullptr;
-		}
+		disable(runtime);
 	}
 
 	return kVThreadReturn;
 }
 
+void MidiModifier::disable(Runtime *runtime) {
+	if (_filePlayer) {
+		_plugIn->getMidi()->deleteFilePlayer(_filePlayer);
+		_filePlayer = nullptr;
+	}
+	if (_notePlayer) {
+		_plugIn->getMidi()->deleteNotePlayer(_notePlayer);
+		_notePlayer = nullptr;
+	}
+}
+
 void MidiModifier::playSingleNote() {
 	if (!_notePlayer)
 		_notePlayer = _plugIn->getMidi()->createNotePlayer();
diff --git a/engines/mtropolis/plugin/standard.h b/engines/mtropolis/plugin/standard.h
index 9fd9407cb19..f01f3c9bf29 100644
--- a/engines/mtropolis/plugin/standard.h
+++ b/engines/mtropolis/plugin/standard.h
@@ -49,6 +49,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Cursor Modifier"; }
@@ -77,6 +78,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 	bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
 	MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
@@ -111,6 +113,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "Media Cue Modifier"; }
@@ -221,6 +224,7 @@ public:
 
 	bool respondsToEvent(const Event &evt) const override;
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+	void disable(Runtime *runtime) override;
 
 	bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
 	MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
@@ -359,6 +363,8 @@ public:
 
 	bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
 
+	void disable(Runtime *runtime) override {}
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "System Info Modifier"; }
 #endif
diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index 1d094953ed1..13e52eabd06 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -8148,6 +8148,9 @@ bool VariableModifier::readAttribute(MiniscriptThread *thread, DynamicValue &res
 	return Modifier::readAttribute(thread, result, attrib);
 }
 
+void VariableModifier::disable(Runtime *runtime) {
+}
+
 DynamicValueWriteProxy VariableModifier::createWriteProxy() {
 	DynamicValueWriteProxy proxy;
 	proxy.pod.objectRef = this;
diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h
index abe8445f30d..d842d08bfae 100644
--- a/engines/mtropolis/runtime.h
+++ b/engines/mtropolis/runtime.h
@@ -2740,6 +2740,9 @@ public:
 	void setHooks(const Common::SharedPtr<ModifierHooks> &hooks);
 	const Common::SharedPtr<ModifierHooks> &getHooks() const;
 
+	// Recursively disable due to containing behavior being disabled
+	virtual void disable(Runtime *runtime) = 0;
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	SupportStatus debugGetSupportStatus() const override;
 	const Common::String &debugGetName() const override;
@@ -2769,6 +2772,8 @@ public:
 
 	bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
 
+	void disable(Runtime *runtime) override;
+
 	virtual DynamicValueWriteProxy createWriteProxy();
 
 private:




More information about the Scummvm-git-logs mailing list