[Scummvm-git-logs] scummvm master -> 4bfffc43a76a9d4446237c15642f0f3c7b2e548c
moralrecordings
code at moral.net.au
Sun Jul 26 04:32:33 UTC 2020
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:
4bfffc43a7 DIRECTOR: Move widgets from cast members to channels (#2372)
Commit: 4bfffc43a76a9d4446237c15642f0f3c7b2e548c
https://github.com/scummvm/scummvm/commit/4bfffc43a76a9d4446237c15642f0f3c7b2e548c
Author: Scott Percival (code at moral.net.au)
Date: 2020-07-26T04:32:29Z
Commit Message:
DIRECTOR: Move widgets from cast members to channels (#2372)
This change is required to support copies of the same cast member running in different channels.
* DIRECTOR: Move widget ownership from cast member to channel
* DIRECTOR: Cache cast dimensions from createWidget
* DIRECTOR: Add null checks for createWidget
* GRAPHICS: MACGUI: Clear active/hover WM references if the widget is destroyed
* DIRECTOR: LINGO: Re-add null check for kTheEditableText
* DIRECTOR: Avoid destroying widgets if the channel isn't dirty
* DIRECTOR: Fix dirty test
* DIRECTOR: Fix text field writeback
* DIRECTOR: Fix null cast check
* DIRECTOR: Add bbox as argument to createWidget
* DIRECTOR: Add setCast method to Channel
* DIRECTOR: Fix use-after-free in Channel::getMask
* DIRECTOR: Fix bounding box for Button sprites
* DIRECTOR: Cache widget dimensions in cast member
* DIRECTOR: Remove widget from channel if nextSprite is empty
* GRAPHICS: MACGUI: Fix MacText::splitString for empty string case
* DIRECTOR: Add null checks for movie and score in processEvents
Changed paths:
engines/director/cast.cpp
engines/director/cast.h
engines/director/castmember.cpp
engines/director/castmember.h
engines/director/channel.cpp
engines/director/channel.h
engines/director/cursor.cpp
engines/director/events.cpp
engines/director/lingo/lingo-the.cpp
engines/director/score.cpp
engines/director/sprite.cpp
graphics/macgui/macbutton.cpp
graphics/macgui/mactext.cpp
graphics/macgui/macwidget.cpp
graphics/macgui/macwindowmanager.cpp
graphics/macgui/macwindowmanager.h
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index f654398fb9..21f73043d3 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -345,7 +345,6 @@ bool Cast::loadArchive() {
loadSpriteImages();
loadSpriteSounds();
- createCastWidgets();
return true;
}
@@ -433,15 +432,6 @@ void Cast::copyCastStxts() {
}
}
-void Cast::createCastWidgets() {
- for (Common::HashMap<int, CastMember *>::iterator c = _loadedCast->begin(); c != _loadedCast->end(); ++c) {
- if (!c->_value)
- continue;
-
- c->_value->createWidget();
- }
-}
-
void Cast::loadSpriteImages() {
debugC(1, kDebugLoading, "****** Preloading sprite images");
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 14e2914b7f..3b599c336c 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -67,7 +67,6 @@ public:
void loadSpriteSounds();
void copyCastStxts();
- void createCastWidgets();
Common::Rect getCastMemberInitialRect(int castId);
void setCastMemberModified(int castId);
CastMember *getCastMember(int castId);
diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp
index 069472c418..5c9415327c 100644
--- a/engines/director/castmember.cpp
+++ b/engines/director/castmember.cpp
@@ -35,7 +35,6 @@ CastMember::CastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndi
_type = kCastTypeNull;
_cast = cast;
_castId = castId;
- _widget = nullptr;
_hilite = false;
_autoHilite = false;
_purgePriority = 3;
@@ -46,7 +45,7 @@ CastMember::CastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndi
}
BitmapCastMember::BitmapCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint32 castTag, uint16 version, uint8 flags1)
- : CastMember(cast, castId, stream) {
+ : CastMember(cast, castId, stream) {
_type = kCastBitmap;
_img = nullptr;
_matte = nullptr;
@@ -163,16 +162,15 @@ BitmapCastMember::~BitmapCastMember() {
delete _matte;
}
-void BitmapCastMember::createWidget() {
- CastMember::createWidget();
-
+Graphics::MacWidget *BitmapCastMember::createWidget(Common::Rect &bbox) {
if (!_img) {
warning("BitmapCastMember::createWidget: No image decoder");
- return;
+ return nullptr;
}
- _widget = new Graphics::MacWidget(g_director->getCurrentStage(), 0, 0, _initialRect.width(), _initialRect.height(), g_director->_wm, false);
- _widget->getSurface()->blitFrom(*_img->getSurface());
+ Graphics::MacWidget *widget = new Graphics::MacWidget(g_director->getCurrentStage(), bbox.left, bbox.top, bbox.width(), bbox.height(), g_director->_wm, false);
+ widget->getSurface()->blitFrom(*_img->getSurface());
+ return widget;
}
void BitmapCastMember::createMatte() {
@@ -297,6 +295,7 @@ TextCastMember::TextCastMember(Cast *cast, uint16 castId, Common::SeekableReadSt
_gutterSize = kSizeNone;
_boxShadow = kSizeNone;
_buttonType = kTypeButton;
+ _editable = false;
_maxHeight = _textHeight = 0;
_bgcolor = 0;
@@ -423,17 +422,11 @@ TextCastMember::TextCastMember(Cast *cast, uint16 castId, Common::SeekableReadSt
}
void TextCastMember::setColors(int *fgcolor, int *bgcolor) {
- if (!_widget)
- return;
-
if (fgcolor)
_fgcolor = *fgcolor;
if (bgcolor)
_bgcolor = *bgcolor;
-
- _widget->setColors(_fgcolor, _bgcolor);
- ((Graphics::MacText *)_widget)->_fullRefresh = true;
}
Graphics::TextAlign TextCastMember::getAlignment() {
@@ -459,24 +452,27 @@ void TextCastMember::importStxt(const Stxt *stxt) {
_ptext = stxt->_ptext;
}
-void TextCastMember::createWidget() {
- CastMember::createWidget();
-
+Graphics::MacWidget *TextCastMember::createWidget(Common::Rect &bbox) {
Graphics::MacFont *macFont = new Graphics::MacFont(_fontId, _fontSize, _textSlant);
+ Graphics::MacWidget *widget = nullptr;
switch (_type) {
case kCastText:
- _widget = new Graphics::MacText(g_director->getCurrentStage(), 0, 0, _initialRect.width(), _initialRect.height(), g_director->_wm, _ftext, macFont, getForeColor(), getBackColor(), _initialRect.width(), getAlignment(), 0, _borderSize, _gutterSize, _boxShadow, _textShadow);
-
- ((Graphics::MacText *)_widget)->draw();
+ widget = new Graphics::MacText(g_director->getCurrentStage(), bbox.left, bbox.top, bbox.width(), bbox.height(), g_director->_wm, _ftext, macFont, getForeColor(), getBackColor(), bbox.width(), getAlignment(), 0, _borderSize, _gutterSize, _boxShadow, _textShadow);
+ ((Graphics::MacText *)widget)->draw();
+ ((Graphics::MacText *)widget)->_focusable = _editable;
+ ((Graphics::MacText *)widget)->setEditable(_editable);
+ ((Graphics::MacText *)widget)->_selectable = _editable;
break;
case kCastButton:
- _widget = new Graphics::MacButton(Graphics::MacButtonType(_buttonType), getAlignment(), g_director->getCurrentStage(), 0, 0, _initialRect.width(), _initialRect.height(), g_director->_wm, _ftext, macFont, getForeColor(), 0xff);
- ((Graphics::MacButton *)_widget)->draw();
- _widget->_focusable = true;
+ // note that we use _initialRect for the dimensions of the button;
+ // the values provided in the sprite bounding box are ignored
+ widget = new Graphics::MacButton(Graphics::MacButtonType(_buttonType), getAlignment(), g_director->getCurrentStage(), bbox.left, bbox.top, _initialRect.width(), _initialRect.height(), g_director->_wm, _ftext, macFont, getForeColor(), 0xff);
+ ((Graphics::MacButton *)widget)->draw();
+ widget->_focusable = true;
- ((Graphics::MacButton *)(_widget))->draw();
+ ((Graphics::MacButton *)widget)->draw();
break;
default:
@@ -484,6 +480,17 @@ void TextCastMember::createWidget() {
}
delete macFont;
+ return widget;
+}
+
+Common::Rect TextCastMember::getWidgetRect() {
+ Graphics::MacWidget *widget = createWidget(_initialRect);
+ Common::Rect result = _initialRect;
+ if (widget) {
+ result = widget->_dims;
+ delete widget;
+ }
+ return result;
}
void TextCastMember::importRTE(byte *text) {
@@ -500,50 +507,29 @@ void TextCastMember::setText(const char *text) {
return;
_ptext = _ftext = text;
-
- if (_widget) {
- Graphics::MacText *wtext = (Graphics::MacText *)_widget;
- wtext->clearText();
- wtext->appendTextDefault(_ftext);
- wtext->draw();
- }
-
_modified = true;
}
Common::String TextCastMember::getText() {
- if (_widget)
- _ptext = ((Graphics::MacText *)_widget)->getEditedString().encode();
-
return _ptext;
}
bool TextCastMember::isModified() {
- return _modified || (_widget ? ((Graphics::MacText *)_widget)->_contentIsDirty || ((Graphics::MacText *)_widget)->_cursorDirty: false);
+ return _modified;
}
bool TextCastMember::isEditable() {
- if (!_widget) {
- warning("TextCastMember::setEditable: Attempt to set editable of null widget");
- return false;
- }
+ return _editable;
+}
- return (Graphics::MacText *)_widget->_editable;
+void TextCastMember::setEditable(bool editable) {
+ _editable = editable;
}
-bool TextCastMember::setEditable(bool editable) {
- if (!_widget) {
- warning("TextCastMember::setEditable: Attempt to set editable of null widget");
- return false;
+void TextCastMember::updateFromWidget(Graphics::MacWidget *widget) {
+ if (widget && _type == kCastText) {
+ _ptext = ((Graphics::MacText *)widget)->getEditedString().encode();
}
-
- Graphics::MacText *text = (Graphics::MacText *)_widget;
- text->setEditable(editable);
- text->_focusable = editable;
- text->_selectable = editable;
- // text->setActive(editable);
-
- return true;
}
ShapeCastMember::ShapeCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version)
diff --git a/engines/director/castmember.h b/engines/director/castmember.h
index c28c5b2d37..b1d53e45a0 100644
--- a/engines/director/castmember.h
+++ b/engines/director/castmember.h
@@ -61,9 +61,11 @@ public:
uint16 getID() { return _castId; }
virtual bool isEditable() { return false; }
- virtual bool setEditable(bool editable) { return false; }
+ virtual void setEditable(bool editable) {}
virtual bool isModified() { return _modified; }
- virtual void createWidget() {}
+ virtual Graphics::MacWidget *createWidget(Common::Rect &bbox) { return nullptr; }
+ virtual void updateFromWidget(Graphics::MacWidget *widget) {}
+ virtual Common::Rect getWidgetRect() { return _initialRect; }
virtual void setColors(int *fgcolor, int *bgcolor) { return; }
virtual uint getForeColor() { return 0; }
@@ -81,8 +83,6 @@ public:
uint32 _size;
uint8 _flags1;
- Graphics::MacWidget *_widget;
-
private:
Cast *_cast;
uint16 _castId;
@@ -92,7 +92,7 @@ class BitmapCastMember : public CastMember {
public:
BitmapCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint32 castTag, uint16 version, uint8 flags1 = 0);
~BitmapCastMember();
- virtual void createWidget() override;
+ virtual Graphics::MacWidget *createWidget(Common::Rect &bbox) override;
void createMatte();
Graphics::Surface *getMatte();
@@ -164,11 +164,13 @@ public:
virtual void setColors(int *fgcolor, int *bgcolor) override;
void setText(const char *text);
- virtual void createWidget() override;
+ virtual Graphics::MacWidget *createWidget(Common::Rect &bbox) override;
+ virtual Common::Rect getWidgetRect() override;
virtual bool isModified() override;
virtual bool isEditable() override;
- virtual bool setEditable(bool editable) override;
+ virtual void setEditable(bool editable) override;
+ virtual void updateFromWidget(Graphics::MacWidget *widget);
Graphics::TextAlign getAlignment();
virtual uint getBackColor() override { return _bgcolor; }
@@ -191,6 +193,7 @@ public:
uint16 _bgpalinfo1, _bgpalinfo2, _bgpalinfo3;
uint16 _fgpalinfo1, _fgpalinfo2, _fgpalinfo3;
ButtonType _buttonType;
+ bool _editable;
Common::String _ftext;
Common::String _ptext;
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index b849c51073..0eed8530a4 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -32,12 +32,15 @@
namespace Director {
-Channel::Channel(Sprite *sp) {
+Channel::Channel(Sprite *sp, int priority) {
_sprite = sp;
+ _widget = nullptr;
_currentPoint = sp->_startPoint;
_delta = Common::Point(0, 0);
_constraint = 0;
+ _mask = nullptr;
+ _priority = priority;
_width = _sprite->_width;
_height = _sprite->_height;
@@ -47,6 +50,13 @@ Channel::Channel(Sprite *sp) {
_sprite->updateCast();
}
+Channel::~Channel() {
+ if (_widget)
+ delete _widget;
+ if (_mask)
+ delete _mask;
+}
+
DirectorPlotData Channel::getPlotData() {
DirectorPlotData pd(g_director->_wm, _sprite->_spriteType, _sprite->_ink, getBackColor(), getForeColor());
pd.colorWhite = pd._wm->_colorWhite;
@@ -66,8 +76,8 @@ DirectorPlotData Channel::getPlotData() {
}
Graphics::ManagedSurface *Channel::getSurface() {
- if (_sprite->_cast && _sprite->_cast->_widget) {
- return _sprite->_cast->_widget->getSurface();
+ if (_widget) {
+ return _widget->getSurface();
} else {
return nullptr;
}
@@ -96,7 +106,14 @@ const Graphics::Surface *Channel::getMask(bool forceMatte) {
CastMember *member = g_director->getCurrentMovie()->getCastMember(_sprite->_castId + 1);
if (member && member->_initialRect == _sprite->_cast->_initialRect) {
- return &member->_widget->getSurface()->rawSurface();
+ Common::Rect bbox(getBbox());
+ Graphics::MacWidget *widget = member->createWidget(bbox);
+ if (_mask)
+ delete _mask;
+ _mask = new Graphics::ManagedSurface();
+ _mask->copyFrom(*widget->getSurface());
+ delete widget;
+ return &_mask->rawSurface();
} else {
warning("Channel::getMask(): Requested cast mask, but no matching mask was found");
return nullptr;
@@ -144,7 +161,7 @@ bool Channel::isActiveText() {
if (_sprite->_spriteType != kTextSprite)
return false;
- if (_sprite->_cast && _sprite->_cast->_widget && _sprite->_cast->_widget->hasAllFocus())
+ if (_widget && _widget->hasAllFocus())
return true;
return false;
@@ -228,12 +245,19 @@ Common::Rect Channel::getBbox(bool unstretched) {
return result;
}
+void Channel::setCast(uint16 castId) {
+ _sprite->setCast(castId);
+ _width = _sprite->_width;
+ _height = _sprite->_height;
+ replaceWidget();
+}
+
void Channel::setClean(Sprite *nextSprite, int spriteId, bool partial) {
if (!nextSprite)
return;
bool newSprite = (_sprite->_spriteType == kInactiveSprite && nextSprite->_spriteType != kInactiveSprite);
- _dirty = false;
+ bool replace = isDirty(nextSprite);
if (nextSprite) {
if (!_sprite->_puppet) {
@@ -259,16 +283,11 @@ void Channel::setClean(Sprite *nextSprite, int spriteId, bool partial) {
_delta = Common::Point(0, 0);
}
- if (_sprite->_cast && _sprite->_cast->_widget) {
+ if (replace) {
_sprite->updateCast();
- Common::Point p(getPosition());
- _sprite->_cast->_modified = false;
- _sprite->_cast->_widget->_dims.moveTo(p.x, p.y);
-
- _sprite->_cast->_widget->_priority = spriteId;
- _sprite->_cast->_widget->draw();
- _sprite->_cast->_widget->_contentIsDirty = false;
+ replaceWidget();
}
+ _dirty = false;
}
void Channel::setWidth(int w) {
@@ -295,6 +314,37 @@ void Channel::setBbox(int l, int t, int r, int b) {
}
}
+void Channel::replaceWidget() {
+ if (_widget) {
+ delete _widget;
+ _widget = nullptr;
+ }
+
+ if (_sprite && _sprite->_cast) {
+ Common::Rect bbox(getBbox());
+ _sprite->_cast->_modified = false;
+
+ _widget = _sprite->_cast->createWidget(bbox);
+ if (_widget) {
+ _widget->_priority = _priority;
+ _widget->draw();
+ _widget->_contentIsDirty = false;
+ }
+ }
+}
+
+bool Channel::updateWidget() {
+ if (_widget && _widget->_contentIsDirty) {
+ if (_sprite->_cast) {
+ _sprite->_cast->updateFromWidget(_widget);
+ }
+ _widget->draw();
+ return true;
+ }
+
+ return false;
+}
+
void Channel::addRegistrationOffset(Common::Point &pos, bool subtract) {
if (_sprite->_cast && _sprite->_cast->_type == kCastBitmap) {
BitmapCastMember *bc = (BitmapCastMember *)(_sprite->_cast);
diff --git a/engines/director/channel.h b/engines/director/channel.h
index 15506c1924..413006bd53 100644
--- a/engines/director/channel.h
+++ b/engines/director/channel.h
@@ -26,6 +26,7 @@
namespace Graphics {
struct Surface;
class ManagedSurface;
+ class MacWidget;
}
namespace Director {
@@ -35,7 +36,8 @@ class Cursor;
class Channel {
public:
- Channel(Sprite *sp);
+ Channel(Sprite *sp, int priority = 0);
+ ~Channel();
DirectorPlotData getPlotData();
const Graphics::Surface *getMask(bool forceMatte = false);
@@ -52,20 +54,26 @@ public:
void setWidth(int w);
void setHeight(int h);
void setBbox(int l, int t, int r, int b);
+ void setCast(uint16 castId);
void setClean(Sprite *nextSprite, int spriteId, bool partial = false);
+ void replaceWidget();
+ bool updateWidget();
void addDelta(Common::Point pos);
public:
Sprite *_sprite;
Cursor _cursor;
+ Graphics::MacWidget *_widget;
bool _dirty;
bool _visible;
uint _constraint;
Common::Point _currentPoint;
Common::Point _delta;
+ Graphics::ManagedSurface *_mask;
+ int _priority;
int _width;
int _height;
diff --git a/engines/director/cursor.cpp b/engines/director/cursor.cpp
index 00e947e197..ed90be9d70 100644
--- a/engines/director/cursor.cpp
+++ b/engines/director/cursor.cpp
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "image/image_decoder.h"
+
#include "director/director.h"
#include "director/cursor.h"
#include "director/movie.h"
@@ -52,10 +54,10 @@ void Cursor::readFromCast(uint cursorId, uint maskId) {
CastMember *cursorCast = g_director->getCurrentMovie()->getCastMember(cursorId);
CastMember *maskCast = g_director->getCurrentMovie()->getCastMember(maskId);
- if (!cursorCast || !cursorCast->_widget || cursorCast->_type != kCastBitmap) {
+ if (!cursorCast || cursorCast->_type != kCastBitmap) {
warning("Cursor::readFromCast: No bitmap cast for cursor");
return;
- } else if (!maskCast || !maskCast->_widget || maskCast->_type != kCastBitmap) {
+ } else if (!maskCast || maskCast->_type != kCastBitmap) {
warning("Cursor::readFromCast: No bitmap mask for cursor");
return;
}
@@ -65,21 +67,24 @@ void Cursor::readFromCast(uint cursorId, uint maskId) {
resetCursor(Graphics::kMacCursorCustom, true, 0, cursorId, maskId);
+ BitmapCastMember *cursorBitmap = (BitmapCastMember *)cursorCast;
+ BitmapCastMember *maskBitmap = (BitmapCastMember *)maskCast;
+
_surface = new byte[getWidth() * getHeight()];
byte *dst = _surface;
for (int y = 0; y < 16; y++) {
const byte *cursor = nullptr, *mask = nullptr;
- if (y < cursorCast->_widget->getSurface()->h &&
- y < maskCast->_widget->getSurface()->h) {
- cursor = (const byte *)cursorCast->_widget->getSurface()->getBasePtr(0, y);
- mask = (const byte *)maskCast->_widget->getSurface()->getBasePtr(0, y);
+ if (y < cursorBitmap->_img->getSurface()->h &&
+ y < maskBitmap->_img->getSurface()->h) {
+ cursor = (const byte *)cursorBitmap->_img->getSurface()->getBasePtr(0, y);
+ mask = (const byte *)maskBitmap->_img->getSurface()->getBasePtr(0, y);
}
for (int x = 0; x < 16; x++) {
- if (x >= cursorCast->_widget->getSurface()->w ||
- x >= maskCast->_widget->getSurface()->w) {
+ if (x >= cursorBitmap->_img->getSurface()->w ||
+ x >= maskBitmap->_img->getSurface()->w) {
cursor = mask = nullptr;
}
diff --git a/engines/director/events.cpp b/engines/director/events.cpp
index bf7b6f4d89..960019f735 100644
--- a/engines/director/events.cpp
+++ b/engines/director/events.cpp
@@ -65,10 +65,26 @@ void DirectorEngine::processEvents() {
uint endTime = g_system->getMillis() + 10;
+ Movie *m = getCurrentMovie();
+ if (m) {
+ Score *sc = m->getScore();
+
+ if (sc && sc->getCurrentFrame() >= sc->_frames.size()) {
+ warning("processEvents: request to access frame %d of %d", sc->getCurrentFrame(), sc->_frames.size() - 1);
+ return;
+ }
+ }
+
+ uint16 spriteId = 0;
+
+ Common::Point pos;
+
while (g_system->getMillis() < endTime) {
while (g_system->getEventManager()->pollEvent(event)) {
- if (_wm->processEvent(event))
+ if (_wm->processEvent(event)) {
+ // window manager has done something! update the channels
continue;
+ }
switch (event.type) {
case Common::EVENT_QUIT:
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index a85f6bfccf..571e4454cb 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -919,16 +919,16 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
if (_vm->getCurrentMovie()->_currentEditableTextChannel != 0) {
Channel *channel = _vm->getCurrentMovie()->getScore()->getChannelById(_vm->getCurrentMovie()->_currentEditableTextChannel);
- if (channel->_sprite->_cast->_widget)
- (((Graphics::MacText *)channel->_sprite->_cast->_widget)->setSelection(d.asInt(), false));
+ if (channel->_widget)
+ (((Graphics::MacText *)channel->_widget)->setSelection(d.asInt(), false));
}
break;
case kTheSelStart:
if (_vm->getCurrentMovie()->_currentEditableTextChannel != 0) {
Channel *channel = _vm->getCurrentMovie()->getScore()->getChannelById(_vm->getCurrentMovie()->_currentEditableTextChannel);
- if (channel->_sprite->_cast->_widget)
- (((Graphics::MacText *)channel->_sprite->_cast->_widget)->setSelection(d.asInt(), true));
+ if (channel->_widget)
+ (((Graphics::MacText *)channel->_widget)->setSelection(d.asInt(), true));
}
break;
case kTheSoundEnabled:
@@ -1218,9 +1218,7 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
if (d.asInt() != sprite->_castId) {
g_director->getCurrentStage()->addDirtyRect(channel->getBbox());
- sprite->setCast(d.asInt());
- channel->_width = sprite->_width;
- channel->_height = sprite->_height;
+ channel->setCast(d.asInt());
} else {
channel->_dirty = false;
}
@@ -1244,7 +1242,8 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
}
break;
case kTheEditableText:
- sprite->_cast ? sprite->_cast->setEditable(d.asInt()) : false;
+ if (sprite->_cast)
+ sprite->_cast->setEditable(d.asInt());
break;
case kTheForeColor:
if (d.asInt() != sprite->_foreColor) {
@@ -1649,7 +1648,6 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
if (member->_type == kCastButton) {
TextCastMember *button = (TextCastMember *)member;
if ((bool)d.asInt() != member->_hilite) {
- ((Graphics::MacButton *) button->_widget)->invertInner();
button->_hilite = !!d.asInt();
}
} else {
@@ -1761,17 +1759,16 @@ Datum Lingo::getTheField(Datum &id1, int field) {
break;
case kTheTextAlign:
d.type = STRING;
- switch (((Graphics::MacText *)member->_widget)->getAlign()) {
- case Graphics::kTextAlignLeft:
+ switch (((TextCastMember *)member)->_textAlign) {
+ case kTextAlignLeft:
d.u.s = new Common::String("left");
break;
- case Graphics::kTextAlignCenter:
+ case kTextAlignCenter:
d.u.s = new Common::String("center");
break;
- case Graphics::kTextAlignRight:
+ case kTextAlignRight:
d.u.s = new Common::String("right");
break;
- case Graphics::kTextAlignInvalid:
default:
warning("Lingo::getTheField: Invalid text align spec");
break;
@@ -1823,20 +1820,19 @@ void Lingo::setTheField(Datum &id1, int field, Datum &d) {
Common::String select = d.asString(true);
select.toLowercase();
- Graphics::TextAlign align;
+ TextAlignType align;
if (select == "\"left\"") {
- align = Graphics::kTextAlignLeft;
+ align = kTextAlignLeft;
} else if (select == "\"center\"") {
- align = Graphics::kTextAlignCenter;
+ align = kTextAlignCenter;
} else if (select == "\"right\"") {
- align = Graphics::kTextAlignRight;
+ align = kTextAlignRight;
} else {
warning("Lingo::setTheField: Unknown text align spec: %s", d.asString(true).c_str());
break;
}
- ((Graphics::MacText *)member->_widget)->setAlignOffset(align);
- ((Graphics::MacText *)member->_widget)->draw();
+ ((TextCastMember *)member)->_textAlign = align;
member->_modified = true;
break;
}
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index fce329da49..af799189d8 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -230,7 +230,7 @@ void Score::startPlay() {
// All frames in the same movie have the same number of channels
if (_playState != kPlayStopped)
for (uint i = 0; i < _frames[1]->_sprites.size(); i++)
- _channels.push_back(new Channel(_frames[1]->_sprites[i]));
+ _channels.push_back(new Channel(_frames[1]->_sprites[i], i));
if (_vm->getVersion() >= 3)
_movie->processEvent(kEventStartMovie);
@@ -438,10 +438,14 @@ void Score::renderSprites(uint16 frameId, RenderMode mode) {
Sprite *currentSprite = channel->_sprite;
Sprite *nextSprite = _frames[frameId]->_sprites[i];
+ // widget content has changed and needs a redraw.
+ // this doesn't include changes in dimension or position!
+ bool widgetRedrawn = channel->updateWidget();
+
if (channel->isActiveText())
_movie->_currentEditableTextChannel = i;
- if (channel->isDirty(nextSprite) || mode == kRenderForceUpdate) {
+ if (channel->isDirty(nextSprite) || widgetRedrawn || mode == kRenderForceUpdate) {
if (!currentSprite->_trails)
_stage->addDirtyRect(channel->getBbox());
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 4dbbb839ff..a9e187b763 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -166,16 +166,13 @@ void Sprite::setCast(uint16 castId) {
// information set in the sprite.
warning("Sprite::setCast(): Working around D2/3 button glitch");
- delete _cast->_widget;
_cast->_type = kCastButton;
((TextCastMember *)_cast)->_buttonType = (ButtonType)(_spriteType - 8);
- ((TextCastMember *)_cast)->createWidget();
}
- if (_cast->_widget) {
- _width = _cast->_widget->_dims.width();
- _height = _cast->_widget->_dims.height();
- }
+ Common::Rect dims = _cast->getWidgetRect();
+ _width = dims.width();
+ _height = dims.height();
} else {
warning("Sprite::setCast(): CastMember id %d has null member", castId);
}
diff --git a/graphics/macgui/macbutton.cpp b/graphics/macgui/macbutton.cpp
index a63431877b..92a5b558e4 100644
--- a/graphics/macgui/macbutton.cpp
+++ b/graphics/macgui/macbutton.cpp
@@ -38,24 +38,23 @@ MacButton::MacButton(MacButtonType buttonType, TextAlign textAlignment, MacWidge
_buttonType = buttonType;
- int offset = 0;
switch (buttonType) {
case kCheckBox:
- offset = 16;
+ _alignOffset.x += 16;
+ _dims.right += 16;
break;
case kRound:
- offset = 4;
- _dims.top -= 2;
- _dims.bottom += 2;
+ _alignOffset.x += 2;
_alignOffset.y += 2;
+ _dims.right += 2;
+ _dims.bottom += 4;
break;
case kRadio:
- offset = 16;
+ _alignOffset.x += 16;
+ _dims.right += 16;
break;
}
- _alignOffset.x += offset;
- _dims.right += offset;
_composeSurface->create(_dims.width(), _dims.height());
_composeSurface->clear(_bgcolor);
}
diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index a87aa32cc9..805336c51b 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -357,13 +357,6 @@ void MacText::splitString(const Common::U32String &str, int curLine) {
D(9, "** splitString(\"%s\")", toPrintable(str.encode()).c_str());
- if (str.empty()) {
- debug(9, "** splitString, empty line");
- return;
- }
-
- Common::U32String paragraph, tmp;
-
if (_textLines.empty()) {
_textLines.resize(1);
_textLines[0].chunks.push_back(_defaultFormatting);
@@ -372,6 +365,13 @@ void MacText::splitString(const Common::U32String &str, int curLine) {
D(9, "** splitString, continuing, %d lines", _textLines.size());
}
+ if (str.empty()) {
+ debug(9, "** splitString, empty line");
+ return;
+ }
+
+ Common::U32String paragraph, tmp;
+
if (curLine == -1)
curLine = _textLines.size() - 1;
@@ -395,7 +395,7 @@ void MacText::splitString(const Common::U32String &str, int curLine) {
paragraph += *l++;
}
- D(9, "** splitString, paragraph: \"%s\"", Common::toPrintable(line.encode()).c_str());
+ D(9, "** splitString, paragraph: \"%s\"", Common::toPrintable(paragraph.encode()).c_str());
// Now process whole paragraph
const Common::U32String::value_type *s = paragraph.c_str();
diff --git a/graphics/macgui/macwidget.cpp b/graphics/macgui/macwidget.cpp
index 9440b4541c..090948abe5 100644
--- a/graphics/macgui/macwidget.cpp
+++ b/graphics/macgui/macwidget.cpp
@@ -54,6 +54,9 @@ MacWidget::~MacWidget() {
if (_parent)
_parent->removeWidget(this, false);
+ if (_wm)
+ _wm->clearWidgetRefs(this);
+
if (_composeSurface) {
_composeSurface->free();
delete _composeSurface;
diff --git a/graphics/macgui/macwindowmanager.cpp b/graphics/macgui/macwindowmanager.cpp
index 9f1c3c029f..729235688a 100644
--- a/graphics/macgui/macwindowmanager.cpp
+++ b/graphics/macgui/macwindowmanager.cpp
@@ -228,6 +228,14 @@ void MacWindowManager::setActiveWidget(MacWidget *widget) {
_activeWidget->setActive(true);
}
+void MacWindowManager::clearWidgetRefs(MacWidget *widget) {
+ if (widget == _hoveredWidget)
+ _hoveredWidget = nullptr;
+
+ if (widget == _activeWidget)
+ _activeWidget = nullptr;
+}
+
MacWindow *MacWindowManager::addWindow(bool scrollable, bool resizable, bool editable) {
MacWindow *w = new MacWindow(_lastId, scrollable, resizable, editable, this);
diff --git a/graphics/macgui/macwindowmanager.h b/graphics/macgui/macwindowmanager.h
index 075221255c..e4b56aefca 100644
--- a/graphics/macgui/macwindowmanager.h
+++ b/graphics/macgui/macwindowmanager.h
@@ -252,6 +252,8 @@ public:
MacWidget *getActiveWidget() { return _activeWidget; }
+ void clearWidgetRefs(MacWidget *widget);
+
void pushCursor(MacCursorType type, Cursor *cursor = nullptr);
void replaceCursor(MacCursorType type, Cursor *cursor = nullptr);
More information about the Scummvm-git-logs
mailing list