diff --git a/src/main.zig b/src/main.zig index 7b64032..412a08d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -323,6 +323,7 @@ pub fn main() !void { .{ .hovered = if (hovered_action) |ha| ha.command else null, .deck = deck_sprites, + .font = canvas.font, }, .{ 0, 0 }, .{ @@ -344,6 +345,7 @@ pub fn main() !void { .{ .hovered = if (hovered_action) |ha| ha.command else null, .deck = deck_sprites, + .font = canvas.font, }, .{ 0, 0 }, .{ @@ -382,6 +384,7 @@ const Action = struct { const RenderResources = struct { hovered: ?[]const u8, deck: DeckSprites, + font: seizer.Canvas.Font, }; pub const Element = struct { @@ -835,6 +838,71 @@ pub const CardElement = struct { } }; +pub const TextElement = struct { + allocator: std.mem.Allocator, + text: []const u8, + command: ?[]const u8, + + pub fn create(allocator: std.mem.Allocator, options: struct { text: []const u8, command: ?[]const u8 }) !*@This() { + const this = try allocator.create(@This()); + errdefer allocator.destroy(this); + + this.* = .{ + .allocator = allocator, + .text = options.text, + .command = options.command, + }; + return this; + } + + pub fn element(this: *@This()) Element { + return Element{ + .pointer = this, + .interface = &Element.Interface{ + .minimum_size = &element_minimum_size, + .render = &element_render, + .get_actions = &element_get_actions, + }, + }; + } + + pub fn element_minimum_size(pointer: ?*anyopaque, render_resources: RenderResources) [2]f32 { + const this: *@This() = @ptrCast(@alignCast(pointer)); + return render_resources.font.textSize(this.text, 1); + } + + pub fn element_render(pointer: ?*anyopaque, canvas: *seizer.Canvas, render_resources: RenderResources, min: [2]f32, max: [2]f32) void { + const this: *@This() = @ptrCast(@alignCast(pointer)); + _ = max; + + const text_size = canvas.writeText(min, this.text, .{}); + + if (render_resources.hovered != null and this.command != null and std.mem.eql(u8, render_resources.hovered.?, this.command.?)) { + canvas.rect( + .{ min[0], min[1] }, + text_size, + .{ .color = .{ 0xAA, 0xFF, 0xAA, 0x60 } }, + ); + } + } + + pub fn element_get_actions(pointer: ?*anyopaque, actions: *std.ArrayList(Action), render_resources: RenderResources, min: [2]f32, max: [2]f32) Element.Error!void { + const this: *@This() = @ptrCast(@alignCast(pointer)); + + _ = render_resources; + + if (this.command) |command| { + try actions.append(.{ + .center = [2]f32{ + (min[0] + max[0]) / 2, + (min[1] + max[1]) / 2, + }, + .command = command, + }); + } + } +}; + /// Handler at the start of a turn, while the player is drawing a card. fn drawCardHandler(arena: std.mem.Allocator, request: Request) HandlerError!Response { if (request.command) |command| { @@ -912,6 +980,14 @@ fn playerTurnHandler(arena: std.mem.Allocator, request: Request) HandlerError!Re } } + var new_meld_text = try TextElement.create(arena, .{ + .text = "New Meld", + .command = "new-meld", + }); + + var melds_hbox = try HBox.create(arena); + try melds_hbox.addElement(new_meld_text.element()); + var draw_pile = try Pile.create(arena, request.game_state.draw_pile.items); draw_pile.hidden = true; @@ -934,6 +1010,7 @@ fn playerTurnHandler(arena: std.mem.Allocator, request: Request) HandlerError!Re var page = try Page.create(arena); try page.addElement(.{ 0.5, 0.5 }, .{ 0.5, 0.5 }, draw_discard_hbox.element()); try page.addElement(.{ 0.5, 1 }, .{ 0.5, 1 }, hand.element()); + try page.addElement(.{ 0.5, 0 }, .{ 0.5, 0 }, melds_hbox.element()); return Response{ .page = page.element() }; }