[Scummvm-git-logs] scummvm master -> 52e54cc0901dfa4d9d8a15e329e7157ecf7275eb
elasota
noreply at scummvm.org
Sun Nov 27 22:02:14 UTC 2022
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:
52e54cc090 MTROPOLIS: Change how variable storage works so variable modifiers can be cloned into the scene tree. Add hack for MTI
Commit: 52e54cc0901dfa4d9d8a15e329e7157ecf7275eb
https://github.com/scummvm/scummvm/commit/52e54cc0901dfa4d9d8a15e329e7157ecf7275eb
Author: elasota (ejlasota at gmail.com)
Date: 2022-11-27T16:54:24-05:00
Commit Message:
MTROPOLIS: Change how variable storage works so variable modifiers can be cloned into the scene tree. Add hack for MTI variable init.
Changed paths:
engines/mtropolis/hacks.cpp
engines/mtropolis/hacks.h
engines/mtropolis/modifiers.cpp
engines/mtropolis/modifiers.h
engines/mtropolis/plugin/standard.cpp
engines/mtropolis/plugin/standard.h
engines/mtropolis/runtime.cpp
engines/mtropolis/runtime.h
diff --git a/engines/mtropolis/hacks.cpp b/engines/mtropolis/hacks.cpp
index 9338e84f9f4..3c29b4532ad 100644
--- a/engines/mtropolis/hacks.cpp
+++ b/engines/mtropolis/hacks.cpp
@@ -1028,6 +1028,21 @@ void addMTIQuirks(const MTropolisGameDescription &desc, Hacks &hacks) {
// Anyway, there are two possible solutions to this: Lock the clock to 60Hz, or ignore the flag.
// Given that the flag should not be set, we ignore the flag.
hacks.ignoreMToonMaintainRateFlag = true;
+
+ // MTI initializes variables in a way that doesn't seem to match mTropolis behavior in any explicable way:
+ //
+ // For example, 0010cb0e "Scene Started => init Benbow" looks like this internally, decompiled:
+ // set local:a.billystate to 0
+ //
+ // In this case "a" is a compound variable and "billyState" is a NON-ALIASED integer variable contained in
+ // the compound. Later, 0009fc9a "Scene Started => play intro" checks local 00007f83 00 'billyState'
+ // to determine if the Benbow intro needs to be played. Since the GUID doesn't match (?) we check by name,
+ // which resolves to the GUID-less (?) alias in the Benbow subsection, which references 00097cf4, a different
+ // variable also named "billyState"
+ //
+ // Haven't figured out anything that would explain why it would reference the variables in the compound
+ // modifier. Probably some quirk of early-version mTropolis.
+ hacks.mtiVariableReferencesHack = true;
}
} // End of namespace HackSuites
diff --git a/engines/mtropolis/hacks.h b/engines/mtropolis/hacks.h
index 371cc976066..cf8a77bd125 100644
--- a/engines/mtropolis/hacks.h
+++ b/engines/mtropolis/hacks.h
@@ -51,6 +51,8 @@ struct Hacks {
bool ignoreMismatchedProjectNameInObjectLookups;
bool removeQuickTimeEdits;
bool ignoreMToonMaintainRateFlag;
+ bool mtiVariableReferencesHack;
+
uint midiVolumeScale; // 256 = 1.0
uint32 minTransitionDuration;
diff --git a/engines/mtropolis/modifiers.cpp b/engines/mtropolis/modifiers.cpp
index 1a0c1d5b315..4db195f4544 100644
--- a/engines/mtropolis/modifiers.cpp
+++ b/engines/mtropolis/modifiers.cpp
@@ -2319,7 +2319,7 @@ bool CompoundVariableModifier::load(ModifierLoaderContext &context, const Data::
}
void CompoundVariableModifier::disable(Runtime *runtime) {
- // Do nothing I guess, no variables can be disdabled
+ // Do nothing I guess, no variables can be disabled
}
Common::SharedPtr<ModifierSaveLoad> CompoundVariableModifier::getSaveLoad() {
@@ -2346,7 +2346,7 @@ void CompoundVariableModifier::visitInternalReferences(IStructuralReferenceVisit
}
bool CompoundVariableModifier::readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) {
- Modifier *var = findChildByName(attrib);
+ Modifier *var = findChildByName(thread->getRuntime(), attrib);
if (var) {
// Shouldn't dereference the value here, some scripts (e.g. "<go dest> on MUI" in Obsidian) depend on it not being dereferenced
result.setObject(var->getSelfReference());
@@ -2356,7 +2356,7 @@ bool CompoundVariableModifier::readAttribute(MiniscriptThread *thread, DynamicVa
}
bool CompoundVariableModifier::readAttributeIndexed(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib, const DynamicValue &index) {
- Modifier *var = findChildByName(attrib);
+ Modifier *var = findChildByName(thread->getRuntime(), attrib);
if (!var || !var->isVariable())
return false;
@@ -2364,7 +2364,7 @@ bool CompoundVariableModifier::readAttributeIndexed(MiniscriptThread *thread, Dy
}
MiniscriptInstructionOutcome CompoundVariableModifier::writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) {
- Modifier *var = findChildByName(attrib);
+ Modifier *var = findChildByName(thread->getRuntime(), attrib);
if (!var)
return kMiniscriptInstructionOutcomeFailed;
@@ -2379,14 +2379,26 @@ MiniscriptInstructionOutcome CompoundVariableModifier::writeRefAttribute(Miniscr
}
MiniscriptInstructionOutcome CompoundVariableModifier::writeRefAttributeIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib, const DynamicValue &index) {
- Modifier *var = findChildByName(attrib);
+ Modifier *var = findChildByName(thread->getRuntime(), attrib);
if (!var || !var->isModifier())
return kMiniscriptInstructionOutcomeFailed;
return var->writeRefAttributeIndexed(thread, writeProxy, "value", index);
}
-Modifier *CompoundVariableModifier::findChildByName(const Common::String &name) const {
+Modifier *CompoundVariableModifier::findChildByName(Runtime *runtime, const Common::String &name) const {
+ if (runtime->getHacks().mtiVariableReferencesHack) {
+ const Common::String &myName = getName();
+
+ if (myName.size() == 1 && myName == "a" || myName == "b" || myName == "c" || myName == "d") {
+ Project *project = runtime->getProject();
+ Modifier *modifier = project->findGlobalVarWithName(MTropolis::toCaseInsensitive(name)).get();
+
+ if (modifier)
+ return modifier;
+ }
+ }
+
for (Common::Array<Common::SharedPtr<Modifier> >::const_iterator it = _children.begin(), itEnd = _children.end(); it != itEnd; ++it) {
Modifier *modifier = it->get();
if (caseInsensitiveEqual(name, modifier->getName()))
@@ -2446,41 +2458,37 @@ const char *CompoundVariableModifier::getDefaultName() const {
return "Compound Variable";
}
-BooleanVariableModifier::BooleanVariableModifier() : _value(false) {
+BooleanVariableModifier::BooleanVariableModifier() : VariableModifier(Common::SharedPtr<VariableStorage>(new BooleanVariableStorage())) {
}
bool BooleanVariableModifier::load(ModifierLoaderContext &context, const Data::BooleanVariableModifier &data) {
if (!loadTypicalHeader(data.modHeader))
return false;
- _value = (data.value != 0);
+ static_cast<BooleanVariableStorage *>(_storage.get())->_value = (data.value != 0);
return true;
}
-Common::SharedPtr<ModifierSaveLoad> BooleanVariableModifier::getSaveLoad() {
- return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
-}
-
bool BooleanVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicValue &value) {
DynamicValue boolValue;
if (!value.convertToType(DynamicValueTypes::kBoolean, boolValue))
return false;
- _value = boolValue.getBool();
+ static_cast<BooleanVariableStorage *>(_storage.get())->_value = boolValue.getBool();
return true;
}
void BooleanVariableModifier::varGetValue(DynamicValue &dest) const {
- dest.setBool(_value);
+ dest.setBool(static_cast<BooleanVariableStorage *>(_storage.get())->_value);
}
#ifdef MTROPOLIS_DEBUG_ENABLE
void BooleanVariableModifier::debugInspect(IDebugInspectionReport *report) const {
VariableModifier::debugInspect(report);
- report->declareDynamic("value", _value ? "true" : "false");
+ report->declareDynamic("value", static_cast<BooleanVariableStorage *>(_storage.get())->_value ? "true" : "false");
}
#endif
@@ -2492,19 +2500,30 @@ const char *BooleanVariableModifier::getDefaultName() const {
return "Boolean Variable";
}
-BooleanVariableModifier::SaveLoad::SaveLoad(BooleanVariableModifier *modifier) : _modifier(modifier) {
- _value = _modifier->_value;
+BooleanVariableStorage::BooleanVariableStorage() : _value(false) {
+}
+
+Common::SharedPtr<ModifierSaveLoad> BooleanVariableStorage::getSaveLoad() {
+ return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
+}
+
+Common::SharedPtr<VariableStorage> BooleanVariableStorage::clone() const {
+ return Common::SharedPtr<VariableStorage>(new BooleanVariableStorage(*this));
+}
+
+BooleanVariableStorage::SaveLoad::SaveLoad(BooleanVariableStorage *storage) : _storage(storage) {
+ _value = _storage->_value;
}
-void BooleanVariableModifier::SaveLoad::commitLoad() const {
- _modifier->_value = _value;
+void BooleanVariableStorage::SaveLoad::commitLoad() const {
+ _storage->_value = _value;
}
-void BooleanVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream) const {
+void BooleanVariableStorage::SaveLoad::saveInternal(Common::WriteStream *stream) const {
stream->writeByte(_value ? 1 : 0);
}
-bool BooleanVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
+bool BooleanVariableStorage::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
byte b = stream->readByte();
if (stream->err())
return false;
@@ -2513,41 +2532,48 @@ bool BooleanVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream,
return true;
}
-IntegerVariableModifier::IntegerVariableModifier() : _value(0) {
+IntegerVariableModifier::IntegerVariableModifier() : VariableModifier(Common::SharedPtr<VariableStorage>(new IntegerVariableStorage())) {
}
bool IntegerVariableModifier::load(ModifierLoaderContext& context, const Data::IntegerVariableModifier& data) {
if (!loadTypicalHeader(data.modHeader))
return false;
- _value = data.value;
+ static_cast<IntegerVariableStorage *>(_storage.get())->_value = data.value;
return true;
}
-Common::SharedPtr<ModifierSaveLoad> IntegerVariableModifier::getSaveLoad() {
+IntegerVariableStorage::IntegerVariableStorage() : _value(0) {
+}
+
+Common::SharedPtr<ModifierSaveLoad> IntegerVariableStorage::getSaveLoad() {
return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}
+Common::SharedPtr<VariableStorage> IntegerVariableStorage::clone() const {
+ return Common::SharedPtr<VariableStorage>(new IntegerVariableStorage(*this));
+}
+
bool IntegerVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicValue &value) {
DynamicValue intValue;
if (!value.convertToType(DynamicValueTypes::kInteger, intValue))
return false;
- _value = intValue.getInt();
+ static_cast<IntegerVariableStorage *>(_storage.get())->_value = intValue.getInt();
return true;
}
void IntegerVariableModifier::varGetValue(DynamicValue &dest) const {
- dest.setInt(_value);
+ dest.setInt(static_cast<IntegerVariableStorage *>(_storage.get())->_value);
}
#ifdef MTROPOLIS_DEBUG_ENABLE
void IntegerVariableModifier::debugInspect(IDebugInspectionReport *report) const {
VariableModifier::debugInspect(report);
- report->declareDynamic("value", Common::String::format("%i", _value));
+ report->declareDynamic("value", Common::String::format("%i", static_cast<IntegerVariableStorage *>(_storage.get())->_value));
}
#endif
@@ -2559,19 +2585,19 @@ const char *IntegerVariableModifier::getDefaultName() const {
return "Integer Variable";
}
-IntegerVariableModifier::SaveLoad::SaveLoad(IntegerVariableModifier *modifier) : _modifier(modifier) {
- _value = _modifier->_value;
+IntegerVariableStorage::SaveLoad::SaveLoad(IntegerVariableStorage *storage) : _storage(storage) {
+ _value = _storage->_value;
}
-void IntegerVariableModifier::SaveLoad::commitLoad() const {
- _modifier->_value = _value;
+void IntegerVariableStorage::SaveLoad::commitLoad() const {
+ _storage->_value = _value;
}
-void IntegerVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream) const {
+void IntegerVariableStorage::SaveLoad::saveInternal(Common::WriteStream *stream) const {
stream->writeSint32BE(_value);
}
-bool IntegerVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
+bool IntegerVariableStorage::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
_value = stream->readSint32BE();
if (stream->err())
@@ -2580,53 +2606,57 @@ bool IntegerVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream,
return true;
}
+
+IntegerRangeVariableModifier::IntegerRangeVariableModifier() : VariableModifier(Common::SharedPtr<VariableStorage>(new IntegerRangeVariableStorage())) {
+}
+
bool IntegerRangeVariableModifier::load(ModifierLoaderContext& context, const Data::IntegerRangeVariableModifier& data) {
if (!loadTypicalHeader(data.modHeader))
return false;
- if (!_range.load(data.range))
+ if (!static_cast<IntegerRangeVariableStorage *>(_storage.get())->_range.load(data.range))
return false;
return true;
}
-Common::SharedPtr<ModifierSaveLoad> IntegerRangeVariableModifier::getSaveLoad() {
- return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
-}
-
bool IntegerRangeVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicValue &value) {
DynamicValue intRangeValue;
if (!value.convertToType(DynamicValueTypes::kIntegerRange, intRangeValue))
return false;
- _range = intRangeValue.getIntRange();
+ static_cast<IntegerRangeVariableStorage *>(_storage.get())->_range = intRangeValue.getIntRange();
return true;
}
void IntegerRangeVariableModifier::varGetValue(DynamicValue &dest) const {
- dest.setIntRange(_range);
+ dest.setIntRange(static_cast<IntegerRangeVariableStorage *>(_storage.get())->_range);
}
bool IntegerRangeVariableModifier::readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) {
+ IntegerRangeVariableStorage *storage = static_cast<IntegerRangeVariableStorage *>(_storage.get());
+
if (attrib == "start") {
- result.setInt(_range.min);
+ result.setInt(storage->_range.min);
return true;
}
if (attrib == "end") {
- result.setInt(_range.max);
+ result.setInt(storage->_range.max);
return true;
}
return Modifier::readAttribute(thread, result, attrib);
}
MiniscriptInstructionOutcome IntegerRangeVariableModifier::writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) {
+ IntegerRangeVariableStorage *storage = static_cast<IntegerRangeVariableStorage *>(_storage.get());
+
if (attrib == "start") {
- DynamicValueWriteIntegerHelper<int32>::create(&_range.min, result);
+ DynamicValueWriteIntegerHelper<int32>::create(&storage->_range.min, result);
return kMiniscriptInstructionOutcomeContinue;
}
if (attrib == "end") {
- DynamicValueWriteIntegerHelper<int32>::create(&_range.max, result);
+ DynamicValueWriteIntegerHelper<int32>::create(&storage->_range.max, result);
return kMiniscriptInstructionOutcomeContinue;
}
return Modifier::writeRefAttribute(thread, result, attrib);
@@ -2634,9 +2664,11 @@ MiniscriptInstructionOutcome IntegerRangeVariableModifier::writeRefAttribute(Min
#ifdef MTROPOLIS_DEBUG_ENABLE
void IntegerRangeVariableModifier::debugInspect(IDebugInspectionReport *report) const {
+ IntegerRangeVariableStorage *storage = static_cast<IntegerRangeVariableStorage *>(_storage.get());
+
VariableModifier::debugInspect(report);
- report->declareDynamic("value", _range.toString());
+ report->declareDynamic("value", storage->_range.toString());
}
#endif
@@ -2648,22 +2680,33 @@ const char *IntegerRangeVariableModifier::getDefaultName() const {
return "Integer Range Variable";
}
-IntegerRangeVariableModifier::SaveLoad::SaveLoad(IntegerRangeVariableModifier *modifier) : _modifier(modifier) {
- _range = _modifier->_range;
+IntegerRangeVariableStorage::IntegerRangeVariableStorage() {
+}
+
+Common::SharedPtr<ModifierSaveLoad> IntegerRangeVariableStorage::getSaveLoad() {
+ return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
+}
+
+Common::SharedPtr<VariableStorage> IntegerRangeVariableStorage::clone() const {
+ return Common::SharedPtr<VariableStorage>(new IntegerRangeVariableStorage(*this));
}
-void IntegerRangeVariableModifier::SaveLoad::commitLoad() const {
- _modifier->_range = _range;
+IntegerRangeVariableStorage::SaveLoad::SaveLoad(IntegerRangeVariableStorage *storage) : _storage(storage) {
+ _range = _storage->_range;
}
-void IntegerRangeVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream) const {
- stream->writeSint32BE(_range.min);
- stream->writeSint32BE(_range.max);
+void IntegerRangeVariableStorage::SaveLoad::commitLoad() const {
+ _storage->_range = _range;
}
-bool IntegerRangeVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
- _range.min = stream->readSint32BE();
- _range.max = stream->readSint32BE();
+void IntegerRangeVariableStorage::SaveLoad::saveInternal(Common::WriteStream *stream) const {
+ stream->writeSint32BE(_storage->_range.min);
+ stream->writeSint32BE(_storage->_range.max);
+}
+
+bool IntegerRangeVariableStorage::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
+ _storage->_range.min = stream->readSint32BE();
+ _storage->_range.max = stream->readSint32BE();
if (stream->err())
return false;
@@ -2671,18 +2714,19 @@ bool IntegerRangeVariableModifier::SaveLoad::loadInternal(Common::ReadStream *st
return true;
}
+VectorVariableModifier::VectorVariableModifier() : VariableModifier(Common::SharedPtr<VariableStorage>(new VectorVariableStorage())) {
+}
+
bool VectorVariableModifier::load(ModifierLoaderContext &context, const Data::VectorVariableModifier &data) {
if (!loadTypicalHeader(data.modHeader))
return false;
- _vector.angleDegrees = data.vector.angleRadians.toDouble() * (180 / M_PI);
- _vector.magnitude = data.vector.magnitude.toDouble();
+ VectorVariableStorage *storage = static_cast<VectorVariableStorage *>(_storage.get());
- return true;
-}
+ storage->_vector.angleDegrees = data.vector.angleRadians.toDouble() * (180 / M_PI);
+ storage->_vector.magnitude = data.vector.magnitude.toDouble();
-Common::SharedPtr<ModifierSaveLoad> VectorVariableModifier::getSaveLoad() {
- return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
+ return true;
}
bool VectorVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicValue &value) {
@@ -2690,21 +2734,27 @@ bool VectorVariableModifier::varSetValue(MiniscriptThread *thread, const Dynamic
if (!value.convertToType(DynamicValueTypes::kVector, vectorValue))
return false;
- _vector = vectorValue.getVector();
+ VectorVariableStorage *storage = static_cast<VectorVariableStorage *>(_storage.get());
+
+ storage->_vector = vectorValue.getVector();
return true;
}
void VectorVariableModifier::varGetValue(DynamicValue &dest) const {
- dest.setVector(_vector);
+ VectorVariableStorage *storage = static_cast<VectorVariableStorage *>(_storage.get());
+
+ dest.setVector(storage->_vector);
}
bool VectorVariableModifier::readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) {
+ VectorVariableStorage *storage = static_cast<VectorVariableStorage *>(_storage.get());
+
if (attrib == "magnitude") {
- result.setFloat(_vector.magnitude);
+ result.setFloat(storage->_vector.magnitude);
return true;
} else if (attrib == "angle") {
- result.setFloat(_vector.angleDegrees);
+ result.setFloat(storage->_vector.angleDegrees);
return true;
}
@@ -2712,11 +2762,13 @@ bool VectorVariableModifier::readAttribute(MiniscriptThread *thread, DynamicValu
}
MiniscriptInstructionOutcome VectorVariableModifier::writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) {
+ VectorVariableStorage *storage = static_cast<VectorVariableStorage *>(_storage.get());
+
if (attrib == "magnitude") {
- DynamicValueWriteFloatHelper<double>::create(&_vector.magnitude, result);
+ DynamicValueWriteFloatHelper<double>::create(&storage->_vector.magnitude, result);
return kMiniscriptInstructionOutcomeContinue;
} else if (attrib == "angle") {
- DynamicValueWriteFloatHelper<double>::create(&_vector.angleDegrees, result);
+ DynamicValueWriteFloatHelper<double>::create(&storage->_vector.angleDegrees, result);
return kMiniscriptInstructionOutcomeContinue;
}
@@ -2727,7 +2779,9 @@ MiniscriptInstructionOutcome VectorVariableModifier::writeRefAttribute(Miniscrip
void VectorVariableModifier::debugInspect(IDebugInspectionReport *report) const {
VariableModifier::debugInspect(report);
- report->declareDynamic("value", _vector.toString());
+ VectorVariableStorage *storage = static_cast<VectorVariableStorage *>(_storage.get());
+
+ report->declareDynamic("value", storage->_vector.toString());
}
#endif
@@ -2739,20 +2793,31 @@ const char *VectorVariableModifier::getDefaultName() const {
return "Vector Variable";
}
-VectorVariableModifier::SaveLoad::SaveLoad(VectorVariableModifier *modifier) : _modifier(modifier) {
- _vector = _modifier->_vector;
+VectorVariableStorage::VectorVariableStorage() {
+}
+
+Common::SharedPtr<ModifierSaveLoad> VectorVariableStorage::getSaveLoad() {
+ return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
+}
+
+Common::SharedPtr<VariableStorage> VectorVariableStorage::clone() const {
+ return Common::SharedPtr<VariableStorage>(new VectorVariableStorage(*this));
}
-void VectorVariableModifier::SaveLoad::commitLoad() const {
- _modifier->_vector = _vector;
+VectorVariableStorage::SaveLoad::SaveLoad(VectorVariableStorage *storage) : _storage(storage) {
+ _vector = _storage->_vector;
}
-void VectorVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream) const {
+void VectorVariableStorage::SaveLoad::commitLoad() const {
+ _storage->_vector = _vector;
+}
+
+void VectorVariableStorage::SaveLoad::saveInternal(Common::WriteStream *stream) const {
stream->writeDoubleBE(_vector.angleDegrees);
stream->writeDoubleBE(_vector.magnitude);
}
-bool VectorVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
+bool VectorVariableStorage::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
_vector.angleDegrees = stream->readDoubleBE();
_vector.magnitude = stream->readDoubleBE();
@@ -2762,18 +2827,19 @@ bool VectorVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream,
return true;
}
+PointVariableModifier::PointVariableModifier() : VariableModifier(Common::SharedPtr<VariableStorage>(new PointVariableStorage())) {
+}
+
bool PointVariableModifier::load(ModifierLoaderContext &context, const Data::PointVariableModifier &data) {
if (!loadTypicalHeader(data.modHeader))
return false;
- _value.x = data.value.x;
- _value.y = data.value.y;
+ PointVariableStorage *storage = static_cast<PointVariableStorage *>(_storage.get());
- return true;
-}
+ if (!data.value.toScummVMPoint(storage->_value))
+ return false;
-Common::SharedPtr<ModifierSaveLoad> PointVariableModifier::getSaveLoad() {
- return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
+ return true;
}
bool PointVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicValue &value) {
@@ -2781,22 +2847,28 @@ bool PointVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicV
if (!value.convertToType(DynamicValueTypes::kPoint, pointValue))
return false;
- _value = pointValue.getPoint();
+ PointVariableStorage *storage = static_cast<PointVariableStorage *>(_storage.get());
+
+ storage->_value = pointValue.getPoint();
return true;
}
void PointVariableModifier::varGetValue(DynamicValue &dest) const {
- dest.setPoint(_value);
+ PointVariableStorage *storage = static_cast<PointVariableStorage *>(_storage.get());
+
+ dest.setPoint(storage->_value);
}
bool PointVariableModifier::readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) {
+ PointVariableStorage *storage = static_cast<PointVariableStorage *>(_storage.get());
+
if (attrib == "x") {
- result.setInt(_value.x);
+ result.setInt(storage->_value.x);
return true;
}
if (attrib == "y") {
- result.setInt(_value.y);
+ result.setInt(storage->_value.y);
return true;
}
@@ -2804,12 +2876,14 @@ bool PointVariableModifier::readAttribute(MiniscriptThread *thread, DynamicValue
}
MiniscriptInstructionOutcome PointVariableModifier::writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) {
+ PointVariableStorage *storage = static_cast<PointVariableStorage *>(_storage.get());
+
if (attrib == "x") {
- DynamicValueWriteIntegerHelper<int16>::create(&_value.x, writeProxy);
+ DynamicValueWriteIntegerHelper<int16>::create(&storage->_value.x, writeProxy);
return kMiniscriptInstructionOutcomeContinue;
}
if (attrib == "y") {
- DynamicValueWriteIntegerHelper<int16>::create(&_value.y, writeProxy);
+ DynamicValueWriteIntegerHelper<int16>::create(&storage->_value.y, writeProxy);
return kMiniscriptInstructionOutcomeContinue;
}
@@ -2820,7 +2894,9 @@ MiniscriptInstructionOutcome PointVariableModifier::writeRefAttribute(Miniscript
void PointVariableModifier::debugInspect(IDebugInspectionReport *report) const {
VariableModifier::debugInspect(report);
- report->declareDynamic("value", pointToString(_value));
+ PointVariableStorage *storage = static_cast<PointVariableStorage *>(_storage.get());
+
+ report->declareDynamic("value", pointToString(storage->_value));
}
#endif
@@ -2832,20 +2908,31 @@ const char *PointVariableModifier::getDefaultName() const {
return "Point Variable";
}
-PointVariableModifier::SaveLoad::SaveLoad(PointVariableModifier *modifier) : _modifier(modifier) {
- _value = _modifier->_value;
+PointVariableStorage::PointVariableStorage() {
}
-void PointVariableModifier::SaveLoad::commitLoad() const {
- _modifier->_value = _value;
+Common::SharedPtr<ModifierSaveLoad> PointVariableStorage::getSaveLoad() {
+ return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}
-void PointVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream) const {
+Common::SharedPtr<VariableStorage> PointVariableStorage::clone() const {
+ return Common::SharedPtr<VariableStorage>(new PointVariableStorage(*this));
+}
+
+PointVariableStorage::SaveLoad::SaveLoad(PointVariableStorage *storage) : _storage(storage) {
+ _value = storage->_value;
+}
+
+void PointVariableStorage::SaveLoad::commitLoad() const {
+ _storage->_value = _value;
+}
+
+void PointVariableStorage::SaveLoad::saveInternal(Common::WriteStream *stream) const {
stream->writeSint16BE(_value.x);
stream->writeSint16BE(_value.y);
}
-bool PointVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
+bool PointVariableStorage::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
_value.x = stream->readSint16BE();
_value.y = stream->readSint16BE();
@@ -2855,20 +2942,18 @@ bool PointVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, u
return true;
}
-FloatingPointVariableModifier::FloatingPointVariableModifier() : _value(0.0) {
+FloatingPointVariableModifier::FloatingPointVariableModifier() : VariableModifier(Common::SharedPtr<FloatingPointVariableStorage>(new FloatingPointVariableStorage())) {
}
bool FloatingPointVariableModifier::load(ModifierLoaderContext &context, const Data::FloatingPointVariableModifier &data) {
if (!loadTypicalHeader(data.modHeader))
return false;
- _value = data.value.toDouble();
+ FloatingPointVariableStorage *storage = static_cast<FloatingPointVariableStorage *>(_storage.get());
- return true;
-}
+ storage->_value = data.value.toDouble();
-Common::SharedPtr<ModifierSaveLoad> FloatingPointVariableModifier::getSaveLoad() {
- return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
+ return true;
}
bool FloatingPointVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicValue &value) {
@@ -2876,20 +2961,26 @@ bool FloatingPointVariableModifier::varSetValue(MiniscriptThread *thread, const
if (!value.convertToType(DynamicValueTypes::kFloat, floatValue))
return false;
- _value = floatValue.getFloat();
+ FloatingPointVariableStorage *storage = static_cast<FloatingPointVariableStorage *>(_storage.get());
+
+ storage->_value = floatValue.getFloat();
return true;
}
void FloatingPointVariableModifier::varGetValue(DynamicValue &dest) const {
- dest.setFloat(_value);
+ FloatingPointVariableStorage *storage = static_cast<FloatingPointVariableStorage *>(_storage.get());
+
+ dest.setFloat(storage->_value);
}
#ifdef MTROPOLIS_DEBUG_ENABLE
void FloatingPointVariableModifier::debugInspect(IDebugInspectionReport *report) const {
VariableModifier::debugInspect(report);
- report->declareDynamic("value", Common::String::format("%g", _value));
+ FloatingPointVariableStorage *storage = static_cast<FloatingPointVariableStorage *>(_storage.get());
+
+ report->declareDynamic("value", Common::String::format("%g", storage->_value));
}
#endif
@@ -2901,20 +2992,31 @@ const char *FloatingPointVariableModifier::getDefaultName() const {
return "Floating Point Variable";
}
-FloatingPointVariableModifier::SaveLoad::SaveLoad(FloatingPointVariableModifier *modifier) : _modifier(modifier) {
- _value = _modifier->_value;
+FloatingPointVariableStorage::FloatingPointVariableStorage() : _value(0.0) {
+}
+
+Common::SharedPtr<ModifierSaveLoad> FloatingPointVariableStorage::getSaveLoad() {
+ return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
}
-void FloatingPointVariableModifier::SaveLoad::commitLoad() const {
- _modifier->_value = _value;
+Common::SharedPtr<VariableStorage> FloatingPointVariableStorage::clone() const {
+ return Common::SharedPtr<VariableStorage>(new FloatingPointVariableStorage(*this));
}
-void FloatingPointVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream) const {
- stream->writeDoubleBE(_value);
+FloatingPointVariableStorage::SaveLoad::SaveLoad(FloatingPointVariableStorage *storage) : _storage(storage) {
+ _value = _storage->_value;
}
-bool FloatingPointVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
- _value = stream->readDoubleBE();
+void FloatingPointVariableStorage::SaveLoad::commitLoad() const {
+ _storage->_value = _value;
+}
+
+void FloatingPointVariableStorage::SaveLoad::saveInternal(Common::WriteStream *stream) const {
+ stream->writeDoubleBE(_storage->_value);
+}
+
+bool FloatingPointVariableStorage::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
+ _storage->_value = stream->readDoubleBE();
if (stream->err())
return false;
@@ -2922,17 +3024,18 @@ bool FloatingPointVariableModifier::SaveLoad::loadInternal(Common::ReadStream *s
return true;
}
+StringVariableModifier::StringVariableModifier() : VariableModifier(Common::SharedPtr<VariableStorage>(new StringVariableStorage())) {
+}
+
bool StringVariableModifier::load(ModifierLoaderContext &context, const Data::StringVariableModifier &data) {
if (!loadTypicalHeader(data.modHeader))
return false;
- _value = data.value;
+ StringVariableStorage *storage = static_cast<StringVariableStorage *>(_storage.get());
- return true;
-}
+ storage->_value = data.value;
-Common::SharedPtr<ModifierSaveLoad> StringVariableModifier::getSaveLoad() {
- return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
+ return true;
}
bool StringVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicValue &value) {
@@ -2940,20 +3043,26 @@ bool StringVariableModifier::varSetValue(MiniscriptThread *thread, const Dynamic
if (!value.convertToType(DynamicValueTypes::kString, stringValue))
return false;
- _value = stringValue.getString();
+ StringVariableStorage *storage = static_cast<StringVariableStorage *>(_storage.get());
+
+ storage->_value = stringValue.getString();
return true;
}
void StringVariableModifier::varGetValue(DynamicValue &dest) const {
- dest.setString(_value);
+ StringVariableStorage *storage = static_cast<StringVariableStorage *>(_storage.get());
+
+ dest.setString(storage->_value);
}
#ifdef MTROPOLIS_DEBUG_ENABLE
void StringVariableModifier::debugInspect(IDebugInspectionReport *report) const {
VariableModifier::debugInspect(report);
- report->declareDynamic("value", _value);
+ StringVariableStorage *storage = static_cast<StringVariableStorage *>(_storage.get());
+
+ report->declareDynamic("value", storage->_value);
}
#endif
@@ -2965,20 +3074,31 @@ const char *StringVariableModifier::getDefaultName() const {
return "String Variable";
}
-StringVariableModifier::SaveLoad::SaveLoad(StringVariableModifier *modifier) : _modifier(modifier) {
- _value = _modifier->_value;
+StringVariableStorage::StringVariableStorage() {
+}
+
+Common::SharedPtr<ModifierSaveLoad> StringVariableStorage::getSaveLoad() {
+ return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
+}
+
+Common::SharedPtr<VariableStorage> StringVariableStorage::clone() const {
+ return Common::SharedPtr<VariableStorage>(new StringVariableStorage(*this));
+}
+
+StringVariableStorage::SaveLoad::SaveLoad(StringVariableStorage *storage) : _storage(storage) {
+ _value = _storage->_value;
}
-void StringVariableModifier::SaveLoad::commitLoad() const {
- _modifier->_value = _value;
+void StringVariableStorage::SaveLoad::commitLoad() const {
+ _storage->_value = _value;
}
-void StringVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream) const {
+void StringVariableStorage::SaveLoad::saveInternal(Common::WriteStream *stream) const {
stream->writeUint32BE(_value.size());
stream->writeString(_value);
}
-bool StringVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
+bool StringVariableStorage::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
uint32 size = stream->readUint32BE();
if (stream->err())
@@ -2999,7 +3119,8 @@ bool StringVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream,
return true;
}
-
+ObjectReferenceVariableModifierV1::ObjectReferenceVariableModifierV1() : VariableModifier(Common::SharedPtr<VariableStorage>(new ObjectReferenceVariableV1Storage())) {
+}
bool ObjectReferenceVariableModifierV1::load(ModifierLoaderContext &context, const Data::ObjectReferenceVariableModifierV1 &data) {
if (!loadTypicalHeader(data.modHeader))
@@ -3022,17 +3143,15 @@ VThreadState ObjectReferenceVariableModifierV1::consumeMessage(Runtime *runtime,
return kVThreadError;
}
-Common::SharedPtr<ModifierSaveLoad> ObjectReferenceVariableModifierV1::getSaveLoad() {
- return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
-}
-
bool ObjectReferenceVariableModifierV1::varSetValue(MiniscriptThread *thread, const DynamicValue &value) {
+ ObjectReferenceVariableV1Storage *storage = static_cast<ObjectReferenceVariableV1Storage *>(_storage.get());
+
// Somewhat tricky aspect: If this is set to another object reference variable modifier, then this will reference
// the other object variable modifier, it will NOT copy it.
if (value.getType() == DynamicValueTypes::kNull)
- _value.reset();
+ storage->_value.reset();
else if (value.getType() == DynamicValueTypes::kObject)
- _value = value.getObject().object;
+ storage->_value = value.getObject().object;
else
return false;
@@ -3051,18 +3170,29 @@ const char *ObjectReferenceVariableModifierV1::getDefaultName() const {
return "Object Reference Variable";
}
-ObjectReferenceVariableModifierV1::SaveLoad::SaveLoad(ObjectReferenceVariableModifierV1 *modifier) : _modifier(modifier) {
+ObjectReferenceVariableV1Storage::ObjectReferenceVariableV1Storage() {
+}
+
+Common::SharedPtr<ModifierSaveLoad> ObjectReferenceVariableV1Storage::getSaveLoad() {
+ return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
+}
+
+Common::SharedPtr<VariableStorage> ObjectReferenceVariableV1Storage::clone() const {
+ return Common::SharedPtr<VariableStorage>(new ObjectReferenceVariableV1Storage(*this));
+}
+
+ObjectReferenceVariableV1Storage::SaveLoad::SaveLoad(ObjectReferenceVariableV1Storage *storage) : _storage(storage) {
}
-void ObjectReferenceVariableModifierV1::SaveLoad::commitLoad() const {
- _modifier->_value = _value;
+void ObjectReferenceVariableV1Storage::SaveLoad::commitLoad() const {
+ _storage->_value = _value;
}
-void ObjectReferenceVariableModifierV1::SaveLoad::saveInternal(Common::WriteStream *stream) const {
+void ObjectReferenceVariableV1Storage::SaveLoad::saveInternal(Common::WriteStream *stream) const {
error("Saving version 1 object reference variables is not currently supported");
}
-bool ObjectReferenceVariableModifierV1::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
+bool ObjectReferenceVariableV1Storage::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
return true;
}
diff --git a/engines/mtropolis/modifiers.h b/engines/mtropolis/modifiers.h
index af76be475a9..f04b84e6d66 100644
--- a/engines/mtropolis/modifiers.h
+++ b/engines/mtropolis/modifiers.h
@@ -1000,7 +1000,7 @@ private:
MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) override;
MiniscriptInstructionOutcome writeRefAttributeIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib, const DynamicValue &index) override;
- Modifier *findChildByName(const Common::String &name) const;
+ Modifier *findChildByName(Runtime *runtime, const Common::String &name) const;
Common::Array<Common::SharedPtr<Modifier> > _children;
};
@@ -1011,8 +1011,6 @@ public:
bool load(ModifierLoaderContext &context, const Data::BooleanVariableModifier &data);
- Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
-
bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
void varGetValue(DynamicValue &dest) const override;
@@ -1022,23 +1020,35 @@ public:
void debugInspect(IDebugInspectionReport *report) const override;
#endif
+private:
+ Common::SharedPtr<Modifier> shallowClone() const override;
+ const char *getDefaultName() const override;
+};
+
+class BooleanVariableStorage : public VariableStorage {
+public:
+ friend class BooleanVariableModifier;
+
+ BooleanVariableStorage();
+
+ Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+
+ Common::SharedPtr<VariableStorage> clone() const override;
+
private:
class SaveLoad : public ModifierSaveLoad {
public:
- explicit SaveLoad(BooleanVariableModifier *modifier);
+ explicit SaveLoad(BooleanVariableStorage *modifier);
private:
void commitLoad() const override;
void saveInternal(Common::WriteStream *stream) const override;
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
- BooleanVariableModifier *_modifier;
+ BooleanVariableStorage *_storage;
bool _value;
};
- Common::SharedPtr<Modifier> shallowClone() const override;
- const char *getDefaultName() const override;
-
bool _value;
};
@@ -1048,8 +1058,6 @@ public:
bool load(ModifierLoaderContext &context, const Data::IntegerVariableModifier &data);
- Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
-
bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
void varGetValue(DynamicValue &dest) const override;
@@ -1059,31 +1067,43 @@ public:
void debugInspect(IDebugInspectionReport *report) const override;
#endif
+private:
+ Common::SharedPtr<Modifier> shallowClone() const override;
+ const char *getDefaultName() const override;
+};
+
+class IntegerVariableStorage : public VariableStorage {
+public:
+ friend class IntegerVariableModifier;
+
+ IntegerVariableStorage();
+
+ Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+
+ Common::SharedPtr<VariableStorage> clone() const override;
+
private:
class SaveLoad : public ModifierSaveLoad {
public:
- explicit SaveLoad(IntegerVariableModifier *modifier);
+ explicit SaveLoad(IntegerVariableStorage *storage);
private:
void commitLoad() const override;
void saveInternal(Common::WriteStream *stream) const override;
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
- IntegerVariableModifier *_modifier;
+ IntegerVariableStorage *_storage;
int32 _value;
};
- Common::SharedPtr<Modifier> shallowClone() const override;
- const char *getDefaultName() const override;
-
int32 _value;
};
class IntegerRangeVariableModifier : public VariableModifier {
public:
- bool load(ModifierLoaderContext &context, const Data::IntegerRangeVariableModifier &data);
+ IntegerRangeVariableModifier();
- Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+ bool load(ModifierLoaderContext &context, const Data::IntegerRangeVariableModifier &data);
bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
void varGetValue(DynamicValue &dest) const override;
@@ -1097,31 +1117,43 @@ public:
void debugInspect(IDebugInspectionReport *report) const override;
#endif
+private:
+ Common::SharedPtr<Modifier> shallowClone() const override;
+ const char *getDefaultName() const override;
+};
+
+class IntegerRangeVariableStorage : public VariableStorage {
+public:
+ friend class IntegerRangeVariableModifier;
+
+ IntegerRangeVariableStorage();
+
+ Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+
+ Common::SharedPtr<VariableStorage> clone() const override;
+
private:
class SaveLoad : public ModifierSaveLoad {
public:
- explicit SaveLoad(IntegerRangeVariableModifier *modifier);
+ explicit SaveLoad(IntegerRangeVariableStorage *storage);
private:
void commitLoad() const override;
void saveInternal(Common::WriteStream *stream) const override;
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
- IntegerRangeVariableModifier *_modifier;
+ IntegerRangeVariableStorage *_storage;
IntRange _range;
};
- Common::SharedPtr<Modifier> shallowClone() const override;
- const char *getDefaultName() const override;
-
IntRange _range;
};
class VectorVariableModifier : public VariableModifier {
public:
- bool load(ModifierLoaderContext &context, const Data::VectorVariableModifier &data);
+ VectorVariableModifier();
- Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+ bool load(ModifierLoaderContext &context, const Data::VectorVariableModifier &data);
bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
void varGetValue(DynamicValue &dest) const override;
@@ -1135,31 +1167,42 @@ public:
void debugInspect(IDebugInspectionReport *report) const override;
#endif
+private:
+ Common::SharedPtr<Modifier> shallowClone() const override;
+ const char *getDefaultName() const override;
+};
+
+class VectorVariableStorage : public VariableStorage {
+ friend class VectorVariableModifier;
+
+ VectorVariableStorage();
+
+ Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+
+ Common::SharedPtr<VariableStorage> clone() const override;
+
private:
class SaveLoad : public ModifierSaveLoad {
public:
- explicit SaveLoad(VectorVariableModifier *modifier);
+ explicit SaveLoad(VectorVariableStorage *storage);
private:
void commitLoad() const override;
void saveInternal(Common::WriteStream *stream) const override;
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
- VectorVariableModifier *_modifier;
+ VectorVariableStorage *_storage;
AngleMagVector _vector;
};
- Common::SharedPtr<Modifier> shallowClone() const override;
- const char *getDefaultName() const override;
-
AngleMagVector _vector;
};
class PointVariableModifier : public VariableModifier {
public:
- bool load(ModifierLoaderContext &context, const Data::PointVariableModifier &data);
+ PointVariableModifier();
- Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+ bool load(ModifierLoaderContext &context, const Data::PointVariableModifier &data);
bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
void varGetValue(DynamicValue &dest) const override;
@@ -1173,23 +1216,35 @@ public:
void debugInspect(IDebugInspectionReport *report) const override;
#endif
+private:
+ Common::SharedPtr<Modifier> shallowClone() const override;
+ const char *getDefaultName() const override;
+};
+
+class PointVariableStorage : public VariableStorage {
+public:
+ friend class PointVariableModifier;
+
+ PointVariableStorage();
+
+ Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+
+ Common::SharedPtr<VariableStorage> clone() const override;
+
private:
class SaveLoad : public ModifierSaveLoad {
public:
- explicit SaveLoad(PointVariableModifier *modifier);
+ explicit SaveLoad(PointVariableStorage *storage);
private:
void commitLoad() const override;
void saveInternal(Common::WriteStream *stream) const override;
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
- PointVariableModifier *_modifier;
+ PointVariableStorage *_storage;
Common::Point _value;
};
- Common::SharedPtr<Modifier> shallowClone() const override;
- const char *getDefaultName() const override;
-
Common::Point _value;
};
@@ -1199,8 +1254,6 @@ public:
bool load(ModifierLoaderContext &context, const Data::FloatingPointVariableModifier &data);
- Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
-
bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
void varGetValue(DynamicValue &dest) const override;
@@ -1210,31 +1263,43 @@ public:
void debugInspect(IDebugInspectionReport *report) const override;
#endif
+private:
+ Common::SharedPtr<Modifier> shallowClone() const override;
+ const char *getDefaultName() const override;
+};
+
+class FloatingPointVariableStorage : public VariableStorage {
+public:
+ friend class FloatingPointVariableModifier;
+
+ FloatingPointVariableStorage();
+
+ Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+
+ Common::SharedPtr<VariableStorage> clone() const override;
+
private:
class SaveLoad : public ModifierSaveLoad {
public:
- explicit SaveLoad(FloatingPointVariableModifier *modifier);
+ explicit SaveLoad(FloatingPointVariableStorage *storage);
private:
void commitLoad() const override;
void saveInternal(Common::WriteStream *stream) const override;
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
- FloatingPointVariableModifier *_modifier;
+ FloatingPointVariableStorage *_storage;
double _value;
};
- Common::SharedPtr<Modifier> shallowClone() const override;
- const char *getDefaultName() const override;
-
double _value;
};
class StringVariableModifier : public VariableModifier {
public:
- bool load(ModifierLoaderContext &context, const Data::StringVariableModifier &data);
+ StringVariableModifier();
- Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+ bool load(ModifierLoaderContext &context, const Data::StringVariableModifier &data);
bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
void varGetValue(DynamicValue &dest) const override;
@@ -1245,62 +1310,88 @@ public:
void debugInspect(IDebugInspectionReport *report) const override;
#endif
+private:
+ Common::SharedPtr<Modifier> shallowClone() const override;
+ const char *getDefaultName() const override;
+};
+
+class StringVariableStorage : public VariableStorage {
+public:
+ friend class StringVariableModifier;
+
+ StringVariableStorage();
+
+ Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+
+ Common::SharedPtr<VariableStorage> clone() const override;
+
private:
class SaveLoad : public ModifierSaveLoad {
public:
- explicit SaveLoad(StringVariableModifier *modifier);
+ explicit SaveLoad(StringVariableStorage *storage);
private:
void commitLoad() const override;
void saveInternal(Common::WriteStream *stream) const override;
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
- StringVariableModifier *_modifier;
+ StringVariableStorage *_storage;
Common::String _value;
};
- Common::SharedPtr<Modifier> shallowClone() const override;
- const char *getDefaultName() const override;
-
Common::String _value;
};
class ObjectReferenceVariableModifierV1 : public VariableModifier {
public:
+ ObjectReferenceVariableModifierV1();
+
bool load(ModifierLoaderContext &context, const Data::ObjectReferenceVariableModifierV1 &data);
+ bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
+ void varGetValue(DynamicValue &dest) const override;
+
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
- Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
-
- bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
- void varGetValue(DynamicValue &dest) const override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Object Reference Variable Modifier V1"; }
SupportStatus debugGetSupportStatus() const override { return kSupportStatusNone; }
#endif
+private:
+ Common::SharedPtr<Modifier> shallowClone() const override;
+ const char *getDefaultName() const override;
+
+ Event _setToSourcesParentWhen;
+};
+
+class ObjectReferenceVariableV1Storage : public VariableStorage {
+public:
+ friend class ObjectReferenceVariableModifierV1;
+
+ ObjectReferenceVariableV1Storage();
+
+ Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+
+ Common::SharedPtr<VariableStorage> clone() const override;
+
private:
class SaveLoad : public ModifierSaveLoad {
public:
- explicit SaveLoad(ObjectReferenceVariableModifierV1 *modifier);
+ explicit SaveLoad(ObjectReferenceVariableV1Storage *storage);
private:
void commitLoad() const override;
void saveInternal(Common::WriteStream *stream) const override;
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
- ObjectReferenceVariableModifierV1 *_modifier;
+ ObjectReferenceVariableV1Storage *_storage;
Common::WeakPtr<RuntimeObject> _value;
};
- Common::SharedPtr<Modifier> shallowClone() const override;
- const char *getDefaultName() const override;
-
Common::WeakPtr<RuntimeObject> _value;
- Event _setToSourcesParentWhen;
};
} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/standard.cpp b/engines/mtropolis/plugin/standard.cpp
index 3c2ab192a8c..db64a446938 100644
--- a/engines/mtropolis/plugin/standard.cpp
+++ b/engines/mtropolis/plugin/standard.cpp
@@ -1960,7 +1960,7 @@ void MediaCueMessengerModifier::visitInternalReferences(IStructuralReferenceVisi
_mediaCue.send.visitInternalReferences(visitor);
}
-ObjectReferenceVariableModifier::ObjectReferenceVariableModifier() {
+ObjectReferenceVariableModifier::ObjectReferenceVariableModifier() : VariableModifier(Common::SharedPtr<VariableStorage>(new ObjectReferenceVariableStorage())) {
}
bool ObjectReferenceVariableModifier::load(const PlugInModifierLoaderContext &context, const Data::Standard::ObjectReferenceVariableModifier &data) {
@@ -1970,36 +1970,36 @@ bool ObjectReferenceVariableModifier::load(const PlugInModifierLoaderContext &co
if (!_setToSourceParentWhen.load(data.setToSourceParentWhen.value.asEvent))
return false;
+ ObjectReferenceVariableStorage *storage = static_cast<ObjectReferenceVariableStorage *>(_storage.get());
+
if (data.objectPath.type == Data::PlugInTypeTaggedValue::kString)
- _objectPath = data.objectPath.value.asString;
+ storage->_objectPath = data.objectPath.value.asString;
else if (data.objectPath.type != Data::PlugInTypeTaggedValue::kNull)
return false;
- _object.reset();
+ storage->_object.reset();
return true;
}
-Common::SharedPtr<ModifierSaveLoad> ObjectReferenceVariableModifier::getSaveLoad() {
- return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
-}
-
// Object reference variables are somewhat unusual in that they don't store a simple value,
// they instead have "object" and "path" attributes AND as a value, they resolve to the
// modifier itself.
bool ObjectReferenceVariableModifier::readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) {
+ ObjectReferenceVariableStorage *storage = static_cast<ObjectReferenceVariableStorage *>(_storage.get());
+
if (attrib == "path") {
- result.setString(_objectPath);
+ result.setString(storage->_objectPath);
return true;
}
if (attrib == "object") {
- if (_object.object.expired())
+ if (storage->_object.object.expired())
resolve(thread->getRuntime());
- if (_object.object.expired())
+ if (storage->_object.object.expired())
result.clear();
else
- result.setObject(_object);
+ result.setObject(storage->_object);
return true;
}
@@ -2041,8 +2041,10 @@ void ObjectReferenceVariableModifier::varGetValue(DynamicValue &dest) const {
void ObjectReferenceVariableModifier::debugInspect(IDebugInspectionReport *report) const {
VariableModifier::debugInspect(report);
- report->declareDynamic("path", _objectPath);
- report->declareDynamic("fullPath", _fullPath);
+ ObjectReferenceVariableStorage *storage = static_cast<ObjectReferenceVariableStorage *>(_storage.get());
+
+ report->declareDynamic("path", storage->_objectPath);
+ report->declareDynamic("fullPath", storage->_fullPath);
}
#endif
@@ -2058,17 +2060,21 @@ MiniscriptInstructionOutcome ObjectReferenceVariableModifier::scriptSetPath(Mini
if (value.getType() != DynamicValueTypes::kString)
return kMiniscriptInstructionOutcomeFailed;
- _objectPath = value.getString();
- _object.reset();
+ ObjectReferenceVariableStorage *storage = static_cast<ObjectReferenceVariableStorage *>(_storage.get());
+
+ storage->_objectPath = value.getString();
+ storage->_object.reset();
return kMiniscriptInstructionOutcomeContinue;
}
MiniscriptInstructionOutcome ObjectReferenceVariableModifier::scriptSetObject(MiniscriptThread *thread, const DynamicValue &value) {
+ ObjectReferenceVariableStorage *storage = static_cast<ObjectReferenceVariableStorage *>(_storage.get());
+
if (value.getType() == DynamicValueTypes::kNull) {
- _object.reset();
- _objectPath.clear();
- _fullPath.clear();
+ storage->_object.reset();
+ storage->_objectPath.clear();
+ storage->_fullPath.clear();
return kMiniscriptInstructionOutcomeContinue;
} else if (value.getType() == DynamicValueTypes::kObject) {
@@ -2076,11 +2082,11 @@ MiniscriptInstructionOutcome ObjectReferenceVariableModifier::scriptSetObject(Mi
if (!obj)
return scriptSetObject(thread, DynamicValue());
- if (!computeObjectPath(obj.get(), _fullPath))
+ if (!computeObjectPath(obj.get(), storage->_fullPath))
return scriptSetObject(thread, DynamicValue());
- _objectPath = _fullPath;
- _object.object = obj;
+ storage->_objectPath = storage->_fullPath;
+ storage->_object.object = obj;
return kMiniscriptInstructionOutcomeContinue;
} else
@@ -2088,52 +2094,60 @@ MiniscriptInstructionOutcome ObjectReferenceVariableModifier::scriptSetObject(Mi
}
MiniscriptInstructionOutcome ObjectReferenceVariableModifier::scriptObjectRefAttrib(MiniscriptThread *thread, DynamicValueWriteProxy &proxy, const Common::String &attrib) {
+ ObjectReferenceVariableStorage *storage = static_cast<ObjectReferenceVariableStorage *>(_storage.get());
+
resolve(thread->getRuntime());
- if (_object.object.expired()) {
+ if (storage->_object.object.expired()) {
thread->error("Attempted to reference an attribute of an object variable object, but the reference is dead");
return kMiniscriptInstructionOutcomeFailed;
}
- return _object.object.lock()->writeRefAttribute(thread, proxy, attrib);
+ return storage->_object.object.lock()->writeRefAttribute(thread, proxy, attrib);
}
MiniscriptInstructionOutcome ObjectReferenceVariableModifier::scriptObjectRefAttribIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &proxy, const Common::String &attrib, const DynamicValue &index) {
+ ObjectReferenceVariableStorage *storage = static_cast<ObjectReferenceVariableStorage *>(_storage.get());
+
resolve(thread->getRuntime());
- if (_object.object.expired()) {
+ if (storage->_object.object.expired()) {
thread->error("Attempted to reference an attribute of an object variable object, but the reference is dead");
return kMiniscriptInstructionOutcomeFailed;
}
- return _object.object.lock()->writeRefAttributeIndexed(thread, proxy, attrib, index);
+ return storage->_object.object.lock()->writeRefAttributeIndexed(thread, proxy, attrib, index);
}
void ObjectReferenceVariableModifier::resolve(Runtime *runtime) {
- if (!_object.object.expired())
+ ObjectReferenceVariableStorage *storage = static_cast<ObjectReferenceVariableStorage *>(_storage.get());
+
+ if (!storage->_object.object.expired())
return;
- _fullPath.clear();
- _object.reset();
+ storage->_fullPath.clear();
+ storage->_object.reset();
- if (_objectPath.size() == 0)
+ if (storage->_objectPath.size() == 0)
return;
- if (_objectPath[0] == '/')
+ if (storage->_objectPath[0] == '/')
resolveAbsolutePath(runtime);
- else if (_objectPath[0] == '.')
- resolveRelativePath(this, _objectPath, 0);
+ else if (storage->_objectPath[0] == '.')
+ resolveRelativePath(this, storage->_objectPath, 0);
else
warning("Object reference variable had an unknown path format");
- if (!_object.object.expired()) {
- if (!computeObjectPath(_object.object.lock().get(), _fullPath)) {
- _object.reset();
+ if (!storage->_object.object.expired()) {
+ if (!computeObjectPath(storage->_object.object.lock().get(), storage->_fullPath)) {
+ storage->_object.reset();
}
}
}
void ObjectReferenceVariableModifier::resolveRelativePath(RuntimeObject *obj, const Common::String &path, size_t startPos) {
+ ObjectReferenceVariableStorage *storage = static_cast<ObjectReferenceVariableStorage *>(_storage.get());
+
bool haveNextLevel = true;
size_t nextLevelPos = startPos;
@@ -2197,11 +2211,13 @@ void ObjectReferenceVariableModifier::resolveRelativePath(RuntimeObject *obj, co
return;
}
- _object.object = obj->getSelfReference();
+ storage->_object.object = obj->getSelfReference();
}
void ObjectReferenceVariableModifier::resolveAbsolutePath(Runtime *runtime) {
- assert(_objectPath[0] == '/');
+ ObjectReferenceVariableStorage *storage = static_cast<ObjectReferenceVariableStorage *>(_storage.get());
+
+ assert(storage->_objectPath[0] == '/');
RuntimeObject *project = this;
for (;;) {
@@ -2219,7 +2235,7 @@ void ObjectReferenceVariableModifier::resolveAbsolutePath(Runtime *runtime) {
bool foundPrefix = false;
if (runtime->getHacks().ignoreMismatchedProjectNameInObjectLookups) {
- size_t slashOffset = _objectPath.findFirstOf('/', 1);
+ size_t slashOffset = storage->_objectPath.findFirstOf('/', 1);
if (slashOffset != Common::String::npos) {
prefixEnd = slashOffset;
foundPrefix = true;
@@ -2230,7 +2246,7 @@ void ObjectReferenceVariableModifier::resolveAbsolutePath(Runtime *runtime) {
"/<project>"};
for (const Common::String &prefix : projectPrefixes) {
- if (_objectPath.size() >= prefix.size() && caseInsensitiveEqual(_objectPath.substr(0, prefix.size()), prefix)) {
+ if (storage->_objectPath.size() >= prefix.size() && caseInsensitiveEqual(storage->_objectPath.substr(0, prefix.size()), prefix)) {
prefixEnd = prefix.size();
foundPrefix = true;
break;
@@ -2242,15 +2258,15 @@ void ObjectReferenceVariableModifier::resolveAbsolutePath(Runtime *runtime) {
return;
// If the object path is longer, then there must be a slash separator, otherwise this doesn't match the project
- if (prefixEnd == _objectPath.size()) {
- _object = ObjectReference(project->getSelfReference());
+ if (prefixEnd == storage->_objectPath.size()) {
+ storage->_object = ObjectReference(project->getSelfReference());
return;
}
- if (_objectPath[prefixEnd] != '/')
+ if (storage->_objectPath[prefixEnd] != '/')
return;
- return resolveRelativePath(project, _objectPath, prefixEnd + 1);
+ return resolveRelativePath(project, storage->_objectPath, prefixEnd + 1);
}
bool ObjectReferenceVariableModifier::computeObjectPath(RuntimeObject *obj, Common::String &outPath) {
@@ -2301,22 +2317,36 @@ MiniscriptInstructionOutcome ObjectReferenceVariableModifier::ObjectWriteInterfa
return static_cast<ObjectReferenceVariableModifier *>(objectRef)->scriptObjectRefAttribIndexed(thread, proxy, attrib, index);
}
-ObjectReferenceVariableModifier::SaveLoad::SaveLoad(ObjectReferenceVariableModifier *modifier) : _modifier(modifier) {
- _objectPath = _modifier->_objectPath;
+ObjectReferenceVariableStorage::SaveLoad::SaveLoad(ObjectReferenceVariableStorage *storage) : _storage(storage) {
+ _objectPath = _storage->_objectPath;
+}
+
+
+
+
+ObjectReferenceVariableStorage::ObjectReferenceVariableStorage() {
+}
+
+Common::SharedPtr<ModifierSaveLoad> ObjectReferenceVariableStorage::getSaveLoad() {
+ return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
+}
+
+Common::SharedPtr<VariableStorage> ObjectReferenceVariableStorage::clone() const {
+ return Common::SharedPtr<VariableStorage>(new ObjectReferenceVariableStorage(*this));
}
-void ObjectReferenceVariableModifier::SaveLoad::commitLoad() const {
- _modifier->_object.reset();
- _modifier->_fullPath.clear();
- _modifier->_objectPath = _objectPath;
+void ObjectReferenceVariableStorage::SaveLoad::commitLoad() const {
+ _storage->_object.reset();
+ _storage->_fullPath.clear();
+ _storage->_objectPath = _objectPath;
}
-void ObjectReferenceVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream) const {
+void ObjectReferenceVariableStorage::SaveLoad::saveInternal(Common::WriteStream *stream) const {
stream->writeUint32BE(_objectPath.size());
stream->writeString(_objectPath);
}
-bool ObjectReferenceVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
+bool ObjectReferenceVariableStorage::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
uint32 stringLen = stream->readUint32BE();
if (stream->err())
return false;
@@ -2721,29 +2751,31 @@ MiniscriptInstructionOutcome MidiModifier::MuteTrackProxyInterface::refAttribInd
return kMiniscriptInstructionOutcomeFailed;
}
-ListVariableModifier::ListVariableModifier() : _list(new DynamicList()), _preferredContentType(DynamicValueTypes::kInteger) {
+ListVariableModifier::ListVariableModifier() : VariableModifier(Common::SharedPtr<VariableStorage>(new ListVariableStorage())) {
}
bool ListVariableModifier::load(const PlugInModifierLoaderContext &context, const Data::Standard::ListVariableModifier &data) {
- _preferredContentType = DynamicValueTypes::kInvalid;
+ ListVariableStorage *storage = static_cast<ListVariableStorage *>(_storage.get());
+
+ storage->_preferredContentType = DynamicValueTypes::kInvalid;
switch (data.contentsType) {
case Data::Standard::ListVariableModifier::kContentsTypeInteger:
- _preferredContentType = DynamicValueTypes::kInteger;
+ storage->_preferredContentType = DynamicValueTypes::kInteger;
break;
case Data::Standard::ListVariableModifier::kContentsTypePoint:
- _preferredContentType = DynamicValueTypes::kPoint;
+ storage->_preferredContentType = DynamicValueTypes::kPoint;
break;
case Data::Standard::ListVariableModifier::kContentsTypeRange:
- _preferredContentType = DynamicValueTypes::kIntegerRange;
+ storage->_preferredContentType = DynamicValueTypes::kIntegerRange;
break;
case Data::Standard::ListVariableModifier::kContentsTypeFloat:
- _preferredContentType = DynamicValueTypes::kFloat;
+ storage->_preferredContentType = DynamicValueTypes::kFloat;
break;
case Data::Standard::ListVariableModifier::kContentsTypeString:
- _preferredContentType = DynamicValueTypes::kString;
+ storage->_preferredContentType = DynamicValueTypes::kString;
break;
case Data::Standard::ListVariableModifier::kContentsTypeObject:
- _preferredContentType = DynamicValueTypes::kObject;
+ storage->_preferredContentType = DynamicValueTypes::kObject;
if (data.persistentValuesGarbled) {
// Ignore and let the game fix it
return true;
@@ -2753,10 +2785,10 @@ bool ListVariableModifier::load(const PlugInModifierLoaderContext &context, cons
}
break;
case Data::Standard::ListVariableModifier::kContentsTypeVector:
- _preferredContentType = DynamicValueTypes::kVector;
+ storage->_preferredContentType = DynamicValueTypes::kVector;
break;
case Data::Standard::ListVariableModifier::kContentsTypeBoolean:
- _preferredContentType = DynamicValueTypes::kBoolean;
+ storage->_preferredContentType = DynamicValueTypes::kBoolean;
break;
default:
warning("Unknown list data type");
@@ -2771,12 +2803,12 @@ bool ListVariableModifier::load(const PlugInModifierLoaderContext &context, cons
if (!dynValue.loadConstant(data.values[i]))
return false;
- if (dynValue.getType() != _preferredContentType) {
+ if (dynValue.getType() != storage->_preferredContentType) {
warning("List mod initialization element had the wrong type");
return false;
}
- if (!_list->setAtIndex(i, dynValue)) {
+ if (!storage->_list->setAtIndex(i, dynValue)) {
warning("Failed to initialize list modifier, value was rejected");
return false;
}
@@ -2789,11 +2821,9 @@ bool ListVariableModifier::isListVariable() const {
return true;
}
-Common::SharedPtr<ModifierSaveLoad> ListVariableModifier::getSaveLoad() {
- return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
-}
-
bool ListVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicValue &value) {
+ ListVariableStorage *storage = static_cast<ListVariableStorage *>(_storage.get());
+
if (value.getType() == DynamicValueTypes::kList) {
// Source value is a list. In this case, it must be convertible, or an error occurs.
Common::SharedPtr<DynamicList> sourceList = value.getList();
@@ -2805,7 +2835,7 @@ bool ListVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicVa
DynamicValue convertedElement;
- if (!sourceElement.convertToType(_preferredContentType, convertedElement)) {
+ if (!sourceElement.convertToType(storage->_preferredContentType, convertedElement)) {
thread->error("Failed to convert list when assigning to a list variable");
return false;
}
@@ -2813,12 +2843,12 @@ bool ListVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicVa
newList->setAtIndex(i, convertedElement);
}
- _list = newList;
+ storage->_list = newList;
} else if (value.getType() == DynamicValueTypes::kObject) {
// Source value is an object. In this case, it must be another list, otherwise this fails without an error.
RuntimeObject *obj = value.getObject().object.lock().get();
if (obj && obj->isModifier() && static_cast<Modifier *>(obj)->isVariable() && static_cast<VariableModifier *>(obj)->isListVariable()) {
- Common::SharedPtr<DynamicList> sourceList = static_cast<ListVariableModifier *>(obj)->_list;
+ Common::SharedPtr<DynamicList> sourceList = static_cast<ListVariableStorage *>(static_cast<ListVariableModifier *>(obj)->_storage.get())->_list;
Common::SharedPtr<DynamicList> newList(new DynamicList());
bool failed = false;
@@ -2828,7 +2858,7 @@ bool ListVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicVa
DynamicValue convertedElement;
- if (!sourceElement.convertToType(_preferredContentType, convertedElement)) {
+ if (!sourceElement.convertToType(storage->_preferredContentType, convertedElement)) {
warning("Failed to convert list when assigning to a list variable. (Non-fatal since it was directly assigned.)");
failed = true;
break;
@@ -2838,16 +2868,16 @@ bool ListVariableModifier::varSetValue(MiniscriptThread *thread, const DynamicVa
}
if (!failed)
- _list = newList;
+ storage->_list = newList;
}
} else {
// Source value is a non-list. In this case, it must be exactly the correct type, except for numbers.
DynamicValue convertedValue;
- if (value.convertToType(_preferredContentType, convertedValue)) {
+ if (value.convertToType(storage->_preferredContentType, convertedValue)) {
Common::SharedPtr<DynamicList> newList(new DynamicList());
newList->setAtIndex(0, convertedValue);
- _list = newList;
+ storage->_list = newList;
} else {
thread->error("Can't assign incompatible value type to a list variable");
return false;
@@ -2862,32 +2892,34 @@ void ListVariableModifier::varGetValue(DynamicValue &dest) const {
}
bool ListVariableModifier::readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) {
+ ListVariableStorage *storage = static_cast<ListVariableStorage *>(_storage.get());
+
if (attrib == "count") {
- result.setInt(_list->getSize());
+ result.setInt(storage->_list->getSize());
return true;
} else if (attrib == "random") {
- if (_list->getSize() == 0)
+ if (storage->_list->getSize() == 0)
return false;
- size_t index = thread->getRuntime()->getRandom()->getRandomNumber(_list->getSize() - 1);
- return _list->getAtIndex(index, result);
+ size_t index = thread->getRuntime()->getRandom()->getRandomNumber(storage->_list->getSize() - 1);
+ return storage->_list->getAtIndex(index, result);
} else if (attrib == "shuffle") {
- _list = _list->clone();
+ storage->_list = storage->_list->clone();
Common::RandomSource *rng = thread->getRuntime()->getRandom();
- size_t listSize = _list->getSize();
+ size_t listSize = storage->_list->getSize();
for (size_t i = 1; i < listSize; i++) {
size_t sourceIndex = i;
- size_t destIndex = rng->getRandomNumber(static_cast<uint>(listSize - 1 - i));
+ size_t destIndex = sourceIndex + rng->getRandomNumber(static_cast<uint>(listSize - 1 - i));
if (sourceIndex != destIndex) {
DynamicValue srcValue;
DynamicValue destValue;
- (void)_list->getAtIndex(sourceIndex, srcValue);
- (void)_list->getAtIndex(destIndex, destValue);
+ (void)storage->_list->getAtIndex(sourceIndex, srcValue);
+ (void)storage->_list->getAtIndex(destIndex, destValue);
- (void)_list->setAtIndex(destIndex, srcValue);
- (void)_list->setAtIndex(sourceIndex, destValue);
+ (void)storage->_list->setAtIndex(destIndex, srcValue);
+ (void)storage->_list->setAtIndex(sourceIndex, destValue);
}
}
@@ -2899,9 +2931,11 @@ bool ListVariableModifier::readAttribute(MiniscriptThread *thread, DynamicValue
}
bool ListVariableModifier::readAttributeIndexed(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib, const DynamicValue &index) {
+ ListVariableStorage *storage = static_cast<ListVariableStorage *>(_storage.get());
+
if (attrib == "value") {
size_t realIndex = 0;
- return _list->dynamicValueToIndex(realIndex, index) && _list->getAtIndex(realIndex, result);
+ return storage->_list->dynamicValueToIndex(realIndex, index) && storage->_list->getAtIndex(realIndex, result);
}
return Modifier::readAttributeIndexed(thread, result, attrib, index);
}
@@ -2916,13 +2950,15 @@ MiniscriptInstructionOutcome ListVariableModifier::writeRefAttribute(MiniscriptT
}
MiniscriptInstructionOutcome ListVariableModifier::writeRefAttributeIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib, const DynamicValue &index) {
+ ListVariableStorage *storage = static_cast<ListVariableStorage *>(_storage.get());
+
if (attrib == "value") {
size_t realIndex = 0;
- if (!_list->dynamicValueToIndex(realIndex, index))
+ if (!storage->_list->dynamicValueToIndex(realIndex, index))
return kMiniscriptInstructionOutcomeFailed;
- _list->createWriteProxyForIndex(realIndex, writeProxy);
- writeProxy.containerList = _list;
+ storage->_list->createWriteProxyForIndex(realIndex, writeProxy);
+ writeProxy.containerList = storage->_list;
return kMiniscriptInstructionOutcomeContinue;
}
return kMiniscriptInstructionOutcomeFailed;
@@ -2932,28 +2968,30 @@ MiniscriptInstructionOutcome ListVariableModifier::writeRefAttributeIndexed(Mini
void ListVariableModifier::debugInspect(IDebugInspectionReport *report) const {
VariableModifier::debugInspect(report);
- size_t listSize = _list->getSize();
+ ListVariableStorage *storage = static_cast<ListVariableStorage *>(_storage.get());
+
+ size_t listSize = storage->_list->getSize();
for (size_t i = 0; i < listSize; i++) {
int cardinal = i + 1;
- switch (_list->getType()) {
+ switch (storage->_list->getType()) {
case DynamicValueTypes::kInteger:
- report->declareLoose(Common::String::format("[%i] = %i", cardinal, _list->getInt()[i]));
+ report->declareLoose(Common::String::format("[%i] = %i", cardinal, storage->_list->getInt()[i]));
break;
case DynamicValueTypes::kFloat:
- report->declareLoose(Common::String::format("[%i] = %g", cardinal, _list->getFloat()[i]));
+ report->declareLoose(Common::String::format("[%i] = %g", cardinal, storage->_list->getFloat()[i]));
break;
case DynamicValueTypes::kPoint:
- report->declareLoose(Common::String::format("[%i] = ", cardinal) + pointToString(_list->getPoint()[i]));
+ report->declareLoose(Common::String::format("[%i] = ", cardinal) + pointToString(storage->_list->getPoint()[i]));
break;
case DynamicValueTypes::kIntegerRange:
- report->declareLoose(Common::String::format("[%i] = ", cardinal) + _list->getIntRange()[i].toString());
+ report->declareLoose(Common::String::format("[%i] = ", cardinal) + storage->_list->getIntRange()[i].toString());
break;
case DynamicValueTypes::kBoolean:
- report->declareLoose(Common::String::format("[%i] = %s", cardinal, _list->getBool()[i] ? "true" : "false"));
+ report->declareLoose(Common::String::format("[%i] = %s", cardinal, storage->_list->getBool()[i] ? "true" : "false"));
break;
case DynamicValueTypes::kVector:
- report->declareLoose(Common::String::format("[%i] = ", cardinal) + _list->getVector()[i].toString());
+ report->declareLoose(Common::String::format("[%i] = ", cardinal) + storage->_list->getVector()[i].toString());
break;
case DynamicValueTypes::kLabel:
report->declareLoose(Common::String::format("[%i] = Label?", cardinal));
@@ -2962,7 +3000,7 @@ void ListVariableModifier::debugInspect(IDebugInspectionReport *report) const {
report->declareLoose(Common::String::format("[%i] = Event?", cardinal));
break;
case DynamicValueTypes::kString:
- report->declareLoose(Common::String::format("[%i] = ", cardinal) + _list->getString()[i]);
+ report->declareLoose(Common::String::format("[%i] = ", cardinal) + storage->_list->getString()[i]);
break;
case DynamicValueTypes::kList:
report->declareLoose(Common::String::format("[%i] = List", cardinal));
@@ -2978,12 +3016,9 @@ void ListVariableModifier::debugInspect(IDebugInspectionReport *report) const {
}
#endif
-ListVariableModifier::ListVariableModifier(const ListVariableModifier &other) : VariableModifier(other), _preferredContentType(other._preferredContentType) {
- if (other._list)
- _list = other._list->clone();
-}
-
MiniscriptInstructionOutcome ListVariableModifier::scriptSetCount(MiniscriptThread *thread, const DynamicValue &value) {
+ ListVariableStorage *storage = static_cast<ListVariableStorage *>(_storage.get());
+
int32 asInteger = 0;
if (!value.roundToInt(asInteger)) {
thread->error("Tried to set a list variable count to something other than an integer");
@@ -2996,15 +3031,15 @@ MiniscriptInstructionOutcome ListVariableModifier::scriptSetCount(MiniscriptThre
}
size_t newSize = asInteger;
- if (newSize > _list->getSize()) {
- if (_list->getSize() == 0) {
+ if (newSize > storage->_list->getSize()) {
+ if (storage->_list->getSize() == 0) {
thread->error("Restoring an empty list by setting its count isn't implemented");
return kMiniscriptInstructionOutcomeFailed;
}
- _list->expandToMinimumSize(newSize);
- } else if (newSize < _list->getSize()) {
- _list->truncateToSize(newSize);
+ storage->_list->expandToMinimumSize(newSize);
+ } else if (newSize < storage->_list->getSize()) {
+ storage->_list->truncateToSize(newSize);
}
return kMiniscriptInstructionOutcomeContinue;
@@ -3018,21 +3053,35 @@ const char *ListVariableModifier::getDefaultName() const {
return "List Variable";
}
-ListVariableModifier::SaveLoad::SaveLoad(ListVariableModifier *modifier) : _modifier(modifier), _list(_modifier->_list) {
+ListVariableStorage::ListVariableStorage() : _preferredContentType(DynamicValueTypes::kInteger), _list(new DynamicList()) {
+}
+
+Common::SharedPtr<ModifierSaveLoad> ListVariableStorage::getSaveLoad() {
+ return Common::SharedPtr<ModifierSaveLoad>(new SaveLoad(this));
+}
+
+Common::SharedPtr<VariableStorage> ListVariableStorage::clone() const {
+ ListVariableStorage *newInstance = new ListVariableStorage();
+ newInstance->_list = Common::SharedPtr<DynamicList>(new DynamicList(*_list));
+ newInstance->_preferredContentType = _preferredContentType;
+ return Common::SharedPtr<VariableStorage>(newInstance);
+}
+
+ListVariableStorage::SaveLoad::SaveLoad(ListVariableStorage *storage) : _storage(storage), _list(storage->_list) {
}
-void ListVariableModifier::SaveLoad::commitLoad() const {
+void ListVariableStorage::SaveLoad::commitLoad() const {
// We don't support deserializing object references (yet?), so just leave the existing values.
// In Obsidian at least, this doesn't matter.
if (_list->getType() != DynamicValueTypes::kObject)
- _modifier->_list = _list;
+ _storage->_list = _list;
}
-void ListVariableModifier::SaveLoad::saveInternal(Common::WriteStream *stream) const {
+void ListVariableStorage::SaveLoad::saveInternal(Common::WriteStream *stream) const {
recursiveWriteList(_list.get(), stream);
}
-bool ListVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
+bool ListVariableStorage::SaveLoad::loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) {
Common::SharedPtr<DynamicList> list = recursiveReadList(stream);
if (list) {
_list = list;
@@ -3042,7 +3091,7 @@ bool ListVariableModifier::SaveLoad::loadInternal(Common::ReadStream *stream, ui
}
}
-void ListVariableModifier::SaveLoad::recursiveWriteList(DynamicList *list, Common::WriteStream *stream) {
+void ListVariableStorage::SaveLoad::recursiveWriteList(DynamicList *list, Common::WriteStream *stream) {
stream->writeUint32BE(list->getType());
stream->writeUint32BE(list->getSize());
@@ -3088,7 +3137,7 @@ void ListVariableModifier::SaveLoad::recursiveWriteList(DynamicList *list, Commo
}
}
-Common::SharedPtr<DynamicList> ListVariableModifier::SaveLoad::recursiveReadList(Common::ReadStream *stream) {
+Common::SharedPtr<DynamicList> ListVariableStorage::SaveLoad::recursiveReadList(Common::ReadStream *stream) {
Common::SharedPtr<DynamicList> list;
list.reset(new DynamicList());
diff --git a/engines/mtropolis/plugin/standard.h b/engines/mtropolis/plugin/standard.h
index dd12aa39927..31b2c9be5f3 100644
--- a/engines/mtropolis/plugin/standard.h
+++ b/engines/mtropolis/plugin/standard.h
@@ -175,14 +175,12 @@ public:
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::ObjectReferenceVariableModifier &data);
- Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+ bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
+ void varGetValue(DynamicValue &dest) const override;
bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
- bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
- void varGetValue(DynamicValue &dest) const override;
-
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Object Reference Variable Modifier"; }
SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
@@ -196,19 +194,6 @@ private:
static MiniscriptInstructionOutcome refAttribIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &proxy, void *objectRef, uintptr ptrOrOffset, const Common::String &attrib, const DynamicValue &index);
};
- class SaveLoad : public ModifierSaveLoad {
- public:
- explicit SaveLoad(ObjectReferenceVariableModifier *modifier);
-
- private:
- void commitLoad() const override;
- void saveInternal(Common::WriteStream *stream) const override;
- bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
-
- ObjectReferenceVariableModifier *_modifier;
- Common::String _objectPath;
- };
-
Common::SharedPtr<Modifier> shallowClone() const override;
const char *getDefaultName() const override;
@@ -225,10 +210,35 @@ private:
static RuntimeObject *getObjectParent(RuntimeObject *obj);
Event _setToSourceParentWhen;
+};
+
+class ObjectReferenceVariableStorage : public VariableStorage {
+public:
+ friend class ObjectReferenceVariableModifier;
+
+ ObjectReferenceVariableStorage();
+
+ Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
+
+ Common::SharedPtr<VariableStorage> clone() const override;
+
+private:
+ class SaveLoad : public ModifierSaveLoad {
+ public:
+ explicit SaveLoad(ObjectReferenceVariableStorage *storage);
+
+ private:
+ void commitLoad() const override;
+ void saveInternal(Common::WriteStream *stream) const override;
+ bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
+
+ ObjectReferenceVariableStorage *_storage;
+ Common::String _objectPath;
+ };
- mutable ObjectReference _object;
- Common::String _objectPath;
Common::String _fullPath;
+ Common::String _objectPath;
+ mutable ObjectReference _object;
};
class MidiModifier : public Modifier {
@@ -319,34 +329,20 @@ private:
MidiNotePlayer *_notePlayer;
};
-class ListVariableModifier : public VariableModifier {
+class ListVariableStorage : public VariableStorage {
public:
- ListVariableModifier();
+ friend class ListVariableModifier;
- bool load(const PlugInModifierLoaderContext &context, const Data::Standard::ListVariableModifier &data);
-
- bool isListVariable() const override;
+ ListVariableStorage();
Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override;
- bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
- void varGetValue(DynamicValue &dest) const override;
-
- bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
- bool readAttributeIndexed(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib, const DynamicValue &index) override;
- MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) override;
- MiniscriptInstructionOutcome writeRefAttributeIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib, const DynamicValue &index) override;
-
-#ifdef MTROPOLIS_DEBUG_ENABLE
- const char *debugGetTypeName() const override { return "List Variable Modifier"; }
- SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
- void debugInspect(IDebugInspectionReport *report) const override;
-#endif
+ Common::SharedPtr<VariableStorage> clone() const override;
private:
class SaveLoad : public ModifierSaveLoad {
public:
- explicit SaveLoad(ListVariableModifier *modifier);
+ explicit SaveLoad(ListVariableStorage *storage);
private:
void commitLoad() const override;
@@ -356,20 +352,41 @@ private:
static void recursiveWriteList(DynamicList *list, Common::WriteStream *stream);
static Common::SharedPtr<DynamicList> recursiveReadList(Common::ReadStream *stream);
- ListVariableModifier *_modifier;
+ ListVariableStorage *_storage;
Common::SharedPtr<DynamicList> _list;
};
- ListVariableModifier(const ListVariableModifier &other);
- ListVariableModifier &operator=(const ListVariableModifier &other);
+ Common::SharedPtr<DynamicList> _list;
+ DynamicValueTypes::DynamicValueType _preferredContentType;
+};
+class ListVariableModifier : public VariableModifier {
+public:
+ ListVariableModifier();
+
+ bool load(const PlugInModifierLoaderContext &context, const Data::Standard::ListVariableModifier &data);
+
+ bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
+ void varGetValue(DynamicValue &dest) const override;
+
+ bool isListVariable() const override;
+
+ bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
+ bool readAttributeIndexed(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib, const DynamicValue &index) override;
+ MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) override;
+ MiniscriptInstructionOutcome writeRefAttributeIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib, const DynamicValue &index) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+ const char *debugGetTypeName() const override { return "List Variable Modifier"; }
+ SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
+ void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
MiniscriptInstructionOutcome scriptSetCount(MiniscriptThread *thread, const DynamicValue &value);
Common::SharedPtr<Modifier> shallowClone() const override;
const char *getDefaultName() const override;
-
- Common::SharedPtr<DynamicList> _list;
- DynamicValueTypes::DynamicValueType _preferredContentType;
};
class SysInfoModifier : public Modifier {
diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index fa35a2428f2..2c2e73a8b6a 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -2677,6 +2677,9 @@ bool WorldManagerInterface::readAttribute(MiniscriptThread *thread, DynamicValue
} else if (attrib == "postponeredraws") {
result.setBool(_postponeRedraws);
return true;
+ } else if (attrib == "clickcount") {
+ result.setInt(thread->getRuntime()->getMultiClickCount());
+ return true;
}
return RuntimeObject::readAttribute(thread, result, attrib);
@@ -4169,7 +4172,8 @@ Runtime::Runtime(OSystem *system, Audio::Mixer *mixer, ISaveUIProvider *saveProv
_cachedMousePosition(Common::Point(0, 0)), _realMousePosition(Common::Point(0, 0)), _trackedMouseOutside(false),
_forceCursorRefreshOnce(true), _autoResetCursor(false), _haveModifierOverrideCursor(false), _sceneGraphChanged(false), _isQuitting(false),
_collisionCheckTime(0), _defaultVolumeState(true), _activeSceneTransitionEffect(nullptr), _sceneTransitionStartTime(0), _sceneTransitionEndTime(0),
- _sharedSceneWasSetExplicitly(false), _modifierOverrideCursorID(0), _subtitleRenderer(subRenderer) {
+ _sharedSceneWasSetExplicitly(false), _modifierOverrideCursorID(0), _subtitleRenderer(subRenderer), _multiClickStartTime(0), _multiClickInterval(500), _multiClickCount(0)
+{
_random.reset(new Common::RandomSource("mtropolis"));
_vthread.reset(new VThread());
@@ -4273,6 +4277,14 @@ bool Runtime::runFrame() {
case kOSEventTypeMouseMove: {
MouseInputEvent *mouseEvt = static_cast<MouseInputEvent *>(evt.get());
+ if (evtType == kOSEventTypeMouseDown) {
+ if (_multiClickStartTime + _multiClickInterval >= _playTime) {
+ _multiClickStartTime = _playTime;
+ _multiClickCount = 1;
+ } else
+ _multiClickCount++;
+ }
+
// Maybe shouldn't post the update mouse button task if non-left buttons are pressed?
if ((evtType == kOSEventTypeMouseDown || evtType == kOSEventTypeMouseUp) && mouseEvt->getButton() == Actions::kMouseButtonLeft) {
UpdateMouseStateTaskData *taskData = _vthread->pushTask("Runtime::updateMouseStateTask", this, &Runtime::updateMouseStateTask);
@@ -5688,18 +5700,22 @@ void Runtime::instantiateIfAlias(Common::SharedPtr<Modifier> &modifier, const Co
error("Failed to resolve alias");
}
- if (!modifier->isVariable()) {
- Common::SharedPtr<Modifier> clonedModifier = templateModifier->shallowClone();
- clonedModifier->setSelfReference(clonedModifier);
- clonedModifier->setRuntimeGUID(allocateRuntimeGUID());
+ Common::SharedPtr<Modifier> clonedModifier = templateModifier->shallowClone();
+ clonedModifier->setSelfReference(clonedModifier);
+ clonedModifier->setRuntimeGUID(allocateRuntimeGUID());
- clonedModifier->setName(modifier->getName());
+ clonedModifier->setName(modifier->getName());
- modifier = clonedModifier;
- clonedModifier->setParent(relinkParent);
+ modifier = clonedModifier;
+ clonedModifier->setParent(relinkParent);
- ModifierChildCloner cloner(this, clonedModifier);
- clonedModifier->visitInternalReferences(&cloner);
+ ModifierChildCloner cloner(this, clonedModifier);
+ clonedModifier->visitInternalReferences(&cloner);
+
+ // Aliased variables use the same variable storage, but are treated as distinct objects.
+ if (clonedModifier->isVariable()) {
+ assert(templateModifier->isVariable());
+ static_cast<VariableModifier *>(clonedModifier.get())->setStorage(static_cast<const VariableModifier *>(templateModifier.get())->getStorage());
}
}
}
@@ -5830,6 +5846,10 @@ void Runtime::setAutoResetCursor(bool enabled) {
_autoResetCursor = enabled;
}
+uint Runtime::getMultiClickCount() const {
+ return _multiClickCount;
+}
+
bool Runtime::isAwaitingSceneTransition() const {
return _sceneTransitionState != kSceneTransitionStateNotTransitioning;
}
@@ -6899,6 +6919,15 @@ Common::SharedPtr<Modifier> Project::resolveAlias(uint32 aliasID) const {
return _globalModifiers.getModifiers()[aliasID - 1];
}
+Common::SharedPtr<Modifier> Project::findGlobalVarWithName(const Common::String &name) const {
+ for (const Common::SharedPtr<Modifier> &modifier : _globalModifiers.getModifiers()) {
+ if (modifier && modifier->isVariable() && MTropolis::caseInsensitiveEqual(name, modifier->getName()))
+ return modifier;
+ }
+
+ return nullptr;
+}
+
void Project::materializeGlobalVariables(Runtime *runtime, ObjectLinkingScope *outerScope) {
for (Common::Array<Common::SharedPtr<Modifier> >::const_iterator it = _globalModifiers.getModifiers().begin(), itEnd = _globalModifiers.getModifiers().end(); it != itEnd; ++it) {
Modifier *modifier = it->get();
@@ -8660,6 +8689,15 @@ void Modifier::debugInspect(IDebugInspectionReport *report) const {
#endif /* MTROPOLIS_DEBUG_ENABLE */
+VariableStorage::~VariableStorage() {
+}
+
+VariableModifier::VariableModifier(const Common::SharedPtr<VariableStorage> &storage) : _storage(storage) {
+}
+
+VariableModifier::VariableModifier(const VariableModifier &other) : Modifier(other), _storage(other._storage->clone()) {
+}
+
bool VariableModifier::isVariable() const {
return true;
}
@@ -8668,6 +8706,19 @@ bool VariableModifier::isListVariable() const {
return false;
}
+
+Common::SharedPtr<ModifierSaveLoad> VariableModifier::getSaveLoad() {
+ return _storage->getSaveLoad();
+}
+
+const Common::SharedPtr<VariableStorage> &VariableModifier::getStorage() const {
+ return _storage;
+}
+
+void VariableModifier::setStorage(const Common::SharedPtr<VariableStorage> &storage) {
+ _storage = storage;
+}
+
bool VariableModifier::readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) {
if (attrib == "value") {
varGetValue(result);
diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h
index 355a4526090..72f61db8ae5 100644
--- a/engines/mtropolis/runtime.h
+++ b/engines/mtropolis/runtime.h
@@ -1648,6 +1648,8 @@ public:
void forceCursorRefreshOnce();
void setAutoResetCursor(bool enabled);
+ uint getMultiClickCount() const;
+
bool isAwaitingSceneTransition() const;
Common::RandomSource *getRandom() const;
@@ -1922,6 +1924,10 @@ private:
uint32 _modifierOverrideCursorID;
bool _haveModifierOverrideCursor;
+ uint32 _multiClickStartTime;
+ uint32 _multiClickInterval;
+ uint _multiClickCount;
+
bool _defaultVolumeState;
// True if any elements were added to the scene, removed from the scene, or reparented since last draw
@@ -2348,6 +2354,7 @@ public:
void loadSceneFromStream(const Common::SharedPtr<Structural> &structural, uint32 streamID, const Hacks &hacks);
Common::SharedPtr<Modifier> resolveAlias(uint32 aliasID) const;
+ Common::SharedPtr<Modifier> findGlobalVarWithName(const Common::String &name) const;
void materializeGlobalVariables(Runtime *runtime, ObjectLinkingScope *scope);
const ProjectPresentationSettings &getPresentationSettings() const;
@@ -2895,14 +2902,29 @@ protected:
Common::SharedPtr<ModifierHooks> _hooks;
};
+class VariableStorage {
+public:
+ virtual ~VariableStorage();
+ virtual Common::SharedPtr<ModifierSaveLoad> getSaveLoad() = 0;
+
+ virtual Common::SharedPtr<VariableStorage> clone() const = 0;
+};
+
class VariableModifier : public Modifier {
public:
+ explicit VariableModifier(const Common::SharedPtr<VariableStorage> &storage);
+ VariableModifier(const VariableModifier &other);
+
virtual bool isVariable() const override;
virtual bool isListVariable() const;
+ virtual Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override final;
+
+ const Common::SharedPtr<VariableStorage> &getStorage() const;
+ void setStorage(const Common::SharedPtr<VariableStorage> &storage);
+
virtual bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) = 0;
virtual void varGetValue(DynamicValue &dest) const = 0;
- virtual Common::SharedPtr<ModifierSaveLoad> getSaveLoad() override = 0;
bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
@@ -2911,11 +2933,16 @@ public:
virtual DynamicValueWriteProxy createWriteProxy();
private:
+ VariableModifier() = delete;
+
struct WriteProxyInterface {
static MiniscriptInstructionOutcome write(MiniscriptThread *thread, const DynamicValue &dest, void *objectRef, uintptr ptrOrOffset);
static MiniscriptInstructionOutcome refAttrib(MiniscriptThread *thread, DynamicValueWriteProxy &proxy, void *objectRef, uintptr ptrOrOffset, const Common::String &attrib);
static MiniscriptInstructionOutcome refAttribIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &proxy, void *objectRef, uintptr ptrOrOffset, const Common::String &attrib, const DynamicValue &index);
};
+
+protected:
+ Common::SharedPtr<VariableStorage> _storage;
};
enum AssetType {
More information about the Scummvm-git-logs
mailing list