From 7b73c7c18e450cdf1b934aecf810e5aebf10acac Mon Sep 17 00:00:00 2001 From: Jeeves Date: Sat, 31 May 2025 22:59:33 -0600 Subject: [PATCH] month-based background color --- src/main.zig | 90 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 7 deletions(-) diff --git a/src/main.zig b/src/main.zig index 3b51e22..b55b038 100644 --- a/src/main.zig +++ b/src/main.zig @@ -11,6 +11,8 @@ pub fn main() !void { raylib.SetWindowMaxSize(1920, 1080); scales = Scales.init(); + datetime = DateTime{ .secs = @intCast(std.time.timestamp()) }; + global_font = raylib.LoadFontEx("font/SCE-PS3-RD-R-LATIN.TTF", 32, 0, 250); raylib.SetTextureFilter(global_font.texture, raylib.TEXTURE_FILTER_BILINEAR); @@ -59,7 +61,9 @@ pub fn main() !void { if (raylib.IsKeyPressed('D')) debug_draw = !debug_draw; if (raylib.IsKeyPressed('S')) raylib.TakeScreenshot("screenshot.png"); - column.updatePositions(); + datetime.update(); + background.update(); + column.update(); raylib.BeginDrawing(); defer raylib.EndDrawing(); @@ -91,6 +95,8 @@ var screen_height: f32 = 272; var scales: Scales = undefined; +var datetime: DateTime = undefined; + /// Cached scaling and positioning values for dynamic window resizing. pub const Scales = struct { font_size_curve: Curve, @@ -246,7 +252,7 @@ pub const Column = struct { self.refresh(false); } - fn updatePositions(self: *Column) void { + fn update(self: *Column) void { const up = raylib.IsKeyPressed(raylib.KEY_UP) or raylib.IsKeyPressedRepeat(raylib.KEY_UP); const down = raylib.IsKeyPressed(raylib.KEY_DOWN) or raylib.IsKeyPressedRepeat(raylib.KEY_DOWN); if (up and self.selected > 0) self.selected -= 1; @@ -375,8 +381,36 @@ pub fn Tweener(comptime T: type, comptime default: T) type { }; } +/// Optimized datetime that only pulls from the system clock every few seconds. +pub const DateTime = struct { + refresh_timer: f32 = 0.0, + secs: u64, + + pub fn update(self: *DateTime) void { + self.refresh_timer += raylib.GetFrameTime(); + if (self.refresh_timer >= 5) { + self.refresh_timer = 0; + self.secs = @intCast(std.time.timestamp()); + } + } + + pub fn getEpochSeconds(self: DateTime) std.time.epoch.EpochSeconds { + const secs = self.secs + @as(u64, @intFromFloat(self.refresh_timer)); + return .{ .secs = secs }; + } + + pub fn getDaySeconds(self: DateTime) std.time.epoch.DaySeconds { + return self.getEpochSeconds().getDaySeconds(); + } + + pub fn getEpochDay(self: DateTime) std.time.epoch.EpochDay { + return self.getEpochSeconds().getEpochDay(); + } +}; + /// Draws the dynamic gradient background. -// TODO shift based on time of day +// TODO subdivided plane gradient +// TODO smoothly transition between gradients over a couple seconds // TODO image wallpaper // TODO slideshow wallpaper // TODO animated image wallpaper @@ -388,10 +422,31 @@ pub const Background = struct { pub fn init() Background { var self: Background = undefined; - self.setColors(NIGHT_08); + self.update(); return self; } + pub fn update(self: *Background) void { + const epoch_day = datetime.getEpochDay(); + const year_day = epoch_day.calculateYearDay(); + const month_day = year_day.calculateMonthDay(); + + const day_seconds = datetime.getDaySeconds(); + const t = @sin(raylib.Remap( + @floatFromInt(day_seconds.secs), + 0, + std.time.s_per_day / 2, + 0, + std.math.pi, + )); + + self.setColors(switch (month_day.month) { + .jun => lerpColors(DAY_06, NIGHT_06, t), + .aug => lerpColors(DAY_08, NIGHT_08, t), + else => @panic("month background colors not implemented"), + }); + } + pub fn setColors(self: *Background, colors: [4]Color) void { self.top_left = colors[0]; self.bottom_right = colors[1]; @@ -421,14 +476,28 @@ pub const Background = struct { fn toRaylib(self: Color) raylib.Color { return .{ - .r = @intFromFloat(self.r * 255.0), - .g = @intFromFloat(self.g * 255.0), - .b = @intFromFloat(self.b * 255.0), + .r = @intFromFloat(std.math.clamp(self.r, 0.0, 1.0) * 255.0), + .g = @intFromFloat(std.math.clamp(self.g, 0.0, 1.0) * 255.0), + .b = @intFromFloat(std.math.clamp(self.b, 0.0, 1.0) * 255.0), .a = 255, }; } + + fn lerp(self: Color, other: Color, t: f32) Color { + return .{ + .r = std.math.lerp(self.r, other.r, t), + .g = std.math.lerp(self.g, other.g, t), + .b = std.math.lerp(self.b, other.b, t), + }; + } }; + fn lerpColors(a: [4]Color, b: [4]Color, t: f32) [4]Color { + var colors = a; + for (&colors, a, b) |*color, aa, bb| color.* = aa.lerp(bb, t); + return colors; + } + pub const DAY_06 = [4]Color{ .{ .r = 0.408, .g = 0.333, .b = 0.643 }, .{ .r = 0.518, .g = 0.365, .b = 0.855 }, @@ -436,6 +505,13 @@ pub const Background = struct { .{ .r = 0.569, .g = 0.325, .b = 0.620 }, }; + pub const NIGHT_06 = [4]Color{ + .{ .r = 0.039, .g = 0.031, .b = 0.035 }, + .{ .r = 0.031, .g = 0.039, .b = 0.035 }, + .{ .r = 0.824, .g = 0.647, .b = 0.878 }, + .{ .r = 0.784, .g = 0.608, .b = 0.831 }, + }; + pub const DAY_08 = [4]Color{ .{ .r = 0.243, .g = 0.608, .b = 0.831 }, .{ .r = 0.039, .g = 0.690, .b = 0.878 },