[Scummvm-git-logs] scummvm master -> 325798bec865485846db8b19a42129dace5f696a
sev-
noreply at scummvm.org
Sat May 18 11:56:06 UTC 2024
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
7bf8744cf3 DIRECTOR: XOBJ: Fix UnitTest screenshot API
2ff3357dac DIRECTOR: Refactor Channel to remove overlay position/dimensions
325798bec8 DIRECTOR: XOBJ: Fix big memory leak in MMovie
Commit: 7bf8744cf3e8876348aa7d0c69dc13137f1f14f4
https://github.com/scummvm/scummvm/commit/7bf8744cf3e8876348aa7d0c69dc13137f1f14f4
Author: Scott Percival (code at moral.net.au)
Date: 2024-05-18T13:56:01+02:00
Commit Message:
DIRECTOR: XOBJ: Fix UnitTest screenshot API
Changed paths:
engines/director/lingo/xlibs/unittest.cpp
diff --git a/engines/director/lingo/xlibs/unittest.cpp b/engines/director/lingo/xlibs/unittest.cpp
index 8e59f3c8136..24075c86a61 100644
--- a/engines/director/lingo/xlibs/unittest.cpp
+++ b/engines/director/lingo/xlibs/unittest.cpp
@@ -102,34 +102,32 @@ void UnitTestXObj::m_isRealDirector(int nargs) {
}
void UnitTestXObj::m_screenshot(int nargs) {
- Common::String filenameBase = g_director->getCurrentMovie()->getArchive()->getFileName();
- if (filenameBase.hasSuffixIgnoreCase(".dir"))
- filenameBase = filenameBase.substr(0, filenameBase.size() - 4);
-
+ if (nargs == 0) {
+ g_lingo->push(Datum(0));
+ warning("UnitTestXObj::m_screenshot(): expected filename argument");
+ return;
+ }
if (nargs > 1) {
g_lingo->dropStack(nargs - 1);
nargs = 1;
}
- if (nargs == 1) {
- Datum name = g_lingo->pop();
- if (name.type == STRING) {
- filenameBase = *name.u.s;
- } else if (name.type != VOID) {
- warning("UnitTestXObj::m_screenshot(): expected string for arg 1, ignoring");
- }
+ Datum name = g_lingo->pop();
+ if (name.type != STRING) {
+ warning("UnitTestXObj::m_screenshot(): expected string for arg 1");
+ g_lingo->push(Datum(0));
+ return;
}
+ Common::String filenameBase = *name.u.s;
Common::FSNode gameDataDir = g_director->_gameDataDir;
- Common::FSNode screenDir = gameDataDir.getChild("utscreen");
+ Common::FSNode screenDir = gameDataDir.getChild("scrtest");
if (!screenDir.exists()) {
screenDir.createDirectory();
}
- // force a full screen redraw before taking the screenshot
- Score *score = g_director->getCurrentMovie()->getScore();
- score->renderSprites(kRenderForceUpdate);
+ // Fetch whatever is in the screen buffer.
+ // Don't force a redraw, we do that in the script with updateStage().
Window *window = g_director->getCurrentWindow();
- window->render();
Graphics::ManagedSurface *windowSurface = window->getSurface();
#ifdef USE_PNG
Commit: 2ff3357dace1fb010d322c0ff3c24b76f666732a
https://github.com/scummvm/scummvm/commit/2ff3357dace1fb010d322c0ff3c24b76f666732a
Author: Scott Percival (code at moral.net.au)
Date: 2024-05-18T13:56:01+02:00
Commit Message:
DIRECTOR: Refactor Channel to remove overlay position/dimensions
The original logic doesn't hold up to testing. The position/width/height
of a sprite can be changed at any time without any extra flags; although
the screen needs to be redrawn before you can see any change.
The main thing that the sprite puppet flag does is determine if sprites
are updated from the score data when the frame changes.
Fixes the broken mouse cursor tracking sprite in Chop Suey.
Fixes the sprite scaling in the Doc Martens minigame in Virtual
Nightclub.
Fixes director-tests/D4-unit/T_SPRT01.DIR
Changed paths:
engines/director/channel.cpp
engines/director/channel.h
engines/director/debugtools.cpp
engines/director/lingo/lingo-events.cpp
engines/director/lingo/lingo-the.cpp
engines/director/score.cpp
engines/director/sprite.cpp
engines/director/sprite.h
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index ccad39a2bb2..1f796578770 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -47,13 +47,10 @@ Channel::Channel(Score *sc, Sprite *sp, int priority) {
_sprite = new Sprite(*sp);
_widget = nullptr;
- _currentPoint = _sprite ? _sprite->_startPoint : Common::Point(0, 0);
_constraint = 0;
_mask = nullptr;
_priority = priority;
- _width = _sprite ? _sprite->_width : 0;
- _height = _sprite ? _sprite->_height : 0;
_movieRate = 0.0;
_movieTime = 0;
@@ -78,13 +75,10 @@ Channel& Channel::operator=(const Channel &channel) {
_sprite = channel._sprite ? new Sprite(*channel._sprite) : nullptr;
_widget = nullptr;
- _currentPoint = channel._currentPoint;
_constraint = channel._constraint;
_mask = nullptr;
_priority = channel._priority;
- _width = channel._width;
- _height = channel._height;
_movieRate = channel._movieRate;
_movieTime = channel._movieTime;
@@ -263,17 +257,16 @@ bool Channel::isDirty(Sprite *nextSprite) {
_sprite->_ink != nextSprite->_ink || _sprite->_backColor != nextSprite->_backColor ||
_sprite->_foreColor != nextSprite->_foreColor;
if (!_sprite->_moveable)
- isDirtyFlag |= _currentPoint != nextSprite->_startPoint;
+ isDirtyFlag |= _sprite->getPosition() != nextSprite->getPosition();
if (isStretched() && !hasTextCastMember(_sprite))
- isDirtyFlag |= _width != nextSprite->_width || _height != nextSprite->_height;
+ isDirtyFlag |= _sprite->_width != nextSprite->_width || _sprite->_height != nextSprite->_height;
}
return isDirtyFlag;
}
bool Channel::isStretched() {
- return _sprite->_stretch || (_sprite->_puppet &&
- (_sprite->_width != _width || _sprite->_height != _height));
+ return _sprite->_stretch;
}
bool Channel::isEmpty() {
@@ -388,54 +381,12 @@ bool Channel::isVideoDirectToStage() {
return ((DigitalVideoCastMember *)_sprite->_cast)->_directToStage;
}
-bool Channel::isBboxDeterminedByChannel() {
- bool isShape = _sprite->_cast && _sprite->_cast->_type == kCastShape;
- // Use the dimensions and position in the Channel:
- // - if the sprite is of a shape, or
- // - if the sprite has the puppet flag enabled
- // Otherwise, use the Sprite dimensions and position (i.e. taken from the
- // frame data in the Score).
- return (isShape || _sprite->_puppet || _sprite->_moveable);
-}
-
-Common::Rect Channel::getBbox(bool unstretched) {
- // Setting unstretched to true always returns the Sprite dimensions.
- bool useOverride = isBboxDeterminedByChannel() && !unstretched;
-
- Common::Rect result(
- useOverride ? _width : _sprite->_width,
- useOverride ? _height : _sprite->_height
- );
- // If this is a cast member, use the cast member's getBbox function
- // so we start with a rect containing the correct registration offset.
- if (_sprite->_cast)
- result = _sprite->_cast->getBbox(result.width(), result.height());
-
- // The origin of the rect should be at the registration offset,
- // e.g. for bitmap sprites this defaults to the centre.
- // Now we move the rect to the correct spot.
- Common::Point startPos = getPosition(unstretched);
- result.translate(startPos.x, startPos.y);
- return result;
-}
-
-Common::Point Channel::getPosition(bool unstretched) {
- bool useOverride = isBboxDeterminedByChannel() && !unstretched;
-
- return Common::Point(
- useOverride ? _currentPoint.x : _sprite->_startPoint.x,
- useOverride ? _currentPoint.y : _sprite->_startPoint.y
- );
-}
-
void Channel::setCast(CastMemberID memberID) {
// release previous widget
if (_sprite->_cast)
_sprite->_cast->releaseWidget();
_sprite->setCast(memberID);
- _width = _sprite->_width;
- _height = _sprite->_height;
replaceWidget();
// Based on Director in a Nutshell, page 15
@@ -515,6 +466,21 @@ void Channel::setClean(Sprite *nextSprite, bool partial) {
_dirty = false;
}
+void Channel::setStretch(bool enabled) {
+ if (!enabled) {
+ // when the stretch flag is manually disabled,
+ // revert whatever dimensions the sprite has to
+ // the default in the cast
+ g_director->getCurrentWindow()->addDirtyRect(getBbox());
+ _dirty = true;
+
+ Common::Rect bbox = _sprite->_cast->getBbox();
+ _sprite->setWidth(bbox.width());
+ _sprite->setHeight(bbox.height());
+ }
+ _sprite->_stretch = enabled;
+}
+
// this is used to for setting and updating text castmember
// e.g. set editable, update dims for auto expanding
void Channel::updateTextCast() {
@@ -530,8 +496,6 @@ void Channel::updateTextCast() {
if (!textWidget->getFixDims() && (_sprite->_width != _widget->_dims.width() || _sprite->_height != _widget->_dims.height())) {
_sprite->_width = _widget->_dims.width();
_sprite->_height = _widget->_dims.height();
- _width = _sprite->_width;
- _height = _sprite->_height;
g_director->getCurrentWindow()->addDirtyRect(_widget->_dims);
}
}
@@ -582,7 +546,6 @@ void Channel::replaceSprite(Sprite *nextSprite) {
if (!nextSprite)
return;
- bool newSprite = (_sprite->_spriteType == kInactiveSprite && nextSprite->_spriteType != kInactiveSprite);
bool widgetKeeped = _sprite->_cast && _widget;
// if there's a video in the old sprite that's different, stop it before we continue
@@ -597,7 +560,6 @@ void Channel::replaceSprite(Sprite *nextSprite) {
if (_sprite->_cast && !canKeepWidget(_sprite, nextSprite)) {
widgetKeeped = false;
_sprite->_cast->releaseWidget();
- newSprite = true;
}
// If the cast member is the same, persist the editable flag
@@ -606,8 +568,8 @@ void Channel::replaceSprite(Sprite *nextSprite) {
editable = _sprite->_editable;
}
- int width = _width;
- int height = _height;
+ int width = _sprite->_width;
+ int height = _sprite->_height;
bool immediate = _sprite->_immediate;
*_sprite = *nextSprite;
@@ -624,46 +586,6 @@ void Channel::replaceSprite(Sprite *nextSprite) {
_sprite->_width = width;
_sprite->_height = height;
}
-
- // Sprites marked moveable are constrained to the same bounding box until
- // the moveable is disabled
- if (!_sprite->_moveable || newSprite)
- _currentPoint = _sprite->_startPoint;
-
- _width = _sprite->_width;
- _height = _sprite->_height;
-}
-
-void Channel::setWidth(int w) {
- _width = MAX<int>(w, 0);
-
- // Based on Director in a Nutshell, page 15
- _sprite->setAutoPuppet(kAPWidth, true);
-}
-
-void Channel::setHeight(int h) {
- _height = MAX<int>(h, 0);
-
- // Based on Director in a Nutshell, page 15
- _sprite->setAutoPuppet(kAPHeight, true);
-}
-
-void Channel::setBbox(int l, int t, int r, int b) {
- _width = r - l;
- _height = b - t;
-
- Common::Rect source(_width, _height);
- if (_sprite->_cast) {
- source = _sprite->_cast->getBbox(_width, _height);
- }
- _currentPoint.x = (int16)(l - source.left);
- _currentPoint.y = (int16)(t - source.top);
-
- if (_width <= 0 || _height <= 0)
- _width = _height = 0;
-
- // Based on Director in a Nutshell, page 15
- _sprite->setAutoPuppet(kAPBbox, true);
}
void Channel::setPosition(int x, int y, bool force) {
@@ -673,18 +595,7 @@ void Channel::setPosition(int x, int y, bool force) {
newPos.x = MIN(constraintBbox.right, MAX(constraintBbox.left, newPos.x));
newPos.y = MIN(constraintBbox.bottom, MAX(constraintBbox.top, newPos.y));
}
- _currentPoint = newPos;
- // Very occasionally, setPosition should override the
- // sprite copy of the position.
- // This is necessary for cases where aspects of the sprite
- // are modified by the score, except for the position
- // (e.g. dragging the animated parts in Face Kit)
- if (force) {
- _sprite->_startPoint = newPos;
- }
-
- // Based on Director in a Nutshell, page 15
- _sprite->setAutoPuppet(kAPLoc, true);
+ _sprite->setPosition(newPos.x, newPos.y);
}
// here is the place for deciding whether the widget can be keep or not
@@ -743,8 +654,6 @@ void Channel::replaceWidget(CastMemberID previousCastId, bool force) {
_sprite->_width = _widget->_dims.width();
_sprite->_height = _widget->_dims.height();
- _width = _sprite->_width;
- _height = _sprite->_height;
}
}
}
diff --git a/engines/director/channel.h b/engines/director/channel.h
index 31937e35a54..1ab290cd5bf 100644
--- a/engines/director/channel.h
+++ b/engines/director/channel.h
@@ -23,6 +23,7 @@
#define DIRECTOR_CHANNEL_H
#include "director/cursor.h"
+#include "director/sprite.h"
namespace Graphics {
struct Surface;
@@ -46,10 +47,11 @@ public:
DirectorPlotData getPlotData();
const Graphics::Surface *getMask(bool forceMatte = false);
- bool isBboxDeterminedByChannel();
- Common::Point getPosition(bool unstretched = false);
+ inline int getWidth() { return _sprite->_width; };
+ inline int getHeight() { return _sprite->_height; };
+ inline Common::Point getPosition() { return _sprite->getPosition(); };
// Return the area of screen to be used for drawing content.
- Common::Rect getBbox(bool unstretched = false);
+ inline Common::Rect getBbox(bool unstretched = false) { return _sprite->getBbox(unstretched); };
bool isStretched();
bool isDirty(Sprite *nextSprite = nullptr);
@@ -61,12 +63,13 @@ public:
bool isActiveVideo();
bool isVideoDirectToStage();
- void setWidth(int w);
- void setHeight(int h);
- void setBbox(int l, int t, int r, int b);
+ inline void setWidth(int w) { _sprite->setWidth(w); replaceWidget(); _dirty = true; };
+ inline void setHeight(int h) { _sprite->setHeight(h); replaceWidget(); _dirty = true; };
+ inline void setBbox(int l, int t, int r, int b) { _sprite->setBbox(l, t, r, b); replaceWidget(); _dirty = true; };
void setPosition(int x, int y, bool force = false);
void setCast(CastMemberID memberID);
void setClean(Sprite *nextSprite, bool partial = false);
+ void setStretch(bool enabled);
bool getEditable();
void setEditable(bool editable);
void replaceSprite(Sprite *nextSprite);
@@ -104,17 +107,6 @@ public:
int _priority;
- // These fields are used for tracking overrides for the position, width and height of
- // the channel, as available in Lingo.
- // Basically, if the sprite -isn't- in puppet mode, Lingo will allow you to set
- // these values to whatever, but the sprite on the screen will still be the position and
- // dimensions from the score frame.
- // If you set puppet mode, the sprite on the screen will use these values instead.
- // If you set puppet mode, change things, then disable puppet mode, it will revert to the score.
- Common::Point _currentPoint;
- int _width;
- int _height;
-
// Used in digital movie sprites
double _movieRate;
int _movieTime;
diff --git a/engines/director/debugtools.cpp b/engines/director/debugtools.cpp
index 41933b9d96d..0867bdcf7ef 100644
--- a/engines/director/debugtools.cpp
+++ b/engines/director/debugtools.cpp
@@ -1053,6 +1053,7 @@ static void showChannels() {
ImGui::TableNextColumn();
if (sprite._castId.member) {
+ Common::Point position = channel.getPosition();
ImGui::Text("%s", sprite._castId.asString().c_str());
ImGui::TableNextColumn();
ImGui::Checkbox("", &channel._visible);
@@ -1067,7 +1068,7 @@ static void showChannels() {
ImGui::TableNextColumn();
ImGui::Text("%d", sprite._thickness);
ImGui::TableNextColumn();
- ImGui::Text("%dx%d@%d,%d", channel._width, channel._height, channel._currentPoint.x, channel._currentPoint.y);
+ ImGui::Text("%dx%d@%d,%d", channel.getWidth(), channel.getHeight(), position.x, position.y);
ImGui::TableNextColumn();
ImGui::Text("%d (%s)", sprite._spriteType, spriteType2str(sprite._spriteType));
ImGui::TableNextColumn();
diff --git a/engines/director/lingo/lingo-events.cpp b/engines/director/lingo/lingo-events.cpp
index 0166f024b18..1547f82d18f 100644
--- a/engines/director/lingo/lingo-events.cpp
+++ b/engines/director/lingo/lingo-events.cpp
@@ -153,7 +153,7 @@ void Movie::resolveScriptEvent(LingoEvent &event) {
_mouseDownWasInButton = true;
if (_score->_channels[spriteId]->_sprite->_moveable) {
- _draggingSpriteOffset = _score->_channels[spriteId]->_currentPoint - event.mousePos;
+ _draggingSpriteOffset = _score->_channels[spriteId]->getPosition() - event.mousePos;
_currentDraggedChannel = _score->_channels[spriteId];
}
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 5f49ba15ef6..d512cdfde4f 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -1331,7 +1331,7 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
d = (int)g_director->transformColor(sprite->_foreColor);
break;
case kTheHeight:
- d = channel->_height;
+ d = channel->getHeight();
break;
case kTheImmediate:
d = sprite->_immediate;
@@ -1346,16 +1346,19 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
d = sprite->_thickness & 0x3;
break;
case kTheLoc:
- d.type = POINT;
- d.u.farr = new FArray;
- d.u.farr->arr.push_back(channel->_currentPoint.x);
- d.u.farr->arr.push_back(channel->_currentPoint.y);
+ {
+ Common::Point position = channel->getPosition();
+ d.type = POINT;
+ d.u.farr = new FArray;
+ d.u.farr->arr.push_back(position.x);
+ d.u.farr->arr.push_back(position.y);
+ }
break;
case kTheLocH:
- d = channel->_currentPoint.x;
+ d = channel->getPosition().x;
break;
case kTheLocV:
- d = channel->_currentPoint.y;
+ d = channel->getPosition().y;
break;
case kTheMoveableSprite:
d = sprite->_moveable;
@@ -1376,12 +1379,15 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
break;
case kTheRect:
// let compiler to optimize this
- d.type = RECT;
- d.u.farr = new FArray;
- d.u.farr->arr.push_back(channel->getBbox().left);
- d.u.farr->arr.push_back(channel->getBbox().top);
- d.u.farr->arr.push_back(channel->getBbox().right);
- d.u.farr->arr.push_back(channel->getBbox().bottom);
+ {
+ Common::Rect bbox = channel->getBbox();
+ d.type = RECT;
+ d.u.farr = new FArray;
+ d.u.farr->arr.push_back(bbox.left);
+ d.u.farr->arr.push_back(bbox.top);
+ d.u.farr->arr.push_back(bbox.right);
+ d.u.farr->arr.push_back(bbox.bottom);
+ }
break;
case kTheRight:
d = channel->getBbox().right;
@@ -1419,7 +1425,7 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
d = sprite->_volume;
break;
case kTheWidth:
- d = channel->_width;
+ d = channel->getWidth();
break;
default:
warning("Lingo::getTheSprite(): Unprocessed getting field \"%s\" of sprite", field2str(field));
@@ -1549,7 +1555,7 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
}
break;
case kTheHeight:
- if (d.asInt() != channel->_height) {
+ if (d.asInt() != channel->getHeight()) {
g_director->getCurrentWindow()->addDirtyRect(channel->getBbox());
channel->setHeight(d.asInt());
channel->_dirty = true;
@@ -1579,21 +1585,21 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
}
break;
case kTheLoc:
- if (channel->_currentPoint.x != d.asPoint().x || channel->_currentPoint.y != d.asPoint().y) {
+ if (channel->getPosition() != d.asPoint()) {
movie->getWindow()->addDirtyRect(channel->getBbox());
channel->_dirty = true;
}
channel->setPosition(d.asPoint().x, d.asPoint().y);
break;
case kTheLocH:
- if (d.asInt() != channel->_currentPoint.x) {
+ if (d.asInt() != channel->getPosition().x) {
// adding the dirtyRect only when the trails is false. Other changes which will add dirtyRect may also apply this patch
// this is for fixing the bug in jman-win. Currently, i've only patched the LocH, LocV and castNum since those are the only ones used in jman
if (!channel->_sprite->_trails) {
movie->getWindow()->addDirtyRect(channel->getBbox());
channel->_dirty = true;
}
- channel->setPosition(d.asInt(), channel->_currentPoint.y);
+ channel->setPosition(d.asInt(), channel->getPosition().y);
}
// Based on Director in a Nutshell, page 15
@@ -1601,12 +1607,12 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
break;
case kTheLocV:
- if (d.asInt() != channel->_currentPoint.y) {
+ if (d.asInt() != channel->getPosition().y) {
if (!channel->_sprite->_trails) {
movie->getWindow()->addDirtyRect(channel->getBbox());
channel->_dirty = true;
}
- channel->setPosition(channel->_currentPoint.x, d.asInt());
+ channel->setPosition(channel->getPosition().x, d.asInt());
}
// Based on Director in a Nutshell, page 15
@@ -1676,15 +1682,7 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
warning("Setting stopTime for non-digital video");
break;
case kTheStretch:
- if ((d.asInt() != 0) != sprite->_stretch) {
- g_director->getCurrentWindow()->addDirtyRect(channel->getBbox());
-
- sprite->_stretch = (d.asInt() != 0);
- channel->_dirty = true;
-
- channel->_width = sprite->_width;
- channel->_height = sprite->_height;
- }
+ channel->setStretch(d.asInt() != 0);
break;
case kTheTrails:
sprite->_trails = (d.asInt() ? true : false);
@@ -1707,7 +1705,7 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
sprite->_volume = d.asInt();
break;
case kTheWidth:
- if (d.asInt() != channel->_width) {
+ if (d.asInt() != channel->getWidth()) {
g_director->getCurrentWindow()->addDirtyRect(channel->getBbox());
channel->setWidth(d.asInt());
channel->_dirty = true;
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 154689350af..f66199bfab1 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -1855,11 +1855,12 @@ Common::String Score::formatChannelInfo() {
for (int i = 0; i < frame._numChannels; i++) {
Channel &channel = *_channels[i + 1];
Sprite &sprite = *channel._sprite;
+ Common::Point position = channel.getPosition();
if (sprite._castId.member) {
result += Common::String::format("CH: %-3d castId: %s, visible: %d, [inkData: 0x%02x [ink: %d, trails: %d, stretch: %d, line: %d], %dx%d@%d,%d type: %d (%s) fg: %d bg: %d], script: %s, colorcode: 0x%x, blendAmount: 0x%x, unk3: 0x%x, constraint: %d, puppet: %d, moveable: %d, movieRate: %f, movieTime: %d (%f)\n",
i + 1, sprite._castId.asString().c_str(), channel._visible, sprite._inkData,
- sprite._ink, sprite._trails, sprite._stretch, sprite._thickness, channel._width, channel._height,
- channel._currentPoint.x, channel._currentPoint.y,
+ sprite._ink, sprite._trails, sprite._stretch, sprite._thickness,
+ channel.getWidth(), channel.getHeight(), position.x, position.y,
sprite._spriteType, spriteType2str(sprite._spriteType), sprite._foreColor, sprite._backColor,
sprite._scriptId.asString().c_str(), sprite._colorcode, sprite._blendAmount, sprite._unk3,
channel._constraint, sprite._puppet, sprite._moveable, channel._movieRate, channel._movieTime, (float)(channel._movieTime/60.0f));
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 73160fa54fc..e4eef5e1bd3 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -407,6 +407,65 @@ bool Sprite::getAutoPuppet(AutoPuppetProperty property) {
return (_autoPuppet & (1 << property)) != 0;
}
+void Sprite::setWidth(int w) {
+ _width = MAX<int>(w, 0);
+
+ // Based on Director in a Nutshell, page 15
+ setAutoPuppet(kAPWidth, true);
+}
+
+void Sprite::setHeight(int h) {
+ _height = MAX<int>(h, 0);
+
+ // Based on Director in a Nutshell, page 15
+ setAutoPuppet(kAPHeight, true);
+}
+
+Common::Rect Sprite::getBbox(bool unstretched) {
+ Common::Rect result(_width, _height);
+ // If this is a cast member, use the cast member's getBbox function
+ // so we start with a rect containing the correct registration offset.
+ if (_cast)
+ result = _cast->getBbox(_width, _height);
+
+ // The origin of the rect should be at the registration offset,
+ // e.g. for bitmap sprites this defaults to the centre.
+ // Now we move the rect to the correct spot.
+ Common::Point startPos = _startPoint;
+ result.translate(startPos.x, startPos.y);
+ return result;
+
+}
+
+void Sprite::setBbox(int l, int t, int r, int b) {
+ _width = r - l;
+ _height = b - t;
+
+ Common::Rect source(_width, _height);
+ if (_cast) {
+ source = _cast->getBbox(_width, _height);
+ }
+ _startPoint.x = (int16)(l - source.left);
+ _startPoint.y = (int16)(t - source.top);
+
+ if (_width <= 0 || _height <= 0)
+ _width = _height = 0;
+
+ // Based on Director in a Nutshell, page 15
+ setAutoPuppet(kAPBbox, true);
+}
+
+Common::Point Sprite::getPosition() {
+ return _startPoint;
+}
+
+void Sprite::setPosition(int x, int y) {
+ _startPoint = Common::Point(x, y);
+
+ // Based on Director in a Nutshell, page 15
+ setAutoPuppet(kAPLoc, true);
+}
+
bool Sprite::checkSpriteType() {
// check whether the sprite type match the cast type
// if it doesn't match, then we treat it as transparent
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
index 6a13a3fabf5..ba3b1710fd8 100644
--- a/engines/director/sprite.h
+++ b/engines/director/sprite.h
@@ -83,6 +83,17 @@ public:
void setAutoPuppet(AutoPuppetProperty property, bool value);
bool getAutoPuppet(AutoPuppetProperty property);
+ inline int getWidth() { return _width; }
+ void setWidth(int w);
+ inline int getHeight() { return _height; }
+ void setHeight(int h);
+
+ Common::Rect getBbox(bool unstretched);
+ void setBbox(int l, int t, int r, int b);
+
+ Common::Point getPosition();
+ void setPosition(int x, int y);
+
Frame *_frame;
Score *_score;
Movie *_movie;
Commit: 325798bec865485846db8b19a42129dace5f696a
https://github.com/scummvm/scummvm/commit/325798bec865485846db8b19a42129dace5f696a
Author: Scott Percival (code at moral.net.au)
Date: 2024-05-18T13:56:01+02:00
Commit Message:
DIRECTOR: XOBJ: Fix big memory leak in MMovie
Changed paths:
engines/director/lingo/xlibs/mmovie.cpp
diff --git a/engines/director/lingo/xlibs/mmovie.cpp b/engines/director/lingo/xlibs/mmovie.cpp
index 01e445999c8..02eaf8e8c11 100644
--- a/engines/director/lingo/xlibs/mmovie.cpp
+++ b/engines/director/lingo/xlibs/mmovie.cpp
@@ -119,6 +119,12 @@ MMovieXObject::MMovieXObject(ObjectType ObjectType) :Object<MMovieXObject>("MMov
MMovieXObject::~MMovieXObject() {
_lastFrame.free();
+ for (auto &it : _movies) {
+ if (it._value._video) {
+ delete it._value._video;
+ it._value._video = nullptr;
+ }
+ }
}
bool MMovieXObject::playSegment(int movieIndex, int segIndex, bool looping, bool restore, bool shiftAbort, bool abortOnClick, bool purge, bool async) {
@@ -203,7 +209,9 @@ void MMovieXObject::updateScreen() {
Graphics::Surface *temp1 = frame->scale(_bounds.width(), _bounds.height(), false);
Graphics::Surface *temp2 = temp1->convertTo(g_director->_pixelformat, movie._video->getPalette());
_lastFrame.copyFrom(*temp2);
+ temp2->free();
delete temp2;
+ temp1->free();
delete temp1;
}
}
More information about the Scummvm-git-logs
mailing list