[Scummvm-git-logs] scummvm master -> d9642925ebe84a33ad31e8cb1186850576902f99

elasota noreply at scummvm.org
Tue Jul 19 21:39:41 UTC 2022


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

Summary:
d285f0e96b MTROPOLIS: Clean up unused namespace def
56161d17f0 MTROPOLIS: Improve anamorphic filter
e43a2fcb89 MTROPOLIS: Fix STransCt wipe duration at 500ms since that seems to be the accurate behavior
0d8ba6982a MTROPOLIS: Make autorefreshcursor trigger later to fix Obsidian wave puzzle completing instantly in the Mac version
d9642925eb MTROPOLIS: Implement mToon stop command


Commit: d285f0e96b7bca8a7e1214b04574f1830fb024a3
    https://github.com/scummvm/scummvm/commit/d285f0e96b7bca8a7e1214b04574f1830fb024a3
Author: elasota (ejlasota at gmail.com)
Date: 2022-07-19T17:38:09-04:00

Commit Message:
MTROPOLIS: Clean up unused namespace def

Changed paths:
    engines/mtropolis/assets.h


diff --git a/engines/mtropolis/assets.h b/engines/mtropolis/assets.h
index 6148ca38b9a..c1824a19243 100644
--- a/engines/mtropolis/assets.h
+++ b/engines/mtropolis/assets.h
@@ -26,9 +26,6 @@
 #include "mtropolis/runtime.h"
 #include "mtropolis/render.h"
 
-namespace Audio {
-} // End of namespace Audio
-
 namespace MTropolis {
 
 struct AssetLoaderContext;


Commit: 56161d17f085e6d598810a9a9efd264c77ee0bf4
    https://github.com/scummvm/scummvm/commit/56161d17f085e6d598810a9a9efd264c77ee0bf4
Author: elasota (ejlasota at gmail.com)
Date: 2022-07-19T17:38:09-04:00

Commit Message:
MTROPOLIS: Improve anamorphic filter

Changed paths:
    engines/mtropolis/hacks.cpp


diff --git a/engines/mtropolis/hacks.cpp b/engines/mtropolis/hacks.cpp
index 5a2b9cf85d9..d263bac2b61 100644
--- a/engines/mtropolis/hacks.cpp
+++ b/engines/mtropolis/hacks.cpp
@@ -156,6 +156,9 @@ private:
 	template<class TPixel>
 	void anamorphicScaleFrameTyped(const Graphics::Surface &src, Graphics::Surface &dest) const;
 
+	static double anamorphicCurve(double d);
+	static double inverseAnamorphicCurve(double d);
+
 	template<class TPixel>
 	void halveWidthTyped(const Graphics::Surface &src, Graphics::Surface &dest) const;
 
@@ -168,6 +171,8 @@ private:
 
 ObsidianRSGLogoAnamorphicFilter::ObsidianRSGLogoAnamorphicFilter() {
 	// Anamorphic rescale, keeps the RSG logo proportional but preserves the vertical spacing!
+	// We use an anamorphic curve of y=x+x^2 which ensures the derivative at 0 is 1, meaning
+	// the rate of change stays constant at with the unfiltered pixels at the edge of the filter.
 	const uint unscaledWidth = 640;
 	const uint unscaledHeight = 480;
 
@@ -184,17 +189,35 @@ ObsidianRSGLogoAnamorphicFilter::ObsidianRSGLogoAnamorphicFilter() {
 
 	const double sideMarginInScaledImage = (static_cast<double>(scaledWidth) - ((static_cast<double>(unscaledWidth) - sideMarginInOriginalImage * 2.0) * scalingFactor)) * 0.5;
 
+	const double originalMarginHeightFraction = sideMarginInOriginalImage / static_cast<double>(unscaledHeight);
+	const double scaledMarginHeightFraction = sideMarginInScaledImage / static_cast<double>(scaledHeight);
+
+	const double targetCurveRatio = scaledMarginHeightFraction / originalMarginHeightFraction;
+
+	// (x + x^2) / x = targetCurveRatio
+	// (x + x^2) = targetCurveRatio * x
+	// 1 + x = targetCurveRatio
+
+	const double xCurveRatio = targetCurveRatio - 1.0;
+	const double yCurveRatio = anamorphicCurve(xCurveRatio);
+
 	const double rightMarginStart = static_cast<double>(scaledWidth) - sideMarginInScaledImage;
 
 	for (uint i = 0; i < scaledWidth; i++) {
 		double pixelCenterX = static_cast<double>(i) + 0.5;
 		double originalImagePixelCenter = 0.0;
 		if (pixelCenterX < sideMarginInScaledImage) {
-			double marginFraction = pixelCenterX / sideMarginInScaledImage;
-			originalImagePixelCenter = sqrt(marginFraction) * sideMarginInOriginalImage;
+			double marginFraction = 1.0 - pixelCenterX / sideMarginInScaledImage;
+			double marginCurveY = marginFraction * yCurveRatio;
+			double marginCurveX = inverseAnamorphicCurve(marginCurveY);
+			double multiplier = 1.0 - marginCurveX / xCurveRatio;
+			originalImagePixelCenter = multiplier * sideMarginInOriginalImage;
 		} else if (pixelCenterX > rightMarginStart) {
-			double marginFraction = (static_cast<double>(scaledWidth) - pixelCenterX) / sideMarginInScaledImage;
-			originalImagePixelCenter = static_cast<double>(unscaledWidth) - sqrt(marginFraction) * sideMarginInOriginalImage;
+			double marginFraction = 1.0 - (static_cast<double>(scaledWidth) - pixelCenterX) / sideMarginInScaledImage;
+			double marginCurveY = marginFraction * yCurveRatio;
+			double marginCurveX = inverseAnamorphicCurve(marginCurveY);
+			double multiplier = 1.0 - marginCurveX / xCurveRatio;
+			originalImagePixelCenter = static_cast<double>(unscaledWidth) - multiplier * sideMarginInOriginalImage;
 		} else {
 			double offsetFromCenter = pixelCenterX - (static_cast<double>(scaledWidth) * 0.5);
 			double offsetFromCenterInOriginalImage = offsetFromCenter * invScalingFactor;
@@ -234,6 +257,14 @@ void ObsidianRSGLogoAnamorphicFilter::anamorphicScaleFrameTyped(const Graphics::
 	}
 }
 
+double ObsidianRSGLogoAnamorphicFilter::anamorphicCurve(double d) {
+	return d + d * d;
+}
+
+double ObsidianRSGLogoAnamorphicFilter::inverseAnamorphicCurve(double d) {
+	return -0.5 + sqrt(0.25 + d);
+}
+
 template<class TPixel>
 void ObsidianRSGLogoAnamorphicFilter::halveWidthTyped(const Graphics::Surface &src, Graphics::Surface &dest) const {
 	const uint widthHigh = src.w;


Commit: e43a2fcb89442f4805ef94c8e21c3c2cfe0acf52
    https://github.com/scummvm/scummvm/commit/e43a2fcb89442f4805ef94c8e21c3c2cfe0acf52
Author: elasota (ejlasota at gmail.com)
Date: 2022-07-19T17:38:09-04:00

Commit Message:
MTROPOLIS: Fix STransCt wipe duration at 500ms since that seems to be the accurate behavior

Changed paths:
    engines/mtropolis/plugin/standard.cpp


diff --git a/engines/mtropolis/plugin/standard.cpp b/engines/mtropolis/plugin/standard.cpp
index b279d185ed5..ab4a147def3 100644
--- a/engines/mtropolis/plugin/standard.cpp
+++ b/engines/mtropolis/plugin/standard.cpp
@@ -1616,13 +1616,12 @@ VThreadState STransCtModifier::consumeMessage(Runtime *runtime, const Common::Sh
 		effect._steps = _steps;
 
 		if (SceneTransitionTypes::loadFromData(effect._transitionType, _transitionType) && SceneTransitionDirections::loadFromData(effect._transitionDirection, _transitionDirection)) {
-			// Weird quirk: Duration doesn't seem to affect duration properly for wipe transitions.
+			// Duration doesn't seem to affect wipe transitions for some reason.
 			// In Obsidian, this mostly effects 180-degree turns.
-			// Good place to test this is in the corners of the Bureau library.
-			const uint32 kMinWipeDuration = 500;
-
-			if (effect._transitionType == SceneTransitionTypes::kWipe && effect._duration < kMinWipeDuration)
-				effect._duration = kMinWipeDuration;
+			// Good place to test this is in the corners of the Bureau library, where it's 0,
+			// but some cases where it is set (e.g. the Spider control room) have the same duration anyway.
+			if (effect._transitionType == SceneTransitionTypes::kWipe)
+				effect._duration = 500;
 
 			runtime->setSceneTransitionEffect(false, &effect);
 		} else {


Commit: 0d8ba6982a11ed36925cf381cdd33dfedf1f53f1
    https://github.com/scummvm/scummvm/commit/0d8ba6982a11ed36925cf381cdd33dfedf1f53f1
Author: elasota (ejlasota at gmail.com)
Date: 2022-07-19T17:38:09-04:00

Commit Message:
MTROPOLIS: Make autorefreshcursor trigger later to fix Obsidian wave puzzle completing instantly in the Mac version

Changed paths:
    engines/mtropolis/runtime.cpp


diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index cb0316cc31e..d994cba6973 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -3507,6 +3507,10 @@ RuntimeObject *MessageDispatch::getRootPropagator() const {
 		case PropagationStack::kStageSendToStructuralModifiers:
 		case PropagationStack::kStageSendToStructuralSelf:
 			return lowest.ptr.structural;
+		case PropagationStack::kStageCheckAndSendToModifier:
+		case PropagationStack::kStageCheckAndSendToStructural:
+		case PropagationStack::kStageCheckAndSendCommand:
+			return _root.lock().get();
 		default:
 			break;
 		}
@@ -4291,7 +4295,6 @@ void Runtime::executeCompleteTransitionToScene(const Common::SharedPtr<Structura
 	}
 
 	{
-		_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(targetSharedScene, LowLevelSceneStateTransitionAction::kAutoResetCursor));
 		_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(targetScene, LowLevelSceneStateTransitionAction::kLoad));
 		queueEventAsLowLevelSceneStateTransitionAction(Event::create(EventIDs::kParentEnabled, 0), targetScene.get(), true, true);
 		queueEventAsLowLevelSceneStateTransitionAction(Event::create(EventIDs::kSceneStarted, 0), targetScene.get(), true, true);
@@ -4302,6 +4305,12 @@ void Runtime::executeCompleteTransitionToScene(const Common::SharedPtr<Structura
 		_sceneStack.push_back(sceneEntry);
 	}
 
+	// This might not be exactly where this belongs but it must go after Parent Enabled for sure, otherwise
+	// the wave puzzle in the Mac version of Obsidian completes instantly because Parent Enabled hasn't had
+	// a chance to clear the flags.  It looks like what's supposed to happen is the cursor override gets
+	// cleared by the scene transition starting and the cursor reset happens after.  Fix this later...
+	_pendingLowLevelTransitions.push_back(LowLevelSceneStateTransitionAction(targetScene, LowLevelSceneStateTransitionAction::kAutoResetCursor));
+
 	_activeMainScene = targetScene;
 	_activeSharedScene = targetSharedScene;
 


Commit: d9642925ebe84a33ad31e8cb1186850576902f99
    https://github.com/scummvm/scummvm/commit/d9642925ebe84a33ad31e8cb1186850576902f99
Author: elasota (ejlasota at gmail.com)
Date: 2022-07-19T17:38:09-04:00

Commit Message:
MTROPOLIS: Implement mToon stop command

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


diff --git a/engines/mtropolis/elements.cpp b/engines/mtropolis/elements.cpp
index eeec9bb08a0..e818c039f91 100644
--- a/engines/mtropolis/elements.cpp
+++ b/engines/mtropolis/elements.cpp
@@ -1125,7 +1125,7 @@ MiniscriptInstructionOutcome MToonElement::writeRefAttribute(MiniscriptThread *t
 	return VisualElement::writeRefAttribute(thread, result, attrib);
 }
 
-VThreadState MToonElement::consumeCommand(Runtime *runtime, const Common::SharedPtr<MessageProperties>& msg) {
+VThreadState MToonElement::consumeCommand(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
 	if (Event::create(EventIDs::kPlay, 0).respondsTo(msg->getEvent())) {
 		StartPlayingTaskData *startPlayingTaskData = runtime->getVThread().pushTask("MToonElement::startPlayingTask", this, &MToonElement::startPlayingTask);
 		startPlayingTaskData->runtime = runtime;
@@ -1137,12 +1137,12 @@ VThreadState MToonElement::consumeCommand(Runtime *runtime, const Common::Shared
 		return kVThreadReturn;
 	}
 	if (Event::create(EventIDs::kStop, 0).respondsTo(msg->getEvent())) {
-		// Works differently from movies: Needs to hide the element and pause
-#ifdef MTROPOLIS_DEBUG_ENABLE
-		if (Debugger *debugger = runtime->debugGetDebugger())
-			debugger->notify(kDebugSeverityError, "mToon element was commanded to stop, but that's not implemented yet");
-#endif
-		warning("mToon element stops are not implemented");
+		ChangeFlagTaskData *becomeVisibleTaskData = runtime->getVThread().pushTask("MToonElement::changeVisibilityTask", static_cast<VisualElement *>(this), &MToonElement::changeVisibilityTask);
+		becomeVisibleTaskData->desiredFlag = false;
+		becomeVisibleTaskData->runtime = runtime;
+
+		StopPlayingTaskData *stopPlayingTaskData = runtime->getVThread().pushTask("MToonElement::startPlayingTask", this, &MToonElement::stopPlayingTask);
+		stopPlayingTaskData->runtime = runtime;
 		return kVThreadReturn;
 	}
 
@@ -1299,6 +1299,17 @@ VThreadState MToonElement::startPlayingTask(const StartPlayingTaskData &taskData
 	return kVThreadReturn;
 }
 
+VThreadState MToonElement::stopPlayingTask(const StopPlayingTaskData &taskData) {
+	_contentsDirty = true;
+	_isPlaying = false;
+
+	Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kStop, 0), DynamicValue(), getSelfReference()));
+	Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, this, false, true, false));
+	taskData.runtime->sendMessageOnVThread(dispatch);
+
+	return kVThreadReturn;
+}
+
 void MToonElement::playMedia(Runtime *runtime, Project *project) {
 	if (_paused)
 		return;
diff --git a/engines/mtropolis/elements.h b/engines/mtropolis/elements.h
index 71732a18248..60609b32995 100644
--- a/engines/mtropolis/elements.h
+++ b/engines/mtropolis/elements.h
@@ -229,12 +229,17 @@ private:
 		Runtime *runtime;
 	};
 
+	struct StopPlayingTaskData {
+		Runtime *runtime;
+	};
+
 	struct ChangeFrameTaskData {
 		Runtime *runtime;
 		uint32 frame;
 	};
 
 	VThreadState startPlayingTask(const StartPlayingTaskData &taskData);
+	VThreadState stopPlayingTask(const StopPlayingTaskData &taskData);
 
 	void playMedia(Runtime *runtime, Project *project) override;
 	MiniscriptInstructionOutcome scriptSetRate(MiniscriptThread *thread, const DynamicValue &value);




More information about the Scummvm-git-logs mailing list