Pixscape is currently in public pre-release.

The runtime and documentation are already usable, but some APIs, workflows, and editor behavior may still evolve before a stable 1.0 release.

Advanced Runtime Integration

Insert custom Artemis systems at specific frame phases or replace final rendering submission.

On this page

Most games only need the normal Runtime APIs. Use these expert hooks only when custom code must run at a specific point in Pixscape’s rendering lifecycle or when the application needs to replace the final rendering submission step.

If the Entity Component System (ECS), Structure of Arrays (SOA), or synchronization model is unfamiliar, read Architecture & Performance first.

Start with the current engine constructor:

PixscapeEngine engine = new PixscapeEngine();

Pre-render systems

Pre-render systems run after Pixscape has synchronized normal scene changes, but before it prepares the final rendering work for the frame. That preparation includes visibility checks, drawing order, Spatial front/behind ordering, and assembling the data that will be sent to the renderer.

engine.setPreRenderSystemCustomizer(builder -> {
    builder.with(new MyPreRenderSystem());
});

This is a render-integration phase, not a general gameplay-update hook. A component change made here does not rerun the synchronization work that already happened earlier in the frame. Do not assume that every render-oriented value computed from that component will update in the same frame.

Post-render systems

Post-render systems run after the current frame has been sent to the renderer and Pixscape has finished processing its tracked changes for that frame, but before the synchronous Artemis World.process() call returns. Internally, that cleanup is called flushing dirty state.

engine.setPostRenderSystemCustomizer(builder -> {
    builder.with(new MyPickingSystem());
});

This phase suits diagnostics, picking, gizmos, overlays, application integration, and state changes intended for a later frame. It cannot alter a frame that has already been submitted.

One system instance per Runtime World

Each Artemis system belongs to exactly one World. Whenever Pixscape builds a scene World, each customizer callback must add fresh system instances. Never reuse the same BaseSystem instance across scene changes.

Configuring a callback does not inject systems into an already-built World. It applies to the next applicable scene World build. The lightweight project bootstrap World created by loadProject(...) does not invoke application customizers.

Custom systems execute synchronously on the thread calling render(), normally the LibGDX render thread. These hooks do not add thread-safety.

Replace final render submission

Final submission is the step that sends the prepared rendering work for the current frame to the GPU. Pixscape stores that prepared work in a frame queue before its normal submission system consumes it.

setRenderSubmitSystemSupplier(...) replaces that final system while preserving Pixscape’s earlier synchronization, visibility checks, ordering, Spatial front/behind ordering, and frame preparation.

engine.setRenderSubmitSystemSupplier(MyRenderSubmitSystem::new);

The supplier must return a fresh, non-null compatible system for each Runtime World. The returned system becomes fully responsible for submitting the frame; Pixscape does not also run its normal RenderSubmitSystem.

The custom system must manage its own GPU and batch lifecycle without disposing borrowed Pixscape-owned frame queues, cameras, batches, metrics, or layer state. Changing the supplier affects future World builds, not the current World. Pass null to restore Pixscape’s default submit system for subsequent builds.

For other engine setup, see Core Module and Scene Loading. Shared AssetManager configuration is covered in Using your own AssetManager.

For direct access to Artemis game and scene state rather than frame-lifecycle hooks, see Expert ECS Access.

Code examples

Configure systems at different stages of the Runtime frame

Register application systems at the phase where their work needs to happen.

PixscapeEngine engine = new PixscapeEngine()
        .setPreRenderSystemCustomizer(builder -> {
            // Normal Runtime synchronization already ran. Changes here do not
            // cause that earlier work to run again in the same frame.

            // Create fresh application system instances here.
            // Artemis systems belong to one Runtime World only.
            builder.with(new CustomRenderDataSystem());
        })
        .setPostRenderSystemCustomizer(builder -> {
            // The current frame was submitted and dirty state flushed.
            // Work here can affect a later frame, not the submitted one.

            // Create fresh application system instances here.
            builder.with(new PickingSystem());
            builder.with(new RuntimeDiagnosticsSystem());
        });

Replace final frame submission

Replace Pixscape’s normal submission system only when the application needs complete control over final GPU submission.

PixscapeEngine engine = new PixscapeEngine()
        .setPreRenderSystemCustomizer(builder -> {
            // Prepare application-specific render data before Pixscape assembles
            // the final rendering work for this frame.
            builder.with(new CustomRenderDataSystem());
        })
        .setRenderSubmitSystemSupplier(() -> {
            // Pixscape already synchronized scene changes, checked visibility,
            // established order, and prepared the frame queue.
            // Return a fresh system for each Runtime World.
            // It owns GPU submission but not borrowed Pixscape render objects.
            return new CustomRenderSubmitSystem();
        })
        .setPostRenderSystemCustomizer(builder -> {
            // Runs after custom submission and dirty-state flushing.
            builder.with(new FrameDiagnosticsSystem());
        });