MTROPOLIS: Add list delete attribute, fix mToon range set by label being off by 1, should fix the key plank in MTI Benbow.

This commit is contained in:
elasota 2022-12-30 16:38:17 -05:00
parent a73e8b3d1c
commit 0e6cccb2c2
4 changed files with 113 additions and 8 deletions

View File

@ -1566,8 +1566,10 @@ MiniscriptInstructionOutcome MToonElement::scriptSetRange(MiniscriptThread *thre
}
for (const MToonMetadata::FrameRangeDef &frameRange : _metadata->frameRanges) {
if (caseInsensitiveEqual(frameRange.name, *nameStrPtr))
return scriptSetRangeTyped(thread, IntRange(frameRange.startFrame, frameRange.endFrame));
if (caseInsensitiveEqual(frameRange.name, *nameStrPtr)) {
// Frame ranges in the metadata are 0-based, but setting the range is 1-based, so add 1
return scriptSetRangeTyped(thread, IntRange(frameRange.startFrame + 1, frameRange.endFrame + 1));
}
}
thread->error("mToon range was assigned to a label but the label doesn't exist in the mToon data");

View File

@ -2936,7 +2936,19 @@ bool ListVariableModifier::readAttributeIndexed(MiniscriptThread *thread, Dynami
if (attrib == "value") {
size_t realIndex = 0;
return storage->_list->dynamicValueToIndex(realIndex, index) && storage->_list->getAtIndex(realIndex, result);
} else if (attrib == "delete") {
size_t realIndex = 0;
if (!storage->_list->dynamicValueToIndex(realIndex, index))
return false;
if (!storage->_list->getAtIndex(realIndex, result))
return false;
storage->_list = storage->_list->clone();
storage->_list->deleteAtIndex(realIndex);
return true;
}
return Modifier::readAttributeIndexed(thread, result, attrib, index);
}

View File

@ -847,6 +847,21 @@ bool DynamicList::setAtIndex(size_t index, const DynamicValue &value) {
}
}
void DynamicList::deleteAtIndex(size_t index) {
if (_container != nullptr) {
size_t size = _container->getSize();
if (size < _container->getSize()) {
for (size_t i = index + 1; i < size; i++) {
DynamicValue valueToMove;
_container->getAtIndex(i, valueToMove);
_container->setAtIndex(i - 1, valueToMove);
}
_container->truncateToSize(size - 1);
}
}
}
void DynamicList::truncateToSize(size_t sz) {
if (sz == 0)
clear();
@ -7955,7 +7970,7 @@ VThreadState VisualElement::consumeCommand(Runtime *runtime, const Common::Share
bool VisualElement::respondsToEvent(const Event &evt) const {
if (Event(EventIDs::kAuthorMessage, 13).respondsTo(evt)) {
if (getRuntime()->getHacks().mtiSceneReturnHack)
if (getRuntime()->getHacks().mtiSceneReturnHack && getParent() && getParent()->isSubsection())
return true;
}
@ -7965,11 +7980,11 @@ bool VisualElement::respondsToEvent(const Event &evt) const {
VThreadState VisualElement::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
if (Event(EventIDs::kAuthorMessage, 13).respondsTo(msg->getEvent())) {
if (getRuntime()->getHacks().mtiSceneReturnHack) {
assert(this->getParent());
assert(this->getParent()->isSubsection());
runtime->addSceneStateTransition(HighLevelSceneTransition(this->getSelfReference().lock().staticCast<Structural>(), HighLevelSceneTransition::kTypeChangeToScene, false, false));
if (getParent() && getParent()->isSubsection()) {
runtime->addSceneStateTransition(HighLevelSceneTransition(this->getSelfReference().lock().staticCast<Structural>(), HighLevelSceneTransition::kTypeChangeToScene, false, false));
return kVThreadReturn;
return kVThreadReturn;
}
}
}
@ -8673,10 +8688,23 @@ bool Modifier::readAttribute(MiniscriptThread *thread, DynamicValue &result, con
Structural *owner = findStructuralOwner();
result.setObject(owner ? owner->getSelfReference() : Common::WeakPtr<RuntimeObject>());
return true;
} else if (attrib == "previous") {
Modifier *sibling = findPrevSibling();
if (sibling)
result.setObject(sibling->getSelfReference());
else
result.clear();
return true;
} else if (attrib == "next") {
Modifier *sibling = findNextSibling();
if (sibling)
result.setObject(sibling->getSelfReference());
else
result.clear();
return true;
}
return false;
}
MiniscriptInstructionOutcome Modifier::writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) {
@ -8749,6 +8777,65 @@ void Modifier::setParent(const Common::WeakPtr<RuntimeObject> &parent) {
_parent = parent;
}
Modifier *Modifier::findNextSibling() const {
RuntimeObject *parent = getParent().lock().get();
if (parent) {
IModifierContainer *container = nullptr;
if (parent->isModifier())
container = static_cast<Modifier *>(parent)->getChildContainer();
else if (parent->isStructural())
container = static_cast<Structural *>(parent);
if (container)
{
const Common::Array<Common::SharedPtr<Modifier> > &neighborhood = container->getModifiers();
bool found = false;
size_t foundIndex = 0;
for (size_t i = 0; i < neighborhood.size(); i++) {
if (neighborhood[i].get() == this) {
foundIndex = i;
found = true;
break;
}
}
if (found && foundIndex < neighborhood.size() - 1)
return neighborhood[foundIndex + 1].get();
}
}
return nullptr;
}
Modifier *Modifier::findPrevSibling() const {
RuntimeObject *parent = getParent().lock().get();
if (parent) {
IModifierContainer *container = nullptr;
if (parent->isModifier())
container = static_cast<Modifier *>(parent)->getChildContainer();
else if (parent->isStructural())
container = static_cast<Structural *>(parent);
if (container) {
const Common::Array<Common::SharedPtr<Modifier> > &neighborhood = container->getModifiers();
bool found = false;
size_t foundIndex = 0;
for (size_t i = 0; i < neighborhood.size(); i++) {
if (neighborhood[i].get() == this) {
foundIndex = i;
found = true;
break;
}
}
if (found && foundIndex > 0)
return neighborhood[foundIndex - 1].get();
}
}
return nullptr;
}
bool Modifier::respondsToEvent(const Event &evt) const {
return false;
}

View File

@ -777,6 +777,7 @@ struct DynamicList {
bool getAtIndex(size_t index, DynamicValue &value) const;
bool setAtIndex(size_t index, const DynamicValue &value);
void deleteAtIndex(size_t index);
void truncateToSize(size_t sz);
void expandToMinimumSize(size_t sz);
size_t getSize() const;
@ -2870,6 +2871,9 @@ public:
const Common::WeakPtr<RuntimeObject> &getParent() const;
void setParent(const Common::WeakPtr<RuntimeObject> &parent);
Modifier *findNextSibling() const;
Modifier *findPrevSibling() const;
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;