zcatgui/src/core/command.zig
reugenio 59c597fc18 feat: zCatGui v0.1.0 - Initial project setup
Immediate Mode GUI library for Zig with software rendering.

Core features:
- SDL2 backend for cross-platform window/events
- Software rasterizer (works everywhere, including SSH)
- Macro recording system (cornerstone feature, like Vim)
- Command-list rendering (DrawRect, DrawText, etc.)
- Layout system with constraints
- Color/Style system with themes

Project structure:
- src/core/: context, command, input, layout, style
- src/macro/: MacroRecorder, MacroPlayer, MacroStorage
- src/render/: Framebuffer, SoftwareRenderer, Font
- src/backend/: Backend interface, SDL2 implementation
- examples/: hello.zig, macro_demo.zig
- docs/: Architecture, research (Gio, immediate-mode libs, Simifactu)

Build: zig build (requires SDL2-devel)
Tests: 16 tests passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-09 01:30:05 +01:00

159 lines
3.5 KiB
Zig

//! DrawCommand - Rendering commands for the software rasterizer
//!
//! The immediate mode UI generates a list of DrawCommands each frame.
//! The software rasterizer then processes these commands to produce pixels.
//!
//! This is the "command list" approach (like microui), not vertex buffers.
const Style = @import("style.zig");
/// A single draw command
pub const DrawCommand = union(enum) {
/// Draw a filled rectangle
rect: RectCommand,
/// Draw text
text: TextCommand,
/// Draw a line
line: LineCommand,
/// Draw a rectangle outline (border)
rect_outline: RectOutlineCommand,
/// Begin clipping to a rectangle
clip: ClipCommand,
/// End clipping
clip_end,
/// No operation (placeholder)
nop,
};
/// Draw a filled rectangle
pub const RectCommand = struct {
x: i32,
y: i32,
w: u32,
h: u32,
color: Style.Color,
};
/// Draw text at a position
pub const TextCommand = struct {
x: i32,
y: i32,
text: []const u8,
color: Style.Color,
/// null means default font
font: ?*anyopaque = null,
};
/// Draw a line between two points
pub const LineCommand = struct {
x1: i32,
y1: i32,
x2: i32,
y2: i32,
color: Style.Color,
};
/// Draw a rectangle outline
pub const RectOutlineCommand = struct {
x: i32,
y: i32,
w: u32,
h: u32,
color: Style.Color,
thickness: u32 = 1,
};
/// Begin clipping to a rectangle
pub const ClipCommand = struct {
x: i32,
y: i32,
w: u32,
h: u32,
};
// =============================================================================
// Helper constructors
// =============================================================================
/// Create a rect command
pub fn rect(x: i32, y: i32, w: u32, h: u32, color: Style.Color) DrawCommand {
return .{ .rect = .{
.x = x,
.y = y,
.w = w,
.h = h,
.color = color,
} };
}
/// Create a text command
pub fn text(x: i32, y: i32, str: []const u8, color: Style.Color) DrawCommand {
return .{ .text = .{
.x = x,
.y = y,
.text = str,
.color = color,
} };
}
/// Create a line command
pub fn line(x1: i32, y1: i32, x2: i32, y2: i32, color: Style.Color) DrawCommand {
return .{ .line = .{
.x1 = x1,
.y1 = y1,
.x2 = x2,
.y2 = y2,
.color = color,
} };
}
/// Create a rect outline command
pub fn rectOutline(x: i32, y: i32, w: u32, h: u32, color: Style.Color) DrawCommand {
return .{ .rect_outline = .{
.x = x,
.y = y,
.w = w,
.h = h,
.color = color,
} };
}
/// Create a clip command
pub fn clip(x: i32, y: i32, w: u32, h: u32) DrawCommand {
return .{ .clip = .{
.x = x,
.y = y,
.w = w,
.h = h,
} };
}
/// Create a clip end command
pub fn clipEnd() DrawCommand {
return .clip_end;
}
// =============================================================================
// Tests
// =============================================================================
const std = @import("std");
test "DrawCommand creation" {
const cmd = rect(10, 20, 100, 50, Style.Color.red);
switch (cmd) {
.rect => |r| {
try std.testing.expectEqual(@as(i32, 10), r.x);
try std.testing.expectEqual(@as(i32, 20), r.y);
try std.testing.expectEqual(@as(u32, 100), r.w);
try std.testing.expectEqual(@as(u32, 50), r.h);
},
else => unreachable,
}
}