diff --git a/binding-sandbox/sandbox-serial-util.cpp b/binding-sandbox/sandbox-serial-util.cpp index d07e8647..a2e164ba 100644 --- a/binding-sandbox/sandbox-serial-util.cpp +++ b/binding-sandbox/sandbox-serial-util.cpp @@ -515,12 +515,40 @@ template <> bool mkxp_sandbox::sandbox_serialize(const Transform &value, void *& } template <> bool mkxp_sandbox::sandbox_deserialize(Transform &value, const void *&data, wasm_size_t &max_size) { - if (!sandbox_deserialize(value.getPosition(), data, max_size)) return false; - if (!sandbox_deserialize(value.getOrigin(), data, max_size)) return false; - if (!sandbox_deserialize(value.getScale(), data, max_size)) return false; - if (!sandbox_deserialize(value.getGlobalOffset(), data, max_size)) return false; - float rotation; - if (!sandbox_deserialize(rotation, data, max_size)) return false; - value.setRotation(rotation); + { + Vec2 position; + if (!sandbox_deserialize(position, data, max_size)) return false; + if (position != value.getPosition()) { + value.setPosition(position); + } + } + { + Vec2 origin; + if (!sandbox_deserialize(origin, data, max_size)) return false; + if (origin != value.getOrigin()) { + value.setOrigin(origin); + } + } + { + Vec2 scale; + if (!sandbox_deserialize(scale, data, max_size)) return false; + if (scale != value.getScale()) { + value.setScale(scale); + } + } + { + Vec2i offset; + if (!sandbox_deserialize(offset, data, max_size)) return false; + if (offset != value.getGlobalOffset()) { + value.setGlobalOffset(offset); + } + } + { + float rotation; + if (!sandbox_deserialize(rotation, data, max_size)) return false; + if (rotation != value.getRotation()) { + value.setRotation(rotation); + } + } return true; } diff --git a/src/display/gl/scene.cpp b/src/display/gl/scene.cpp index 34087467..483f2203 100644 --- a/src/display/gl/scene.cpp +++ b/src/display/gl/scene.cpp @@ -110,11 +110,11 @@ void Scene::composite(Exception &exception) SceneElement::SceneElement(Scene &scene, int z, int spriteY) - : link(this), + : scene(&scene), + link(this), creationStamp(shState->genTimeStamp()), z(z), visible(true), - scene(&scene), spriteY(spriteY) { scene.insert(*this); @@ -220,10 +220,27 @@ bool SceneElement::sandbox_serialize_scene_element(void *&data, mkxp_sandbox::wa bool SceneElement::sandbox_deserialize_scene_element(const void *&data, mkxp_sandbox::wasm_size_t &max_size) { - if (!mkxp_sandbox::sandbox_deserialize(creationStamp, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize((int32_t &)z, data, max_size)) return false; + { + uint64_t value = creationStamp; + if (!mkxp_sandbox::sandbox_deserialize(creationStamp, data, max_size)) return false; + if (creationStamp != value) { + deserModified = true; + } + } + { + int32_t value = (int32_t)z; + if (!mkxp_sandbox::sandbox_deserialize((int32_t &)z, data, max_size)) return false; + if (z != value) { + deserModified = true; + } + } if (!mkxp_sandbox::sandbox_deserialize(visible, data, max_size)) return false; return true; } + +void SceneElement::sandbox_deserialize_begin_scene_element() +{ + deserModified = false; +} #endif // MKXPZ_REROO diff --git a/src/display/gl/scene.h b/src/display/gl/scene.h index 175dda60..1ed3834d 100644 --- a/src/display/gl/scene.h +++ b/src/display/gl/scene.h @@ -75,10 +75,11 @@ public: const Geometry &getGeometry() const { return geometry; } + void reinsert(SceneElement &element); + protected: void insert(SceneElement &element); void insertAfter(SceneElement &element, SceneElement &after); - void reinsert(SceneElement &element); /* Notify all elements that geometry has changed */ void notifyGeometryChange(); @@ -108,8 +109,14 @@ public: #ifdef MKXPZ_RETRO bool sandbox_serialize_scene_element(void *&data, mkxp_sandbox::wasm_size_t &max_size) const; bool sandbox_deserialize_scene_element(const void *&data, mkxp_sandbox::wasm_size_t &max_size); + void sandbox_deserialize_begin_scene_element(); #endif // MKXPZ_REROO + Scene *scene; +#ifdef MKXPZ_RETRO + bool deserModified; +#endif // MKXPZ_RETRO + protected: /* A bit about OpenGL state: * @@ -145,7 +152,6 @@ protected: uint64_t creationStamp; int z; bool visible; - Scene *scene; friend class Scene; friend class Viewport; diff --git a/src/display/gl/transform.h b/src/display/gl/transform.h index f0ba0de2..6b64783c 100644 --- a/src/display/gl/transform.h +++ b/src/display/gl/transform.h @@ -66,10 +66,6 @@ public: matrix[15] = 1; } - Vec2 &getPosition() { return position; } - Vec2 &getOrigin() { return origin; } - Vec2 &getScale() { return scale; } - Vec2i &getGlobalOffset() { return offset; } const Vec2 &getPosition() const { return position; } const Vec2 &getOrigin() const { return origin; } const Vec2 &getScale() const { return scale; } diff --git a/src/display/plane.cpp b/src/display/plane.cpp index fa2b3e10..7a4e04f4 100644 --- a/src/display/plane.cpp +++ b/src/display/plane.cpp @@ -360,7 +360,6 @@ bool Plane::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) if (!mkxp_sandbox::sandbox_serialize(p->zoomX, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->zoomY, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->sceneGeo, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_serialize(p->qArray, data, max_size)) return false; if (!sandbox_serialize_viewport_element(data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->bitmap, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->color, data, max_size)) return false; @@ -408,7 +407,6 @@ bool Plane::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &ma p->quadSourceDirty = true; } } - if (!mkxp_sandbox::sandbox_deserialize(p->qArray, data, max_size)) return false; if (!sandbox_deserialize_viewport_element(data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->bitmap, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->color, data, max_size)) return false; @@ -437,5 +435,10 @@ void Plane::sandbox_deserialize_end() p->bitmapDisposal(); } } + + if (isDisposed()) return; + if (deserModified) { + scene->reinsert(*this); + } } #endif // MKXPZ_RETRO diff --git a/src/display/sprite.cpp b/src/display/sprite.cpp index 155e9483..4d5f21a9 100644 --- a/src/display/sprite.cpp +++ b/src/display/sprite.cpp @@ -62,7 +62,11 @@ struct SpritePrivate Rect *srcRect; sigslot::connection srcRectCon; #ifdef MKXPZ_RETRO + uint64_t deserSavedBitmapId; Rect deserSavedSrcRect; + bool deserMirrorChanged; + bool deserYChanged; + bool deserBushDepthChanged; #endif // MKXPZ_RETRO bool mirrored; @@ -862,11 +866,9 @@ void Sprite::releaseResources() #ifdef MKXPZ_RETRO bool Sprite::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const { - if (!mkxp_sandbox::sandbox_serialize(p->quad, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->trans, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->mirrored, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize((int32_t)p->bushDepth, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_serialize(p->efBushDepth, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->bushOpacity, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->opacity, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->blendType, data, max_size)) return false; @@ -884,7 +886,6 @@ bool Sprite::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) if (!mkxp_sandbox::sandbox_serialize((int32_t)p->wave.length, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize((int32_t)p->wave.speed, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->wave.phase, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_serialize(p->wave.qArray, data, max_size)) return false; if (!sandbox_serialize_viewport_element(data, max_size)) return false; @@ -899,11 +900,37 @@ bool Sprite::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) bool Sprite::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size) { - if (!mkxp_sandbox::sandbox_deserialize(p->quad, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize(p->trans, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize(p->mirrored, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->bushDepth, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize(p->efBushDepth, data, max_size)) return false; + { + float old_y = p->trans.getPosition().y; + float old_zoom_y = p->trans.getScale().y; + if (!mkxp_sandbox::sandbox_deserialize(p->trans, data, max_size)) return false; + if (p->trans.getPosition().y != old_y) { + p->deserYChanged = true; + if (rgssVer >= 2) { + p->wave.dirty = true; + } + } + if (p->trans.getScale().y != old_zoom_y) { + p->deserBushDepthChanged = true; + if (rgssVer >= 2) { + p->wave.dirty = true; + } + } + } + { + bool value = p->mirrored; + if (!mkxp_sandbox::sandbox_deserialize(p->mirrored, data, max_size)) return false; + if (p->mirrored != value) { + p->deserMirrorChanged = true; + } + } + { + int32_t value = (int32_t)p->bushDepth; + if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->bushDepth, data, max_size)) return false; + if ((int32_t)p->bushDepth != value) { + p->deserBushDepthChanged = true; + } + } if (!mkxp_sandbox::sandbox_deserialize(p->bushOpacity, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->opacity, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->blendType, data, max_size)) return false; @@ -917,11 +944,34 @@ bool Sprite::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &m if (!mkxp_sandbox::sandbox_deserialize(p->sceneOrig, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->isVisible, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->wave.amp, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->wave.length, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->wave.speed, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize(p->wave.phase, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize(p->wave.qArray, data, max_size)) return false; + { + int32_t value = (int32_t)p->wave.amp; + if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->wave.amp, data, max_size)) return false; + if ((int32_t)p->wave.amp != value) { + p->wave.dirty = true; + } + } + { + int32_t value = (int32_t)p->wave.length; + if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->wave.length, data, max_size)) return false; + if ((int32_t)p->wave.length != value) { + p->wave.dirty = true; + } + } + { + int32_t value = (int32_t)p->wave.speed; + if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->wave.speed, data, max_size)) return false; + if ((int32_t)p->wave.speed != value) { + p->wave.dirty = true; + } + } + { + float value = p->wave.phase; + if (!mkxp_sandbox::sandbox_deserialize(p->wave.phase, data, max_size)) return false; + if (p->wave.phase != value) { + p->wave.dirty = true; + } + } if (!sandbox_deserialize_viewport_element(data, max_size)) return false; @@ -942,12 +992,18 @@ void Sprite::sandbox_deserialize_begin() p->bitmapDispCon.disconnect(); + p->deserSavedBitmapId = p->bitmap == nullptr ? 0 : p->bitmap->id; + p->srcRectCon.disconnect(); if (p->srcRect != nullptr) { p->deserSavedSrcRect = *p->srcRect; } else { p->deserSavedSrcRect.set(0, 0, 0, 0); } + + p->deserMirrorChanged = false; + + p->deserBushDepthChanged = false; } void Sprite::sandbox_deserialize_end() @@ -962,6 +1018,11 @@ void Sprite::sandbox_deserialize_end() } } + if (isDisposed()) return; + if (p->bitmap != nullptr && (p->bitmap->deserModified || p->bitmap->id != p->deserSavedBitmapId)) { + p->wave.dirty = true; + } + if (isDisposed()) return; if (p->srcRect != nullptr) { p->srcRectCon = p->srcRect->valueChanged.connect(&SpritePrivate::onSrcRectChange, p); @@ -969,5 +1030,25 @@ void Sprite::sandbox_deserialize_end() p->onSrcRectChange(); } } + + if (isDisposed()) return; + if (p->deserMirrorChanged) { + p->onSrcRectChange(); + } + + if (isDisposed()) return; + if (p->deserYChanged && rgssVer >= 2) { + setSpriteY(p->trans.getPositionI().y); + } + + if (isDisposed()) return; + if (p->deserBushDepthChanged) { + p->recomputeBushDepth(); + } + + if (isDisposed()) return; + if (deserModified) { + scene->reinsert(*this); + } } #endif // MKXPZ_RETRO diff --git a/src/display/tilemap-common.h b/src/display/tilemap-common.h index f4b4890a..ec2cbbbd 100644 --- a/src/display/tilemap-common.h +++ b/src/display/tilemap-common.h @@ -196,12 +196,12 @@ struct FlashMap GLMeta::vaoUnbind(vao); } -private: void setDirty() { dirty = true; } +private: size_t quadCount() const { return vertices.size() / 4; diff --git a/src/display/tilemap.cpp b/src/display/tilemap.cpp index 48c10475..d59e1af3 100644 --- a/src/display/tilemap.cpp +++ b/src/display/tilemap.cpp @@ -343,6 +343,7 @@ struct TilemapPrivate sigslot::connection prioritiesCon; #ifdef MKXPZ_RETRO uint64_t deserSavedPrioritiesId; + uint64_t deserSavedDataId; #endif // MKXPZ_RETRO /* Dispose watches */ @@ -1639,6 +1640,8 @@ void Tilemap::sandbox_deserialize_begin() p->prioritiesCon.disconnect(); p->deserSavedPrioritiesId = p->priorities == nullptr ? 0 : p->priorities->id; + + p->deserSavedDataId = p->flashMap.getData() == nullptr ? 0 : p->flashMap.getData()->id; } void Tilemap::sandbox_deserialize_end() @@ -1670,9 +1673,9 @@ void Tilemap::sandbox_deserialize_end() } if (isDisposed()) return; - if (p->tileset != nullptr) { + if (p->tileset != nullptr && !p->tileset->isDisposed()) { p->tilesetCon = p->tileset->modified.connect(&TilemapPrivate::invalidateAtlasSize, p); - if (p->tileset->deserModified) { + if (p->tileset->deserModified || p->tileset->id != p->deserSavedTilesetId) { p->invalidateAtlasSize(); } } @@ -1704,8 +1707,18 @@ void Tilemap::sandbox_deserialize_end() } if (isDisposed()) return; - if (p->tileset->deserModified) { - p->invalidateAtlasSize(); + if (p->flashMap.getData() != nullptr && (p->flashMap.getData()->deserModified || p->flashMap.getData()->id != p->deserSavedDataId)) { + p->flashMap.setDirty(); + } + + if (isDisposed()) return; + if (p->elem.ground->deserModified) { + p->elem.ground->scene->reinsert(*p->elem.ground); + } + for (size_t i = 0; i < zlayersMax; ++i) { + if (p->elem.zlayers[i]->deserModified) { + p->elem.zlayers[i]->scene->reinsert(*p->elem.zlayers[i]); + } } } #endif // MKXPZ_RETRO diff --git a/src/display/tilemapvx.cpp b/src/display/tilemapvx.cpp index cc5e44b0..dc73649f 100644 --- a/src/display/tilemapvx.cpp +++ b/src/display/tilemapvx.cpp @@ -105,6 +105,7 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader sigslot::connection flagsCon; #ifdef MKXPZ_RETRO uint64_t deserSavedFlagsId; + uint64_t deserSavedDataId; #endif // MKXPZ_RETRO sigslot::connection prepareCon; @@ -679,6 +680,7 @@ bool TilemapVX::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t Scene::Geometry old_geo = p->sceneGeo; if (!mkxp_sandbox::sandbox_deserialize(p->sceneGeo, data, max_size)) return false; if (p->sceneGeo != old_geo) { + p->buffersDirty = true; p->mapViewportDirty = true; } } @@ -736,6 +738,8 @@ void TilemapVX::sandbox_deserialize_begin() p->flagsCon.disconnect(); p->deserSavedFlagsId = p->flags == nullptr ? 0 : p->flags->id; + + p->deserSavedDataId = p->flashMap.getData() == nullptr ? 0 : p->flashMap.getData()->id; } void TilemapVX::sandbox_deserialize_end() @@ -781,5 +785,18 @@ void TilemapVX::sandbox_deserialize_end() p->invalidateBuffers(); } } + + if (isDisposed()) return; + if (p->flashMap.getData() != nullptr && (p->flashMap.getData()->deserModified || p->flashMap.getData()->id != p->deserSavedDataId)) { + p->flashMap.setDirty(); + } + + if (isDisposed()) return; + if (p->above.deserModified) { + p->above.scene->reinsert(p->above); + } + if (p->deserModified) { + p->scene->reinsert(*p); + } } #endif // MKXPZ_RETRO diff --git a/src/display/viewport.cpp b/src/display/viewport.cpp index 1b2a7883..aed1f15a 100644 --- a/src/display/viewport.cpp +++ b/src/display/viewport.cpp @@ -259,6 +259,8 @@ bool Viewport::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t void Viewport::sandbox_deserialize_begin() { + sandbox_deserialize_begin_scene_element(); + if (isDisposed()) return; p->rectCon.disconnect(); @@ -278,6 +280,11 @@ void Viewport::sandbox_deserialize_end() p->onRectChange(); } } + + if (isDisposed()) return; + if (deserModified) { + scene->reinsert(*this); + } } #endif // MXKPZ_RETRO @@ -339,6 +346,8 @@ bool ViewportElement::sandbox_deserialize_viewport_element(const void *&data, mk void ViewportElement::sandbox_deserialize_begin_viewport_element() { + sandbox_deserialize_begin_scene_element(); + viewportDispCon.disconnect(); } diff --git a/src/display/window.cpp b/src/display/window.cpp index 3f9cfc2b..45eb50fd 100644 --- a/src/display/window.cpp +++ b/src/display/window.cpp @@ -1087,5 +1087,10 @@ void Window::sandbox_deserialize_end() p->markControlVertDirty(); } } + + if (isDisposed()) return; + if (deserModified) { + scene->reinsert(*this); + } } #endif // MKXPZ_RETRO diff --git a/src/display/windowvx.cpp b/src/display/windowvx.cpp index 8f23ad5d..1062fc3c 100644 --- a/src/display/windowvx.cpp +++ b/src/display/windowvx.cpp @@ -1353,5 +1353,10 @@ void WindowVX::sandbox_deserialize_end() p->invalidateBaseTex(); } } + + if (isDisposed()) return; + if (deserModified) { + scene->reinsert(*this); + } } #endif // MKXPZ_RETRO