# How to Customize Themes and UI Configuration in ArmorPaint

> Customize ArmorPaint themes and UI configuration. Learn to modify colors, dimensions, and layout using source code, runtime patching, or JSON files for a personalized workflow.

- Repository: [Armory 3D/armorpaint](https://github.com/armory3d/armorpaint)
- Tags: how-to-guide
- Published: 2026-09-11

---

**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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/ui_sidebar.c)** (lines 18-20) – Swaps `BUTTON_COL` with `SEPARATOR_COL` when rendering sidebar backgrounds, then restores the original value.
- **[`ui_view2d.c`](https://github.com/armory3d/armorpaint/blob/main/ui_view2d.c)** (lines 379-382) – Applies `WINDOW_BG_COL` and `SEPARATOR_COL` to the 2D viewport interface.
- **[`ui_nodes.c`](https://github.com/armory3d/armorpaint/blob/main/ui_nodes.c)** (lines 108-112) – Customizes `BUTTON_COL` and `SHADOWS` flags specifically for the node editor's search interface.
- **[`ui_menubar.c`](https://github.com/armory3d/armorpaint/blob/main/ui_menubar.c)** (lines 98-102) – Handles menubar background rendering and highlight states using theme colors.
- **[`ui_menu.c`](https://github.com/armory3d/armorpaint/blob/main/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:

```c
/* 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`](https://github.com/armory3d/armorpaint/blob/main/ui_config.json)):

```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:

```c
/* 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:

```c
// 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`](https://github.com/armory3d/armorpaint/blob/main/util_ui.c) for permanent changes, patching values in [`main.c`](https://github.com/armory3d/armorpaint/blob/main/main.c) for runtime overrides, and loading external JSON configurations for user-level customization.
- **Critical files** consuming theme data include [`ui_toolbar.c`](https://github.com/armory3d/armorpaint/blob/main/ui_toolbar.c), [`ui_sidebar.c`](https://github.com/armory3d/armorpaint/blob/main/ui_sidebar.c), [`ui_view2d.c`](https://github.com/armory3d/armorpaint/blob/main/ui_view2d.c), and [`ui_nodes.c`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/ui_toolbar.c) and [`ui_sidebar.c`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/ui_sidebar.c) when it swaps `BUTTON_COL` with `SEPARATOR_COL` during sidebar rendering.