From 298de29e5f9d4d0d0d2b51a3e3e639bc9d84ce9a Mon Sep 17 00:00:00 2001 From: Mathieu Moran Date: Thu, 17 Sep 2026 00:48:00 -0400 Subject: [PATCH] Fix menu reveal: MoveToAnim is absolute; register unlabeled anim children - MoveToAnim x/y/z are absolute target positions, not offsets: objects are authored in their hidden state and tweened to the visible position (e.g. the LANGUAGES title -500 -> 20). JPCSP's offset treatment is wrong. - Register unlabeled child entries (animation records) under the 'children' property with a synthetic zero-padded name, so BaseAnim.play can reach them. Previously anim containers had zero children and played nothing. --- .../dev/quoije/umd/rco/anim/MoveToAnim.java | 20 ++++++++++--------- .../quoije/umd/rco/vsmx/objects/Resource.java | 9 ++++++++- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/dev/quoije/umd/rco/anim/MoveToAnim.java b/core/src/main/java/dev/quoije/umd/rco/anim/MoveToAnim.java index 5196b5b..11d9013 100644 --- a/core/src/main/java/dev/quoije/umd/rco/anim/MoveToAnim.java +++ b/core/src/main/java/dev/quoije/umd/rco/anim/MoveToAnim.java @@ -20,24 +20,26 @@ public class MoveToAnim extends BaseAnim { @Override protected void doPlay(VsmxBaseObject object) { applyTo(ref, target -> { + // x/y/z are absolute target positions: objects are authored in their + // hidden state (e.g. off-screen) and tweened to the visible position. float tx = x.getFloatValue(); float ty = y.getFloatValue(); float tz = z.getFloatValue(); long millis = (long) duration.getFloatValue(); if (millis <= 0) { - target.animX = tx; - target.animY = ty; - target.animZ = tz; + target.posX.setFloatValue(tx); + target.posY.setFloatValue(ty); + target.posZ.setFloatValue(tz); target.onDisplayUpdated(); return; } - float sx = target.animX; - float sy = target.animY; - float sz = target.animZ; + float sx = target.posX.getFloatValue(); + float sy = target.posY.getFloatValue(); + float sz = target.posZ.getFloatValue(); Animator.getInstance().add(new Tween(millis, accelMode.getIntValue(), p -> { - target.animX = sx + (tx - sx) * p; - target.animY = sy + (ty - sy) * p; - target.animZ = sz + (tz - sz) * p; + target.posX.setFloatValue(sx + (tx - sx) * p); + target.posY.setFloatValue(sy + (ty - sy) * p); + target.posZ.setFloatValue(sz + (tz - sz) * p); target.onDisplayUpdated(); })); }); diff --git a/core/src/main/java/dev/quoije/umd/rco/vsmx/objects/Resource.java b/core/src/main/java/dev/quoije/umd/rco/vsmx/objects/Resource.java index 2dfcd99..2b6efe9 100644 --- a/core/src/main/java/dev/quoije/umd/rco/vsmx/objects/Resource.java +++ b/core/src/main/java/dev/quoije/umd/rco/vsmx/objects/Resource.java @@ -70,7 +70,14 @@ public class Resource extends BaseNativeObject { if (!entry.subEntries.isEmpty()) { VsmxObject children = new VsmxObject(interpreter, null); object.setPropertyValue(childrenName, children); - for (RcoFile.Entry child : entry.subEntries) { + for (int i = 0; i < entry.subEntries.size(); i++) { + RcoFile.Entry child = entry.subEntries.get(i); + // Unlabeled children (e.g. animation records) still need to be + // registered under "children" so scripts/anim playback can reach + // them. Assign a synthetic zero-padded name, as JPCSP does. + if (child.label == null) { + child.label = String.format("%04d", i); + } createObjectFromEntry(interpreter, display, controller, children, child); } }