Skip to content

Repository files navigation

ModularUI2 Preview

Preview and interact with real ModularUI2 Java layouts without starting Minecraft. The previewer compiles a small Java project and runs the real ModularUI2 screen lifecycle in a local runtime. It can open the GUI in a clickable desktop window, rebuild that window as files change, or render a full-screen PNG with machine-readable layout data for automated inspection.

The normal workflow is deliberately small:

  1. copy or write ModularPanel construction code;
  2. add the textures used by that code;
  3. choose a workflow:
    • open to click and inspect the GUI manually;
    • watch to keep an interactive window open while editing Java, textures, or configuration;
    • render to produce preview.png, bounds.json, and optional scripted interaction captures.

The preview project uses normal ModularUI2 classes and widget APIs. There is no second layout language to translate back into production code.

Requirements

  • Windows, Linux, or macOS;
  • JDK 21;
  • internet access on the first run so the Gradle Wrapper can download build dependencies.

Gradle does not need to be installed separately.

Install a release

Download the ZIP on Windows or the tar.gz archive on Linux and macOS, extract it, and run preview.bat help or ./preview.sh help. Release archives already contain the compiled previewer and do not require Gradle. They still require JDK 21 because preview projects compile Java source code on every build.

The launchers use JAVA_HOME when it is set, otherwise they use java and javac from PATH. A JRE without javac is not sufficient.

Publish a release

Push a version tag to build and publish the release archives:

git tag v0.1.0
git push origin v0.1.0

GitHub Actions verifies the project and attaches a versioned ZIP and tar.gz archive to the tag's release. Regular pushes and pull requests run verification without publishing a release.

Minecraft font

The previewer uses the original Minecraft 1.7.10 font from the developer's local client.jar; Minecraft assets are not included in this repository. For a normal GTNH development setup no configuration is needed. The launcher automatically checks:

%USERPROFILE%\.gradle\caches\retro_futura_gradle\mc-vanilla\1.7.10\client.jar

When GRADLE_USER_HOME is set, its cache is checked instead.

If the JAR is elsewhere, point the previewer at it before launching. In PowerShell:

$env:MODULARUI2_PREVIEW_MINECRAFT_JAR = "C:\path\to\client.jar"
.\preview.bat render examples\starter-panel

In Command Prompt:

set MODULARUI2_PREVIEW_MINECRAFT_JAR=C:\path\to\client.jar
preview.bat render examples\starter-panel

On Linux or macOS:

MODULARUI2_PREVIEW_MINECRAFT_JAR=/path/to/client.jar ./preview.sh render examples/starter-panel

Use the Minecraft 1.7.10 client.jar downloaded or generated by RetroFuturaGradle.

Try the included GUI

From the repository root, open the GT5 Basic Electrolyzer in an interactive desktop window:

preview.bat open examples\gt5-electrolyzer-direct

On Linux or macOS:

./preview.sh open examples/gt5-electrolyzer-direct

The example is a visual extraction of the production GT5 Basic Electrolyzer layout. Its textures are copied from the GT5 production assets used by the layout. Hover and click its local toggle buttons to verify pressed, hovered, and changed widget states. Interaction runs entirely inside the previewer; it does not simulate a Minecraft server or machine backend.

Use watch instead of open while editing the example. A successful rebuild replaces the displayed GUI. A compilation or render failure leaves the last working GUI visible and retries after the next file change:

preview.bat watch examples\gt5-electrolyzer-direct

Use render when you need artifacts for a screenshot comparison or an agent rather than a desktop window:

preview.bat render examples\gt5-electrolyzer-direct

For a minimal project intended to be copied and edited, run:

preview.bat render examples\starter-panel

The result is written to:

output/StarterPanelPreview/preview.png
output/StarterPanelPreview/bounds.json

The first launch builds the local previewer distribution. Warm renders normally finish in one or two seconds.

Create a preview project

Create a complete starter project:

preview.bat init my-machine-preview

The command creates this shape:

my-machine-preview/
  preview.properties
  src/
    preview/
      java/
        example/
          StarterPanelPreview.java
      resources/
        assets/

The generated preview.properties selects the Java entrypoint and the simulated monitor:

preview.entrypoint=example.StarterPanelPreview
screen.width=1920
screen.height=1080
gui.scale=auto
screen.background=#101820

Edit src/preview/java/example/StarterPanelPreview.java and replace the starter panel with production-shaped layout code. Open it interactively with:

preview.bat open my-machine-preview

Switch to watch for continuous rebuilding, or use render when you need PNG and JSON artifacts. The previewer compiles every .java file below src/preview/java on each run.

Add textures

Put preview-owned assets below:

src/preview/resources/assets/<domain>/<path>

For this production texture reference:

UITexture.fullImage("mymod", "textures/gui/machine.png")

the corresponding file is:

src/preview/resources/assets/mymod/textures/gui/machine.png

The previewer also supplies the assets contained in its pinned ModularUI2 and ModularUI artifacts. A direct visual preview normally needs only the mod-specific textures used by the panel.

Use production GUI code

There are two supported project shapes.

Direct panel preview

Copy the production panel-building code into the preview entrypoint and remove machine logic that is irrelevant to drawing. Keep the real widget classes, positions, sizes, texture paths, and panel structure.

Use this mode for fast layout and appearance iteration. The included GT5 Electrolyzer is the reference example.

Production builder integration

When the GUI builder can be loaded without starting Forge, point the preview project at the mod's compiled output with runtime-classpath.txt:

C:\work\MyMod\build\classes\java\main
C:\work\MyMod\build\resources\main
C:\path\to\a-production-dependency.jar

Use one directory or JAR per line. Empty lines and lines beginning with # are ignored. Relative entries are resolved from the preview project directory.

Do not add ModularUI2 or ModularUI to this file. The previewer supplies the pinned versions that match its headless runtime:

  • ModularUI2 2.3.84-1.7.10;
  • ModularUI 1.3.4.

The entrypoint constructs representative state and calls the production builder:

public final class MyMachinePreview implements PreviewEntrypoint {

    @Override
    public Class<?> previewedClass() {
        return MyMachineGui.class;
    }

    @Override
    public Object createPanel(Context context) {
        MyMachine machine = new MyMachine();
        machine.setStoredEnergy(4_000);
        return MyMachineGui.build(
            machine,
            (PanelSyncManager) context.panelSyncManager());
    }
}

previewedClass() records the production GUI class in bounds.json. This makes it possible to verify that the screenshot came from production code rather than a lookalike adapter.

The Galaxia Oxygen Filler under integrations/galaxia-oxygen-filler demonstrates this integration shape. It requires a compiled Galaxia checkout and its production dependencies in runtime-classpath.txt.

Additional project inputs

  • libs/ contains ordinary project runtime JARs.
  • extensions/ contains previewer extension providers.
  • assets/ is an alternative asset root equivalent to src/preview/resources/assets/.
  • runtime-classpath.txt contains compiled production classes, resources, and dependencies.

The normal direct-panel project does not need any of these directories.

Interactive preview

Open the configured panel in a desktop window:

preview.bat open project-directory

Mouse hover, left and right button presses, releases, clicks, and wheel scrolling are sent to the real ModularUI2 screen. The panel stays alive until the window is closed, so local widget callbacks can change the next rendered frame. This mode does not simulate a Minecraft server or network-backed behavior.

For continuous layout work, watch the project instead:

preview.bat watch project-directory

The previewer waits until changed Java, assets, configuration, or runtime inputs have remained stable for 300 milliseconds, then compiles a fresh UI session. A successful build replaces the displayed session and updates preview.png and bounds.json. A failed build leaves the last successful layout visible and marks it stale below the simulated monitor; the next file change retries automatically.

For repeatable agent-driven interaction, create a text file such as actions.txt:

# Coordinates use the full preview framebuffer.
move 960 540
click left

# Widget paths come from bounds.json, for example 0/3/1.
move-widget 0/3/1
scroll down 2
capture after-scroll

Run the full file in one live session:

preview.bat render project-directory --actions actions.txt

Available commands are move x y, move-widget path, press left|right, release left|right, click left|right, scroll up|down [amount], and capture name. Each capture is written below output/<PreviewClass>/captures/<name>/ as preview.png, bounds.json, and actions.json. Invalid commands and missing widget paths report the source line.

Command reference

Create a runnable starter:

preview.bat init project-directory

Render once using the entrypoint from preview.properties:

preview.bat render project-directory

Override the entrypoint and output directory:

preview.bat render project-directory --class fully.qualified.PreviewClass --output output/my-iteration

Open an interactive window or show command help:

preview.bat open project-directory
preview.bat watch project-directory
preview.bat help

The shell launcher accepts the same commands:

./preview.sh init project-directory
./preview.sh render project-directory [--class name] [--output directory] [--config file] [--actions file]
./preview.sh open project-directory [--class name] [--config file]
./preview.sh watch project-directory [--class name] [--output directory] [--config file]
./preview.sh help

Output artifacts

Every successful render produces:

  • preview.png: the entire simulated monitor, not a cropped panel;
  • bounds.json: framebuffer size, GUI scale, panel bounds, widget bounds, provenance, consumed assets, warnings, and completion status.

A healthy render has:

  • status equal to complete;
  • the expected previewedClass and panelCodeSource;
  • the expected mod texture paths in assets;
  • an empty warnings array.

Fidelity and current limits

The runtime executes real ModularPanel, ModularScreen, ModularContainer, sync collection, player-slot binding, widget initialization, layout, update, and draw calls.

The production acceptance surface covers rectangles, text, ModularUI2 textures, progress bars, empty item slots, player inventory, and full-screen GUI scaling.

The headless Minecraft/OpenGL boundary is intentionally smaller than the game. Entity rendering, non-empty item-stack icons, custom shaders or framebuffers, and mod-specific direct OpenGL code are not complete. Keyboard input, text entry, drag-and-drop, animation ticks, hot reload, and server/network simulation are not part of the local interaction host. A reachable missing ABI is a previewer implementation gap; do not replace production GUI code with an invented lookalike to hide it.

Troubleshooting

Missing preview.entrypoint

Add the fully qualified preview class to preview.properties:

preview.entrypoint=example.MyMachinePreview

The package declaration, directory structure, and configured class name must agree.

A production class does not compile

Build the mod, then add its class directory, resource directory, and required production dependencies to runtime-classpath.txt.

For quick visual iteration, use a direct panel preview and remove machine lifecycle code that is not needed to construct the panel.

A texture is missing

Check the exact domain and path passed to UITexture, then place the PNG under the matching assets/<domain>/... path. Inspect the assets array in bounds.json to confirm which file was consumed.

The panel is clipped

gui.scale=auto uses Minecraft's scale calculation for the configured framebuffer. Set an explicit value such as gui.scale=2 while diagnosing unusually large layouts.

Verify the previewer

Run the complete verification suite:

gradlew.bat agentVerify
./gradlew agentVerify

The suite compiles the runtime, runs its tests, and renders the bundled GT5 example without an external classpath.

License

ModularUI2 Preview is licensed under LGPL-3.0-only. Third-party components and the GT5 example are listed in THIRD_PARTY_NOTICES.md.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages