const Self = @This(); const rl = @import("raylib"); const std = @import("std"); const LayoutFrame = struct { ox: f32, oy: f32, sx: f32, sy: f32, }; const LayoutStack = std.BoundedArray(LayoutFrame, 16); stack: LayoutStack, pub fn init() Self { var stack = LayoutStack.init(0) catch unreachable; stack.append(.{ .ox = 0, .oy = 0, .sx = 1, .sy = 1, }) catch unreachable; return Self { .stack = stack }; } pub fn deinit(self: *Self) void { if (self.stack.len > 1) { @panic(".push() was called more times than .pop()"); } } pub fn top(self: *Self) *LayoutFrame { return &self.stack.buffer[self.stack.len-1]; } pub fn push(self: *Self) void { const top_frame = self.top(); self.stack.append(top_frame.*) catch @panic("LayoutStack is too small, increase hard-coded limit"); } pub fn pop(self: *Self) void { if (self.stack.len == 1) { @panic(".pop() was called more times than .push()"); } _ = self.stack.pop(); } pub fn translate(self: *Self, x: f32, y: f32) void { const top_frame = self.top(); top_frame.ox += x * top_frame.sx; top_frame.oy += y * top_frame.sy; } pub fn scale(self: *Self, x: f32, y: f32) void { const top_frame = self.top(); top_frame.sx *= x; top_frame.sy *= y; } pub fn rect(self: *Self, x: f32, y: f32, width: f32, height: f32) rl.Rectangle { const top_frame = self.top(); return rl.Rectangle { .x = x * top_frame.sx + top_frame.ox, .y = y * top_frame.sy + top_frame.oy, .width = width * top_frame.sx, .height = height * top_frame.sy }; }