Skip to content

whutdev/pinevex-renderer

Repository files navigation

Pinevex Renderer

A high-fidelity UI renderer for Roblox-style interface trees

Python 3.12+ License: Apache 2.0 Web Demo

Test Pinevex Renderer with your own screengui RBXM in our web demo!

Pinevex Renderer rendering a Roblox-style RobuxShop UI

Rendered by Pinevex Renderer

Pinevex Renderer rendering a Roblox-style SLS lobby UI

Rendered by Pinevex Renderer

Pinevex Renderer rendering a Roblox-style upgrade UI

Rendered by Pinevex Renderer

Pinevex Renderer rendering a Roblox-style HUD test UI

Rendered by Pinevex Renderer

Pinevex Renderer rendering RTL2PCParts from an RBXM file

yes, pinevex renderer can render THIS! ( and almost anything! )

Pinevex Renderer is a CPU-only renderer that achieves near-parity with Roblox's internal UI engine for structured Roblox-style UI JSON.

Try it in the live web demo: pinevex-renderer-demo.vercel.app.

The web demo accepts Pinevex JSON directly or a binary ScreenGui .rbxm, which it parses into Pinevex JSON before rendering.

The project originally existed to generate AI synthetic training data: structured Roblox-style UI trees could be rendered into reference images for model training, reconstruction, and validation loops.

It takes a nested UI tree and produces PNG previews that are close enough to be useful for reconstruction, validation, and export workflows. The renderer handles scale/offset layout, nested hierarchy, text fitting, strokes, gradients, rounded corners, tiled textures, icon references, and optional Luau generation.

It also includes a Tk step-by-step paint debugger for inspecting each render operation with Left/Right controls, plus hit-testing helpers for finding which UI objects overlap a region.

This repository is intentionally scoped to the renderer layer.

Why this exists

Screenshot-to-editable-UI systems need more than image similarity. A generated result has to become structured, editable UI, then render back into something close to the original screenshot.

Roblox UI coverage

The renderer uses Roblox-native UI concepts and exports matching Luau instances where possible. It is not a complete reimplementation of every Studio property, but it covers the common surface used by game UI screenshots.

Supported GuiObject classes:

  • Frame
  • CanvasGroup
  • ScrollingFrame
  • TextLabel
  • TextButton
  • TextBox
  • ImageLabel
  • ImageButton

Accepted for layout/export compatibility:

  • ScreenGui
  • ViewportFrame
  • VideoFrame

Supported core GuiObject properties:

  • Size and Position as UDim2 scale/offset values
  • AnchorPoint
  • BackgroundColor3
  • BackgroundTransparency
  • BorderSizePixel
  • ZIndex
  • LayoutOrder
  • Visible
  • ClipsDescendants
  • Rotation
  • AutomaticSize
  • SizeConstraint

Supported Roblox UI instances and constraints:

  • UICorner: CornerRadius
  • UIStroke: Color, Transparency, Thickness, ApplyStrokeMode, BorderStrokePosition, LineJoinMode, StrokeSizingMode, plus gradient strokes
  • UIGradient: Color, Transparency, Rotation, Offset
  • UIPadding: PaddingTop, PaddingBottom, PaddingLeft, PaddingRight
  • UIListLayout: FillDirection, HorizontalAlignment, VerticalAlignment, Padding, Wraps, SortOrder = LayoutOrder
  • UIGridLayout: CellSize, CellPadding, FillDirection, HorizontalAlignment, VerticalAlignment, SortOrder = LayoutOrder
  • UIAspectRatioConstraint: AspectRatio
  • UITextSizeConstraint: MinTextSize, MaxTextSize
  • UIScale: Scale

Supported text properties:

  • Text
  • TextColor3
  • TextSize
  • TextScaled
  • TextWrapped
  • TextTransparency
  • TextXAlignment
  • TextYAlignment
  • RichText
  • LineHeight
  • FontFace families, weights, and styles

Supported image properties:

  • Image
  • ImageColor3
  • ImageTransparency
  • ScaleType: Stretch, Fit, Crop, Tile, Slice
  • TileSize
  • SliceCenter
  • SliceScale
  • ImageRectSize
  • ImageRectOffset

Supported ScrollingFrame behavior:

  • CanvasSize
  • AutomaticCanvasSize
  • ScrollingDirection
  • ScrollBarImageColor3
  • ScrollBarImageTransparency
  • ScrollBarThickness
  • normalized preview-time canvasPosition for rendering scrolled content

Quick start

Use the hosted demo here: https://pinevex-renderer-demo.vercel.app.

Create a Python environment and install dependencies:

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Start the API:

uvicorn api.index:app --reload

Render the included example to a PNG:

curl -s http://127.0.0.1:8000/preview.png \
  -H 'Content-Type: application/json' \
  --data '{"pinevex_object": '"$(cat examples/simple-ui.json)"', "viewport_size": [420, 180], "transparent_background": true}' \
  --output preview.png

The larger examples/rtl2pcparts.json fixture was parsed from examples/RTL2PCParts.rbxm, copied from Downloads/RTL2PCParts.rbxm, and is also available as a quick-load example in the web demo.

API

GET /health

Returns a small status payload confirming the vendored runtime pieces are present.

GET /font-health

Returns bundled font diagnostics. If RENDERER_API_KEY is set, this endpoint requires authorization.

POST /preview.png

Returns a rendered PNG directly.

{
  "pinevex_object": {
    "type": "Frame",
    "size": [1, 0, 1, 0],
    "bg": [24, 28, 36],
    "children": []
  },
  "viewport_size": [420, 180],
  "transparent_background": true
}

POST /render

Returns a JSON response with the normalized object, optional base64 PNG preview, and optional Luau output.

{
  "pinevex_object": {"type": "Frame", "children": []},
  "allow_partial": true,
  "include_preview": true,
  "include_luau": true,
  "viewport_size": [1204, 168],
  "transparent_background": true
}

pinevex_object may be a JSON object or a string containing partial JSON. viewport_size accepts [width, height], {"width": 1204, "height": 168}, "1204x168", or "1204,168". When omitted, the renderer uses 1920x1080. Set transparent_background to true to return a PNG with a transparent canvas instead of a white canvas.

Step-by-step debugger

Capture every visual paint operation for a Pinevex JSON file:

PYTHONPATH=src python -m ui_engine.debug_stepper examples/simple-ui.json \
  --viewport-size 420x180 \
  --output-dir pinevex_steps

The command writes numbered PNG frames and steps.json. Add --tk to open the step-through GUI:

PYTHONPATH=src python -m ui_engine.debug_stepper examples/simple-ui.json \
  --viewport-size 420x180 \
  --output-dir pinevex_steps \
  --tk

Use Left/Right, Space, Home, or End to inspect the render one draw call at a time.

Useful flags:

  • --tk opens the Tkinter step-through viewer.
  • --debug overlays renderer debug outlines.
  • --transparent uses a transparent canvas.
  • --crop crops frames when the input object sets _crop: true.

The same feature is available from Python:

from ui_engine.debug_stepper import capture_steps, save_steps

steps, metadata = capture_steps(pinevex_object, width=420, height=180)
save_steps(steps, output_dir="pinevex_steps", metadata=metadata)

When importing ui_engine directly from a source checkout, run Python with PYTHONPATH=src or add src/ to sys.path.

For occlusion and selection debugging, ui_engine.hit_test exposes get_objects_at_region, get_objects_at_instance, get_instance_rect, and get_instance_region.

JSON shape

The renderer expects a nested UI tree with Roblox-like fields:

{
  "type": "TextButton",
  "name": "PrimaryButton",
  "size": [0.58, 0, 0.28, 0],
  "position": [0.5, 0, 0.68, 0],
  "anchor": [0.5, 0.5],
  "bg": [64, 179, 108],
  "corner": 0.12,
  "text": "Open",
  "textColor": [255, 255, 255],
  "textScaled": true,
  "font": "Montserrat",
  "fontWeight": "Bold",
  "children": []
}

See examples/simple-ui.json for a complete minimal example.

Configuration

  • RENDERER_API_KEY: optional bearer token required by render endpoints when set.
  • ICON_CACHE_DIR: optional cache directory for fetched Roblox asset thumbnails. Defaults to /tmp/pinevex-renderer/cache/icons.
  • PINEVEX_RENDERER_ICON_OVERRIDES: optional path to a local JSON map of Roblox asset IDs to bundled icon keys. This is useful for private renderer parity fixes and should not be committed.
  • PINEVEX_RENDERER_ROBLOX_FONT_DIRS: optional PATH-separated list of local Roblox font directories used as extra fallbacks.

Repository scope

This repository contains the renderer/API runtime and small examples. The bundled icon manifest is a minimal texture-key subset, not the private asset catalog, and does not include concrete private asset IDs.

Source layout note

The renderer core lives in src/ui_engine. This repository originally only scoped the Vercel/web-demo wrapper, and ui_engine was imported as a vendored runtime from the larger Pinevex project. The repo has since grown into the public renderer artifact, so the renderer now uses a conventional src/ layout.

License

Pinevex-authored source code is licensed under the Apache License 2.0.

Bundled third-party fonts and native runtime libraries retain their original licenses. See THIRD_PARTY_NOTICES.md.

Project structure

api/
  index.py                      FastAPI entrypoint
examples/
  simple-ui.json                Minimal renderable UI tree
  RTL2PCParts.rbxm              Source RBXM for the PC parts shop example
  rtl2pcparts.json              Parsed Pinevex JSON fixture for that RBXM
src/
  ui_engine/                    Layout, text, image, hit-test, step debugger, and Skia rendering code
vendor/
  icon_library/manifest.json    Minimal public texture-key manifest
  native/                       Linux runtime libraries for hosted rendering
  product_output/               Pinevex postprocess and Luau export helpers
requirements.txt
vercel.json

Status

This is a technical artifact extracted from a larger screenshot-to-editable-UI reconstruction project. It is useful as a renderer/API reference, but it is not packaged as a polished product SDK.


Note: README.md written by GPT 5.5, roughly human-reviewed.

About

High-fidelity UI renderer for Roblox-style interface trees

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors