[Scummvm-git-logs] scummvm master -> 19fa715408a01c54c7c72e0000f900cba3879cde

elasota noreply at scummvm.org
Wed Jun 22 04:35:32 UTC 2022


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

Summary:
562feebd3c MTROPOLIS: Add movie loops
19fa715408 MTROPOLIS: Fix int ranges being truncated to 16-bits


Commit: 562feebd3c1655e3451ae2891ef7a835708a6d9d
    https://github.com/scummvm/scummvm/commit/562feebd3c1655e3451ae2891ef7a835708a6d9d
Author: elasota (ejlasota at gmail.com)
Date: 2022-06-22T00:32:02-04:00

Commit Message:
MTROPOLIS: Add movie loops

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


diff --git a/engines/mtropolis/elements.cpp b/engines/mtropolis/elements.cpp
index d77f51827d2..5d26d9f4620 100644
--- a/engines/mtropolis/elements.cpp
+++ b/engines/mtropolis/elements.cpp
@@ -603,8 +603,18 @@ MiniscriptInstructionOutcome MovieElement::writeRefAttribute(MiniscriptThread *t
 }
 
 VThreadState MovieElement::consumeCommand(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	// The reaction to the Play command should be to fire Unpaused and then fire Played.
+	// At First Cel is NOT fired by Play commands for some reason.
+
 	if (Event::create(EventIDs::kPlay, 0).respondsTo(msg->getEvent())) {
-		// These reverse order
+		if (_paused)
+		{
+			_paused = false;
+			Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kUnpause, 0), DynamicValue(), getSelfReference()));
+			Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, this, false, true, false));
+			runtime->sendMessageOnVThread(dispatch);
+		}
+
 		{
 			Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kPlay, 0), DynamicValue(), getSelfReference()));
 			Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, this, false, true, false));
@@ -690,6 +700,17 @@ bool MovieElement::canAutoPlay() const {
 	return _visible && !_paused;
 }
 
+void MovieElement::queueAutoPlayEvents(Runtime *runtime, bool isAutoPlaying) {
+	// At First Cel event fires even if the movie isn't playing, and it fires before Played
+	if (_visible) {
+		Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kAtFirstCel, 0), DynamicValue(), getSelfReference()));
+		Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, this, false, true, false));
+		runtime->queueMessage(dispatch);
+	}
+
+	VisualElement::queueAutoPlayEvents(runtime, isAutoPlaying);
+}
+
 void MovieElement::render(Window *window) {
 	if (_needsReset) {
 		_videoDecoder->setReverse(_reversed);
@@ -731,7 +752,8 @@ void MovieElement::playMedia(Runtime *runtime, Project *project) {
 				if (_videoDecoder->isPaused())
 					_videoDecoder->pauseVideo(false);
 
-				_currentPlayState = kMediaStatePlaying;
+				if (_currentPlayState != kMediaStatePlayingLastFrame)
+					_currentPlayState = kMediaStatePlaying;
 				checkContinuously = true;
 			}
 		} else {
@@ -747,25 +769,25 @@ void MovieElement::playMedia(Runtime *runtime, Project *project) {
 		uint32 targetTS = _currentTimestamp;
 
 		int framesDecodedThisFrame = 0;
-		while (_videoDecoder->needsUpdate()) {
-			if (_playEveryFrame && framesDecodedThisFrame > 0)
-				break;
-
-			const Graphics::Surface *decodedFrame = _videoDecoder->decodeNextFrame();
-
-			// GNARLY HACK: QuickTimeDecoder doesn't return true for endOfVideo or false for needsUpdate until it
-			// tries decoding past the end, so we're assuming that the decoded frame memory stays valid until we
-			// actually have a new frame and continuing to use it.
-			if (decodedFrame) {
-				_contentsDirty = true;
-				framesDecodedThisFrame++;
-				_displayFrame = decodedFrame;
-				if (_playEveryFrame)
+		if (_currentPlayState == kMediaStatePlaying) {
+			while (_videoDecoder->needsUpdate()) {
+				if (_playEveryFrame && framesDecodedThisFrame > 0)
 					break;
+
+				const Graphics::Surface *decodedFrame = _videoDecoder->decodeNextFrame();
+
+				// QuickTimeDecoder doesn't return true for endOfVideo or false for needsUpdate until it
+				// tries decoding past the end, so we're assuming that the decoded frame memory stays valid until we
+				// actually have a new frame and continuing to use it.
+				if (decodedFrame) {
+					_contentsDirty = true;
+					framesDecodedThisFrame++;
+					_displayFrame = decodedFrame;
+					if (_playEveryFrame)
+						break;
+				}
 			}
-		}
 
-		if (_currentPlayState == kMediaStatePlaying) {
 			if (_videoDecoder->endOfVideo())
 				targetTS = _reversed ? _playRange.min : _playRange.max;
 			else
@@ -782,10 +804,14 @@ void MovieElement::playMedia(Runtime *runtime, Project *project) {
 
 		// Sync TS to the end of video if we hit the end
 
+		bool triggerEndEvents = false;
+
+		if (_currentPlayState == kMediaStatePlayingLastFrame)
+			triggerEndEvents = true;
+
 		if (targetTS != _currentTimestamp) {
 			assert(!_paused);
 
-			
 			// Check media cues
 			for (MediaCueState *mediaCue : _mediaCues)
 				mediaCue->checkTimestampChange(runtime, _currentTimestamp, targetTS, checkContinuously, true);
@@ -793,32 +819,37 @@ void MovieElement::playMedia(Runtime *runtime, Project *project) {
 			_currentTimestamp = targetTS;
 
 			if (_currentTimestamp == maxTS) {
-				Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kAtLastCel, 0), DynamicValue(), getSelfReference()));
-				Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, this, false, true, false));
-				runtime->queueMessage(dispatch);
+				if (maxTS == _maxTimestamp) {
+					// If this play range plays through to the end, then delay end events 1 frame so it has a chance to render
+					_currentPlayState = kMediaStatePlayingLastFrame;
+				} else
+					triggerEndEvents = true;
 			}
+		}
 
-			if (_currentTimestamp == minTS) {
-				Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kAtFirstCel, 0), DynamicValue(), getSelfReference()));
+		if (triggerEndEvents) {
+			if (!_loop) {
+				_paused = true;
+
+				Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kPause, 0), DynamicValue(), getSelfReference()));
 				Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, this, false, true, false));
 				runtime->queueMessage(dispatch);
+
+				_currentPlayState = kMediaStateStopped;
 			}
-		}
 
-		if (_currentPlayState == kMediaStatePlaying && _videoDecoder->endOfVideo()) {
-			if (_alternate) {
-				_reversed = !_reversed;
-				if (!_videoDecoder->setReverse(_reversed)) {
-					warning("Failed to reverse video decoder, disabling it");
-					_videoDecoder.reset();
-				}
+			Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kAtLastCel, 0), DynamicValue(), getSelfReference()));
+			Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, this, false, true, false));
+			runtime->queueMessage(dispatch);
 
-				uint32 endTS = _reversed ? _playRange.min : _playRange.max;
-				_videoDecoder->setEndTime(Audio::Timestamp(0, _timeScale).addFrames(endTS));
-			} else {
-				// It doesn't look like movies fire any events upon reaching the end, just At Last Cel and At First Cel
-				_videoDecoder->stop();
-				_currentPlayState = kMediaStateStopped;
+			// For some reason, At First Cel isn't fired for movies, even when they loop or are set to timevalue 0
+			_videoDecoder->stop();
+			_currentPlayState = kMediaStateStopped;
+
+			if (_loop) {
+				_needsReset = true;
+				_currentTimestamp = _reversed ? _playRange.max : _playRange.min;
+				_contentsDirty = true;
 			}
 		}
 	}
@@ -951,6 +982,7 @@ VThreadState MovieElement::startPlayingTask(const StartPlayingTaskData &taskData
 		_videoDecoder->stop();
 		_currentPlayState = kMediaStateStopped;
 		_needsReset = true;
+		_contentsDirty = true;
 
 		_shouldPlayIfNotPaused = true;
 		_paused = false;
diff --git a/engines/mtropolis/elements.h b/engines/mtropolis/elements.h
index 61f2986b229..ddd6a30570c 100644
--- a/engines/mtropolis/elements.h
+++ b/engines/mtropolis/elements.h
@@ -44,6 +44,7 @@ struct MToonMetadata;
 
 enum MediaState {
 	kMediaStatePlaying,
+	kMediaStatePlayingLastFrame,
 	kMediaStateStopped,
 	kMediaStatePaused,
 };
@@ -87,6 +88,7 @@ public:
 	void deactivate() override;
 
 	bool canAutoPlay() const override;
+	void queueAutoPlayEvents(Runtime *runtime, bool isAutoPlaying) override;
 
 	void render(Window *window) override;
 	void playMedia(Runtime *runtime, Project *project) override;
diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index b12a23f7a81..7d88a485109 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -2963,8 +2963,7 @@ MiniscriptInstructionOutcome Structural::scriptSetPaused(MiniscriptThread *threa
 	// while at the Bureau light carousel, since the lever isn't flagged as paused but is set paused
 	// via an init script, and the lever trigger is detected via the pause event.
 	//
-	// (It's possible that this is actually yet another case of the event simply not being sent when the
-	// property is set from script... need to verify and update this comment.)
+	// The event does, however, need to be sent immediately.
 	if (!thread->getRuntime()->isAwaitingSceneTransition()) {
 		Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(targetValue ? EventIDs::kPause : EventIDs::kUnpause, 0), DynamicValue(), getSelfReference()));
 		Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, this, false, true, false));
@@ -6435,6 +6434,14 @@ bool Element::canAutoPlay() const {
 	return false;
 }
 
+void Element::queueAutoPlayEvents(Runtime *runtime, bool isAutoPlaying) {
+	if (isAutoPlaying) {
+		Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kPlay, 0), DynamicValue(), getSelfReference()));
+		Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, this, false, false, true));
+		runtime->queueMessage(dispatch);
+	}
+}
+
 bool Element::isElement() const {
 	return true;
 }
@@ -6462,11 +6469,7 @@ void Element::triggerAutoPlay(Runtime *runtime) {
 
 	_haveCheckedAutoPlay = true;
 
-	if (canAutoPlay()) {
-		Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kPlay, 0), DynamicValue(), getSelfReference()));
-		Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, this, false, false, true));
-		runtime->queueMessage(dispatch);
-	}
+	queueAutoPlayEvents(runtime, canAutoPlay());
 }
 
 bool Element::resolveMediaMarkerLabel(const Label& label, int32 &outResolution) const {
diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h
index 86ddad15c9e..6df6b561b08 100644
--- a/engines/mtropolis/runtime.h
+++ b/engines/mtropolis/runtime.h
@@ -2263,6 +2263,8 @@ public:
 
 	virtual bool isVisual() const = 0;
 	virtual bool canAutoPlay() const;
+	virtual void queueAutoPlayEvents(Runtime *runtime, bool isAutoPlaying);
+
 	bool isElement() const override;
 
 	uint32 getStreamLocator() const;


Commit: 19fa715408a01c54c7c72e0000f900cba3879cde
    https://github.com/scummvm/scummvm/commit/19fa715408a01c54c7c72e0000f900cba3879cde
Author: elasota (ejlasota at gmail.com)
Date: 2022-06-22T00:32:35-04:00

Commit Message:
MTROPOLIS: Fix int ranges being truncated to 16-bits

Changed paths:
    engines/mtropolis/miniscript.cpp


diff --git a/engines/mtropolis/miniscript.cpp b/engines/mtropolis/miniscript.cpp
index 4ad96e0e0a7..a1b09850c4c 100644
--- a/engines/mtropolis/miniscript.cpp
+++ b/engines/mtropolis/miniscript.cpp
@@ -1331,7 +1331,7 @@ MiniscriptInstructionOutcome RangeCreate::execute(MiniscriptThread *thread) cons
 
 		switch (v->getType()) {
 		case DynamicValueTypes::kFloat:
-			coords[i] = static_cast<int32>(floor(v->getFloat() + 0.5)) & 0xffff;
+			coords[i] = static_cast<int32>(floor(v->getFloat() + 0.5));
 			break;
 		case DynamicValueTypes::kInteger:
 			coords[i] = v->getInt();




More information about the Scummvm-git-logs mailing list