Debugging Tools and Techniques for ArmorPaint Development: A Complete Guide

ArmorPaint provides a comprehensive debugging ecosystem including --debug command-line builds that generate symbol-rich binaries, an in-app Debug tab for real-time GPU diagnostics, console logging utilities, and support for external native debuggers like GDB, LLDB, and Visual Studio.

ArmorPaint is a 3D painting tool built by the armory3d/armorpaint repository with a hybrid JavaScript build system and C rendering engine. Understanding the debugging tools and techniques for ArmorPaint development is essential for contributors working across both the scripting layer and native graphics code.

Enabling Debug Builds from the Command Line

The build pipeline in base/tools/make.js orchestrates Debug configuration through the --debug flag. When invoked, the script sets goptions.debug to true at line 970, triggering compiler flags that generate binaries with full debug symbols.

Additionally, the runtime in paint/project.js parses command-line arguments at line 5, storing the debug state in flags.embed. This allows the application to detect if it was launched with --debug or --embed flags.

To build and run in Debug mode:


# Generate Debug binaries with symbols

node base/tools/make.js --debug

# Launch with debug runtime checks

./build/Debug/ArmorPaint --debug

The resulting executable retains symbol tables required for breakpoint debugging and enables additional runtime assertions throughout the codebase.

Runtime Debugging Features

Once running a Debug build, ArmorPaint exposes several diagnostic interfaces compiled conditionally via the is_debug macro.

The Debug UI Tab (tab_debug.c)

The dedicated Debug tab, implemented in paint/sources/ui/tab_debug.c, provides visual inspection of render targets and performance counters. This UI component only registers when is_debug is defined during compilation.

In paint/sources/ui/ui_base.c at line 351, conditional blocks push draw callbacks into the UI array when debugging is active:

#ifdef is_debug
    // Add a draw callback that visualises the current render target
    any_array_push(a0, _draw_callback_create(tab_debug_draw));
#endif

This allows developers to overlay texture previews and diagnostic geometry directly in the viewport without affecting Release builds.

In-App Console Logging (console.c)

The central logging API in paint/sources/console.c routes diagnostic messages to the internal console pane. The functions console_log, console_error, console_info, and console_toast provide runtime feedback without external tooling.

Example usage from native code:

console_log("Loaded texture %s", texture_name);
console_error("Failed to load mesh");

These calls appear in the Console tab (tab_console.c), creating a unified logging surface for both JavaScript build messages and C runtime events.

External Debugger Integration

Because Debug builds emit full symbol information, ArmorPaint supports attaching industry-standard native debuggers. The build system generates platform-specific project files that you can open directly in your IDE.

On Linux, navigate to the output directory and launch GDB:

cd build/Debug
gdb ./ArmorPaint
(gdb) run

# Set breakpoints, inspect variables, step through rendering code

For Windows development, running make.js with --debug emits .vcxproj files compatible with Visual Studio. The generated ArmorPaint.sln includes proper Debug configurations with working directory settings and symbol paths pre-configured. On macOS, the script produces .xcodeproj files for LLDB debugging within Xcode.

Performance Profiling and Hot Reloading

Beyond static debugging, ArmorPaint includes dynamic analysis tools for GPU optimization and script iteration.

Frame Performance Monitoring (main.c)

The Debug tab captures real-time metrics through the notification system defined in paint/sources/main.c at line 391. Using sys_notify_on_next_frame callbacks, the engine records frame times, draw-call counts, and GPU memory allocation statistics.

This instrumentation helps identify bottlenecks in the rendering pipeline by correlating CPU-side code execution with GPU frame metrics displayed in the Debug UI.

Script Console for Rapid Iteration (tab_console.c)

The console supports hot-reloading via text_to_text_node_run, allowing developers to execute JavaScript commands at runtime by typing into the Console tab. Errors return immediately to the console pane, creating a fast feedback loop for testing build logic or automation scripts without restarting the application.

Summary

  • Debug builds are enabled via --debug in make.js, generating symbol-rich binaries in build/Debug/ with the _DEBUG and is_debug definitions.
  • In-app diagnostics include the Debug tab (tab_debug.c) for render target inspection and the Console (console.c) for logging via console_log() and related functions.
  • Conditional compilation wraps debug-only code in #ifdef is_debug blocks, ensuring zero overhead in Release binaries.
  • External tooling integrates with GDB, LLDB, Visual Studio, and Xcode through automatically generated project files.
  • Performance profiling leverages frame callbacks in main.c to display real-time GPU statistics.

Frequently Asked Questions

How do I compile ArmorPaint in Debug mode?

Run the build script with the --debug flag: node base/tools/make.js --debug. This sets goptions.debug in the build configuration, passes -g to the compiler, and defines is_debug for conditional compilation.

Where are debug symbols stored in ArmorPaint builds?

Debug symbols are embedded directly into the executables located in build/Debug/. The make.js script configures the compiler to generate these symbols automatically when the Debug flag is present.

Can I use Visual Studio to debug ArmorPaint?

Yes. The build system generates .vcxproj and .sln files when you run the Debug configuration. Open ArmorPaint.sln in Visual Studio, set breakpoints in the C source files, and press F5 to launch the debugger with full symbol support.

How do I view render targets and GPU performance in real-time?

Open the Debug tab in the UI, which is available only in Debug builds. This panel, driven by tab_debug.c and updated via callbacks in main.c, displays live render target previews, frame times, and memory statistics without requiring external profiling tools.

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 →