[Scummvm-git-logs] scummvm master -> 6acba4efc43f062a4b68aff9b90ccd4185ae8e27

elasota noreply at scummvm.org
Mon Jan 2 23:09:12 UTC 2023


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:
6acba4efc4 MTROPOLIS: Fire "show" commands to unhide elements at scene load instead of them being immediately visible.  Fixes MTI B


Commit: 6acba4efc43f062a4b68aff9b90ccd4185ae8e27
    https://github.com/scummvm/scummvm/commit/6acba4efc43f062a4b68aff9b90ccd4185ae8e27
Author: elasota (ejlasota at gmail.com)
Date: 2023-01-02T18:08:33-05:00

Commit Message:
MTROPOLIS: Fire "show" commands to unhide elements at scene load instead of them being immediately visible.  Fixes MTI Benbow outro.

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


diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index 1db8503e168..7cad07bac2e 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -4138,6 +4138,10 @@ Runtime::ConsumeMessageTaskData::ConsumeMessageTaskData() : consumer(nullptr) {
 Runtime::ConsumeCommandTaskData::ConsumeCommandTaskData() : structural(nullptr) {
 }
 
+Runtime::ApplyDefaultVisibilityTaskData::ApplyDefaultVisibilityTaskData() : element(nullptr), targetVisibility(false) {
+}
+
+
 Runtime::UpdateMouseStateTaskData::UpdateMouseStateTaskData() : mouseDown(false) {
 }
 
@@ -4444,7 +4448,7 @@ bool Runtime::runFrame() {
 		}
 
 		// 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.
+		// after Scene Started, Scene Changed, and element Show events, 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:
@@ -4780,12 +4784,34 @@ void Runtime::executeLowLevelSceneStateTransition(const LowLevelSceneStateTransi
 			forceCursorRefreshOnce();
 		}
 		break;
+	case LowLevelSceneStateTransitionAction::kShowDefaultVisibleElements:
+		executeSceneChangeRecursiveVisibilityChange(action.getScene().get(), true);
+		break;
+	case LowLevelSceneStateTransitionAction::kHideAllElements:
+		executeSceneChangeRecursiveVisibilityChange(action.getScene().get(), false);
+		break;
 	default:
 		assert(false);
 		break;
 	}
 }
 
+void Runtime::executeSceneChangeRecursiveVisibilityChange(Structural *structural, bool showing) {
+	const Common::Array<Common::SharedPtr<Structural> > &children = structural->getChildren();
+
+	// Queue in reverse order since VThread sends are LIFO
+	for (size_t i = 0; i < children.size(); i++)
+		executeSceneChangeRecursiveVisibilityChange(children[children.size() - 1 - i].get(), showing);
+
+	if (structural->isElement() && static_cast<Element *>(structural)->isVisual()) {
+		VisualElement *visual = static_cast<VisualElement *>(structural);
+
+		ApplyDefaultVisibilityTaskData *taskData = getVThread().pushTask("Runtime::applyDefaultVisibility", this, &Runtime::applyDefaultVisibility);
+		taskData->element = visual;
+		taskData->targetVisibility = showing;
+	}
+}
+
 void Runtime::executeCompleteTransitionToScene(const Common::SharedPtr<Structural> &targetScene) {
 	// NOTE: Transitioning to the same scene is allowed, Obsidian relies on this to avoid getting stuck
 	// after going up the wrong side in the Bureau chapter final area (i.e. after reaching the sky face).
@@ -4813,6 +4839,7 @@ void Runtime::executeCompleteTransitionToScene(const Common::SharedPtr<Structura
 		Common::SharedPtr<Structural> stackedScene = _sceneStack[i].scene;
 
 		queueEventAsLowLevelSceneStateTransitionAction(Event(EventIDs::kSceneEnded, 0), _activeMainScene.get(), true, true);
+		_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(_activeMainScene, LowLevelSceneStateTransitionAction::kHideAllElements));
 		queueEventAsLowLevelSceneStateTransitionAction(Event(EventIDs::kParentDisabled, 0), _activeMainScene.get(), true, true);
 		_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(_activeMainScene, LowLevelSceneStateTransitionAction::kUnload));
 
@@ -4825,6 +4852,7 @@ void Runtime::executeCompleteTransitionToScene(const Common::SharedPtr<Structura
 	if (targetSharedScene != _activeSharedScene) {
 		if (_activeSharedScene) {
 			queueEventAsLowLevelSceneStateTransitionAction(Event(EventIDs::kSceneEnded, 0), _activeSharedScene.get(), true, true);
+			_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(_activeMainScene, LowLevelSceneStateTransitionAction::kHideAllElements));
 			queueEventAsLowLevelSceneStateTransitionAction(Event(EventIDs::kParentDisabled, 0), _activeSharedScene.get(), true, true);
 			_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(_activeSharedScene, LowLevelSceneStateTransitionAction::kUnload));
 		}
@@ -4833,6 +4861,8 @@ void Runtime::executeCompleteTransitionToScene(const Common::SharedPtr<Structura
 		queueEventAsLowLevelSceneStateTransitionAction(Event(EventIDs::kParentEnabled, 0), targetSharedScene.get(), true, true);
 		queueEventAsLowLevelSceneStateTransitionAction(Event(EventIDs::kSceneStarted, 0), targetSharedScene.get(), true, true);
 
+		_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(targetSharedScene, LowLevelSceneStateTransitionAction::kShowDefaultVisibleElements));
+
 		SceneStackEntry sharedSceneEntry;
 		sharedSceneEntry.scene = targetSharedScene;
 
@@ -4942,6 +4972,7 @@ void Runtime::executeHighLevelSceneTransition(const HighLevelSceneTransition &tr
 						_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(targetSharedScene, LowLevelSceneStateTransitionAction::kLoad));
 						queueEventAsLowLevelSceneStateTransitionAction(Event(EventIDs::kParentEnabled, 0), targetSharedScene.get(), true, true);
 						queueEventAsLowLevelSceneStateTransitionAction(Event(EventIDs::kSceneStarted, 0), targetSharedScene.get(), true, true);
+						_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(targetSharedScene, LowLevelSceneStateTransitionAction::kShowDefaultVisibleElements));
 
 						SceneStackEntry sharedSceneEntry;
 						sharedSceneEntry.scene = targetScene;
@@ -4993,6 +5024,7 @@ void Runtime::executeHighLevelSceneTransition(const HighLevelSceneTransition &tr
 				_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(targetSharedScene, LowLevelSceneStateTransitionAction::kLoad));
 				queueEventAsLowLevelSceneStateTransitionAction(Event(EventIDs::kParentEnabled, 0), targetSharedScene.get(), true, true);
 				queueEventAsLowLevelSceneStateTransitionAction(Event(EventIDs::kSceneStarted, 0), targetSharedScene.get(), true, true);
+				_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(targetSharedScene, LowLevelSceneStateTransitionAction::kShowDefaultVisibleElements));
 
 				SceneStackEntry sharedSceneEntry;
 				sharedSceneEntry.scene = targetSharedScene;
@@ -5022,6 +5054,8 @@ void Runtime::executeSharedScenePostSceneChangeActions() {
 		if (_activeMainScene == subsectionScenes[1])
 			queueEventAsLowLevelSceneStateTransitionAction(Event(EventIDs::kSharedSceneNoPrevScene, 0), _activeSharedScene.get(), true, true);
 	}
+
+	_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(_activeMainScene, LowLevelSceneStateTransitionAction::kShowDefaultVisibleElements));
 }
 
 void Runtime::recursiveDeactivateStructural(Structural *structural) {
@@ -5725,6 +5759,29 @@ VThreadState Runtime::updateMousePositionTask(const UpdateMousePositionTaskData
 	return kVThreadReturn;
 }
 
+VThreadState Runtime::applyDefaultVisibility(const ApplyDefaultVisibilityTaskData &data) {
+	Event evt;
+	if (data.targetVisibility) {
+		if (data.element->isVisibleByDefault() == false || data.element->isVisible())
+			return kVThreadReturn;
+
+		evt = Event(EventIDs::kElementShow, 0);
+	} else {
+		if (!data.element->isVisible())
+			return kVThreadReturn;
+
+		evt = Event(EventIDs::kElementHide, 0);
+	}
+
+	// Visibility change events are sourced from the element
+ 	Common::SharedPtr<MessageProperties> props(new MessageProperties(evt, DynamicValue(), data.element->getSelfReference()));
+	Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(props, data.element, false, false, true));
+
+	sendMessageOnVThread(dispatch);
+
+	return kVThreadReturn;
+}
+
 void Runtime::updateMainWindowCursor() {
 	const uint32 kHandPointUpID = 10005;
 	const uint32 kArrowID = 10011;
@@ -7894,7 +7951,7 @@ VisualElementRenderProperties &VisualElementRenderProperties::operator=(const Vi
 */
 
 VisualElement::VisualElement()
-	: _rect(0, 0, 0, 0), _cachedAbsoluteOrigin(Common::Point(0, 0)), _contentsDirty(true), _directToScreen(false), _visible(true), _layer(0) {
+	: _rect(0, 0, 0, 0), _cachedAbsoluteOrigin(Common::Point(0, 0)), _contentsDirty(true), _directToScreen(false), _visible(false), _layer(0) {
 }
 
 bool VisualElement::isVisual() const {
@@ -7909,6 +7966,10 @@ bool VisualElement::isVisible() const {
 	return _visible;
 }
 
+bool VisualElement::isVisibleByDefault() const {
+	return _visibleByDefault;
+}
+
 void VisualElement::setVisible(Runtime *runtime, bool visible) {
 	if (_visible != visible) {
 		runtime->setSceneGraphDirty();
@@ -8329,7 +8390,7 @@ void VisualElement::debugInspect(IDebugInspectionReport *report) const {
 #endif
 
 MiniscriptInstructionOutcome VisualElement::scriptSetVisibility(MiniscriptThread *thread, const DynamicValue &result) {
-	// FIXME: Need to make this fire Show/Hide events!
+	// FIXME: Need to make this fire Show/Hide events??
 	if (result.getType() == DynamicValueTypes::kBoolean) {
 		const bool targetValue = result.getBool();
 		if (_visible != targetValue) {
@@ -8348,7 +8409,7 @@ bool VisualElement::loadCommon(const Common::String &name, uint32 guid, const Da
 
 	_name = name;
 	_guid = guid;
-	_visible = ((elementFlags & Data::ElementFlags::kHidden) == 0);
+	_visibleByDefault = ((elementFlags & Data::ElementFlags::kHidden) == 0);	// Element isn't actually flagged as visible until after Scene Changed, when Show commands are fired
 	_directToScreen = ((elementFlags & Data::ElementFlags::kNotDirectToScreen) == 0);
 	_streamLocator = streamLocator;
 	_sectionID = sectionID;
diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h
index f852fb60367..3977e97ed43 100644
--- a/engines/mtropolis/runtime.h
+++ b/engines/mtropolis/runtime.h
@@ -1313,6 +1313,8 @@ struct LowLevelSceneStateTransitionAction {
 		kUnload,
 		kSendMessage,
 		kAutoResetCursor,
+		kHideAllElements,
+		kShowDefaultVisibleElements,
 	};
 
 	explicit LowLevelSceneStateTransitionAction(const Common::SharedPtr<MessageDispatch> &msg);
@@ -1573,7 +1575,6 @@ public:
 
 	void addVolume(int volumeID, const char *name, bool isMounted);
 	bool getVolumeState(const Common::String &name, int &outVolumeID, bool &outIsMounted) const;
-	void setDefaultVolumeState(bool defaultState);
 
 	void addSceneStateTransition(const HighLevelSceneTransition &transition);
 
@@ -1762,6 +1763,13 @@ private:
 		Common::SharedPtr<MessageProperties> message;
 	};
 
+	struct ApplyDefaultVisibilityTaskData {
+		ApplyDefaultVisibilityTaskData();
+
+		VisualElement *element;
+		bool targetVisibility;
+	};
+
 	struct UpdateMouseStateTaskData {
 		UpdateMouseStateTaskData();
 
@@ -1806,6 +1814,7 @@ private:
 	void executeHighLevelSceneTransition(const HighLevelSceneTransition &transition);
 	void executeCompleteTransitionToScene(const Common::SharedPtr<Structural> &scene);
 	void executeSharedScenePostSceneChangeActions();
+	void executeSceneChangeRecursiveVisibilityChange(Structural *structural, bool showing);
 
 	void recursiveAutoPlayMedia(Structural *structural);
 	void recursiveDeactivateStructural(Structural *structural);
@@ -1831,6 +1840,7 @@ private:
 	VThreadState consumeCommandTask(const ConsumeCommandTaskData &data);
 	VThreadState updateMouseStateTask(const UpdateMouseStateTaskData &data);
 	VThreadState updateMousePositionTask(const UpdateMousePositionTaskData &data);
+	VThreadState applyDefaultVisibility(const ApplyDefaultVisibilityTaskData &data);
 
 	void updateMainWindowCursor();
 
@@ -2692,6 +2702,7 @@ public:
 	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
 
 	bool isVisible() const;
+	bool isVisibleByDefault() const;
 	void setVisible(Runtime *runtime, bool visible);
 
 	bool isDirectToScreen() const;
@@ -2787,6 +2798,7 @@ protected:
 
 	bool _directToScreen;
 	bool _visible;
+	bool _visibleByDefault;
 	Common::Rect _rect;
 	Common::Point _cachedAbsoluteOrigin;
 	uint16 _layer;




More information about the Scummvm-git-logs mailing list