How to Customize Themes and UI Configuration in ArmorPaint

ArmorPaint's visual appearance is controlled by a global g_theme structure that defines colors, dimensions, and layout parameters, enabling deep UI customization through source code modification, runtime patching, or JSON configuration files.

ArmorPaint (from the armory3d/armorpaint repository) implements its user interface through the Kinc UI layer, utilizing a centralized theming system that decouples visual styling from drawing logic. The global g_theme structure, accessed throughout paint/sources/ui/, stores every color value, size constant, and layout flag used when rendering windows, toolbars, sidebars, and menus. By manipulating this structure, you can transform the application's entire look-and-feel without touching the underlying drawing code.

Understanding the Global g_theme Structure

The g_theme struct serves as the single source of truth for all UI cosmetic properties in ArmorPaint. When the application initializes, this structure is populated with default values that subsequent drawing routines reference via direct field access. Because the theme is global, any modification—whether compiled into the binary or applied at runtime—immediately propagates to all interface elements.

Key fields within g_theme include hexadecimal color values for backgrounds and separators, pixel dimensions for buttons and scrollbars, and boolean flags controlling shadows and fill behaviors. The UI code in paint/sources/ui/ reads these fields every frame, ensuring dynamic theme changes take effect instantly.

Key Theme Parameters and Default Values

The g_theme structure exposes granular control over ArmorPaint's interface aesthetics. The following parameters represent the most commonly customized fields:

  • WINDOW_BG_COL – Background color of primary windows (default: 0xff2d2d2d)
  • SEPARATOR_COL – Color of divider lines between UI sections (default: 0xff4b4b4b)
  • HIGHLIGHT_COL – Accent color for selected or active elements (default: 0xffc0c0c0)
  • BUTTON_COL – Default button background color (defaults to WINDOW_BG_COL)
  • ELEMENT_H – Standard height in pixels for UI components (default: 28)
  • BUTTON_H – Specific height for button elements (typically set equal to ELEMENT_H)
  • FILL_BUTTON_BG – Boolean controlling whether buttons render solid backgrounds (default: true)
  • SHADOWS – Boolean enabling drop-shadow effects under UI elements (default: true)
  • SCROLL_W – Width of full scrollbars in pixels (default: 12)
  • SCROLL_MINI_W – Width of minimized scrollbars (default: 8)

Three Methods to Customize ArmorPaint Themes

You can customize the interface through three distinct approaches, each offering different trade-offs between permanence, flexibility, and ease of distribution.

Method 1: Editing Source and Rebuilding

For permanent, baked-in theme changes, modify the default value assignments in the theme initialization code. This typically occurs in paint/sources/util/util_ui.c or within the Kinc UI startup routine.

After adjusting the hex colors or dimension values, recompile the project using make or your platform-specific build scripts. The resulting binary will contain your custom theme as the new default, eliminating the need for external configuration files.

Method 2: Runtime Patching in main.c

To override themes programmatically without rebuilding the entire application, insert assignment statements early in main.c or any initialization function that executes before the first UI draw call. Because g_theme is a global pointer, direct field modifications take effect immediately across all subsequent drawing operations.

This approach is ideal for developers creating custom builds or testing color schemes iteratively without waiting for full recompilation cycles.

Method 3: JSON Configuration Files

ArmorPaint supports external theme overrides through JSON configuration files such as base/project.js or generated krom settings. Add entries mapping theme field names to hex or integer values, and the parsing code will populate g_theme during startup.

This method allows end users to customize their interface without accessing source code or recompiling, as the application reads these values at runtime before initializing the UI system.

Core UI Files That Reference Theme Values

The following source files in paint/sources/ui/ directly consume g_theme fields, determining how your customizations manifest visually:

  • ui_toolbar.c (lines 44-53) – Reads HIGHLIGHT_COL for toolbar backgrounds and temporarily mutates ELEMENT_H, BUTTON_H, and BUTTON_COL during drawing operations.
  • ui_sidebar.c (lines 18-20) – Swaps BUTTON_COL with SEPARATOR_COL when rendering sidebar backgrounds, then restores the original value.
  • ui_view2d.c (lines 379-382) – Applies WINDOW_BG_COL and SEPARATOR_COL to the 2D viewport interface.
  • ui_nodes.c (lines 108-112) – Customizes BUTTON_COL and SHADOWS flags specifically for the node editor's search interface.
  • ui_menubar.c (lines 98-102) – Handles menubar background rendering and highlight states using theme colors.
  • ui_menu.c (lines 40-45) – Temporarily disables FILL_BUTTON_BG and adjusts element heights when drawing dropdown menus.

Practical Implementation Examples

The following code snippets demonstrate how to implement each customization method in practice.

Hard-Coding a Dark Theme in main.c

This example overrides the default theme immediately after UI initialization to create a high-contrast dark interface with gold accents:

/* After engine and UI initialization */
g_theme->WINDOW_BG_COL   = 0xff181818;   // Deep charcoal background
g_theme->SEPARATOR_COL   = 0xff404040;   // Subtle separators
g_theme->HIGHLIGHT_COL   = 0xffffd700;   // Gold highlights
g_theme->ELEMENT_H       = 34;           // Larger touch targets
g_theme->BUTTON_H        = g_theme->ELEMENT_H;
g_theme->BUTTON_COL      = g_theme->WINDOW_BG_COL;
g_theme->FILL_BUTTON_BG  = true;
g_theme->SHADOWS         = false;        // Flat design aesthetic

Loading Colors from JSON Configuration

Define your theme in a configuration file (e.g., ui_config.json):

{
  "window_bg_col": "0xff181818",
  "separator_col": "0xff404040",
  "highlight_col": "0xffffd700",
  "element_h": 34,
  "fill_button_bg": true,
  "shadows": false
}

Parse these values during application startup:

/* After parsing JSON data */
if (json_has(data, "window_bg_col"))
    g_theme->WINDOW_BG_COL = json_get_u32(data, "window_bg_col");
if (json_has(data, "separator_col"))
    g_theme->SEPARATOR_COL = json_get_u32(data, "separator_col");
if (json_has(data, "highlight_col"))
    g_theme->HIGHLIGHT_COL = json_get_u32(data, "highlight_col");
if (json_has(data, "element_h"))
    g_theme->ELEMENT_H = json_get_i32(data, "element_h");
g_theme->BUTTON_H = g_theme->ELEMENT_H;
if (json_has(data, "fill_button_bg"))
    g_theme->FILL_BUTTON_BG = json_get_bool(data, "fill_button_bg");
if (json_has(data, "shadows"))
    g_theme->SHADOWS = json_get_bool(data, "shadows");

Temporary Runtime Color Override

For contextual UI changes within specific drawing routines, save and restore theme values:

// Inside a custom node drawing function
u32 original_color = g_theme->BUTTON_COL;    // Preserve current theme
g_theme->BUTTON_COL = 0xff0066ff;           // Apply temporary blue
ui_draw_button(...);                         // Draw with custom color
g_theme->BUTTON_COL = original_color;       // Restore global theme

Summary

  • ArmorPaint theming centers on the global g_theme structure defined in the Kinc UI layer and accessed throughout paint/sources/ui/.
  • Key customizable parameters include WINDOW_BG_COL, HIGHLIGHT_COL, ELEMENT_H, BUTTON_H, and boolean flags like SHADOWS and FILL_BUTTON_BG.
  • Three implementation strategies exist: editing source code in util_ui.c for permanent changes, patching values in main.c for runtime overrides, and loading external JSON configurations for user-level customization.
  • Critical files consuming theme data include ui_toolbar.c, ui_sidebar.c, ui_view2d.c, and ui_nodes.c, each referencing specific g_theme fields to determine rendering behavior.

Frequently Asked Questions

Where is the theme configuration stored in ArmorPaint?

The theme configuration resides in the global g_theme struct, typically initialized in paint/sources/util/util_ui.c or the Kinc UI startup routine, with runtime usage distributed across files in paint/sources/ui/ such as ui_toolbar.c and ui_sidebar.c.

Do I need to rebuild ArmorPaint to change UI colors?

No. While editing defaults in the source code requires recompilation, you can override colors at runtime by modifying g_theme fields in main.c before the UI renders, or by loading a JSON configuration file that the application parses into the theme structure on startup.

What is the easiest way to modify UI element sizes?

Adjust the ELEMENT_H field in g_theme, which controls the standard height for most interface components. Remember to also update BUTTON_H to match if you want consistent button sizing, as seen in the source code where these values are通常 assigned together.

Can I change themes dynamically while ArmorPaint is running?

Yes. Because g_theme is a global structure accessed during every draw call, modifications to its fields take effect immediately without restarting the application. You can temporarily override values for specific drawing operations (such as changing a button color for a single frame) then restore the original values, as demonstrated in ui_sidebar.c when it swaps BUTTON_COL with SEPARATOR_COL during sidebar rendering.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →