Handle viewport changes when deserializing save states in libretro builds

This commit is contained in:
刘皓 2025-05-30 18:44:21 -04:00
parent 4202d94b79
commit 755565d3d6
No known key found for this signature in database
GPG key ID: 7901753DB465B711
10 changed files with 66 additions and 19 deletions

View file

@ -224,14 +224,14 @@ bool SceneElement::sandbox_deserialize_scene_element(const void *&data, mkxp_san
uint64_t value = creationStamp;
if (!mkxp_sandbox::sandbox_deserialize(creationStamp, data, max_size)) return false;
if (creationStamp != value) {
deserModified = true;
deserSceneElementModified = 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;
deserSceneElementModified = true;
}
}
if (!mkxp_sandbox::sandbox_deserialize(visible, data, max_size)) return false;
@ -241,6 +241,6 @@ bool SceneElement::sandbox_deserialize_scene_element(const void *&data, mkxp_san
void SceneElement::sandbox_deserialize_begin_scene_element()
{
deserModified = false;
deserSceneElementModified = false;
}
#endif // MKXPZ_REROO

View file

@ -114,7 +114,7 @@ public:
Scene *scene;
#ifdef MKXPZ_RETRO
bool deserModified;
bool deserSceneElementModified;
#endif // MKXPZ_RETRO
protected:

View file

@ -437,7 +437,7 @@ void Plane::sandbox_deserialize_end()
}
if (isDisposed()) return;
if (deserModified) {
if (deserSceneElementModified) {
scene->reinsert(*this);
}
}

View file

@ -1047,7 +1047,7 @@ void Sprite::sandbox_deserialize_end()
}
if (isDisposed()) return;
if (deserModified) {
if (deserSceneElementModified) {
scene->reinsert(*this);
}
}

View file

@ -1712,11 +1712,11 @@ void Tilemap::sandbox_deserialize_end()
}
if (isDisposed()) return;
if (p->elem.ground->deserModified) {
if (p->elem.ground->deserSceneElementModified) {
p->elem.ground->scene->reinsert(*p->elem.ground);
}
for (size_t i = 0; i < zlayersMax; ++i) {
if (p->elem.zlayers[i]->deserModified) {
if (p->elem.zlayers[i]->deserSceneElementModified) {
p->elem.zlayers[i]->scene->reinsert(*p->elem.zlayers[i]);
}
}

View file

@ -792,10 +792,10 @@ void TilemapVX::sandbox_deserialize_end()
}
if (isDisposed()) return;
if (p->above.deserModified) {
if (p->above.deserSceneElementModified) {
p->above.scene->reinsert(p->above);
}
if (p->deserModified) {
if (p->deserSceneElementModified) {
p->scene->reinsert(*p);
}
}

View file

@ -37,6 +37,10 @@
#define GUARD_V(value, expression) do { expression; if (exception.is_error()) return value; } while (0)
#define GUARD(expression) GUARD_V(, expression)
#ifdef MKXPZ_RETRO
static uint64_t next_id = 1;
#endif // MKXPZ_RETRO
struct ViewportPrivate
{
/* Needed for geometry changes */
@ -46,6 +50,7 @@ struct ViewportPrivate
sigslot::connection rectCon;
#ifdef MKXPZ_RETRO
Rect deserSavedRect;
bool deserScreenRectChanged;
#endif // MKXPZ_RETRO
Color *color;
@ -105,6 +110,9 @@ struct ViewportPrivate
Viewport::Viewport(int x, int y, int width, int height)
: SceneElement(*shState->screen()),
#ifdef MKXPZ_RETRO
id(next_id++),
#endif // MKXPZ_RETRO
sceneLink(this)
{
initViewport(x, y, width, height);
@ -112,6 +120,9 @@ Viewport::Viewport(int x, int y, int width, int height)
Viewport::Viewport(Rect *rect)
: SceneElement(*shState->screen()),
#ifdef MKXPZ_RETRO
id(next_id++),
#endif // MKXPZ_RETRO
sceneLink(this)
{
initViewport(rect->x, rect->y, rect->width, rect->height);
@ -119,6 +130,9 @@ Viewport::Viewport(Rect *rect)
Viewport::Viewport()
: SceneElement(*shState->screen()),
#ifdef MKXPZ_RETRO
id(next_id++),
#endif // MKXPZ_RETRO
sceneLink(this)
{
const Graphics &graphics = shState->graphics();
@ -236,8 +250,9 @@ void Viewport::releaseResources()
bool Viewport::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const
{
if (!mkxp_sandbox::sandbox_serialize(p->screenRect, data, max_size)) return false;
if (!mkxp_sandbox::sandbox_serialize(p->isOnScreen, data, max_size)) return false;
if (!sandbox_serialize_scene_element(data, max_size)) return false;
if (!mkxp_sandbox::sandbox_serialize(p->rect, data, max_size)) return false;
if (!mkxp_sandbox::sandbox_serialize(p->color, data, max_size)) return false;
if (!mkxp_sandbox::sandbox_serialize(p->tone, data, max_size)) return false;
@ -247,9 +262,16 @@ bool Viewport::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_siz
bool Viewport::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
{
if (!mkxp_sandbox::sandbox_deserialize(p->screenRect, data, max_size)) return false;
if (!mkxp_sandbox::sandbox_deserialize(p->isOnScreen, data, max_size)) return false;
{
IntRect value = p->screenRect;
if (!mkxp_sandbox::sandbox_deserialize(p->screenRect, data, max_size)) return false;
if (p->screenRect != value) {
p->deserScreenRectChanged = true;
}
}
if (!sandbox_deserialize_scene_element(data, max_size)) return false;
if (!mkxp_sandbox::sandbox_deserialize(p->rect, data, max_size)) return false;
if (!mkxp_sandbox::sandbox_deserialize(p->color, data, max_size)) return false;
if (!mkxp_sandbox::sandbox_deserialize(p->tone, data, max_size)) return false;
@ -269,6 +291,8 @@ void Viewport::sandbox_deserialize_begin()
} else {
p->deserSavedRect.set(0, 0, 0, 0);
}
p->deserScreenRectChanged = false;
}
void Viewport::sandbox_deserialize_end()
@ -282,7 +306,12 @@ void Viewport::sandbox_deserialize_end()
}
if (isDisposed()) return;
if (deserModified) {
if (p->deserScreenRectChanged) {
p->recomputeOnScreen();
}
if (isDisposed()) return;
if (deserSceneElementModified) {
scene->reinsert(*this);
}
}
@ -349,15 +378,28 @@ void ViewportElement::sandbox_deserialize_begin_viewport_element()
sandbox_deserialize_begin_scene_element();
viewportDispCon.disconnect();
deserSavedViewportId = m_viewport == nullptr ? 0 : m_viewport->id;
}
void ViewportElement::sandbox_deserialize_end_viewport_element()
{
if (m_viewport != nullptr) {
viewportDispCon = m_viewport->wasDisposed.connect(&ViewportElement::viewportElementDisposal, this);
if (m_viewport->isDisposed()) {
viewportElementDisposal();
if (rgssVer == 1) {
viewportDispCon = m_viewport->wasDisposed.connect(&ViewportElement::viewportElementDisposal, this);
if (m_viewport->isDisposed()) {
viewportElementDisposal();
}
}
if (m_viewport->id != deserSavedViewportId) {
setScene(*m_viewport);
onViewportChange();
onGeometryChange(scene->getGeometry());
}
} else if (deserSavedViewportId != 0) {
setScene(*shState->screen());
onViewportChange();
onGeometryChange(scene->getGeometry());
}
}
#endif // MXKPZ_RETRO

View file

@ -52,6 +52,8 @@ public:
void initDynAttribs();
#ifdef MKXPZ_RETRO
const uint64_t id; // Globally unique nonzero ID for this viewport, for change detection during save state deserialization
bool sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const;
bool sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
void sandbox_deserialize_begin();
@ -100,6 +102,9 @@ private:
void (*m_dispose)(void *);
Viewport *m_viewport;
sigslot::connection viewportDispCon;
#ifdef MKXPZ_RETRO
uint64_t deserSavedViewportId;
#endif // MKXPZ_RETRO
void viewportElementDisposal();
};

View file

@ -1089,7 +1089,7 @@ void Window::sandbox_deserialize_end()
}
if (isDisposed()) return;
if (deserModified) {
if (deserSceneElementModified) {
scene->reinsert(*this);
}
}

View file

@ -1355,7 +1355,7 @@ void WindowVX::sandbox_deserialize_end()
}
if (isDisposed()) return;
if (deserModified) {
if (deserSceneElementModified) {
scene->reinsert(*this);
}
}