MTROPOLIS: Add mToon assets and elements and fix some things

This commit is contained in:
elasota
2022-06-16 21:58:09 +02:00
committed by Eugene Sandulenko
parent 7b48322af5
commit ea7eaa4a15
15 changed files with 550 additions and 22 deletions
+2
View File
@@ -65,6 +65,8 @@ IAssetFactory *getAssetFactoryForDataObjectType(const Data::DataObjectTypes::Dat
return AssetFactory<MovieAsset, Data::MovieAsset>::getInstance();
case Data::DataObjectTypes::kImageAsset:
return AssetFactory<ImageAsset, Data::ImageAsset>::getInstance();
case Data::DataObjectTypes::kMToonAsset:
return AssetFactory<MToonAsset, Data::MToonAsset>::getInstance();
case Data::DataObjectTypes::kTextAsset:
return AssetFactory<TextAsset, Data::TextAsset>::getInstance();
+56
View File
@@ -194,6 +194,62 @@ ImageAsset::ImageFormat ImageAsset::getImageFormat() const {
return _imageFormat;
}
bool MToonAsset::load(AssetLoaderContext &context, const Data::MToonAsset &data) {
if (data.haveMacPart)
_imageFormat = kImageFormatMac;
else if (data.haveWinPart)
_imageFormat = kImageFormatWindows;
else
return false;
_frameDataPosition = data.frameDataPosition;
_sizeOfFrameData = data.sizeOfFrameData;
if (!_rect.load(data.rect))
return false;
_bitsPerPixel = data.bitsPerPixel;
_codecID = data.codecID;
_frames.resize(data.frames.size());
for (size_t i = 0; i < _frames.size(); i++) {
if (!_frames[i].load(context, data.frames[i]))
return false;
}
_frameRanges.resize(data.frameRangesPart.frameRanges.size());
for (size_t i = 0; i < _frameRanges.size(); i++) {
if (!_frameRanges[i].load(context, data.frameRangesPart.frameRanges[i]))
return false;
}
_codecData = data.codecData;
}
AssetType MToonAsset::getAssetType() const {
return kAssetTypeMToon;
}
bool MToonAsset::FrameDef::load(AssetLoaderContext &context, const Data::MToonAsset::FrameDef &data) {
compressedSize = data.compressedSize;
dataOffset = data.dataOffset;
decompressedBytesPerRow = data.decompressedBytesPerRow;
decompressedSize = data.decompressedSize;
isKeyFrame = (data.keyframeFlag != 0);
if (!rect.load(data.rect1))
return false;
return true;
}
bool MToonAsset::FrameRangeDef::load(AssetLoaderContext &context, const Data::MToonAsset::FrameRangeDef &data) {
name = data.name;
startFrame = data.startFrame;
endFrame = data.endFrame;
return true;
}
bool TextAsset::load(AssetLoaderContext &context, const Data::TextAsset &data) {
_assetID = data.assetID;
+50
View File
@@ -105,6 +105,8 @@ public:
size_t getStreamIndex() const;
ImageFormat getImageFormat() const;
const Common::SharedPtr<Graphics::Surface> &loadContent();
private:
Rect16 _rect;
ColorDepthMode _colorDepth;
@@ -112,6 +114,54 @@ private:
uint32 _size;
size_t _streamIndex;
ImageFormat _imageFormat;
Common::SharedPtr<Graphics::Surface> _surface;
};
struct MToonAsset : public Asset {
public:
bool load(AssetLoaderContext &context, const Data::MToonAsset &data);
AssetType getAssetType() const override;
enum ImageFormat {
kImageFormatMac,
kImageFormatWindows,
};
struct FrameDef {
Rect16 rect;
uint32 dataOffset;
uint32 compressedSize;
uint32 decompressedSize;
uint16 decompressedBytesPerRow;
bool isKeyFrame;
bool load(AssetLoaderContext &context, const Data::MToonAsset::FrameDef &data);
};
struct FrameRangeDef {
uint32 startFrame;
uint32 endFrame;
Common::String name;
bool load(AssetLoaderContext &context, const Data::MToonAsset::FrameRangeDef &data);
};
private:
ImageFormat _imageFormat;
uint32 _frameDataPosition;
uint32 _sizeOfFrameData;
Rect16 _rect;
uint16 _bitsPerPixel;
uint32 _codecID;
Common::Array<FrameDef> _frames;
Common::Array<FrameRangeDef> _frameRanges;
Common::Array<uint8> _codecData;
};
class TextAsset : public Asset {
+108 -2
View File
@@ -853,7 +853,7 @@ DataReadErrorCode MToonElement::load(DataReader &reader) {
if (!reader.readU32(structuralFlags) || !reader.readU32(sizeIncludingTag) || !reader.readU32(guid)
|| !reader.readU16(lengthOfName) || !reader.readU32(elementFlags) || !reader.readU16(layer)
|| !reader.readU32(animationFlags) || !reader.readBytes(unknown4) || !reader.readU16(sectionID)
|| !rect1.load(reader) || !rect2.load(reader) || !reader.readU32(unknown5)
|| !rect1.load(reader) || !rect2.load(reader) || !reader.readU32(assetID)
|| !reader.readU32(rateTimes10000) || !reader.readU32(streamLocator) || !reader.readU32(unknown6)
|| !reader.readTerminatedStr(name, lengthOfName))
return kDataReadErrorReadFailed;
@@ -1032,6 +1032,20 @@ DataReadErrorCode MiniscriptModifier::load(DataReader &reader) {
return kDataReadErrorNone;
}
DataReadErrorCode SaveAndRestoreModifier::load(DataReader &reader) {
if (_revision != 0x3e9)
return kDataReadErrorUnsupportedRevision;
if (!modHeader.load(reader) || !reader.readBytes(unknown1) || !saveWhen.load(reader) || !restoreWhen.load(reader)
|| !saveOrRestoreValue.load(reader) || !reader.readBytes(unknown5) || !reader.readU8(lengthOfFilePath)
|| !reader.readU8(lengthOfFileName) || !reader.readU8(lengthOfVariableName) || !reader.readU8(lengthOfVariableString)
|| !reader.readNonTerminatedStr(varName, lengthOfVariableName) || !reader.readNonTerminatedStr(varString, lengthOfVariableString)
|| !reader.readNonTerminatedStr(filePath, lengthOfFilePath) || !reader.readNonTerminatedStr(fileName, lengthOfFileName))
return kDataReadErrorReadFailed;
return kDataReadErrorNone;
}
DataReadErrorCode MessengerModifier::load(DataReader &reader) {
if (_revision != 0x3ea)
return kDataReadErrorUnsupportedRevision;
@@ -1629,6 +1643,95 @@ DataReadErrorCode ImageAsset::load(DataReader &reader) {
return kDataReadErrorNone;
}
DataReadErrorCode MToonAsset::load(DataReader &reader) {
if (_revision != 1)
return kDataReadErrorUnsupportedRevision;
if (!reader.readU32(marker) || !reader.readBytes(unknown1) || !reader.readU32(assetID))
return kDataReadErrorReadFailed;
haveMacPart = false;
haveWinPart = false;
if (reader.getProjectFormat() == kProjectFormatMacintosh) {
haveMacPart = true;
if (!reader.readBytes(platform.mac.unknown10))
return kDataReadErrorReadFailed;
} else if (reader.getProjectFormat() == kProjectFormatWindows) {
haveWinPart = true;
if (!reader.readBytes(platform.win.unknown11))
return kDataReadErrorReadFailed;
} else
return kDataReadErrorUnrecognized;
if (!reader.readU32(frameDataPosition) || !reader.readU32(sizeOfFrameData) || !reader.readU32(mtoonHeader[0])
|| !reader.readU32(mtoonHeader[1]) || !reader.readU16(version) || !reader.readBytes(unknown2)
|| !reader.readU32(encodingFlags) || !rect.load(reader) || !reader.readU16(numFrames)
|| !reader.readBytes(unknown3) || !reader.readU16(bitsPerPixel) || !reader.readU32(codecID)
|| !reader.readBytes(unknown4_1) || !reader.readU32(codecDataSize) || !reader.readBytes(unknown4_2))
return kDataReadErrorReadFailed;
if (mtoonHeader[0] != 0 || mtoonHeader[1] != 0x546f6f6e)
return kDataReadErrorUnrecognized;
if (numFrames > 0) {
frames.resize(numFrames);
for (size_t i = 0; i < numFrames; i++) {
FrameDef &frame = frames[i];
if (!reader.readBytes(frame.unknown12) || !frame.rect1.load(reader) || !reader.readU32(frame.dataOffset)
|| !reader.readBytes(frame.unknown13) || !reader.readU32(frame.compressedSize) || !reader.readU8(frame.unknown14)
|| !reader.readU8(frame.keyframeFlag) || !reader.readU8(frame.platformBit) || !reader.readU8(frame.unknown15)
|| !frame.rect2.load(reader) || !reader.readU32(frame.hdpiFixed) || !reader.readU32(frame.vdpiFixed)
|| !reader.readU16(frame.bitsPerPixel) || !reader.readU32(frame.unknown16) || !reader.readU16(frame.decompressedBytesPerRow))
return kDataReadErrorReadFailed;
if (reader.getProjectFormat() == kProjectFormatMacintosh) {
if (!reader.readBytes(frame.platform.mac.unknown17))
return kDataReadErrorReadFailed;
} else if (reader.getProjectFormat() == kProjectFormatWindows) {
if (!reader.readBytes(frame.platform.win.unknown18))
return kDataReadErrorReadFailed;
} else
return kDataReadErrorUnrecognized;
if (!reader.readU32(frame.decompressedSize))
return kDataReadErrorReadFailed;
}
}
if (codecDataSize > 0) {
codecData.resize(codecDataSize);
if (!reader.read(&codecData[0], codecDataSize))
return kDataReadErrorReadFailed;
}
if (encodingFlags & kEncodingFlag_HasRanges) {
if (!reader.readU32(frameRangesPart.tag) || !reader.readU32(frameRangesPart.sizeIncludingTag) || !reader.readU32(frameRangesPart.numFrameRanges))
return kDataReadErrorReadFailed;
if (frameRangesPart.tag != 1)
return kDataReadErrorUnrecognized;
if (frameRangesPart.numFrameRanges > 0) {
frameRangesPart.frameRanges.resize(frameRangesPart.numFrameRanges);
for (size_t i = 0; i < frameRangesPart.numFrameRanges; i++) {
FrameRangeDef &frameRange = frameRangesPart.frameRanges[i];
if (!reader.readU32(frameRange.startFrame) || !reader.readU32(frameRange.endFrame) || !reader.readU8(frameRange.lengthOfName) || !reader.readU8(frameRange.unknown14))
return kDataReadErrorReadFailed;
if (!reader.readTerminatedStr(frameRange.name, frameRange.lengthOfName))
return kDataReadErrorReadFailed;
}
}
}
return kDataReadErrorNone;
}
DataReadErrorCode TextAsset::load(DataReader &reader) {
if (_revision != 3)
return kDataReadErrorReadFailed;
@@ -1775,6 +1878,9 @@ DataReadErrorCode loadDataObject(const PlugInModifierRegistry &registry, DataRea
case DataObjectTypes::kMiniscriptModifier:
dataObject = new MiniscriptModifier();
break;
case DataObjectTypes::kSaveAndRestoreModifier:
dataObject = new SaveAndRestoreModifier();
break;
case DataObjectTypes::kMessengerModifier:
dataObject = new MessengerModifier();
break;
@@ -1871,7 +1977,7 @@ DataReadErrorCode loadDataObject(const PlugInModifierRegistry &registry, DataRea
break;
case DataObjectTypes::kMToonAsset:
//dataObject = new MToonAsset();
dataObject = new MToonAsset();
break;
case DataObjectTypes::kTextAsset:
+144 -15
View File
@@ -122,7 +122,7 @@ enum DataObjectType {
kCursorModifierV1 = 0x3ca, // NYI - Obsolete version
kGradientModifier = 0x4b0, // NYI
kColorTableModifier = 0x4c4, // NYI
kSaveAndRestoreModifier = 0x4d8, // NYI
kSaveAndRestoreModifier = 0x4d8,
kCompoundVariableModifier = 0x2c7,
kBooleanVariableModifier = 0x321,
@@ -272,7 +272,7 @@ struct Label {
//
// InternalTypeTaggedValue is used by internal modifiers for messenger payloads and set modifiers
// and seems to match Miniscript ops too.
// InternalTypeTaggedValue is always 44 bytes in size and stores string data elsewhere in the containing structure.
// InternalTypeTaggedValue is always 46 bytes in size and stores string data elsewhere in the containing structure.
//
// PlugInTypeTaggedValue is used by plug-ins and is fully self-contained.
//
@@ -394,7 +394,7 @@ struct ProjectLabelMap : public DataObject {
Common::String name;
uint32_t numChildren;
uint32 numChildren;
LabelTree *children;
};
@@ -407,7 +407,7 @@ struct ProjectLabelMap : public DataObject {
uint32 unknown2;
Common::String name;
uint32_t numChildren;
uint32 numChildren;
LabelTree *tree;
};
@@ -678,7 +678,7 @@ struct MToonElement : public StructuralDef {
uint16 sectionID;
Rect rect1;
Rect rect2;
uint32 unknown5;
uint32 assetID;
uint32 rateTimes10000;
uint32 streamLocator;
uint32 unknown6;
@@ -814,7 +814,6 @@ struct TypicalModifierHeader {
};
struct MiniscriptModifier : public DataObject {
TypicalModifierHeader modHeader;
Event enableWhen;
uint8 unknown6[11];
@@ -826,6 +825,30 @@ protected:
DataReadErrorCode load(DataReader &reader) override;
};
struct SaveAndRestoreModifier : public DataObject {
TypicalModifierHeader modHeader;
uint8 unknown1[4];
Event saveWhen;
Event restoreWhen;
InternalTypeTaggedValue saveOrRestoreValue;
uint8 unknown5[8];
uint8 lengthOfFilePath;
uint8 lengthOfFileName;
uint8 lengthOfVariableName;
uint8 lengthOfVariableString;
Common::String varName;
Common::String varString;
Common::String filePath;
Common::String fileName;
protected:
DataReadErrorCode load(DataReader &reader) override;
};
enum MessageFlags {
kMessageFlagNoRelay = 0x20000000,
kMessageFlagNoCascade = 0x40000000,
@@ -936,15 +959,15 @@ struct DragMotionModifier : public DataObject {
Event disableWhen;
struct WinPart {
uint8_t unknown2;
uint8_t constrainHorizontal;
uint8_t constrainVertical;
uint8_t constrainToParent;
uint8 unknown2;
uint8 constrainHorizontal;
uint8 constrainVertical;
uint8 constrainToParent;
};
struct MacPart {
uint8_t flags;
uint8_t unknown3;
uint8 flags;
uint8 unknown3;
enum Flags {
kConstrainToParent = 0x10,
@@ -963,7 +986,7 @@ struct DragMotionModifier : public DataObject {
bool haveMacPart;
bool haveWinPart;
Rect constraintMargin;
uint16_t unknown1;
uint16 unknown1;
protected:
DataReadErrorCode load(DataReader &reader) override;
@@ -1205,7 +1228,7 @@ struct TextStyleModifier : public DataObject {
uint16 unknown3;
Event applyWhen;
Event removeWhen;
uint16_t lengthOfFontFamilyName;
uint16 lengthOfFontFamilyName;
Common::String fontFamilyName;
@@ -1497,7 +1520,7 @@ struct ImageAsset : public DataObject {
uint32 persistFlags;
uint32 unknown1;
uint8_t unknown2[4];
uint8 unknown2[4];
uint32 assetID;
uint32 unknown3;
@@ -1520,6 +1543,112 @@ protected:
DataReadErrorCode load(DataReader &reader) override;
};
struct MToonAsset : public DataObject {
struct MacPart {
uint8 unknown10[88];
};
struct WinPart {
uint8 unknown11[54];
};
struct FrameDef {
struct MacPart {
uint8 unknown17[4];
};
struct WinPart {
uint8 unknown18[2];
};
union PlatformUnion {
MacPart mac;
WinPart win;
};
uint8 unknown12[4];
Rect rect1;
uint32 dataOffset;
uint8 unknown13[2];
uint32 compressedSize;
uint8 unknown14;
uint8 keyframeFlag;
uint8 platformBit;
uint8 unknown15;
Rect rect2;
uint32 hdpiFixed;
uint32 vdpiFixed;
uint16 bitsPerPixel;
uint32 unknown16;
uint16 decompressedBytesPerRow;
uint32 decompressedSize;
PlatformUnion platform;
};
struct FrameRangeDef {
uint32 startFrame;
uint32 endFrame;
uint8 lengthOfName;
uint8 unknown14;
Common::String name; // Null terminated
};
enum {
kEncodingFlag_TemporalCompression = 0x80,
kEncodingFlag_HasRanges = 0x20000000,
kEncodingFlag_Trimming = 0x08,
};
uint32 marker;
uint8 unknown1[8];
uint32 assetID;
bool haveMacPart;
bool haveWinPart;
union PlatformUnion {
MacPart mac;
WinPart win;
} platform;
uint32 frameDataPosition;
uint32 sizeOfFrameData;
// mToon data
uint32 mtoonHeader[2];
uint16 version;
uint8 unknown2[4];
uint32 encodingFlags;
Rect rect;
uint16 numFrames;
uint8 unknown3[14];
uint16 bitsPerPixel;
uint32 codecID;
uint8 unknown4_1[8];
uint32 codecDataSize;
uint8 unknown4_2[4];
Common::Array<FrameDef> frames;
Common::Array<uint8> codecData;
struct FrameRangePart {
uint32 tag;
uint32 sizeIncludingTag;
uint32 numFrameRanges;
Common::Array<FrameRangeDef> frameRanges;
};
FrameRangePart frameRangesPart;
protected:
DataReadErrorCode load(DataReader &reader) override;
};
struct TextAsset : public DataObject {
struct MacFormattingSpan {
uint8 unknown9[2];
+2
View File
@@ -66,6 +66,8 @@ IElementFactory *getElementFactoryForDataObjectType(const Data::DataObjectTypes:
return ElementFactory<MovieElement, Data::MovieElement>::getInstance();
case Data::DataObjectTypes::kImageElement:
return ElementFactory<ImageElement, Data::ImageElement>::getInstance();
case Data::DataObjectTypes::kMToonElement:
return ElementFactory<MToonElement, Data::MToonElement>::getInstance();
case Data::DataObjectTypes::kTextLabelElement:
return ElementFactory<TextLabelElement, Data::TextLabelElement>::getInstance();
case Data::DataObjectTypes::kSoundElement:
+38 -1
View File
@@ -284,7 +284,7 @@ void ImageElement::activate() {
pixelFmt = Graphics::PixelFormat::createFormatCLUT8();
break;
case kColorDepthMode16Bit:
bytesPerRow = width * 2;
bytesPerRow = (width * 2 + 3) / 4 * 4;
pixelFmt = Graphics::createPixelFormat<1555>();
break;
case kColorDepthMode32Bit:
@@ -402,6 +402,43 @@ void ImageElement::render(Window *window) {
}
}
MToonElement::MToonElement() {
}
MToonElement::~MToonElement() {
}
bool MToonElement::load(ElementLoaderContext &context, const Data::MToonElement &data) {
if (!loadCommon(data.name, data.guid, data.rect1, data.elementFlags, data.layer, data.streamLocator, data.sectionID))
return false;
_cacheBitmap = ((data.elementFlags & Data::ElementFlags::kCacheBitmap) != 0);
_paused = ((data.elementFlags & Data::ElementFlags::kPaused) != 0);
_loop = ((data.animationFlags & Data::AnimationFlags::kLoop) != 0);
_maintainRate = ((data.elementFlags & Data::AnimationFlags::kPlayEveryFrame) == 0); // NOTE: Inverted intentionally
_assetID = data.assetID;
_runtime = context.runtime;
_rateTimes10000 = data.rateTimes10000;
return true;
}
void MToonElement::activate() {
}
void MToonElement::deactivate() {
_renderSurface.reset();
}
void MToonElement::render(Window *window) {
if (_renderSurface) {
Common::Rect srcRect(_renderSurface->w, _renderSurface->h);
Common::Rect destRect(_cachedAbsoluteOrigin.x, _cachedAbsoluteOrigin.y, _cachedAbsoluteOrigin.x + _rect.getWidth(), _cachedAbsoluteOrigin.y + _rect.getHeight());
window->getSurface()->blitFrom(*_renderSurface, srcRect, destRect);
}
}
TextLabelElement::TextLabelElement() : _needsRender(false), _isBitmap(false) {
}
+31
View File
@@ -128,6 +128,37 @@ private:
Runtime *_runtime;
};
class MToonElement : public VisualElement {
public:
MToonElement();
~MToonElement();
bool load(ElementLoaderContext &context, const Data::MToonElement &data);
void activate() override;
void deactivate() override;
void render(Window *window) override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "mToon Element"; }
SupportStatus debugGetSupportStatus() const override { return kSupportStatusPartial; }
#endif
private:
bool _cacheBitmap;
bool _loop;
// If set, then carry over residual frame time and display at the desired rate. If not set, reset residual each frame for smoother animation.
bool _maintainRate;
uint32 _assetID;
Runtime *_runtime;
uint32 _rateTimes10000;
Common::SharedPtr<Graphics::Surface> _renderSurface;
};
class TextLabelElement : public VisualElement {
public:
TextLabelElement();
+21 -2
View File
@@ -56,6 +56,23 @@ void MiniscriptReferences::linkInternalReferences(ObjectLinkingScope *scope) {
}
}
void MiniscriptReferences::visitInternalReferences(IStructuralReferenceVisitor *visitor) {
for (LocalRef &ref : _localRefs) {
Common::SharedPtr<RuntimeObject> obj = ref.resolution.lock();
if (obj) {
if (obj->isModifier()) {
Common::WeakPtr<Modifier> mod = obj.staticCast<Modifier>();
visitor->visitWeakModifierRef(mod);
ref.resolution = mod;
} else if (obj->isStructural()) {
Common::WeakPtr<Structural> struc = obj.staticCast<Structural>();
visitor->visitWeakStructuralRef(struc);
ref.resolution = struc;
}
}
}
}
Common::WeakPtr<RuntimeObject> MiniscriptReferences::getRefByIndex(uint index) const {
if (index >= _localRefs.size())
return Common::WeakPtr<RuntimeObject>();
@@ -1075,16 +1092,18 @@ MiniscriptInstructionOutcome BuiltinFunc::executeNum2Str(MiniscriptThread *threa
const DynamicValue &inputDynamicValue = thread->getStackValueFromTop(0).value;
switch (inputDynamicValue.getType()) {
case DynamicValueTypes::kInteger:
result.format("%i", static_cast<int>(inputDynamicValue.getInt()));
result = Common::String::format("%i", static_cast<int>(inputDynamicValue.getInt()));
break;
case DynamicValueTypes::kFloat:
result.format("%g", static_cast<double>(inputDynamicValue.getFloat()));
result = Common::String::format("%g", static_cast<double>(inputDynamicValue.getFloat()));
break;
default:
thread->error("Invalid input value to num2str");
return kMiniscriptInstructionOutcomeFailed;
}
returnValue->setString(result);
return kMiniscriptInstructionOutcomeContinue;
}
+1
View File
@@ -49,6 +49,7 @@ public:
explicit MiniscriptReferences(const Common::Array<LocalRef> &localRefs);
void linkInternalReferences(ObjectLinkingScope *scope);
void visitInternalReferences(IStructuralReferenceVisitor *visitor);
Common::WeakPtr<RuntimeObject> getRefByIndex(uint index) const;
+2
View File
@@ -67,6 +67,8 @@ IModifierFactory *getModifierFactoryForDataObjectType(const Data::DataObjectType
return ModifierFactory<BehaviorModifier, Data::BehaviorModifier>::getInstance();
case Data::DataObjectTypes::kMiniscriptModifier:
return ModifierFactory<MiniscriptModifier, Data::MiniscriptModifier>::getInstance();
case Data::DataObjectTypes::kSaveAndRestoreModifier:
return ModifierFactory<SaveAndRestoreModifier, Data::SaveAndRestoreModifier>::getInstance();
case Data::DataObjectTypes::kAliasModifier:
return ModifierFactory<AliasModifier, Data::AliasModifier>::getInstance();
case Data::DataObjectTypes::kChangeSceneModifier:
+47
View File
@@ -132,6 +132,10 @@ Common::SharedPtr<Modifier> BehaviorModifier::shallowClone() const {
return Common::SharedPtr<Modifier>(new BehaviorModifier(*this));
}
void BehaviorModifier::linkInternalReferences(ObjectLinkingScope *scope) {
Modifier::linkInternalReferences(scope);
}
void BehaviorModifier::visitInternalReferences(IStructuralReferenceVisitor* visitor) {
for (Common::Array<Common::SharedPtr<Modifier> >::iterator it = _children.begin(), itEnd = _children.end(); it != itEnd; ++it) {
visitor->visitChildModifierRef(*it);
@@ -176,6 +180,49 @@ void MiniscriptModifier::linkInternalReferences(ObjectLinkingScope* scope) {
_references->linkInternalReferences(scope);
}
void MiniscriptModifier::visitInternalReferences(IStructuralReferenceVisitor *visitor) {
_references->visitInternalReferences(visitor);
}
bool SaveAndRestoreModifier::load(ModifierLoaderContext &context, const Data::SaveAndRestoreModifier &data) {
if (!loadTypicalHeader(data.modHeader))
return false;
if (!_saveWhen.load(data.saveWhen) || !_restoreWhen.load(data.restoreWhen))
return false;
if (!_saveOrRestoreValue.load(data.saveOrRestoreValue, data.varName, data.varString))
return false;
_filePath = data.filePath;
_fileName = data.fileName;
return true;
}
bool SaveAndRestoreModifier::respondsToEvent(const Event &evt) const {
if (_saveWhen.respondsTo(evt) || _restoreWhen.respondsTo(evt))
return true;
return false;
}
VThreadState SaveAndRestoreModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
if (_saveWhen.respondsTo(msg->getEvent())) {
error("Saves not implemented yet");
return kVThreadReturn;
} else if (_restoreWhen.respondsTo(msg->getEvent())) {
error("Restores not implemented yet");
return kVThreadReturn;
}
return kVThreadError;
}
Common::SharedPtr<Modifier> SaveAndRestoreModifier::shallowClone() const {
return Common::SharedPtr<Modifier>(new SaveAndRestoreModifier(*this));
}
bool MessengerModifier::load(ModifierLoaderContext &context, const Data::MessengerModifier &data) {
if (!loadTypicalHeader(data.modHeader))
return false;
+26
View File
@@ -71,6 +71,7 @@ private:
VThreadState propagateTask(const PropagateTaskData &taskData);
Common::SharedPtr<Modifier> shallowClone() const override;
void linkInternalReferences(ObjectLinkingScope *scope) override;
void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
Common::Array<Common::SharedPtr<Modifier> > _children;
@@ -96,6 +97,7 @@ public:
private:
Common::SharedPtr<Modifier> shallowClone() const override;
void linkInternalReferences(ObjectLinkingScope *scope) override;
void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
Event _enableWhen;
@@ -103,6 +105,30 @@ private:
Common::SharedPtr<MiniscriptReferences> _references;
};
class SaveAndRestoreModifier : public Modifier {
public:
bool load(ModifierLoaderContext &context, const Data::SaveAndRestoreModifier &data);
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Save And Restore Modifier"; }
SupportStatus debugGetSupportStatus() const override { return kSupportStatusPartial; }
#endif
private:
Common::SharedPtr<Modifier> shallowClone() const override;
Event _saveWhen;
Event _restoreWhen;
DynamicValue _saveOrRestoreValue;
Common::String _filePath;
Common::String _fileName;
};
class MessengerModifier : public Modifier {
public:
bool load(ModifierLoaderContext &context, const Data::MessengerModifier &data);
+19 -1
View File
@@ -3391,7 +3391,7 @@ void Runtime::loadScene(const Common::SharedPtr<Structural>& scene) {
scene->materializeDescendents(this, subsection->getSceneLoadMaterializeScope());
debug(1, "Scene materialized OK");
recursiveActivateStructural(scene.get());
debug(1, "Scene added to renderer OK");
debug(1, "Structural elements activated OK");
#ifdef MTROPOLIS_DEBUG_ENABLE
if (_debugger) {
@@ -4767,6 +4767,9 @@ bool VisualElement::readAttribute(MiniscriptThread *thread, DynamicValue &result
} else if (attrib == "height") {
result.setInt(_rect.bottom - _rect.top);
return true;
} else if (attrib == "globalposition") {
result.setPoint(getGlobalPosition());
return true;
}
return Element::readAttribute(thread, result, attrib);
@@ -4791,6 +4794,21 @@ const Rect16 &VisualElement::getRelativeRect() const {
return _rect;
}
Point16 VisualElement::getGlobalPosition() const {
Point16 pos = Point16::create(0, 0);
if (_parent && _parent->isElement()) {
Element *element = static_cast<Element *>(_parent);
if (element->isVisual()) {
pos = static_cast<VisualElement *>(element)->getGlobalPosition();
}
}
pos.x += _rect.left;
pos.y += _rect.top;
return pos;
}
const Point16 &VisualElement::getCachedAbsoluteOrigin() const {
return _cachedAbsoluteOrigin;
}
+3 -1
View File
@@ -1958,6 +1958,7 @@ public:
bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) override;
Point16 getGlobalPosition() const;
const Rect16 &getRelativeRect() const;
// The cached absolute origin is from the last time the element was rendered.
@@ -2055,7 +2056,7 @@ protected:
bool loadTypicalHeader(const Data::TypicalModifierHeader &typicalHeader);
// Links any references contained in the object, resolving static GUIDs to runtime object references.
// If you override this, you must override visitInternalReferences too.
// If you override this, you should override visitInternalReferences too
virtual void linkInternalReferences(ObjectLinkingScope *scope);
Structural *findStructuralOwner() const;
@@ -2096,6 +2097,7 @@ enum AssetType {
kAssetTypeColorTable,
kAssetTypeImage,
kAssetTypeText,
kAssetTypeMToon,
};
class Asset {