Repository navigation
SparkConsole
SparkConsole is a standalone debug console application. Windows uses named pipes for engine communication; non-Windows builds expose bidirectional inherited stdin/stdout development transport. It provides development-time inspection and registered commands.
Release boundary: SparkConsole is a required Windows build product in
stable-v1, but the profile and this transport are blocked and uncertified. Non-Windows console paths are development implementations outside the profile.
Source: SparkConsole/src/
┌──────────────────────────────┐ Windows Named Pipes ┌──────────────────────────────┐
│ SparkEngine │ ◄──────────────────► │ SparkConsole │
│ │ │ │
│ ┌────────────────────────┐ │ Engine Output │ ┌────────────────────────┐ │
│ │ SimpleConsole │ │ ──────────────────► │ │ ConsoleApp │ │
│ │ (thread-safe logger) │ │ │ │ (main loop + display) │ │
│ └────────────────────────┘ │ User Commands │ ├────────────────────────┤ │
│ │ ◄──────────────────── │ │ CommandParser │ │
│ ┌────────────────────────┐ │ │ │ (tokenize + parse) │ │
│ │ Engine Subsystems │ │ │ ├────────────────────────┤ │
│ │ (Graphics, Physics, │ │ │ │ CommandRegistry │ │
│ │ Audio, Input, etc.) │ │ │ │ (register + dispatch) │ │
│ └────────────────────────┘ │ │ └────────────────────────┘ │
└──────────────────────────────┘ └──────────────────────────────┘
| File | Responsibility |
|---|---|
ConsoleApp.h |
Main application class -- run loop, I/O threads, display, tab completion, aliases |
CommandParser.h |
Static utility -- tokenizes command lines respecting quoted strings |
CommandRegistry.h |
Command storage -- registers handlers, dispatches commands, provides help |
SparkConsole runs as a separate process alongside SparkEngine. On the Windows
development path, the engine launches it and establishes bidirectional named
pipes. The full log path is longer than the diagram: SPARK_LOG_* -> Spark::Logger
-> ConsoleSink -> SimpleConsole -> ConsoleProcessManager pipe ->
SparkConsole.exe. Logger::InstallDefaultSinks (called once per process by the
gameplay lifecycle) installs the ConsoleSink together with the FileSink that
writes the per-user Logs/SparkEngine_<timestamp>.log; until that call runs, log
macros do not reach the console process. InstallDefaultSinks begins with ClearSinks(), so it
must run before any editor panel registers its own sink — a panel sink installed first is
silently dropped. The engine-to-console mirror queue is bounded at 4096 lines with drop-oldest and
emits a single [WARN] SparkConsole mirror dropped N log line(s): outgoing queue full notice per
burst once the pipe drains; the log file keeps the full record.
ConsoleProcessManager::Initialize() returning true only means "initialization attempted without
error" (child launched, no trusted executable found, or the console compiled out of a Shipping
build) — IsConsoleRunning() is the liveness answer. SparkConsole's human-facing output goes to
its own console screen buffer (CONOUT$, allocating a console if the launching
process has none); stdout is reserved exclusively for commands sent back to the
engine on Windows as well as Linux, and the console no longer feeds its own
banner to the engine as commands. Non-Windows paths use inherited stdin/stdout and
do not implement the same pipe transport.
-
Engine Output: SparkEngine writes log messages (via the installed
ConsoleSink), diagnostic data, and command results to the output pipe - User Commands: SparkConsole reads user input, parses it, and either handles it locally or forwards it to the engine via the input pipe
-
Background Thread: A dedicated
m_engineInputThreadreads engine output asynchronously, protected bym_outputMutex
On the Windows development path, SparkEngine attempts to launch SparkConsole only
when the packaged console executable can be resolved and -no-subprocess is not
present. Otherwise launch it explicitly and provide the applicable transport.
cd build\bin
SparkConsole.exeIn standalone mode, SparkConsole provides local diagnostics and built-in commands but cannot control the engine (engine-forwarded commands will report "not connected").
class ConsoleApp {
public:
ConsoleApp();
~ConsoleApp();
void Run(); // Main execution loop
private:
// Thread functions
void ReadEngineInput(); // Background thread: reads engine pipe
void ReadUserInput(); // Main thread: reads keyboard input
// Display
void PrintLog(const std::wstring& msg);
void PrintEngineLog(const std::wstring& msg);
void PrintResult(const std::string& result);
void SetConsoleColor(WORD color); // Windows
void SetConsoleColor(int color); // Linux
// Command handling
void ExecuteCommand(const std::string& cmdLine);
void RegisterDefaultCommands();
bool ShouldForwardToEngine(const std::string& command);
// History management
void AddToHistory(const std::string& cmd);
std::string GetPreviousCommand(); // Up arrow
std::string GetNextCommand(); // Down arrow
// Tab completion
std::vector<std::string> GetCompletions(const std::string& prefix);
void HandleTabCompletion(std::string& input);
// Alias system
std::string ResolveAlias(const std::string& input);
};The CommandRegistry stores all registered commands and dispatches execution:
class CommandRegistry {
public:
struct CommandInfo {
std::string name; // Command name (e.g., "physics_info")
std::string description; // Human-readable description
std::string usage; // Usage string (e.g., "physics_gravity <x y z>")
CommandHandler handler; // std::function<std::string(const CommandArgs&)>
};
void RegisterCommand(const std::string& name,
const std::string& description,
const std::string& usage,
CommandHandler handler);
std::string ExecuteCommand(const std::string& name, const CommandArgs& args);
bool HasCommand(const std::string& name) const;
std::vector<CommandInfo> GetAllCommands() const;
std::string GetCommandHelp(const std::string& name) const;
};The CommandParser tokenizes command lines while respecting quoted strings:
class CommandParser {
public:
// Parse "physics_gravity 0 -9.81 0" into name="physics_gravity", args=["0","-9.81","0"]
static bool ParseCommandLine(const std::string& commandLine,
std::string& commandName,
CommandArgs& args);
// Tokenize with quote support: 'echo "hello world"' -> ["echo", "hello world"]
static std::vector<std::string> Tokenize(const std::string& commandLine);
};help # List all available commands with descriptions
engine_status # Show engine system initialization status (all subsystems)
status # Quick engine status summary
diag # Run full diagnostics (memory, GPU, CPU, subsystems)
fps # Show current framerate and frame time
quit # Shut down the engine gracefully
Graphics Commands (see Rendering and Graphics)
graphics_info # GPU adapter, driver version, feature level
render_path <path> # Set render pipeline: forward, deferred, forward+, clustered
quality <preset> # Set quality preset: low, medium, high, ultra
wireframe # Toggle wireframe rendering mode
ssao <on|off> # Toggle screen-space ambient occlusion
ssr <on|off> # Toggle screen-space reflections
bloom <on|off> # Toggle bloom post-processing
msaa <1|2|4|8> # Set MSAA sample count
vsync <on|off> # Toggle vertical sync
resolution <w> <h> # Set render resolution
fullscreen # Toggle fullscreen mode
Physics Commands (see Physics)
physics_info # Physics world statistics (body count, constraint count, etc.)
physics_gravity <x y z> # Set gravity vector (default: 0 -9.81 0)
physics_debug <on|off> # Toggle collision shape debug visualization
physics_pause # Pause physics simulation
physics_step # Single-step physics by one fixed timestep
physics_material <name> # Show properties of a named physics material
Audio Commands (see Audio)
audio_info # Audio system status (XAudio2 device, channel count)
audio_master <vol> # Set master volume (0.0-1.0)
audio_sfx <vol> # Set SFX channel volume (0.0-1.0)
audio_music <vol> # Set music channel volume (0.0-1.0)
audio_play <name> # Play a loaded sound by name
audio_stop_all # Stop all currently playing sounds
audio_list # List all loaded sound resources
audio_sources # Show active audio source positions and states
Input Commands (see Input System)
input_info # Input system status (mouse state, key count, gamepad)
input_sensitivity <val> # Set mouse sensitivity multiplier (0.1-10.0)
input_deadzone <val> # Set mouse dead zone threshold (0.0-10.0)
input_invert_y # Toggle Y-axis inversion for mouse look
input_bindings # List all current key bindings
input_log <on|off> # Toggle input event logging to console
input_stats # Show input statistics (press counts, mouse distance)
Scene Commands (see Scene Management)
scene_info # Current scene info (node count, lights, cameras)
scene_list # List all scene nodes with hierarchy
scene_load <path> # Load a scene from file
scene_save <path> # Save current scene to file
scene_clear # Clear all scene nodes
profile_start # Start profiling session (begins capturing data)
profile_stop # Stop profiling session
profile_report # Print profiling report (function timings, call counts)
profile_gpu # GPU timing data per pass (geometry, lighting, post-process)
memory_info # Memory usage report (system RAM, VRAM, allocations)
frame_time # Frame time breakdown (CPU, GPU, present, idle)
Networking Commands (see Networking)
net_info # Network status (connected, protocol, session ID)
net_stats # Ping, jitter, packet loss, bandwidth
net_connect <host> <port> # Connect to a game server
net_disconnect # Disconnect from current server
Scripting Commands (see Scripting with AngelScript)
script_reload # Hot-reload all AngelScript files
script_run <file> # Execute a script file immediately
script_list # List all loaded script modules
time_set <hour> # Set time of day (0-24, decimal hours)
time_speed <mult> # Set time progression speed (1.0 = real-time)
weather_set <type> # Set weather type: clear, rain, snow, fog, storm
weather_intensity <val> # Set weather intensity (0.0-1.0)
When a command is entered, SparkConsole determines whether to handle it locally or forward it to the engine:
User Input
│
▼
CommandParser::ParseCommandLine()
│
├─► Local command? (help, clear, alias, history)
│ │
│ ▼
│ CommandRegistry::ExecuteCommand()
│ │
│ ▼
│ Display result locally
│
└─► Engine command? (physics_*, graphics_*, audio_*, etc.)
│
▼
Forward via named pipe to SparkEngine
│
▼
Engine processes command
│
▼
Result returned via output pipe
│
▼
Display result in console
Commands are forwarded to the engine when they are not registered in the local CommandRegistry. Built-in local commands include: help, clear, history, alias, exit.
SparkConsole supports tab completion for command names:
- Press Tab to cycle through matching completions
- The completion list is populated from all registered commands (both local and engine-side)
- Pressing Tab multiple times cycles through all matches
- The completion state resets when the input changes
// Internal state
std::vector<std::string> m_tabCompletions;
int m_tabIndex = -1;
std::string m_tabPrefix;- Up Arrow: Navigate to previous commands
- Down Arrow: Navigate to next commands
- History is stored in
m_commandHistory(vector of strings) - Protected by
m_historyMutexfor thread safety - Maximum history depth is unlimited within a session
Define command shortcuts:
alias gs "graphics_info"
alias pg "physics_gravity 0 -9.81 0"
alias reset "quality high; vsync on; msaa 4"
Aliases are stored in m_aliases (std::unordered_map<std::string, std::string>) and resolved before command parsing via ResolveAlias().
Engine subsystems register their own console commands during initialization. Each subsystem calls RegisterCommand() on the engine's console system with:
-
Command name -- unique identifier (e.g.,
physics_gravity) - Description -- human-readable help text
-
Usage string -- parameter documentation (e.g.,
physics_gravity <x y z>) -
Handler function --
std::function<std::string(const CommandArgs&)>that processes arguments and returns a result string
// In your subsystem initialization:
console.RegisterCommand(
"mycommand",
"Description of what this command does",
"mycommand <arg1> [arg2]",
[this](const CommandArgs& args) -> std::string {
if (args.empty()) return "Error: missing argument";
// Process command...
return "Command executed successfully";
}
);SparkConsole uses multiple threads for responsive I/O:
| Thread | Purpose | Synchronization |
|---|---|---|
| Main thread | User input reading, command execution | -- |
| Engine input thread | Reads engine pipe output asynchronously | m_outputMutex |
| (both) | Access to command history | m_historyMutex |
The m_running flag (std::atomic<bool>) signals all threads to shut down cleanly.
Engine output messages are buffered in m_messageBuffer (std::deque<std::wstring>) with a maximum size of 1000 entries to prevent unbounded memory growth. Oldest messages are discarded when the limit is reached.
- Windows named-pipe communication is local IPC; no latency budget is certified
- The engine input thread runs continuously but blocks on pipe reads (no CPU spin)
- Message buffer caps at 1000 entries to bound memory usage
- Tab completion scans the registered command set linearly
- Command parsing uses simple tokenization -- no regex or complex grammar
| Platform | Communication | Status |
|---|---|---|
| Windows 11 x64 | Named Pipes (HANDLE) |
Required stable-v1 product path; blocked/uncertified |
| Linux | stdout / stdin (file descriptors) | Bidirectional inherited development transport |
| macOS | stdout / stdin | Bidirectional inherited development transport |
On non-Windows platforms, m_consoleOutput and m_consoleInput are integer file descriptors instead of Windows HANDLE values. The SetConsoleColor() function uses ANSI escape codes instead of SetConsoleTextAttribute().
- Pipe disconnection: If the engine process terminates, the engine input thread detects the broken pipe and prints a "connection lost" message. SparkConsole continues in standalone mode.
- Unknown commands: Commands not found in the local registry are forwarded to the engine. If the engine also does not recognize them, an "unknown command" error is returned.
- Malformed arguments: Each command handler is responsible for validating its arguments and returning descriptive error messages.
-
Thread shutdown: The destructor joins
m_engineInputThreadafter settingm_running = false.
SparkEngine failed to launch or crashed during startup. Check:
- Both executables exist in
build/bin/ - Run with a debugger attached for error details
- Verify named pipe permissions (run as same user)
- Run
engine_statusto check which subsystems initialized successfully - Verify the engine's main loop is running (CPU usage should be active)
- Check for a deadlock -- if the engine is blocked on a dialog or assertion, pipe communication stalls
- Ensure commands are registered before SparkConsole connects
- Try
helpto verify the command list is populated
- Ensure your terminal supports ANSI escape codes
- Some terminals require
TERM=xterm-256color
- Getting Started -- Running SparkConsole
- Troubleshooting -- Common console issues
- Rendering and Graphics -- Graphics commands and render paths
- Physics -- Physics simulation commands
- Audio -- Audio system commands
- AI and Navigation -- AI and pathfinding systems
- Scene Management -- Scene loading and management
- Terrain and Procedural Generation -- Weather and terrain systems
- Input System -- Input debugging commands
- Event System -- Event-related commands
Published from 2b03dc797148. Edit the canonical source in wiki/.
- Documentation
- Docs route
- Wiki index
- Guides
- Tutorials
- Samples
- Examples
- API Reference
- API route
- Reference
- Build Guide
- Dependencies
- FAQ
- Changelog
- Roadmap
- Contributing
- Code of Conduct
- Home
- FAQ
- Getting Started
- Quick-Start Tutorial
- Making Your First Game
- Making Your First Multiplayer Game
- Artist Workflow Guide
- Editor Walkthrough
- Migration Guide
- How SparkEngine Works
- Architecture Overview
- Engine Architecture Flowchart
- Creating a Game Module
- Game Modules (catalog)
- Entity Component System
- Rendering and Graphics
- Physics
- Cloth Simulation
- Audio
- Input System
- Camera System
- Scripting with AngelScript
- Visual Scripting
- AI and Navigation
- Animation
- 2D Systems
- Networking
- Dedicated Server
- Multiplayer Quick Start
- Area Server Architecture
- Scene Management
- Large World Support
- Collaborative Editing
- Coroutine System
- Event System
- Event Response System
- Job System
- UI System
- UI Layout Extensions
- Localization
- Dialogue System
- Destruction System
- Replay System
- Achievement System
- Loading System
- Mod System
- Content Delivery
- Tween System
- Memory Integrity
- Gameplay Systems
- Terrain and Procedural Generation
- Save System
- Persistence System
- Day Night Cycle and Weather
- Cinematic Sequencer
- Runtime Prefabs
- SparkEditor
- Editor Tutorials
- SparkConsole
- SparkDaemon
- Shader Pipeline
- Asset Pipeline
- Asset Validation
- Asset Migration
- Game Packaging
- Online Services
- DataTable System
- Loot and Crafting System
- CSG System
- Font System
- Timer Manager
- Movie Render Pipeline
- HLOD and World Partition
- Remote Debug System
- Selection Manager
- Asset Dependency Graph
- Editor Automation
- File Watcher
- Project Templates
- System Requirements
- VR Support
- Mobile Platform
- Accessibility
- Platform Input
- Platform Certification
- Cross-Compilation: Wine Testing
- RHI Abstraction Layer
- D3D11 Backend
- D3D12 Backend
- Vulkan Backend
- OpenGL Backend
- Metal Backend
- DXR Raytracing
- Hybrid Ray Tracing
- Upscaling (DLSS/FSR)
- Render Graph
- Shader Graph
- GPU Particles
- GPU-Driven Rendering
- Volumetric Fog
- Volumetric Clouds
- Global Illumination
- Virtual Texturing
- Water Rendering
- Clustered Lighting
- Material System
- Post-Processing
- Shadow System
- Particle System
- Decal System
- Sky and Atmosphere
- Foliage System
- Mesh Shaders
- Neural Rendering
- Configuration Reference
- Performance Tips
- Benchmark Framework
- Threading Model
- Fuzz Policy and Parser Security
- Memory Safety
- Memory Management Patterns
- Build System and CMake Modules
- Profiler and Debugging
- Performance Profiling Guide
- Telemetry System
- Crash Reporting
- Golden Image Testing
- Utilities
- Testing
- Fuzz Policy and Parser Security
- Codebase Statistics
- Codebase Health
- Error Handling Patterns
- Hot Reload Overview
- Troubleshooting
- Contributing
- Workflow Patterns
- Build Optimizations
- CI Reproducible Builds
- GitHub API and PR Checks
- Git Rebase Conflicts
- Clang-Format
- Code Quality Violations
- AI Bloat Pattern
- MinGW + Wine Cross-Compilation
- Live Editor Testing
- Engine & Renderer Landscape
- DuetOS Portability Catalog
- Five-Engine Analysis
- Eleven-Engine Analysis
- ThorVG / Unity Graphics Analysis
- Advanced Techniques Catalog
- Third-Party Library Evaluation
- Engine Viability Evaluation
- Engine Feature Recommendations
- Project Recommendations
- Mac Compatibility Analysis
- Codebase Observations
- Codebase Bloat Audit
- Test Suite Audit
- Documentation Coverage Audit
- ThirdParty Dependencies Audit
- Load Test Baseline
- Gameplay Systems Status
- SparkGame Module Status
- Stub and Abandoned Features
- Memory Integrity System
- Memory Safety Evaluation
- Hardware Acceleration Systems
- Jolt Physics Integration
- GPU/CPU Separation Plan
- Daemon Services Architecture
- Reflection & Polymorphism Refactoring Plan
- SparkBuild In-Tree
- Wine No-JobSystem Breakthrough
- Wine Role and Fallback Tiers