Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/armory3d/armorpaint/llms.txt

Use this file to discover all available pages before exploring further.

ArmorPaint includes a built-in script editor powered by the MiniC interpreter, letting you automate tasks, inspect application state, and prototype new behaviours without recompiling the application. Unlike plugins — which are loaded at startup and run continuously — scripts are evaluated on demand by pressing Run in the Scripts tab. A script can, however, register persistent update callbacks so it continues to run across frames after execution. Both scripts and plugins share the same MiniC API surface, making it straightforward to promote a finished script into a proper plugin.
MiniC is a C-language subset. Standard library headers (#include <stdio.h> and similar), the C preprocessor, pointer arithmetic on arbitrary types, and other advanced C features are not available. Use only the registered builtins exposed through minic_api.c.

MiniC Language

MiniC is a lightweight interpreter embedded directly in ArmorPaint. It understands a large subset of C syntax — structs, pointers, typed arrays, control flow, and function definitions — but it executes scripts through an interpreter rather than compiling them to native code. This makes it suitable for live automation and rapid prototyping directly inside the application. Key characteristics:
  • C-like syntax: functions, structs, if/else, for/while, return, and basic pointer operations work as expected.
  • Registered builtins: all ArmorPaint, engine, math, UI, file, and array APIs are pre-registered as native functions — no #include is required.
  • Garbage-collected heap: memory is managed by ArmorPaint’s GC; use gc_alloc / gc_free for manual control when needed.
  • printf support: the built-in printf formats a string and writes to the Console via console_log.

Script Editor

The Script editor is accessible as Workspace 3 (WORKSPACE_SCRIPT = 3 in enums.h) or by opening the Scripts tab in the right sidebar. The editor features:
  • Syntax highlighting loaded from text_coloring.json.
  • Line numbers and scroll-past-end mode.
  • Minimap — a scaled overview of the full script rendered as a tiny raster, visible when the panel is wider than 800 scaled pixels.
  • Autocomplete (Ctrl+Space) — lists registered builtin names that match the identifier prefix at the cursor.
  • Toggle comment (Ctrl+/) — adds or removes // on the current line.
  • Multiple script files — managed via a combo box; scripts are saved inside the project file as project.script_datas.
To run a script, click the Run button. ArmorPaint calls minic_eval on the current script text, which executes the top-level statements (typically your main() function call).
Use console_log, console_info, and console_error to print diagnostic output while developing scripts. Messages appear in the Console tab at the bottom of the UI.

Script API Reference

Context Access

These functions return live pointers to ArmorPaint’s global state structures. Fields are defined in types.h and exposed to MiniC as registered structs.
// Returns the full application context (tool, brush settings, viewport mode, etc.)
context_t *script_get_context();

// Returns user preferences (window size, plugin list, keymap, theme, etc.)
config_t  *script_get_config();

// Returns the current project (assets, layers, materials, camera, scripts, etc.)
project_t *script_get_project();
typedef struct context {
    mesh_object_t paint_object;  // The active paint mesh object
    int           ddirty;        // Draw dirty flag — set to 2 to force a viewport redraw
    int           pdirty;        // Paint dirty
    int           rdirty;        // Render dirty
    void         *material;      // Active material slot
    void         *layer;         // Active layer slot
    void         *brush;         // Active brush slot
    int           tool;          // Active tool (tool_type_t)
    float         brush_radius;
    float         brush_opacity;
    float         brush_hardness;
    float         brush_scale;
    float         brush_angle;
    int           brush_blending;
    int           viewport_mode; // viewport_mode_t
    int           xray;
    bool          capturing_screenshot;
} context_t;
typedef struct project {
    char          *version;
    string_array_t assets;
    int            is_bgra;
    char          *envmap;
    float          envmap_strength;
    float          envmap_angle;
    float          camera_fov;
    f32_array_t    camera_world;
    f32_array_t    camera_origin;
    void          *swatches;
    void          *brush_nodes;
    void          *material_nodes;
    string_array_t font_assets;
    void          *layer_datas;
    void          *mesh_datas;
    string_array_t script_datas; // All script source strings in the project
} project_t;

Update Callbacks

Scripts can persist across frames by registering callback functions with the engine.
// Register a function to be called every engine frame
void script_notify_on_update(void *fn);

// Register a function to be called exactly once on the next frame
void script_notify_on_next_frame(void *fn);

// Call fn once after delay seconds have elapsed
void script_timer(float delay, void *fn);

Stage Management

ArmorPaint supports named stages (scenes). Scripts can switch stages directly or with a fade transition.
// Immediately switch to the named stage
void  script_set_stage(char *name);

// Fade to black, switch to stage, then fade back in
void  script_fade_to_stage(char *name);

// Return the name of the currently active stage (or NULL)
char *script_get_stage();

Scene Objects

// Find a paint object in g_project by name
object_t *script_get_object(char *name);

// Tween an object's position toward `to` at the given speed
void      script_tween_to(object_t *obj, vec4_t to, float speed);

// Switch the active tilesheet animation on the material of the given object
void      script_set_tilesheet_anim(object_t *obj, char *anim);

Exposed Application API

The following functions from minic_api.c cover the most common scripting operations.

Context Control

// Set the viewport display mode (viewport_mode_t enum)
void context_set_viewport_mode(int mode);

// Set camera control style: 0 = Orbit, 1 = Rotate, 2 = Fly
void context_set_camera_controls(int i);

// Activate a tool by tool_type_t index
void context_select_tool(int i);

// Returns the currently active paint mesh object
mesh_object_t *context_main_object();
VIEWPORT_MODE_NONE          = -1
VIEWPORT_MODE_LIT           =  0
VIEWPORT_MODE_BASE_COLOR    =  1
VIEWPORT_MODE_NORMAL_MAP    =  2
VIEWPORT_MODE_OCCLUSION     =  3
VIEWPORT_MODE_ROUGHNESS     =  4
VIEWPORT_MODE_METALLIC      =  5
VIEWPORT_MODE_OPACITY       =  6
VIEWPORT_MODE_HEIGHT        =  7
VIEWPORT_MODE_EMISSION      =  8
VIEWPORT_MODE_SUBSURFACE    =  9
VIEWPORT_MODE_TEXCOORD      = 10
VIEWPORT_MODE_OBJECT_NORMAL = 11
VIEWPORT_MODE_MATERIAL_ID   = 12
VIEWPORT_MODE_OBJECT_ID     = 13
VIEWPORT_MODE_MASK          = 14
VIEWPORT_MODE_PATH_TRACE    = 15

Project

// Save the current project; pass true to quit after saving
void  project_save(bool save_and_quit);

// Get the current project file path
char *project_filepath_get();

// Override the current project file path
void  project_filepath_set(char *s);

Export

// Export textures to disk at the given path
// Set bake_material to true to bake fill layers before exporting
void export_texture_run(char *path, bool bake_material);

Viewport and Screenshot

// Create an off-screen render target (gpu_texture_format_t for format)
gpu_texture_t *gpu_create_render_target(int width, int height, int format);

// Capture the viewport into target; x/y/w/h are normalised 0–1 UV coordinates
void viewport_capture_screenshot_to(gpu_texture_t *target,
                                     float x, float y, float w, float h);

// Save the captured texture to disk (opens the file-save dialog)
void viewport_save_texture(gpu_texture_t *screenshot);

Console

void console_log(char *s);    // Regular message
void console_info(char *s);   // Informational (highlighted)
void console_error(char *s);  // Error (shown in red)

UI

// Show a modal message box with an optional Copy button
void ui_box_show_message(char *title, char *text, bool copyable);

Automation Example — Batch Export

The following script exports all textures for the current project to a fixed output path and logs a completion message.
void main() {
    export_texture_run("/output/my_texture", false);
    console_log("Export complete");
}
Run it from the Scripts tab by clicking Run. Combine it with script_timer or script_notify_on_update if you need to trigger the export after a delay or condition.

Screenshot Capture Example

This script creates a 2048×2048 render target, captures the full viewport into it, and opens the save dialog.
void main() {
    gpu_texture_t *target = gpu_create_render_target(2048, 2048, 0);
    viewport_capture_screenshot_to(target, 0.0, 0.0, 1.0, 1.0);
    viewport_save_texture(target);
}

Object Rotation Example

The built-in rotate.c template from the Scripts menu shows how to use script_notify_on_update to run code every frame:
void on_update() {
    mesh_object_t *o = context_main_object();
    transform_rotate(o->base->transform, vec4_z_axis(), 0.005);
    context_t *c = script_get_context();
    c->ddirty = 2; // Force a viewport redraw each frame
}

void main() {
    script_notify_on_update(on_update);
}
Setting context.ddirty = 2 after modifying a transform tells the renderer that the scene has changed and a new frame should be drawn. Without it, the viewport may not update.

Build docs developers (and LLMs) love