diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp index e81838c6ca1..a60a2bfd4f7 100644 --- a/engines/director/castmember.cpp +++ b/engines/director/castmember.cpp @@ -550,6 +550,30 @@ Common::String BitmapCastMember::formatInfo() { ); } +PictureReference *BitmapCastMember::getPicture() const { + auto picture = new PictureReference; + + // Not sure if we can make the assumption that the owning + // BitmapCastMember will live as long as any reference, + // so we'll make a copy of the Picture. + picture->_picture = new Picture(*_picture); + + return picture; +} + +void BitmapCastMember::setPicture(PictureReference &picture) { + delete _picture; + _picture = new Picture(*picture._picture); + + // Force redither + delete _ditheredImg; + _ditheredImg = nullptr; + + // Make sure we get redrawn + setModified(true); + // TODO: Should size be adjusted? +} + void BitmapCastMember::setPicture(Image::ImageDecoder &image, bool adjustSize) { delete _picture; _picture = new Picture(image); diff --git a/engines/director/castmember.h b/engines/director/castmember.h index 81f0fbfbbc1..1f38c9be2cf 100644 --- a/engines/director/castmember.h +++ b/engines/director/castmember.h @@ -137,6 +137,8 @@ public: Common::String formatInfo() override; + PictureReference *getPicture() const; + void setPicture(PictureReference &picture); void setPicture(Image::ImageDecoder &image, bool adjustSize); Picture *_picture = nullptr; diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp index ce81990b56a..9314167a060 100644 --- a/engines/director/lingo/lingo-builtins.cpp +++ b/engines/director/lingo/lingo-builtins.cpp @@ -1767,9 +1767,9 @@ void LB::b_objectp(int nargs) { } void LB::b_pictureP(int nargs) { - g_lingo->pop(); - warning("STUB: b_pictureP"); - g_lingo->push(Datum(0)); + Datum d = g_lingo->pop(); + Datum res((d.type == PICTUREREF) ? 1 : 0); + g_lingo->push(res); } void LB::b_stringp(int nargs) { diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp index 80e99b56f95..aba78187dda 100644 --- a/engines/director/lingo/lingo-object.cpp +++ b/engines/director/lingo/lingo-object.cpp @@ -963,7 +963,8 @@ Datum BitmapCastMember::getField(int field) { d = _clut; break; case kThePicture: - warning("STUB: BitmapCastMember::getField(): Unprocessed getting field \"%s\" of cast %d", g_lingo->field2str(field), _castId); + d.type = PICTUREREF; + d.u.picture = getPicture(); break; default: d = CastMember::getField(field); @@ -993,7 +994,12 @@ bool BitmapCastMember::setField(int field, const Datum &d) { _clut = d.asInt(); return true; case kThePicture: - warning("STUB: BitmapCastMember::setField(): Unprocessed setting field \"%s\" of cast %d", g_lingo->field2str(field), _castId); + if (d.type == PICTUREREF && d.u.picture != nullptr) { + setPicture(*d.u.picture); + return true; + } else { + warning("BitmapCastMember::setField(): Wrong Datum type %d for kThePicture (or nullptr)", d.type); + } return false; default: break; diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp index 0a22e1f49ca..244d71468dc 100644 --- a/engines/director/lingo/lingo.cpp +++ b/engines/director/lingo/lingo.cpp @@ -938,6 +938,9 @@ void Datum::reset() { case MENUREF: delete u.menu; break; + case PICTUREREF: + delete u.picture; + break; default: warning("Datum::reset(): Unprocessed REF type %d", type); break; @@ -1163,6 +1166,9 @@ Common::String Datum::asString(bool printonly) const { case MENUREF: s = Common::String::format("menu(%d, %d)", u.menu->menuIdNum, u.menu->menuItemIdNum); break; + case PICTUREREF: + s = Common::String::format("picture: %p", (void*)u.picture->_picture); + break; default: warning("Incorrect operation asString() for type: %s", type2str()); } @@ -1228,6 +1234,8 @@ const char *Datum::type2str(bool ilk) const { return ilk ? "object" : "OBJECT"; case PARRAY: return ilk ? "proplist" : "PARRAY"; + case PICTUREREF: + return ilk ? "picture" : "PICTUREREF"; case POINT: return ilk ? "point" : "POINT"; case PROPREF: @@ -1267,6 +1275,8 @@ int Datum::equalTo(Datum &d, bool ignoreCase) const { return u.obj == d.u.obj; case CASTREF: return *u.cast == *d.u.cast; + case PICTUREREF: + return 0; // Original always returns 0 on picture reference comparison default: break; } diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h index f6dffd0fdd1..1180a1d879e 100644 --- a/engines/director/lingo/lingo.h +++ b/engines/director/lingo/lingo.h @@ -41,6 +41,7 @@ namespace Director { struct ChunkReference; struct MenuReference; +struct PictureReference; struct TheEntity; struct TheEntityField; struct LingoArchive; @@ -144,6 +145,7 @@ struct Datum { /* interpreter stack type */ ChunkReference *cref; /* CHUNKREF */ CastMemberID *cast; /* CASTREF, FIELDREF */ MenuReference *menu; /* MENUREF */ + PictureReference *picture; /* PICTUREREF */ } u; int *refCount; @@ -209,6 +211,13 @@ struct MenuReference { MenuReference(); }; +struct PictureReference { + Picture *_picture = nullptr; + ~PictureReference() { + delete _picture; + } +}; + struct PCell { Datum p; Datum v; diff --git a/engines/director/lingo/tests/equality.lingo b/engines/director/lingo/tests/equality.lingo index 7e8bf9c9a48..c84b9a44fc8 100644 --- a/engines/director/lingo/tests/equality.lingo +++ b/engines/director/lingo/tests/equality.lingo @@ -19,3 +19,8 @@ scummvmAssert(" 0) -- Invalid comparisons should return FALSE scummvmAssert(not (#test <= 0)) + +-- Picture comparisons are always false, even between the exact same cast. +set a to the picture of cast 1 +scummvmAssert(a <> a) +scummvmAssert(a <> the picture of cast 1) -- always false diff --git a/engines/director/types.h b/engines/director/types.h index 52d0319024c..5d9ddefc5aa 100644 --- a/engines/director/types.h +++ b/engines/director/types.h @@ -357,6 +357,7 @@ enum DatumType { MENUREF, OBJECT, PARRAY, + PICTUREREF, POINT, PROPREF, RECT,