Add JavaFX menu renderer and player window
- RcoRenderer implements Display: draws the live RCO object tree onto a Canvas, decodes PNG textures, handles focus and resource changes (thread-safe via Platform.runLater). - PageObject now implements root/children semantics and open/close/display so opening a page adds its objects to the renderer. - Object getImage() returns the ImageObject so the UI can decode PNGs. - PlayerApp wires menu + video: loads the RCO, runs the VSMX script, executes onAutoPlay, plays video via PlaybackEngine with YUV->ARGB blitting and PTS pacing, and routes arrow/Enter keys to the controller. - Runs end-to-end on Batman Begins (window, menu load, playback).
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
package dev.quoije.umd.rco;
|
||||
|
||||
import dev.quoije.umd.rco.vsmx.interpreter.VsmxBaseObject;
|
||||
|
||||
/** The rendering surface backing an RCO menu. Implemented by the UI layer. */
|
||||
public interface Display {
|
||||
|
||||
void setFocus(IDisplay display);
|
||||
|
||||
void add(IDisplay display);
|
||||
void add(VsmxBaseObject object);
|
||||
|
||||
void remove(IDisplay display);
|
||||
void remove(VsmxBaseObject object);
|
||||
|
||||
void repaint();
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ public class ButtonObject extends BasePositionObject {
|
||||
|
||||
@Override
|
||||
public Object getImage() {
|
||||
return image.getImage() == null ? null : image.getImage().getImage();
|
||||
return image.getImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,6 +13,6 @@ public class IconObject extends BasePositionObject {
|
||||
|
||||
@Override
|
||||
public Object getImage() {
|
||||
return unknownImage16.getImage() == null ? null : unknownImage16.getImage().getImage();
|
||||
return unknownImage16.getImage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,14 @@
|
||||
package dev.quoije.umd.rco.object;
|
||||
|
||||
import dev.quoije.umd.rco.ObjectField;
|
||||
import dev.quoije.umd.rco.RcoFile;
|
||||
import dev.quoije.umd.rco.type.EventType;
|
||||
import dev.quoije.umd.rco.type.IntType;
|
||||
import dev.quoije.umd.rco.vsmx.interpreter.VsmxBaseObject;
|
||||
import dev.quoije.umd.rco.vsmx.interpreter.VsmxInterpreter;
|
||||
import dev.quoije.umd.rco.vsmx.interpreter.VsmxNativeObject;
|
||||
import dev.quoije.umd.rco.vsmx.interpreter.VsmxObject;
|
||||
import dev.quoije.umd.rco.vsmx.objects.Resource;
|
||||
|
||||
/** A menu page. */
|
||||
public class PageObject extends BaseObject {
|
||||
@@ -15,8 +20,66 @@ public class PageObject extends BaseObject {
|
||||
@ObjectField(order = 4) public EventType onContextMenu;
|
||||
@ObjectField(order = 5) public EventType onActivate;
|
||||
|
||||
@Override
|
||||
public VsmxBaseObject createVsmxObject(VsmxInterpreter interpreter, VsmxBaseObject parent, RcoFile.Entry entry) {
|
||||
VsmxBaseObject object = super.createVsmxObject(interpreter, parent, entry);
|
||||
VsmxObject root = new VsmxObject(interpreter, null);
|
||||
object.setPropertyValue(Resource.rootName, root);
|
||||
return root;
|
||||
}
|
||||
|
||||
private void display(VsmxBaseObject object) {
|
||||
if (!object.hasPropertyValue(Resource.childrenName)) {
|
||||
return;
|
||||
}
|
||||
VsmxBaseObject children = object.getPropertyValue(Resource.childrenName);
|
||||
for (String childName : children.getPropertyNames()) {
|
||||
VsmxBaseObject child = children.getPropertyValue(childName);
|
||||
display.add(child);
|
||||
display(child);
|
||||
}
|
||||
}
|
||||
|
||||
private void hide(VsmxBaseObject object) {
|
||||
if (!object.hasPropertyValue(Resource.childrenName)) {
|
||||
return;
|
||||
}
|
||||
VsmxBaseObject children = object.getPropertyValue(Resource.childrenName);
|
||||
for (String childName : children.getPropertyNames()) {
|
||||
VsmxBaseObject child = children.getPropertyValue(childName);
|
||||
display.remove(child);
|
||||
hide(child);
|
||||
}
|
||||
}
|
||||
|
||||
private BasePositionObject getFirstButton(VsmxBaseObject object) {
|
||||
if (!object.hasPropertyValue(Resource.childrenName)) {
|
||||
return null;
|
||||
}
|
||||
VsmxBaseObject children = object.getPropertyValue(Resource.childrenName);
|
||||
for (String childName : children.getPropertyNames()) {
|
||||
VsmxBaseObject child = children.getPropertyValue(childName);
|
||||
if (child instanceof VsmxNativeObject nativeObject && nativeObject.getObject() instanceof UButtonObject button) {
|
||||
return button;
|
||||
}
|
||||
BasePositionObject button = getFirstButton(child);
|
||||
if (button != null) {
|
||||
return button;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public VsmxBaseObject open(VsmxBaseObject object) {
|
||||
trigger(onInit);
|
||||
|
||||
if (display != null && object.hasPropertyValue(Resource.rootName)) {
|
||||
display(object.getPropertyValue(Resource.rootName));
|
||||
BasePositionObject button = getFirstButton(object.getPropertyValue(Resource.rootName));
|
||||
if (button != null) {
|
||||
button.setFocus();
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
@@ -26,6 +89,9 @@ public class PageObject extends BaseObject {
|
||||
}
|
||||
|
||||
public void close(VsmxBaseObject object) {
|
||||
if (display != null && object.hasPropertyValue(Resource.rootName)) {
|
||||
hide(object.getPropertyValue(Resource.rootName));
|
||||
}
|
||||
trigger(onCancel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,6 @@ public class PlaneObject extends BasePositionObject {
|
||||
|
||||
@Override
|
||||
public Object getImage() {
|
||||
return image.getImage() == null ? null : image.getImage().getImage();
|
||||
return image.getImage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public class UButtonObject extends BasePositionObject {
|
||||
|
||||
@Override
|
||||
public Object getImage() {
|
||||
return image.getImage() == null ? null : image.getImage().getImage();
|
||||
return image.getImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user