Wire RCO texture property to the renderer; fix group parent positions
- Expose the RCO image table as resource.texturetable[label] - Route native-object property assignment through set<Name>(BaseNativeObject) reflection so 'plane.texture = image' reaches PlaneObject.setTexture - Plane/UButton/Button/Icon draw their runtime texture in preference to the static image, and seed the texture property from the static image - Store the RCO entry's VSMX object so group children inherit parent position
This commit is contained in:
@@ -15,3 +15,4 @@ Thumbs.db
|
|||||||
|
|
||||||
# Disc images
|
# Disc images
|
||||||
*.iso
|
*.iso
|
||||||
|
reference/
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public final class RcoFile {
|
|||||||
public final List<Entry> subEntries = new ArrayList<>();
|
public final List<Entry> subEntries = new ArrayList<>();
|
||||||
public byte[] data;
|
public byte[] data;
|
||||||
public String[] texts;
|
public String[] texts;
|
||||||
|
public ImageObject image;
|
||||||
public BaseObject obj;
|
public BaseObject obj;
|
||||||
public VsmxBaseObject vsmxObject;
|
public VsmxBaseObject vsmxObject;
|
||||||
|
|
||||||
@@ -269,7 +270,9 @@ public final class RcoFile {
|
|||||||
if (imgData != null && comp != COMPRESSION_NONE) {
|
if (imgData != null && comp != COMPRESSION_NONE) {
|
||||||
imgData = decompressImage(imgData, comp, sizeUnpacked);
|
imgData = decompressImage(imgData, comp, sizeUnpacked);
|
||||||
}
|
}
|
||||||
images.put(entryOffset, new ImageObject(imgData));
|
ImageObject imageObject = new ImageObject(imgData);
|
||||||
|
images.put(entryOffset, imageObject);
|
||||||
|
entry.image = imageObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case TABLE_MODEL -> {
|
case TABLE_MODEL -> {
|
||||||
|
|||||||
@@ -97,6 +97,18 @@ public abstract class BaseObject extends BaseNativeObject implements IDisplay {
|
|||||||
public VsmxBaseObject createVsmxObject(VsmxInterpreter interpreter, VsmxBaseObject parent, RcoFile.Entry entry) {
|
public VsmxBaseObject createVsmxObject(VsmxInterpreter interpreter, VsmxBaseObject parent, RcoFile.Entry entry) {
|
||||||
VsmxNativeObject object = new VsmxNativeObject(interpreter, this);
|
VsmxNativeObject object = new VsmxNativeObject(interpreter, this);
|
||||||
setObject(object);
|
setObject(object);
|
||||||
|
entry.vsmxObject = object;
|
||||||
|
|
||||||
|
// Seed the "texture" property with this object's static image so the
|
||||||
|
// script can read or replace it. Assignment is routed through the
|
||||||
|
// native setTexture setter, when one exists.
|
||||||
|
Object staticImage = getImage();
|
||||||
|
if (staticImage instanceof ImageObject imageObject) {
|
||||||
|
VsmxNativeObject textureObject = new VsmxNativeObject(interpreter, imageObject);
|
||||||
|
imageObject.setObject(textureObject);
|
||||||
|
object.setPropertyValue("texture", textureObject);
|
||||||
|
}
|
||||||
|
|
||||||
if (entry.label != null) {
|
if (entry.label != null) {
|
||||||
name = entry.label;
|
name = entry.label;
|
||||||
object.setPropertyValue("name", new VsmxString(interpreter, entry.label));
|
object.setPropertyValue("name", new VsmxString(interpreter, entry.label));
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import dev.quoije.umd.rco.type.EventType;
|
|||||||
import dev.quoije.umd.rco.type.ImageType;
|
import dev.quoije.umd.rco.type.ImageType;
|
||||||
import dev.quoije.umd.rco.type.IntType;
|
import dev.quoije.umd.rco.type.IntType;
|
||||||
import dev.quoije.umd.rco.type.TextType;
|
import dev.quoije.umd.rco.type.TextType;
|
||||||
|
import dev.quoije.umd.rco.vsmx.objects.BaseNativeObject;
|
||||||
|
|
||||||
/** A button object. */
|
/** A button object. */
|
||||||
public class ButtonObject extends BasePositionObject {
|
public class ButtonObject extends BasePositionObject {
|
||||||
@@ -24,11 +25,25 @@ public class ButtonObject extends BasePositionObject {
|
|||||||
@ObjectField(order = 212) public EventType onContextMenu;
|
@ObjectField(order = 212) public EventType onContextMenu;
|
||||||
@ObjectField(order = 213) public IntType unknownInt40;
|
@ObjectField(order = 213) public IntType unknownInt40;
|
||||||
|
|
||||||
|
/** Runtime texture assigned by the script; overrides the static image. */
|
||||||
|
private ImageObject texture;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getImage() {
|
public Object getImage() {
|
||||||
|
if (texture != null) {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
return image.getImage();
|
return image.getImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Called via the VSMX {@code texture} property setter. */
|
||||||
|
public void setTexture(BaseNativeObject texture) {
|
||||||
|
if (texture instanceof ImageObject imageObject) {
|
||||||
|
this.texture = imageObject;
|
||||||
|
}
|
||||||
|
onDisplayUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getFocusImage() {
|
public Object getFocusImage() {
|
||||||
return focus.getImage();
|
return focus.getImage();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package dev.quoije.umd.rco.object;
|
|||||||
|
|
||||||
import dev.quoije.umd.rco.ObjectField;
|
import dev.quoije.umd.rco.ObjectField;
|
||||||
import dev.quoije.umd.rco.type.ImageType;
|
import dev.quoije.umd.rco.type.ImageType;
|
||||||
|
import dev.quoije.umd.rco.vsmx.objects.BaseNativeObject;
|
||||||
|
|
||||||
/** An icon object. */
|
/** An icon object. */
|
||||||
public class IconObject extends BasePositionObject {
|
public class IconObject extends BasePositionObject {
|
||||||
@@ -11,8 +12,22 @@ public class IconObject extends BasePositionObject {
|
|||||||
@ObjectField(order = 202) public ImageType unknownImage18;
|
@ObjectField(order = 202) public ImageType unknownImage18;
|
||||||
@ObjectField(order = 203) public ImageType unknownImage20;
|
@ObjectField(order = 203) public ImageType unknownImage20;
|
||||||
|
|
||||||
|
/** Runtime texture assigned by the script; overrides the static image. */
|
||||||
|
private ImageObject texture;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getImage() {
|
public Object getImage() {
|
||||||
|
if (texture != null) {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
return unknownImage16.getImage();
|
return unknownImage16.getImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Called via the VSMX {@code texture} property setter. */
|
||||||
|
public void setTexture(BaseNativeObject texture) {
|
||||||
|
if (texture instanceof ImageObject imageObject) {
|
||||||
|
this.texture = imageObject;
|
||||||
|
}
|
||||||
|
onDisplayUpdated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
package dev.quoije.umd.rco.object;
|
package dev.quoije.umd.rco.object;
|
||||||
|
|
||||||
|
import dev.quoije.umd.rco.vsmx.objects.BaseNativeObject;
|
||||||
|
|
||||||
/** An image entry from the RCO IMG table (raw bytes until decoded by the UI). */
|
/** An image entry from the RCO IMG table (raw bytes until decoded by the UI). */
|
||||||
public final class ImageObject {
|
public class ImageObject extends BaseNativeObject {
|
||||||
|
|
||||||
private final byte[] data;
|
private final byte[] data;
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package dev.quoije.umd.rco.object;
|
|||||||
import dev.quoije.umd.rco.ObjectField;
|
import dev.quoije.umd.rco.ObjectField;
|
||||||
import dev.quoije.umd.rco.type.ImageType;
|
import dev.quoije.umd.rco.type.ImageType;
|
||||||
import dev.quoije.umd.rco.type.IntType;
|
import dev.quoije.umd.rco.type.IntType;
|
||||||
|
import dev.quoije.umd.rco.vsmx.objects.BaseNativeObject;
|
||||||
|
|
||||||
/** A plane (textured rectangle). */
|
/** A plane (textured rectangle). */
|
||||||
public class PlaneObject extends BasePositionObject {
|
public class PlaneObject extends BasePositionObject {
|
||||||
@@ -11,8 +12,22 @@ public class PlaneObject extends BasePositionObject {
|
|||||||
@ObjectField(order = 201) public ImageType image;
|
@ObjectField(order = 201) public ImageType image;
|
||||||
@ObjectField(order = 202) public IntType unknownInt18;
|
@ObjectField(order = 202) public IntType unknownInt18;
|
||||||
|
|
||||||
|
/** Runtime texture assigned by the script; overrides the static image. */
|
||||||
|
private ImageObject texture;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getImage() {
|
public Object getImage() {
|
||||||
|
if (texture != null) {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
return image.getImage();
|
return image.getImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Called via the VSMX {@code texture} property setter. */
|
||||||
|
public void setTexture(BaseNativeObject texture) {
|
||||||
|
if (texture instanceof ImageObject imageObject) {
|
||||||
|
this.texture = imageObject;
|
||||||
|
}
|
||||||
|
onDisplayUpdated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import dev.quoije.umd.rco.ObjectField;
|
|||||||
import dev.quoije.umd.rco.type.EventType;
|
import dev.quoije.umd.rco.type.EventType;
|
||||||
import dev.quoije.umd.rco.type.ImageType;
|
import dev.quoije.umd.rco.type.ImageType;
|
||||||
import dev.quoije.umd.rco.type.IntType;
|
import dev.quoije.umd.rco.type.IntType;
|
||||||
|
import dev.quoije.umd.rco.vsmx.objects.BaseNativeObject;
|
||||||
|
|
||||||
/** A user button object (navigation with onLeft/onRight/onUp/onDown events). */
|
/** A user button object (navigation with onLeft/onRight/onUp/onDown events). */
|
||||||
public class UButtonObject extends BasePositionObject {
|
public class UButtonObject extends BasePositionObject {
|
||||||
@@ -19,11 +20,25 @@ public class UButtonObject extends BasePositionObject {
|
|||||||
@ObjectField(order = 208) public EventType onDown;
|
@ObjectField(order = 208) public EventType onDown;
|
||||||
@ObjectField(order = 209) public IntType unknownInt32;
|
@ObjectField(order = 209) public IntType unknownInt32;
|
||||||
|
|
||||||
|
/** Runtime texture assigned by the script; overrides the static image. */
|
||||||
|
private ImageObject texture;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getImage() {
|
public Object getImage() {
|
||||||
|
if (texture != null) {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
return image.getImage();
|
return image.getImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Called via the VSMX {@code texture} property setter. */
|
||||||
|
public void setTexture(BaseNativeObject texture) {
|
||||||
|
if (texture instanceof ImageObject imageObject) {
|
||||||
|
this.texture = imageObject;
|
||||||
|
}
|
||||||
|
onDisplayUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFocus() {
|
public void setFocus() {
|
||||||
trigger(onFocusIn);
|
trigger(onFocusIn);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package dev.quoije.umd.rco.vsmx.interpreter;
|
|||||||
|
|
||||||
import dev.quoije.umd.rco.vsmx.objects.BaseNativeObject;
|
import dev.quoije.umd.rco.vsmx.objects.BaseNativeObject;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
/** A VSMX object wrapping a native Java object. */
|
/** A VSMX object wrapping a native Java object. */
|
||||||
public class VsmxNativeObject extends VsmxObject {
|
public class VsmxNativeObject extends VsmxObject {
|
||||||
|
|
||||||
@@ -17,6 +19,27 @@ public class VsmxNativeObject extends VsmxObject {
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigning a native object to a property is routed through a matching
|
||||||
|
* {@code set<Name>(BaseNativeObject)} method when the wrapped object
|
||||||
|
* declares one. This is how {@code plane.texture = image} reaches
|
||||||
|
* {@code PlaneObject.setTexture}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setPropertyValue(String name, VsmxBaseObject value) {
|
||||||
|
if (object != null && name != null && !name.isEmpty() && value instanceof VsmxNativeObject nativeValue) {
|
||||||
|
String setterName = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
|
||||||
|
try {
|
||||||
|
Method setter = object.getClass().getMethod(setterName, BaseNativeObject.class);
|
||||||
|
setter.invoke(object, nativeValue.getObject());
|
||||||
|
return;
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
// No matching setter; fall back to storing the property.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.setPropertyValue(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return object == null ? super.toString() : object.toString() + super.toString();
|
return object == null ? super.toString() : object.toString() + super.toString();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import dev.quoije.umd.rco.vsmx.interpreter.VsmxBaseObject;
|
|||||||
import dev.quoije.umd.rco.vsmx.interpreter.VsmxInterpreter;
|
import dev.quoije.umd.rco.vsmx.interpreter.VsmxInterpreter;
|
||||||
import dev.quoije.umd.rco.vsmx.interpreter.VsmxNativeObject;
|
import dev.quoije.umd.rco.vsmx.interpreter.VsmxNativeObject;
|
||||||
import dev.quoije.umd.rco.vsmx.interpreter.VsmxObject;
|
import dev.quoije.umd.rco.vsmx.interpreter.VsmxObject;
|
||||||
|
import dev.quoije.umd.rco.vsmx.interpreter.VsmxString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The resource native object, exposing the RCO object tables to the script.
|
* The resource native object, exposing the RCO object tables to the script.
|
||||||
@@ -50,6 +51,15 @@ public class Resource extends BaseNativeObject {
|
|||||||
|
|
||||||
private static void createObjectFromEntry(VsmxInterpreter interpreter, Display display, Controller controller,
|
private static void createObjectFromEntry(VsmxInterpreter interpreter, Display display, Controller controller,
|
||||||
VsmxBaseObject parent, RcoFile.Entry entry) {
|
VsmxBaseObject parent, RcoFile.Entry entry) {
|
||||||
|
if (entry.image != null) {
|
||||||
|
VsmxNativeObject object = new VsmxNativeObject(interpreter, entry.image);
|
||||||
|
entry.image.setObject(object);
|
||||||
|
if (entry.label != null) {
|
||||||
|
object.setPropertyValue("name", new VsmxString(interpreter, entry.label));
|
||||||
|
parent.setPropertyValue(entry.label, object);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (entry.obj == null) {
|
if (entry.obj == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user