[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