DIRECTOR: Change member refs to use CastMemberID

This commit is contained in:
djsrv 2021-06-30 18:41:00 -04:00
parent 1724a158c6
commit 615995fdc1
25 changed files with 289 additions and 284 deletions

View File

@ -115,7 +115,8 @@ const Graphics::Surface *Channel::getMask(bool forceMatte) {
return nullptr;
}
} else if (_sprite->_ink == kInkTypeMask) {
CastMember *member = g_director->getCurrentMovie()->getCastMember(_sprite->_castId + 1);
CastMemberID maskID(_sprite->_castId.member + 1, _sprite->_castId.castLib);
CastMember *member = g_director->getCurrentMovie()->getCastMember(maskID);
if (member && member->_initialRect == _sprite->_cast->_initialRect) {
Common::Rect bbox(getBbox());
@ -287,24 +288,24 @@ Common::Rect Channel::getBbox(bool unstretched) {
return result;
}
void Channel::setCast(uint16 castId) {
_sprite->setCast(castId);
void Channel::setCast(CastMemberID memberID) {
_sprite->setCast(memberID);
_width = _sprite->_width;
_height = _sprite->_height;
replaceWidget(0);
replaceWidget();
}
void Channel::setClean(Sprite *nextSprite, int spriteId, bool partial) {
if (!nextSprite)
return;
uint16 previousCastId = 0;
CastMemberID previousCastId(0, 0);
bool replace = isDirty(nextSprite);
if (nextSprite) {
if (nextSprite->_cast && (_dirty || _sprite->_castId != nextSprite->_castId)) {
if (nextSprite->_cast->_type == kCastDigitalVideo) {
Common::String path = nextSprite->_cast->getCast()->getVideoPath(nextSprite->_castId);
Common::String path = nextSprite->_cast->getCast()->getVideoPath(nextSprite->_castId.member);
if (!path.empty()) {
((DigitalVideoCastMember *)nextSprite->_cast)->loadVideo(pathMakeRelative(path));
@ -452,15 +453,15 @@ void Channel::setBbox(int l, int t, int r, int b) {
// here is the place for deciding whether the widget can be keep or not
// here's the definition, we first need to have widgets to keep, and the cast is not modified(modified means we need to re-create the widget)
// and the castId should be same while castId should not be zero
bool Channel::canKeepWidget(uint16 castId) {
if (_widget && _sprite && _sprite->_cast && !_sprite->_cast->isModified() && castId && castId == _sprite->_castId) {
bool Channel::canKeepWidget(CastMemberID castId) {
if (_widget && _sprite && _sprite->_cast && !_sprite->_cast->isModified() && castId.member && castId == _sprite->_castId) {
return true;
}
return false;
}
bool Channel::canKeepWidget(Sprite *currentSprite, Sprite *nextSprite) {
if (_widget && currentSprite && currentSprite->_cast && nextSprite && nextSprite->_cast && !currentSprite->_cast->isModified() && currentSprite->_castId == nextSprite->_castId && currentSprite->_castId) {
if (_widget && currentSprite && currentSprite->_cast && nextSprite && nextSprite->_cast && !currentSprite->_cast->isModified() && currentSprite->_castId == nextSprite->_castId && currentSprite->_castId.member) {
return true;
}
return false;
@ -468,10 +469,10 @@ bool Channel::canKeepWidget(Sprite *currentSprite, Sprite *nextSprite) {
// currently, when we are setting hilite, we delete the widget and the re-create it
// so we may optimize this if this operation takes much time
void Channel::replaceWidget(uint16 previousCastId) {
void Channel::replaceWidget(CastMemberID previousCastId) {
// if the castmember is the same, and we are not modifying anything which cannot be handle by channel. Then we don't replace the widget
if (canKeepWidget(previousCastId)) {
debug(5, "Channel::replaceWidget(): skip deleting %d %s", _sprite->_castId, numToCastNum(_sprite->_castId));
debug(5, "Channel::replaceWidget(): skip deleting %s", _sprite->_castId.asString().c_str());
return;
}

View File

@ -58,18 +58,18 @@ public:
void setWidth(int w);
void setHeight(int h);
void setBbox(int l, int t, int r, int b);
void setCast(uint16 castId);
void setCast(CastMemberID memberID);
void setClean(Sprite *nextSprite, int spriteId, bool partial = false);
void setEditable(bool editable);
void replaceSprite(Sprite *nextSprite);
void replaceWidget(uint16 previousCastId = 0);
void replaceWidget(CastMemberID previousCastId = CastMemberID(0, 0));
bool updateWidget();
void updateTextCast();
void updateGlobalAttr();
void addDelta(Common::Point pos);
bool canKeepWidget(uint16 castId);
bool canKeepWidget(CastMemberID castId);
bool canKeepWidget(Sprite *currentSprite, Sprite *nextSprite);
public:

View File

@ -34,8 +34,8 @@ Cursor::Cursor() {
_cursorResId = 0;
_cursorType = Graphics::kMacCursorArrow;
_cursorCastId = 0;
_cursorMaskId = 0;
_cursorCastId = CastMemberID(0, 0);
_cursorMaskId = CastMemberID(0, 0);
_usePalette = false;
}
@ -47,7 +47,7 @@ bool Cursor::operator==(const Cursor &c) {
_cursorMaskId == c._cursorMaskId;
}
void Cursor::readFromCast(uint cursorId, uint maskId) {
void Cursor::readFromCast(CastMemberID cursorId, CastMemberID maskId) {
if (cursorId == _cursorCastId && maskId == _cursorMaskId)
return;
@ -147,7 +147,7 @@ void Cursor::readFromResource(int resourceId) {
}
}
void Cursor::resetCursor(Graphics::MacCursorType type, bool shouldClear, int resId, uint castId, uint maskId) {
void Cursor::resetCursor(Graphics::MacCursorType type, bool shouldClear, int resId, CastMemberID castId, CastMemberID maskId) {
if (shouldClear)
clear();

View File

@ -37,10 +37,10 @@ class Cursor : public Graphics::MacCursor {
public:
Cursor();
void readFromCast(uint cursorId, uint maskId);
void readFromCast(CastMemberID cursorId, CastMemberID maskId);
void readFromResource(int resourceId);
bool isEmpty() { return !(_cursorResId || _cursorCastId); }
bool isEmpty() { return _cursorResId == 0 && _cursorCastId.member == 0; }
bool operator==(const Cursor &c);
virtual byte getKeyColor() const override { return _keyColor; }
@ -50,11 +50,11 @@ class Cursor : public Graphics::MacCursor {
Graphics::MacCursorType _cursorType;
int _cursorResId;
uint _cursorCastId;
uint _cursorMaskId;
CastMemberID _cursorCastId;
CastMemberID _cursorMaskId;
private:
void resetCursor(Graphics::MacCursorType type, bool shouldClear = false, int resId = 0, uint castId = 0, uint maskId = 0);
void resetCursor(Graphics::MacCursorType type, bool shouldClear = false, int resId = 0, CastMemberID castId = CastMemberID(0, 0), CastMemberID maskId = CastMemberID(0, 0));
private:
bool _usePalette;

View File

@ -42,12 +42,12 @@ Frame::Frame(Score *score, int numChannels) {
_numChannels = numChannels;
_sound1 = 0;
_sound2 = 0;
_sound1 = CastMemberID(0, 0);
_sound2 = CastMemberID(0, 0);
_soundType1 = 0;
_soundType2 = 0;
_actionId = 0;
_actionId = CastMemberID(0, 0);
_skipFrameFlag = 0;
_blend = 0;
@ -91,7 +91,7 @@ Frame::Frame(const Frame &frame) {
_score = frame._score;
debugC(1, kDebugLoading, "Frame. action: %d transType: %d transDuration: %d", _actionId, _transType, _transDuration);
debugC(1, kDebugLoading, "Frame. action: %s transType: %d transDuration: %d", _actionId.asString().c_str(), _transType, _transDuration);
_sprites.resize(_numChannels + 1);
@ -131,7 +131,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
if (version < kFileVer400) {
// Sound/Tempo/Transition
_actionId = stream->readByte();
_actionId = CastMemberID(stream->readByte(), 0);
_soundType1 = stream->readByte(); // type: 0x17 for sounds (sound is cast id), 0x16 for MIDI (sound is cmd id)
uint8 transFlags = stream->readByte(); // 0x80 is whole stage (vs changed area), rest is duration in 1/4ths of a second
@ -144,10 +144,10 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
_transChunkSize = stream->readByte();
_tempo = stream->readByte();
_transType = static_cast<TransitionType>(stream->readByte());
_sound1 = stream->readUint16();
_sound1 = CastMemberID(stream->readUint16(), 0);
if (_vm->getPlatform() == Common::kPlatformMacintosh) {
_sound2 = stream->readUint16();
_sound2 = CastMemberID(stream->readUint16(), 0);
_soundType2 = stream->readByte();
} else {
stream->read(unk, 3);
@ -158,7 +158,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
_blend = stream->readByte();
if (_vm->getPlatform() != Common::kPlatformMacintosh) {
_sound2 = stream->readUint16();
_sound2 = CastMemberID(stream->readUint16(), 0);
_soundType2 = stream->readByte();
}
@ -188,7 +188,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
stream->read(unk, 4);
}
debugC(8, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1, _skipFrameFlag, _blend, _sound2, _soundType2);
debugC(8, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId.member, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1.member, _skipFrameFlag, _blend, _sound2.member, _soundType2);
if (_vm->getPlatform() == Common::kPlatformMacintosh)
stream->read(unk, 3);
@ -210,9 +210,9 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
_transChunkSize = stream->readByte();
_tempo = stream->readByte();
_transType = static_cast<TransitionType>(stream->readByte());
_sound1 = stream->readUint16();
_sound1 = CastMemberID(stream->readUint16(), 0);
_sound2 = stream->readUint16();
_sound2 = CastMemberID(stream->readUint16(), 0);
_soundType2 = stream->readByte();
_skipFrameFlag = stream->readByte();
@ -222,7 +222,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
_colorSound1 = stream->readByte();
_colorSound2 = stream->readByte();
_actionId = stream->readUint16();
_actionId = CastMemberID(stream->readUint16(), 0);
_colorScript = stream->readByte();
_colorTrans = stream->readByte();
@ -247,7 +247,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
stream->readByte();
debugC(8, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1, _skipFrameFlag, _blend, _sound2, _soundType2);
debugC(8, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId.member, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1.member, _skipFrameFlag, _blend, _sound2.member, _soundType2);
} else if (version >= kFileVer500 && version < kFileVer600) {
// Sound/Tempo/Transition channel
stream->read(unk, 24);
@ -269,7 +269,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
Sprite &sprite = *_sprites[i + 1];
if (version < kFileVer500) {
sprite._scriptId = stream->readByte();
sprite._scriptId = CastMemberID(stream->readByte(), 0);
sprite._spriteType = (SpriteType)stream->readByte();
sprite._enabled = sprite._spriteType != kInactiveSprite;
if (version >= kFileVer400) {
@ -287,7 +287,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
if (sprite.isQDShape()) {
sprite._pattern = stream->readUint16();
} else {
sprite._castId = stream->readUint16();
sprite._castId = CastMemberID(stream->readUint16(), 0);
}
sprite._startPoint.y = (int16)stream->readUint16();
@ -297,7 +297,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
sprite._width = (int16)stream->readUint16();
if (version >= kFileVer400) {
sprite._scriptId = stream->readUint16();
sprite._scriptId = CastMemberID(stream->readUint16(), 0);
// & 0x0f scorecolor
// 0x10 forecolor is rgb
// 0x20 bgcolor is rgb
@ -310,11 +310,13 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
sprite._spriteType = (SpriteType)stream->readByte();
sprite._inkData = stream->readByte();
sprite._castIndex = stream->readUint16();
sprite._castId = stream->readUint16();
uint16 castLib = stream->readUint16();
uint16 memberID = stream->readUint16();
sprite._castId = CastMemberID(memberID, castLib);
sprite._scriptCastIndex = stream->readUint16();
sprite._scriptId = stream->readUint16();
uint16 scriptCastLib = stream->readUint16();
uint16 scriptMemberID = stream->readUint16();
sprite._scriptId = CastMemberID(scriptMemberID, scriptCastLib);
sprite._foreColor = _vm->transformColor((uint8)stream->readByte());
sprite._backColor = _vm->transformColor((uint8)stream->readByte());
@ -336,8 +338,9 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
sprite._foreColor = _vm->transformColor((uint8)stream->readByte());
sprite._backColor = _vm->transformColor((uint8)stream->readByte());
sprite._castIndex = stream->readUint16();
sprite._castId = stream->readUint16();
uint16 castLib = stream->readUint16();
uint16 memberID = stream->readUint16();
sprite._castId = CastMemberID(memberID, castLib);
/* uint32 spriteId = */stream->readUint32();
@ -369,12 +372,12 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
if (sprite._castId) {
debugC(4, kDebugLoading, "CH: %-3d castId: %03d(%s) [flags:%04x [ink: %x trails: %d line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d] script: %d, flags2: %x, unk2: %x, unk3: %x",
i + 1, sprite._castId, numToCastNum(sprite._castId), sprite._inkData,
if (sprite._castId.member) {
debugC(4, kDebugLoading, "CH: %-3d castId: %s [flags:%04x [ink: %x trails: %d line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d] script: %s, flags2: %x, unk2: %x, unk3: %x",
i + 1, sprite._castId.asString().c_str(), sprite._inkData,
sprite._ink, sprite._trails, sprite._thickness, sprite._width, sprite._height,
sprite._startPoint.x, sprite._startPoint.y,
sprite._spriteType, sprite._foreColor, sprite._backColor, sprite._scriptId, sprite._colorcode, sprite._blendAmount, sprite._unk3);
sprite._spriteType, sprite._foreColor, sprite._backColor, sprite._scriptId.asString().c_str(), sprite._colorcode, sprite._blendAmount, sprite._unk3);
} else {
debugC(4, kDebugLoading, "CH: %-3d castId: 000", i + 1);
}
@ -387,7 +390,7 @@ void Frame::readMainChannels(Common::SeekableReadStreamEndian &stream, uint16 of
while (offset < finishPosition) {
switch(offset) {
case kScriptIdPosition:
_actionId = stream.readByte();
_actionId = CastMemberID(stream.readByte(), 0);
offset++;
break;
case kSoundType1Position:
@ -417,7 +420,7 @@ void Frame::readMainChannels(Common::SeekableReadStreamEndian &stream, uint16 of
offset++;
break;
case kSound1Position:
_sound1 = stream.readUint16();
_sound1 = CastMemberID(stream.readUint16(), 0);
offset+=2;
break;
case kSkipFrameFlagsPosition:
@ -429,7 +432,7 @@ void Frame::readMainChannels(Common::SeekableReadStreamEndian &stream, uint16 of
offset++;
break;
case kSound2Position:
_sound2 = stream.readUint16();
_sound2 = CastMemberID(stream.readUint16(), 0);
offset += 2;
break;
case kSound2TypePosition:
@ -449,7 +452,7 @@ void Frame::readMainChannels(Common::SeekableReadStreamEndian &stream, uint16 of
}
}
debugC(1, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1, _skipFrameFlag, _blend, _sound2, _soundType2);
debugC(1, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId.member, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1.member, _skipFrameFlag, _blend, _sound2.member, _soundType2);
}
void Frame::readPaletteInfo(Common::SeekableReadStreamEndian &stream) {
@ -499,7 +502,7 @@ void Frame::readSprite(Common::SeekableReadStreamEndian &stream, uint16 offset,
fieldPosition += 2;
break;
case kSpritePositionCastId:
sprite._castId = stream.readUint16();
sprite._castId = CastMemberID(stream.readUint16(), 0);
fieldPosition += 2;
break;
case kSpritePositionY:
@ -525,7 +528,7 @@ void Frame::readSprite(Common::SeekableReadStreamEndian &stream, uint16 offset,
break;
}
}
warning("Frame::readSprite(): %03d(%d)[%x,%x,%02x %02x,%d/%d/%d/%d]", sprite._castId, sprite._enabled, x1, x2, sprite._thickness, sprite._inkData, sprite._startPoint.x, sprite._startPoint.y, sprite._width, sprite._height);
warning("Frame::readSprite(): %s(%d)[%x,%x,%02x %02x,%d/%d/%d/%d]", sprite._castId.asString().c_str(), sprite._enabled, x1, x2, sprite._thickness, sprite._inkData, sprite._startPoint.x, sprite._startPoint.y, sprite._width, sprite._height);
}

View File

@ -101,7 +101,7 @@ private:
public:
int _numChannels;
byte _channelData[kChannelDataSize];
uint16 _actionId;
CastMemberID _actionId;
uint16 _transDuration;
uint8 _transArea; // 1 - Whole Window, 0 - Changing Area
uint8 _transChunkSize;
@ -109,9 +109,9 @@ public:
PaletteInfo _palette;
uint8 _tempo;
uint16 _sound1;
CastMemberID _sound1;
uint8 _soundType1;
uint16 _sound2;
CastMemberID _sound2;
uint8 _soundType2;
byte _colorTempo;

View File

@ -1518,9 +1518,9 @@ void LB::b_cursor(int nargs) {
Datum sprite = d.u.farr->operator[](0);
Datum mask = d.u.farr->operator[](1);
g_lingo->func_cursor(sprite.asCastId(), mask.asCastId());
g_lingo->func_cursor(sprite.asMemberID(), mask.asMemberID());
} else {
g_lingo->func_cursor(d.asInt(), -1);
g_lingo->func_cursor(d.asInt());
}
}
@ -1658,25 +1658,24 @@ void LB::b_installMenu(int nargs) {
// installMenu castNum
Datum d = g_lingo->pop();
int castId = d.asCastId();
if (castId == 0) {
CastMemberID memberID = d.asMemberID();
if (memberID.member == 0) {
g_director->_wm->removeMenu();
return;
}
CastMember *member = g_director->getCurrentMovie()->getCastMember(castId);
CastMember *member = g_director->getCurrentMovie()->getCastMember(memberID);
if (!member) {
g_lingo->lingoError("installMenu: Unknown cast number #%d", castId);
g_lingo->lingoError("installMenu: Unknown %s", memberID.asString().c_str());
return;
}
if (member->_type != kCastText) {
g_lingo->lingoError("installMenu: Cast member %d is not a field", castId);
g_lingo->lingoError("installMenu: %s is not a field", memberID.asString().c_str());
return;
}
TextCastMember *field = static_cast<TextCastMember *>(member);
Common::String menuStxt = g_lingo->_compiler->codePreprocessor(field->getText().c_str(), field->getCast()->_lingoArchive, kNoneScript, castId, true);
Common::String menuStxt = g_lingo->_compiler->codePreprocessor(field->getText().c_str(), field->getCast()->_lingoArchive, kNoneScript, memberID.member, true);
Common::String line;
int linenum = -1; // We increment it before processing
@ -1843,14 +1842,10 @@ void LB::b_puppetPalette(int nargs) {
palette = kClutNTSC;
} else if (palStr.equalsIgnoreCase("Metallic")) {
palette = kClutMetallic;
} else {
CastMember *member = g_director->getCurrentMovie()->getCastMemberByName(palStr);
if (member && member->_type == kCastPalette)
palette = ((PaletteCastMember *)member)->getPaletteId();
}
} else {
CastMember *member = g_director->getCurrentMovie()->getCastMember(d.asInt());
}
if (!palette) {
CastMember *member = g_director->getCurrentMovie()->getCastMember(d.asMemberID());
if (member && member->_type == kCastPalette)
palette = ((PaletteCastMember *)member)->getPaletteId();
@ -1896,7 +1891,7 @@ void LB::b_puppetSound(int nargs) {
return;
}
int castId = castMember.asCastId();
CastMemberID castId = castMember.asMemberID();
sound->playCastMember(castId, channel);
}
@ -2414,26 +2409,26 @@ void LB::b_version(int nargs) {
///////////////////
void LB::b_cast(int nargs) {
Datum d = g_lingo->pop();
Datum res = d.asCastId();
Datum res = d.asMemberID();
res.type = CASTREF;
g_lingo->push(res);
}
void LB::b_script(int nargs) {
Datum d = g_lingo->pop();
int castId = d.asCastId();
CastMember *cast = g_director->getCurrentMovie()->getCastMember(castId);
CastMemberID memberID = d.asMemberID();
CastMember *cast = g_director->getCurrentMovie()->getCastMember(memberID);
if (cast) {
ScriptContext *script = nullptr;
if (cast->_type == kCastLingoScript) {
// script cast can be either a movie script or score script
script = g_director->getCurrentMovie()->getScriptContext(kMovieScript, castId);
script = g_director->getCurrentMovie()->getScriptContext(kMovieScript, memberID);
if (!script)
script = g_director->getCurrentMovie()->getScriptContext(kScoreScript, castId);
script = g_director->getCurrentMovie()->getScriptContext(kScoreScript, memberID);
} else {
g_director->getCurrentMovie()->getScriptContext(kCastScript, castId);
g_director->getCurrentMovie()->getScriptContext(kCastScript, memberID);
}
if (script) {

View File

@ -358,7 +358,7 @@ Datum Lingo::findVarV4(int varType, const Datum &id) {
}
break;
case 6: // field
res = id.asCastId();
res = id.asMemberID();
res.type = FIELDREF;
break;
default:
@ -396,7 +396,7 @@ void LC::cb_delete() {
}
void LC::cb_hilite() {
Datum fieldID = g_lingo->pop().asCastId();
Datum fieldID = g_lingo->pop().asMemberID();
fieldID.type = FIELDREF;
Datum chunkRef = readChunkRef(fieldID);
g_lingo->push(chunkRef);
@ -756,7 +756,7 @@ void LC::cb_v4theentitypush() {
break;
case kTEAChunk:
{
Datum fieldRef = g_lingo->pop().asCastId();
Datum fieldRef = g_lingo->pop().asMemberID();
fieldRef.type = FIELDREF;
Datum chunkRef = readChunkRef(fieldRef);
result = g_lingo->getTheEntity(entity, chunkRef, field);
@ -862,7 +862,7 @@ void LC::cb_v4theentityassign() {
break;
case kTEAChunk:
{
Datum fieldRef = g_lingo->pop().asCastId();
Datum fieldRef = g_lingo->pop().asMemberID();
fieldRef.type = FIELDREF;
Datum chunkRef = readChunkRef(fieldRef);
g_lingo->setTheEntity(entity, chunkRef, field, value);

View File

@ -1633,7 +1633,8 @@ void LC::c_delete() {
void LC::c_hilite() {
Datum d = g_lingo->pop();
int fieldId, start, end;
CastMemberID fieldId;
int start, end;
if (d.type == CHUNKREF) {
start = d.u.cref->start;
end = d.u.cref->end;
@ -1644,13 +1645,13 @@ void LC::c_hilite() {
src = src.u.cref->source;
}
if (src.isCastRef()) {
fieldId = src.u.i;
fieldId = *d.u.cast;
} else {
warning("BUILDBOT: c_hilite: bad chunk ref field type: %s", src.type2str());
return;
}
} else if (d.isCastRef()) {
fieldId = d.u.i;
fieldId = *d.u.cast;
start = 0;
end = -1;
} else {
@ -1675,7 +1676,7 @@ void LC::c_hilite() {
void LC::c_fieldref() {
Datum d = g_lingo->pop();
Datum res = d.asCastId();
Datum res = d.asMemberID();
res.type = FIELDREF;
g_lingo->push(res);
}

View File

@ -128,7 +128,7 @@ void Movie::queueSpriteEvent(LEvent event, int eventId, int spriteId) {
Sprite *sprite = _score->getSpriteById(spriteId);
// Sprite (score) script
if (sprite->_scriptId) {
if (sprite->_scriptId.member) {
ScriptContext *script = getScriptContext(kScoreScript, sprite->_scriptId);
if (script) {
// In D3 the event lingo is not contained in a handler
@ -162,8 +162,8 @@ void Movie::queueFrameEvent(LEvent event, int eventId) {
// } else {
assert(_score->_frames[_score->getCurrentFrame()] != nullptr);
int scriptId = _score->_frames[_score->getCurrentFrame()]->_actionId;
if (!scriptId)
CastMemberID scriptId = _score->_frames[_score->getCurrentFrame()]->_actionId;
if (!scriptId.member)
return;
ScriptContext *script = getScriptContext(kScoreScript, scriptId);
@ -188,7 +188,7 @@ void Movie::queueMovieEvent(LEvent event, int eventId) {
for (ScriptContextHash::iterator it = mainArchive->scriptContexts[kMovieScript].begin();
it != mainArchive->scriptContexts[kMovieScript].end(); ++it) {
if (it->_value->_eventHandlers.contains(event)) {
_eventQueue.push(LingoEvent(event, eventId, kMovieScript, it->_key, false));
_eventQueue.push(LingoEvent(event, eventId, kMovieScript, CastMemberID(it->_key, 0), false));
return;
}
}
@ -197,7 +197,7 @@ void Movie::queueMovieEvent(LEvent event, int eventId) {
for (ScriptContextHash::iterator it = sharedArchive->scriptContexts[kMovieScript].begin();
it != sharedArchive->scriptContexts[kMovieScript].end(); ++it) {
if (it->_value->_eventHandlers.contains(event)) {
_eventQueue.push(LingoEvent(event, eventId, kMovieScript, it->_key, false));
_eventQueue.push(LingoEvent(event, eventId, kMovieScript, CastMemberID(it->_key, 0), false));
return;
}
}
@ -228,13 +228,19 @@ void Movie::registerEvent(LEvent event, int targetId) {
case kEventKeyUp:
case kEventKeyDown:
case kEventTimeout:
if (getScriptContext(kEventScript, event)) {
_eventQueue.push(LingoEvent(kEventGeneric, eventId, kEventScript, event, true));
{
CastMemberID scriptID = CastMemberID(event, 0);
if (getScriptContext(kEventScript, scriptID)) {
_eventQueue.push(LingoEvent(kEventGeneric, eventId, kEventScript, scriptID, true));
}
}
break;
case kEventMenuCallback:
if (getScriptContext(kEventScript, targetId)) {
_eventQueue.push(LingoEvent(kEventGeneric, eventId, kEventScript, targetId, true));
{
CastMemberID scriptID = CastMemberID(targetId, 0);
if (getScriptContext(kEventScript, scriptID)) {
_eventQueue.push(LingoEvent(kEventGeneric, eventId, kEventScript, scriptID, true));
}
}
break;
default:
@ -336,7 +342,7 @@ void Lingo::processEvents() {
}
}
void Lingo::processEvent(LEvent event, ScriptType st, int scriptId, int channelId) {
void Lingo::processEvent(LEvent event, ScriptType st, CastMemberID scriptId, int channelId) {
_currentChannelId = channelId;
if (!_eventHandlerTypes.contains(event))
@ -345,11 +351,11 @@ void Lingo::processEvent(LEvent event, ScriptType st, int scriptId, int channelI
ScriptContext *script = g_director->getCurrentMovie()->getScriptContext(st, scriptId);
if (script && script->_eventHandlers.contains(event)) {
debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d): executing event handler", _eventHandlerTypes[event], scriptType2str(st), scriptId);
debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %s): executing event handler", _eventHandlerTypes[event], scriptType2str(st), scriptId.asString().c_str());
LC::call(script->_eventHandlers[event], 0, false);
execute(_pc);
} else {
debugC(9, kDebugEvents, "Lingo::processEvent(%s, %s, %d): no handler", _eventHandlerTypes[event], scriptType2str(st), scriptId);
debugC(9, kDebugEvents, "Lingo::processEvent(%s, %s, %s): no handler", _eventHandlerTypes[event], scriptType2str(st), scriptId.asString().c_str());
}
}

View File

@ -301,15 +301,16 @@ void Lingo::func_play(Datum &frame, Datum &movie) {
func_goto(frame, movie);
}
void Lingo::func_cursor(int cursorId, int maskId) {
void Lingo::func_cursor(CastMemberID cursorId, CastMemberID maskId) {
Cursor cursor;
cursor.readFromCast(cursorId, maskId);
// TODO: Figure out why there are artifacts here
_vm->_wm->replaceCursor(cursor._cursorType, ((Graphics::Cursor *)&cursor));
}
if (maskId == -1) {
cursor.readFromResource(cursorId);
} else {
cursor.readFromCast(cursorId, maskId);
}
void Lingo::func_cursor(int cursorId) {
Cursor cursor;
cursor.readFromResource(cursorId);
// TODO: Figure out why there are artifacts here
_vm->_wm->replaceCursor(cursor._cursorType, ((Graphics::Cursor *)&cursor));
}

View File

@ -593,10 +593,11 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
break;
case kTheMouseCast:
{
// TODO: How is this handled with multiple casts in D5?
Common::Point pos = g_director->getCurrentWindow()->getMousePos();
uint16 spriteId = score->getSpriteIDFromPos(pos);
d.type = INT;
d.u.i = score->getSpriteById(spriteId)->_castId;
d.u.i = score->getSpriteById(spriteId)->_castId.member;
if (d.u.i == 0)
d.u.i = -1;
}
@ -1139,7 +1140,8 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
d.u.i = channel->getBbox().bottom;
break;
case kTheCastNum:
d.u.i = sprite->_castId;
// TODO: How is this handled with multiple casts in D5?
d.u.i = sprite->_castId.member;
break;
case kTheConstraint:
d.u.i = channel->_constraint;
@ -1151,8 +1153,9 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
d.type = ARRAY;
d.u.farr = new DatumArray(2);
d.u.farr->operator[](0) = (int)channel->_cursor._cursorCastId;
d.u.farr->operator[](1) = (int)channel->_cursor._cursorMaskId;
// TODO: How is this handled with multiple casts in D5?
d.u.farr->operator[](0) = (int)channel->_cursor._cursorCastId.member;
d.u.farr->operator[](1) = (int)channel->_cursor._cursorMaskId.member;
}
break;
case kTheEditableText:
@ -1293,11 +1296,11 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
break;
case kTheCastNum:
{
int castId = d.asCastId();
CastMemberID castId = d.asMemberID();
CastMember *castMember = g_director->getCurrentMovie()->getCastMember(castId);
if (castMember && castMember->_type == kCastDigitalVideo) {
Common::String path = castMember->getCast()->getVideoPath(castId);
Common::String path = castMember->getCast()->getVideoPath(castId.member);
if (!path.empty()) {
((DigitalVideoCastMember *)castMember)->loadVideo(pathMakeRelative(path));
((DigitalVideoCastMember *)castMember)->startVideo(channel);
@ -1321,9 +1324,9 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
if (d.type == CASTREF) {
// Reference: CastMember ID
// Find the first channel that uses this cast.
int castId = d.u.i;
CastMemberID memberID = *d.u.cast;
for (uint i = 0; i < score->_channels.size(); i++) {
if (score->_channels[i]->_sprite->_castId == castId) {
if (score->_channels[i]->_sprite->_castId == memberID) {
channelId = i;
break;
}
@ -1342,8 +1345,8 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
channel->_cursor.readFromResource(d.asInt());
score->_cursorDirty = true;
} else if (d.type == ARRAY && d.u.farr->size() == 2) {
uint cursorId = d.u.farr->operator[](0).asCastId();
uint maskId = d.u.farr->operator[](1).asCastId();
CastMemberID cursorId = d.u.farr->operator[](0).asMemberID();
CastMemberID maskId = d.u.farr->operator[](1).asMemberID();
if (cursorId == channel->_cursor._cursorCastId &&
maskId == channel->_cursor._cursorMaskId)
@ -1502,7 +1505,7 @@ Datum Lingo::getTheCast(Datum &id1, int field) {
return d;
}
int id = id1.asCastId();
CastMemberID id = id1.asMemberID();
CastMember *member = movie->getCastMember(id);
if (!member) {
@ -1517,7 +1520,7 @@ Datum Lingo::getTheCast(Datum &id1, int field) {
}
if (!member->hasField(field)) {
warning("Lingo::getTheCast(): CastMember %d has no property '%s'", id, field2str(field));
warning("Lingo::getTheCast(): %s has no property '%s'", id.asString().c_str(), field2str(field));
return d;
}
@ -1533,16 +1536,16 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
return;
}
int id = id1.asCastId();
CastMemberID id = id1.asMemberID();
CastMember *member = movie->getCastMember(id);
if (!member) {
g_lingo->lingoError("Lingo::setTheCast(): CastMember %d not found", id);
g_lingo->lingoError("Lingo::setTheCast(): %s not found", id.asString().c_str());
return;
}
if (!member->hasField(field)) {
warning("Lingo::setTheCast(): CastMember %d has no property '%s'", id, field2str(field));
warning("Lingo::setTheCast(): %s has no property '%s'", id.asString().c_str(), field2str(field));
return;
}
@ -1558,24 +1561,24 @@ Datum Lingo::getTheField(Datum &id1, int field) {
return d;
}
int id = id1.asCastId();
CastMemberID id = id1.asMemberID();
CastMember *member = movie->getCastMember(id);
if (!member) {
if (field == kTheLoaded) {
d = 0;
} else {
g_lingo->lingoError("Lingo::getTheField(): CastMember %d not found", id);
g_lingo->lingoError("Lingo::getTheField(): %s not found", id.asString().c_str());
}
return d;
}
if (member->_type != kCastText) {
g_lingo->lingoError("Lingo::getTheField(): CastMember %d is not a field", id);
g_lingo->lingoError("Lingo::getTheField(): %s is not a field", id.asString().c_str());
return d;
}
if (!member->hasField(field)) {
warning("Lingo::getTheField(): CastMember %d has no property '%s'", id, field2str(field));
warning("Lingo::getTheField(): %s has no property '%s'", id.asString().c_str(), field2str(field));
return d;
}
@ -1591,20 +1594,20 @@ void Lingo::setTheField(Datum &id1, int field, Datum &d) {
return;
}
int id = id1.asCastId();
CastMemberID id = id1.asMemberID();
CastMember *member = movie->getCastMember(id);
if (!member) {
g_lingo->lingoError("Lingo::setTheField(): CastMember %d not found", id);
g_lingo->lingoError("Lingo::setTheField(): %s not found", id.asString().c_str());
return;
}
if (member->_type != kCastText) {
g_lingo->lingoError("Lingo::setTheField(): CastMember %d is not a field", id);
g_lingo->lingoError("Lingo::setTheField(): %s is not a field", id.asString().c_str());
return;
}
if (!member->hasField(field)) {
warning("Lingo::setTheField(): CastMember %d has no property '%s'", id, field2str(field));
warning("Lingo::setTheField(): %s has no property '%s'", id.asString().c_str(), field2str(field));
return;
}
@ -1639,18 +1642,19 @@ Datum Lingo::getTheChunk(Datum &chunk, int field) {
return d;
}
CastMember *member = movie->getCastMember(src.u.i);
CastMemberID memberID = *src.u.cast;
CastMember *member = movie->getCastMember(memberID);
if (!member) {
g_lingo->lingoError("Lingo::getTheChunk(): CastMember %d not found", src.u.i);
g_lingo->lingoError("Lingo::getTheChunk(): %s not found", memberID.asString().c_str());
return d;
}
if (member->_type != kCastText) {
g_lingo->lingoError("Lingo::getTheChunk(): CastMember %d is not a field", src.u.i);
g_lingo->lingoError("Lingo::getTheChunk(): %s is not a field", memberID.asString().c_str());
return d;
}
if (!((TextCastMember *)member)->hasChunkField(field)) {
warning("Lingo::getTheChunk(): CastMember %d has no chunk property '%s'", src.u.i, field2str(field));
warning("Lingo::getTheChunk(): %s has no chunk property '%s'", memberID.asString().c_str(), field2str(field));
return d;
}
@ -1685,18 +1689,19 @@ void Lingo::setTheChunk(Datum &chunk, int field, Datum &d) {
return;
}
CastMember *member = movie->getCastMember(src.u.i);
CastMemberID memberID = *src.u.cast;
CastMember *member = movie->getCastMember(memberID);
if (!member) {
g_lingo->lingoError("Lingo::setTheChunk(): CastMember %d not found", src.u.i);
g_lingo->lingoError("Lingo::setTheChunk(): %s not found", memberID.asString().c_str());
return;
}
if (member->_type != kCastText) {
g_lingo->lingoError("Lingo::setTheChunk(): CastMember %d is not a field", src.u.i);
g_lingo->lingoError("Lingo::setTheChunk(): %s is not a field", memberID.asString().c_str());
return;
}
if (!((TextCastMember *)member)->hasChunkField(field)) {
warning("Lingo::setTheChunk(): CastMember %d has no chunk property '%s'", src.u.i, field2str(field));
warning("Lingo::setTheChunk(): %s has no chunk property '%s'", memberID.asString().c_str(), field2str(field));
return;
}
@ -1730,13 +1735,13 @@ void Lingo::getObjectProp(Datum &obj, Common::String &propName) {
return;
}
int id = obj.u.i;
CastMemberID id = *obj.u.cast;
CastMember *member = movie->getCastMember(id);
if (!member) {
if (propName.equalsIgnoreCase("loaded")) {
d = 0;
} else {
g_lingo->lingoError("Lingo::getObjectProp(): CastMember %d not found", id);
g_lingo->lingoError("Lingo::getObjectProp(): %s not found", id.asString().c_str());
}
g_lingo->push(d);
return;
@ -1745,7 +1750,7 @@ void Lingo::getObjectProp(Datum &obj, Common::String &propName) {
if (member->hasProp(propName)) {
d = member->getProp(propName);
} else {
g_lingo->lingoError("Lingo::getObjectProp(): CastMember %d has no property '%s'", id, propName.c_str());
g_lingo->lingoError("Lingo::getObjectProp(): %s has no property '%s'", id.asString().c_str(), propName.c_str());
}
g_lingo->push(d);
return;
@ -1781,17 +1786,17 @@ void Lingo::setObjectProp(Datum &obj, Common::String &propName, Datum &val) {
return;
}
int id = obj.u.i;
CastMemberID id = *obj.u.cast;
CastMember *member = movie->getCastMember(id);
if (!member) {
g_lingo->lingoError("Lingo::setObjectProp(): CastMember %d not found", id);
g_lingo->lingoError("Lingo::setObjectProp(): %s not found", id.asString().c_str());
return;
}
if (member->hasProp(propName)) {
member->setProp(propName, val);
} else {
g_lingo->lingoError("Lingo::setObjectProp(): CastMember %d has no property '%s'", id, propName.c_str());
g_lingo->lingoError("Lingo::setObjectProp(): %s has no property '%s'", id.asString().c_str(), propName.c_str());
}
} else {
g_lingo->lingoError("Lingo::setObjectProp: Invalid object: %s", obj.asString(true).c_str());

View File

@ -449,7 +449,7 @@ void Lingo::execute(uint pc) {
_abort = false;
}
void Lingo::executeScript(ScriptType type, uint16 id) {
void Lingo::executeScript(ScriptType type, CastMemberID id) {
Movie *movie = _vm->getCurrentMovie();
if (!movie) {
warning("Request to execute script with no movie");
@ -459,16 +459,16 @@ void Lingo::executeScript(ScriptType type, uint16 id) {
ScriptContext *sc = movie->getScriptContext(type, id);
if (!sc) {
debugC(3, kDebugLingoExec, "Request to execute non-existent script type %d id %d", type, id);
debugC(3, kDebugLingoExec, "Request to execute non-existent script type %d id %d of castLib %d", type, id.member, id.castLib);
return;
}
if (!sc->_eventHandlers.contains(kEventGeneric)) {
debugC(3, kDebugLingoExec, "Request to execute script type %d id %d with no scopeless lingo", type, id);
debugC(3, kDebugLingoExec, "Request to execute script type %d id %d of castLib %d with no scopeless lingo", type, id.member, id.castLib);
return;
}
debugC(1, kDebugLingoExec, "Executing script type: %s, id: %d", scriptType2str(type), id);
debugC(1, kDebugLingoExec, "Executing script type: %s, id: %d, castLib %d", scriptType2str(type), id.member, id.castLib);
Symbol sym = sc->_eventHandlers[kEventGeneric];
LC::call(sym, 0, false);
@ -625,6 +625,13 @@ Datum::Datum(AbstractObject *val) {
}
}
Datum::Datum(const CastMemberID &val) {
u.cast = new CastMemberID(val);
type = CASTREF;
refCount = new int;
*refCount = 1;
}
void Datum::reset() {
if (!refCount)
return;
@ -664,6 +671,10 @@ void Datum::reset() {
case CHUNKREF:
delete u.cref;
break;
case CASTREF:
case FIELDREF:
delete u.cast;
break;
default:
break;
}
@ -802,20 +813,10 @@ Common::String Datum::asString(bool printonly) const {
s = Common::String::format("property: #%s", u.s->c_str());
break;
case CASTREF:
s = Common::String::format("cast %d", u.i);
s = Common::String::format("member %d of castLib %d", u.cast->member, u.cast->castLib);
break;
case FIELDREF:
{
int idx = u.i;
CastMember *member = g_director->getCurrentMovie()->getCastMember(idx);
if (!member) {
warning("asString(): Unknown cast id %d", idx);
s = "";
break;
}
s = Common::String::format("field: \"%s\"", ((TextCastMember *)member)->getText().c_str());
}
s = Common::String::format("field %d of castLib %d", u.cast->member, u.cast->castLib);
break;
case CHUNKREF:
{
@ -875,40 +876,11 @@ Common::String Datum::asString(bool printonly) const {
return s;
}
int Datum::asCastId() const {
Movie *movie = g_director->getCurrentMovie();
if (!movie) {
warning("Datum::asCastId: No movie");
return 0;
}
CastMemberID Datum::asMemberID() const {
if (type == CASTREF || type == FIELDREF)
return *u.cast;
int castId = 0;
switch (type) {
case STRING:
{
CastMember *member = movie->getCastMemberByName(asString());
if (member)
return member->getID();
warning("Datum::asCastId: reference to non-existent cast member: %s", asString().c_str());
return -1;
}
break;
case INT:
case CASTREF:
castId = u.i;
break;
case FLOAT:
castId = u.f;
break;
case VOID:
warning("Datum::asCastId: reference to VOID cast ID");
break;
default:
error("Datum::asCastId: unsupported cast ID type %s", type2str());
}
return castId;
return g_lingo->resolveCastMember(*this, 0);
}
bool Datum::isRef() const {
@ -1056,7 +1028,7 @@ void Lingo::runTests() {
if (!debugChannelSet(-1, kDebugCompileOnly)) {
if (!_compiler->_hadError)
executeScript(kTestScript, counter);
executeScript(kTestScript, CastMemberID(counter, 0));
else
debug(">> Skipping execution");
}
@ -1072,7 +1044,7 @@ void Lingo::runTests() {
void Lingo::executeImmediateScripts(Frame *frame) {
for (uint16 i = 0; i <= _vm->getCurrentMovie()->getScore()->_numChannelsDisplayed; i++) {
if (_vm->getCurrentMovie()->getScore()->_immediateActions.contains(frame->_sprites[i]->_scriptId)) {
if (_vm->getCurrentMovie()->getScore()->_immediateActions.contains(frame->_sprites[i]->_scriptId.member)) {
// From D5 only explicit event handlers are processed
// Before that you could specify commands which will be executed on mouse up
if (_vm->getVersion() < 500)
@ -1189,10 +1161,9 @@ void Lingo::varAssign(const Datum &var, const Datum &value) {
warning("varAssign: Assigning to a reference to an empty movie");
return;
}
int castId = var.u.i;
CastMember *member = movie->getCastMember(castId);
CastMember *member = movie->getCastMember(*var.u.cast);
if (!member) {
warning("varAssign: Unknown cast id %d", castId);
warning("varAssign: Unknown %s", var.u.cast->asString().c_str());
return;
}
switch (member->_type) {
@ -1310,10 +1281,9 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
warning("varFetch: Assigning to a reference to an empty movie");
return result;
}
int castId = var.u.i;
CastMember *member = movie->getCastMember(castId);
CastMember *member = movie->getCastMember(*var.u.cast);
if (!member) {
warning("varFetch: Unknown cast id %d", castId);
warning("varFetch: Unknown %s", var.u.cast->asString().c_str());
return result;
}
switch (member->_type) {

View File

@ -112,6 +112,7 @@ struct Datum { /* interpreter stack type */
PropertyArray *parr; /* PARRAY */
AbstractObject *obj; /* OBJECT */
ChunkReference *cref; /* CHUNKREF */
CastMemberID *cast; /* CASTREF, FIELDREF */
} u;
int *refCount;
@ -123,6 +124,7 @@ struct Datum { /* interpreter stack type */
Datum(double val);
Datum(const Common::String &val);
Datum(AbstractObject *val);
Datum(const CastMemberID &val);
void reset();
~Datum() {
@ -133,7 +135,7 @@ struct Datum { /* interpreter stack type */
double asFloat() const;
int asInt() const;
Common::String asString(bool printonly = false) const;
int asCastId() const;
CastMemberID asMemberID() const;
bool isRef() const;
bool isVarRef() const;
@ -199,11 +201,11 @@ struct LingoEvent {
LEvent event;
int eventId;
ScriptType scriptType;
int scriptId;
CastMemberID scriptId;
bool passByDefault;
int channelId;
LingoEvent (LEvent e, int ei, ScriptType st, int si, bool pass, int ci = -1) {
LingoEvent (LEvent e, int ei, ScriptType st, CastMemberID si, bool pass, int ci = -1) {
event = e;
eventId = ei;
scriptType = st;
@ -242,7 +244,7 @@ public:
void resetLingo();
void executeHandler(const Common::String &name);
void executeScript(ScriptType type, uint16 id);
void executeScript(ScriptType type, CastMemberID id);
void printStack(const char *s, uint pc);
void printCallStack(uint pc);
Common::String decodeInstruction(LingoArchive *archive, ScriptData *sd, uint pc, uint *newPC = NULL);
@ -264,7 +266,7 @@ public:
// lingo-events.cpp
private:
void initEventHandlerTypes();
void processEvent(LEvent event, ScriptType st, int entityId, int channelId = -1);
void processEvent(LEvent event, ScriptType st, CastMemberID scriptId, int channelId = -1);
public:
ScriptType event2script(LEvent ev);
@ -313,7 +315,8 @@ public:
void func_gotoprevious();
void func_play(Datum &frame, Datum &movie);
void func_playdone();
void func_cursor(int cursorId, int maskId);
void func_cursor(CastMemberID cursorId, CastMemberID maskId);
void func_cursor(int cursorId);
int func_marker(int m);
uint16 func_label(Datum &label);

View File

@ -296,34 +296,54 @@ void Movie::loadSharedCastsFrom(Common::String filename) {
_sharedCast->loadArchive();
}
CastMember *Movie::getCastMember(int castId) {
CastMember *result = _cast->getCastMember(castId);
if (result == nullptr && _sharedCast) {
result = _sharedCast->getCastMember(castId);
CastMember *Movie::getCastMember(CastMemberID memberID) {
CastMember *result = nullptr;
if (memberID.castLib == 0) {
result = _cast->getCastMember(memberID.member);
if (result == nullptr && _sharedCast) {
result = _sharedCast->getCastMember(memberID.member);
}
} else {
warning("Movie::getCastMember: Unknown castLib %d", memberID.castLib);
}
return result;
}
CastMember *Movie::getCastMemberByName(const Common::String &name) {
CastMember *result = _cast->getCastMemberByName(name);
if (result == nullptr && _sharedCast) {
result = _sharedCast->getCastMemberByName(name);
CastMember *Movie::getCastMemberByName(const Common::String &name, int castLib) {
CastMember *result = nullptr;
if (castLib == 0) {
result = _cast->getCastMemberByName(name);
if (result == nullptr && _sharedCast) {
result = _sharedCast->getCastMemberByName(name);
}
} else {
warning("Movie::getCastMemberByName: Unknown castLib %d", castLib);
}
return result;
}
CastMemberInfo *Movie::getCastMemberInfo(int castId) {
CastMemberInfo *result = _cast->getCastMemberInfo(castId);
if (result == nullptr && _sharedCast) {
result = _sharedCast->getCastMemberInfo(castId);
CastMemberInfo *Movie::getCastMemberInfo(CastMemberID memberID) {
CastMemberInfo *result = nullptr;
if (memberID.castLib == 0) {
result = _cast->getCastMemberInfo(memberID.member);
if (result == nullptr && _sharedCast) {
result = _sharedCast->getCastMemberInfo(memberID.member);
}
} else {
warning("Movie::getCastMemberInfo: Unknown castLib %d", memberID.castLib);
}
return result;
}
const Stxt *Movie::getStxt(int castId) {
const Stxt *result = _cast->getStxt(castId);
if (result == nullptr && _sharedCast) {
result = _sharedCast->getStxt(castId);
const Stxt *Movie::getStxt(CastMemberID memberID) {
const Stxt *result = nullptr;
if (memberID.castLib == 0) {
result = _cast->getStxt(memberID.member);
if (result == nullptr && _sharedCast) {
result = _sharedCast->getStxt(memberID.member);
}
} else {
warning("Movie::getStxt: Unknown castLib %d", memberID.castLib);
}
return result;
}
@ -336,10 +356,15 @@ LingoArchive *Movie::getSharedLingoArch() {
return _sharedCast ? _sharedCast->_lingoArchive : nullptr;
}
ScriptContext *Movie::getScriptContext(ScriptType type, uint16 id) {
ScriptContext *result = _cast->_lingoArchive->getScriptContext(type, id);
if (result == nullptr && _sharedCast) {
result = _sharedCast->_lingoArchive->getScriptContext(type, id);
ScriptContext *Movie::getScriptContext(ScriptType type, CastMemberID id) {
ScriptContext *result = nullptr;
if (id.castLib == 0) {
result = _cast->_lingoArchive->getScriptContext(type, id.member);
if (result == nullptr && _sharedCast) {
result = _sharedCast->_lingoArchive->getScriptContext(type, id.member);
}
} else {
warning("Movie::getScriptContext: Unknown castLib %d", id.castLib);
}
return result;
}

View File

@ -117,14 +117,14 @@ public:
void clearSharedCast();
void loadSharedCastsFrom(Common::String filename);
CastMember *getCastMember(int castId);
CastMember *getCastMemberByName(const Common::String &name);
CastMemberInfo *getCastMemberInfo(int castId);
const Stxt *getStxt(int castId);
CastMember *getCastMember(CastMemberID memberID);
CastMember *getCastMemberByName(const Common::String &name, int castLib);
CastMemberInfo *getCastMemberInfo(CastMemberID memberID);
const Stxt *getStxt(CastMemberID memberID);
LingoArchive *getMainLingoArch();
LingoArchive *getSharedLingoArch();
ScriptContext *getScriptContext(ScriptType type, uint16 id);
ScriptContext *getScriptContext(ScriptType type, CastMemberID id);
Symbol getHandler(const Common::String &name);
// events.cpp

View File

@ -98,8 +98,9 @@ int Score::getCurrentPalette() {
}
int Score::resolvePaletteId(int id) {
// TODO: Palette ID should be a CastMemberID to allow for palettes in different casts
if (id > 0) {
CastMember *member = _movie->getCastMember(id);
CastMember *member = _movie->getCastMember(CastMemberID(id, 0));
id = (member && member->_type == kCastPalette) ? ((PaletteCastMember *)member)->getPaletteId() : 0;
}
@ -458,7 +459,7 @@ void Score::renderFrame(uint16 frameId, RenderMode mode) {
if (mode != kRenderNoWindowRender)
_window->render();
if (_frames[frameId]->_sound1 || _frames[frameId]->_sound2)
if (_frames[frameId]->_sound1.member || _frames[frameId]->_sound2.member)
playSoundChannel(frameId);
if (_cursorDirty) {
@ -513,7 +514,7 @@ void Score::renderSprites(uint16 frameId, RenderMode mode) {
_movie->_videoPlayback = true;
_window->addDirtyRect(channel->getBbox());
debugC(2, kDebugImages, "Score::renderSprites(): CH: %-3d castId: %03d(%s) [ink: %d, puppet: %d, moveable: %d, visible: %d] [bbox: %d,%d,%d,%d] [type: %d fg: %d bg: %d] [script: %d]", i, currentSprite->_castId, numToCastNum(currentSprite->_castId), currentSprite->_ink, currentSprite->_puppet, currentSprite->_moveable, channel->_visible, PRINT_RECT(channel->getBbox()), currentSprite->_spriteType, currentSprite->_foreColor, currentSprite->_backColor, currentSprite->_scriptId);
debugC(2, kDebugImages, "Score::renderSprites(): CH: %-3d castId: %s [ink: %d, puppet: %d, moveable: %d, visible: %d] [bbox: %d,%d,%d,%d] [type: %d fg: %d bg: %d] [script: %s]", i, currentSprite->_castId.asString().c_str(), currentSprite->_ink, currentSprite->_puppet, currentSprite->_moveable, channel->_visible, PRINT_RECT(channel->getBbox()), currentSprite->_spriteType, currentSprite->_foreColor, currentSprite->_backColor, currentSprite->_scriptId.asString().c_str());
} else {
channel->setClean(nextSprite, i, true);
}
@ -618,7 +619,7 @@ Common::List<Channel *> Score::getSpriteIntersections(const Common::Rect &r) {
return intersections;
}
uint16 Score::getSpriteIdByMemberId(uint16 id) {
uint16 Score::getSpriteIdByMemberId(CastMemberID id) {
for (uint i = 0; i < _channels.size(); i++)
if (_channels[i]->_sprite->_castId == id)
return i;
@ -657,7 +658,7 @@ Channel *Score::getChannelById(uint16 id) {
void Score::playSoundChannel(uint16 frameId) {
Frame *frame = _frames[frameId];
debugC(5, kDebugLoading, "playSoundChannel(): Sound1 %d Sound2 %d", frame->_sound1, frame->_sound2);
debugC(5, kDebugLoading, "playSoundChannel(): Sound1 %s Sound2 %s", frame->_sound1.asString().c_str(), frame->_sound2.asString().c_str());
DirectorSound *sound = _vm->getSoundManager();
sound->playCastMember(frame->_sound1, 1, false);
sound->playCastMember(frame->_sound2, 2, false);
@ -776,7 +777,7 @@ void Score::loadFrames(Common::SeekableReadStreamEndian &stream, uint16 version)
frame->readChannels(str, version);
delete str;
debugC(8, kDebugLoading, "Score::loadFrames(): Frame %d actionId: %d", _frames.size(), frame->_actionId);
debugC(8, kDebugLoading, "Score::loadFrames(): Frame %d actionId: %s", _frames.size(), frame->_actionId.asString().c_str());
_frames.push_back(frame);
} else {
@ -792,7 +793,7 @@ void Score::setSpriteCasts() {
for (uint16 j = 0; j < _frames[i]->_sprites.size(); j++) {
_frames[i]->_sprites[j]->setCast(_frames[i]->_sprites[j]->_castId);
debugC(1, kDebugImages, "Score::setSpriteCasts(): Frame: %d Channel: %d castId: %d type: %d", i, j, _frames[i]->_sprites[j]->_castId, _frames[i]->_sprites[j]->_spriteType);
debugC(1, kDebugImages, "Score::setSpriteCasts(): Frame: %d Channel: %d castId: %s type: %d", i, j, _frames[i]->_sprites[j]->_castId.asString().c_str(), _frames[i]->_sprites[j]->_spriteType);
}
}
}
@ -886,12 +887,12 @@ void Score::loadActions(Common::SeekableReadStreamEndian &stream) {
// Now let's scan which scripts are actually referenced
for (uint i = 0; i < _frames.size(); i++) {
if (_frames[i]->_actionId <= _actions.size())
scriptRefs[_frames[i]->_actionId] = true;
if ((uint)_frames[i]->_actionId.member <= _actions.size())
scriptRefs[_frames[i]->_actionId.member] = true;
for (uint16 j = 0; j <= _frames[i]->_numChannels; j++) {
if (_frames[i]->_sprites[j]->_scriptId <= _actions.size())
scriptRefs[_frames[i]->_sprites[j]->_scriptId] = true;
if ((uint)_frames[i]->_sprites[j]->_scriptId.member <= _actions.size())
scriptRefs[_frames[i]->_sprites[j]->_scriptId.member] = true;
}
}

View File

@ -106,7 +106,7 @@ public:
uint16 getActiveSpriteIDFromPos(Common::Point pos);
bool checkSpriteIntersection(uint16 spriteId, Common::Point pos);
Common::List<Channel *> getSpriteIntersections(const Common::Rect &r);
uint16 getSpriteIdByMemberId(uint16 id);
uint16 getSpriteIdByMemberId(CastMemberID id);
bool renderTransition(uint16 frameId);
void renderFrame(uint16 frameId, RenderMode mode = kRenderModeNormal);

View File

@ -95,21 +95,21 @@ void DirectorSound::playStream(Audio::AudioStream &stream, uint8 soundChannel) {
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_channels[soundChannel - 1].handle, &stream, -1, _channels[soundChannel - 1].volume);
}
void DirectorSound::playCastMember(int castId, uint8 soundChannel, bool allowRepeat) {
if (castId == 0) {
void DirectorSound::playCastMember(CastMemberID memberID, uint8 soundChannel, bool allowRepeat) {
if (memberID.member == 0) {
stopSound(soundChannel);
} else {
CastMember *soundCast = _vm->getCurrentMovie()->getCastMember(castId);
CastMember *soundCast = _vm->getCurrentMovie()->getCastMember(memberID);
if (soundCast) {
if (soundCast->_type != kCastSound) {
warning("DirectorSound::playCastMember: attempted to play a non-SoundCastMember cast member %d", castId);
warning("DirectorSound::playCastMember: attempted to play a non-SoundCastMember %s", memberID.asString().c_str());
} else {
if (!allowRepeat && lastPlayingCast(soundChannel) == castId)
if (!allowRepeat && lastPlayingCast(soundChannel) == memberID)
return;
bool looping = ((SoundCastMember *)soundCast)->_looping;
AudioDecoder *ad = ((SoundCastMember *)soundCast)->_audio;
if (!ad) {
warning("DirectorSound::playCastMember: no audio data attached to cast member %d", castId);
warning("DirectorSound::playCastMember: no audio data attached to %s", memberID.asString().c_str());
return;
}
Audio::AudioStream *as;
@ -122,10 +122,10 @@ void DirectorSound::playCastMember(int castId, uint8 soundChannel, bool allowRep
return;
}
playStream(*as, soundChannel);
_channels[soundChannel - 1].lastPlayingCast = castId;
_channels[soundChannel - 1].lastPlayingCast = memberID;
}
} else {
warning("DirectorSound::playCastMember: couldn't find cast member %d", castId);
warning("DirectorSound::playCastMember: couldn't find %s", memberID.asString().c_str());
}
}
}
@ -194,9 +194,9 @@ bool DirectorSound::isChannelValid(uint8 soundChannel) {
return true;
}
int DirectorSound::lastPlayingCast(uint8 soundChannel) {
CastMemberID DirectorSound::lastPlayingCast(uint8 soundChannel) {
if (!isChannelValid(soundChannel))
return false;
return CastMemberID(0, 0);
return _channels[soundChannel - 1].lastPlayingCast;
}
@ -207,7 +207,7 @@ void DirectorSound::stopSound(uint8 soundChannel) {
cancelFade(soundChannel);
_mixer->stopHandle(_channels[soundChannel - 1].handle);
_channels[soundChannel - 1].lastPlayingCast = 0;
_channels[soundChannel - 1].lastPlayingCast = CastMemberID(0, 0);
return;
}
@ -216,7 +216,7 @@ void DirectorSound::stopSound() {
cancelFade(i + 1);
_mixer->stopHandle(_channels[i].handle);
_channels[i].lastPlayingCast = 0;
_channels[i].lastPlayingCast = CastMemberID(0, 0);
}
_mixer->stopHandle(_scriptSound);

View File

@ -48,11 +48,11 @@ struct FadeParams {
struct SoundChannel {
Audio::SoundHandle handle;
int lastPlayingCast;
CastMemberID lastPlayingCast;
byte volume;
FadeParams *fade;
SoundChannel(): handle(), lastPlayingCast(0), volume(255), fade(nullptr) {}
SoundChannel(): handle(), volume(255), fade(nullptr) {}
};
class DirectorSound {
@ -73,14 +73,14 @@ public:
void playFile(Common::String filename, uint8 soundChannel);
void playMCI(Audio::AudioStream &stream, uint32 from, uint32 to);
void playStream(Audio::AudioStream &stream, uint8 soundChannel);
void playCastMember(int castId, uint8 soundChannel, bool allowRepeat = true);
void playCastMember(CastMemberID memberID, uint8 soundChannel, bool allowRepeat = true);
void systemBeep();
void registerFade(uint8 soundChannel, bool fadeIn, int ticks);
bool fadeChannel(uint8 soundChannel);
bool isChannelActive(uint8 soundChannel);
int lastPlayingCast(uint8 soundChannel);
CastMemberID lastPlayingCast(uint8 soundChannel);
void stopSound(uint8 soundChannel);
void stopSound();

View File

@ -38,17 +38,15 @@ Sprite::Sprite(Frame *frame) {
_score = _frame->getScore();
_movie = _score->getMovie();
_scriptId = 0;
_scriptCastIndex = 0;
_scriptId = CastMemberID(0, 0);
_colorcode = 0;
_blendAmount = 0;
_unk3 = 0;
_enabled = false;
_castId = 0;
_castId = CastMemberID(0, 0);
_pattern = 0;
_castIndex = 0;
_spriteType = kInactiveSprite;
_inkData = 0;
_ink = kInkTypeCopy;
@ -263,11 +261,11 @@ void Sprite::setPattern(uint16 pattern) {
}
}
void Sprite::setCast(uint16 castId) {
CastMember *member = _movie->getCastMember(castId);
_castId = castId;
void Sprite::setCast(CastMemberID memberID) {
CastMember *member = _movie->getCastMember(memberID);
_castId = memberID;
if (castId == 0)
if (memberID.member == 0)
return;
if (member) {
@ -293,7 +291,7 @@ void Sprite::setCast(uint16 castId) {
_height = dims.height();
}
} else {
warning("Sprite::setCast(): CastMember id %d(%s) has null member", castId, numToCastNum(castId));
warning("Sprite::setCast(): %s has null member", memberID.asString().c_str());
}
}

View File

@ -74,7 +74,7 @@ public:
uint16 getPattern();
void setPattern(uint16 pattern);
void setCast(uint16 castid);
void setCast(CastMemberID memberID);
bool isQDShape();
Graphics::Surface *getQDMatte();
void createQDMatte();
@ -83,20 +83,18 @@ public:
Score *_score;
Movie *_movie;
uint16 _scriptId;
uint16 _scriptCastIndex;
CastMemberID _scriptId;
byte _colorcode; // x40 editable, 0x80 moveable
byte _blendAmount;
uint32 _unk3;
bool _enabled;
uint16 _castIndex;
SpriteType _spriteType;
byte _inkData;
InkType _ink;
uint16 _trails;
uint16 _castId;
CastMemberID _castId;
uint16 _pattern;
CastMember *_cast;

View File

@ -378,7 +378,7 @@ struct CastMemberID {
return member != c.member || castLib != c.castLib;
}
const char *str() const;
Common::String asString() const;
};
struct Datum;

View File

@ -201,15 +201,13 @@ char *numToCastNum(int num) {
return res;
}
const char *CastMemberID::str() const {
static char res[40];
Common::String CastMemberID::asString() const {
Common::String res = Common::String::format("member %d", member);
if (g_director->getVersion() < 400 || g_director->getCurrentMovie()->_allowOutdatedLingo)
snprintf(res, 40, "member %d(%s)", member, numToCastNum(member));
else if (g_director->getVersion() < 500)
snprintf(res, 40, "member %d", member);
else
snprintf(res, 40, "member %d of castLib %d", member, castLib);
res += "(" + Common::String(numToCastNum(member)) + ")";
else if (g_director->getVersion() >= 500)
res += Common::String::format(" of castLib %d", castLib);
return res;
}

View File

@ -173,7 +173,7 @@ void Window::inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::Mana
inkBlitSurface(&pd, srcRect, channel->getMask());
}
} else {
warning("Window::inkBlitFrom: No source surface: spriteType: %d, castType: %d, castId: %d", channel->_sprite->_spriteType, channel->_sprite->_cast ? channel->_sprite->_cast->_type : 0, channel->_sprite->_castId);
warning("Window::inkBlitFrom: No source surface: spriteType: %d, castType: %d, castId: %s", channel->_sprite->_spriteType, channel->_sprite->_cast ? channel->_sprite->_cast->_type : 0, channel->_sprite->_castId.asString().c_str());
}
}