add canvas scaling
This commit is contained in:
parent
0174a3f3f0
commit
c2e784bfb2
78
src/game.zig
Normal file
78
src/game.zig
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const Math = @import("./math.zig");
|
||||||
|
const Vec2 = Math.Vec2;
|
||||||
|
const rgb = Math.rgb;
|
||||||
|
|
||||||
|
const Window = @import("./window.zig");
|
||||||
|
|
||||||
|
const imgui = @import("./imgui.zig");
|
||||||
|
|
||||||
|
const Gfx = @import("./graphics.zig");
|
||||||
|
|
||||||
|
const Game = @This();
|
||||||
|
|
||||||
|
pub const Input = struct {
|
||||||
|
dt: f32,
|
||||||
|
move: Vec2
|
||||||
|
};
|
||||||
|
|
||||||
|
canvas_size: Vec2,
|
||||||
|
position: Vec2 = .init(0, 0),
|
||||||
|
|
||||||
|
pub fn init() !Game {
|
||||||
|
return Game{
|
||||||
|
.canvas_size = .init(320, 180)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Game) void {
|
||||||
|
_ = self; // autofix
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getInput(self: *Game, window: *Window) Input {
|
||||||
|
_ = self; // autofix
|
||||||
|
const dt = @as(f32, @floatFromInt(window.frame_dt_ns)) / std.time.ns_per_s;
|
||||||
|
|
||||||
|
var move = Vec2.init(0, 0);
|
||||||
|
if (window.down_keys.contains(.W)) {
|
||||||
|
move.y -= 1;
|
||||||
|
}
|
||||||
|
if (window.down_keys.contains(.S)) {
|
||||||
|
move.y += 1;
|
||||||
|
}
|
||||||
|
if (move.x == 0) {
|
||||||
|
if (window.down_keys.contains(.A)) {
|
||||||
|
move.x -= 1;
|
||||||
|
}
|
||||||
|
if (window.down_keys.contains(.D)) {
|
||||||
|
move.x += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Input{
|
||||||
|
.dt = dt,
|
||||||
|
.move = move
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tick(self: *Game, input: Input) !void {
|
||||||
|
|
||||||
|
const velocity = input.move.multiplyScalar(100);
|
||||||
|
self.position = self.position.add(velocity.multiplyScalar(input.dt));
|
||||||
|
|
||||||
|
Gfx.drawRectangle(.init(0, 0), .init(self.canvas_size.x, self.canvas_size.y), rgb(255, 255, 255));
|
||||||
|
Gfx.drawRectangle(self.position, .init(10, 10), rgb(255, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn debug(self: *Game) !void {
|
||||||
|
_ = self; // autofix
|
||||||
|
if (!imgui.beginWindow(.{
|
||||||
|
.name = "Debug",
|
||||||
|
.pos = Vec2.init(20, 20),
|
||||||
|
.size = Vec2.init(400, 200),
|
||||||
|
})) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
defer imgui.endWindow();
|
||||||
|
}
|
||||||
@ -1297,6 +1297,16 @@ pub fn popScissor() void {
|
|||||||
sgl.scissorRectf(rect.pos.x, rect.pos.y, rect.size.x, rect.size.y, true);
|
sgl.scissorRectf(rect.pos.x, rect.pos.y, rect.size.x, rect.size.y, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pushTransform(translation: Vec2, scale: f32) void {
|
||||||
|
sgl.pushMatrix();
|
||||||
|
sgl.translate(translation.x, translation.y, 0);
|
||||||
|
sgl.scale(scale, scale, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn popTransform() void {
|
||||||
|
sgl.popMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn event(ev: [*c]const sapp.Event) bool {
|
pub fn event(ev: [*c]const sapp.Event) bool {
|
||||||
return imgui.handleEvent(ev.*);
|
return imgui.handleEvent(ev.*);
|
||||||
}
|
}
|
||||||
|
|||||||
224
src/main.zig
224
src/main.zig
@ -16,97 +16,35 @@ const sg = sokol.gfx;
|
|||||||
const sapp = sokol.app;
|
const sapp = sokol.app;
|
||||||
const sglue = sokol.glue;
|
const sglue = sokol.glue;
|
||||||
|
|
||||||
const log = std.log.scoped(.ui);
|
const log = std.log.scoped(.main);
|
||||||
|
|
||||||
|
var gpa: std.mem.Allocator = undefined;
|
||||||
|
|
||||||
var window: Window = undefined;
|
var window: Window = undefined;
|
||||||
var event_queue: std.ArrayListUnmanaged(Event) = .empty;
|
|
||||||
var mouse_inside_window: bool = false;
|
|
||||||
var event_queue_full_shown = false;
|
var event_queue_full_shown = false;
|
||||||
var sokol_logger: sapp.Logger = .{ .func = sokolLogCallback };
|
|
||||||
|
|
||||||
fn signalHandler(sig: i32) callconv(.c) void {
|
fn signalHandler(sig: i32) callconv(.c) void {
|
||||||
_ = sig;
|
_ = sig;
|
||||||
sapp.requestQuit();
|
sapp.requestQuit();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initErrorable() !void {
|
|
||||||
// const allocator = window.app.allocator;
|
|
||||||
|
|
||||||
try Gfx.init(.{
|
|
||||||
.allocator = window.gpa,
|
|
||||||
.logger = @as(*sokol.gfx.Logger, @ptrFromInt(@intFromPtr(&sokol_logger))).*,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn init() void {
|
export fn init() void {
|
||||||
var zone = tracy.initZone(@src(), .{ });
|
var zone = tracy.initZone(@src(), .{ });
|
||||||
defer zone.deinit();
|
defer zone.deinit();
|
||||||
|
|
||||||
initErrorable() catch |e| {
|
Window.init(&window, gpa) catch |e| {
|
||||||
log.err("init() failed: {}", .{e});
|
log.err("init() failed: {}", .{e});
|
||||||
sapp.requestQuit();
|
sapp.requestQuit();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cStrToZig(c_str: [*c]const u8) [:0]const u8 {
|
|
||||||
return @import("std").mem.span(c_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sokolLogFmt(log_level: u32, comptime format: []const u8, args: anytype) void {
|
|
||||||
const log_sokol = std.log.scoped(.sokol);
|
|
||||||
|
|
||||||
if (log_level == 0) {
|
|
||||||
log_sokol.err(format, args);
|
|
||||||
} else if (log_level == 1) {
|
|
||||||
log_sokol.err(format, args);
|
|
||||||
} else if (log_level == 2) {
|
|
||||||
log_sokol.warn(format, args);
|
|
||||||
} else {
|
|
||||||
log_sokol.info(format, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sokolLogCallback(tag: [*c]const u8, log_level: u32, log_item: u32, message: [*c]const u8, line_nr: u32, filename: [*c]const u8, user_data: ?*anyopaque) callconv(.c) void {
|
|
||||||
_ = user_data;
|
|
||||||
|
|
||||||
if (filename != null) {
|
|
||||||
const format = "[{s}][id:{}] {s}:{}: {s}";
|
|
||||||
const args = .{
|
|
||||||
cStrToZig(tag orelse "-"),
|
|
||||||
log_item,
|
|
||||||
std.fs.path.basename(cStrToZig(filename orelse "-")),
|
|
||||||
line_nr,
|
|
||||||
cStrToZig(message orelse "")
|
|
||||||
};
|
|
||||||
|
|
||||||
sokolLogFmt(log_level, format, args);
|
|
||||||
} else {
|
|
||||||
const format = "[{s}][id:{}] {s}";
|
|
||||||
const args = .{
|
|
||||||
cStrToZig(tag orelse "-"),
|
|
||||||
log_item,
|
|
||||||
cStrToZig(message orelse "")
|
|
||||||
};
|
|
||||||
|
|
||||||
sokolLogFmt(log_level, format, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn frameErrorable() !void {
|
|
||||||
Gfx.beginFrame();
|
|
||||||
defer Gfx.endFrame();
|
|
||||||
|
|
||||||
// try window.frame(event_queue.items);
|
|
||||||
event_queue.clearRetainingCapacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn frame() void {
|
export fn frame() void {
|
||||||
tracy.frameMark();
|
tracy.frameMark();
|
||||||
|
|
||||||
const zone = tracy.initZone(@src(), .{ });
|
const zone = tracy.initZone(@src(), .{ });
|
||||||
defer zone.deinit();
|
defer zone.deinit();
|
||||||
|
|
||||||
frameErrorable() catch |e| {
|
window.frame() catch |e| {
|
||||||
log.err("frame() failed: {}", .{e});
|
log.err("frame() failed: {}", .{e});
|
||||||
if (@errorReturnTrace()) |trace| {
|
if (@errorReturnTrace()) |trace| {
|
||||||
std.debug.dumpStackTrace(trace.*);
|
std.debug.dumpStackTrace(trace.*);
|
||||||
@ -119,152 +57,14 @@ export fn cleanup() void {
|
|||||||
const zone = tracy.initZone(@src(), .{ });
|
const zone = tracy.initZone(@src(), .{ });
|
||||||
defer zone.deinit();
|
defer zone.deinit();
|
||||||
|
|
||||||
// window.beforeExit() catch |e| {
|
|
||||||
// log.err("window.beforeExit() failed: {}", .{e});
|
|
||||||
// if (@errorReturnTrace()) |trace| {
|
|
||||||
// std.debug.dumpStackTrace(trace.*);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const allocator = window.app.allocator;
|
|
||||||
|
|
||||||
window.deinit();
|
window.deinit();
|
||||||
Gfx.deinit();
|
|
||||||
// event_queue.deinit(allocator);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn appendToEventQueue(e_ptr: [*c]const sapp.Event) !bool {
|
|
||||||
const e = e_ptr.*;
|
|
||||||
blk: switch (e.type) {
|
|
||||||
.MOUSE_DOWN => {
|
|
||||||
const mouse_button = Window.MouseButton.fromSokol(e.mouse_button) orelse break :blk;
|
|
||||||
|
|
||||||
try appendEvent(Event{
|
|
||||||
.mouse_pressed = .{
|
|
||||||
.button = mouse_button,
|
|
||||||
.position = Vec2.init(e.mouse_x, e.mouse_y)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.MOUSE_UP => {
|
|
||||||
const mouse_button = MouseButton.fromSokol(e.mouse_button) orelse break :blk;
|
|
||||||
|
|
||||||
try appendEvent(Event{
|
|
||||||
.mouse_released = .{
|
|
||||||
.button = mouse_button,
|
|
||||||
.position = Vec2.init(e.mouse_x, e.mouse_y)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.MOUSE_MOVE => {
|
|
||||||
if (!mouse_inside_window) {
|
|
||||||
try appendEvent(Event{
|
|
||||||
.mouse_enter = Vec2.init(e.mouse_x, e.mouse_y)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
try appendEvent(Event{
|
|
||||||
.mouse_move = Vec2.init(e.mouse_x, e.mouse_y)
|
|
||||||
});
|
|
||||||
|
|
||||||
mouse_inside_window = true;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.MOUSE_ENTER => {
|
|
||||||
if (!mouse_inside_window) {
|
|
||||||
try appendEvent(Event{
|
|
||||||
.mouse_enter = Vec2.init(e.mouse_x, e.mouse_y)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
mouse_inside_window = true;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.RESIZED => {
|
|
||||||
if (mouse_inside_window) {
|
|
||||||
try appendEvent(Event{
|
|
||||||
.mouse_leave = {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
try appendEvent(Event{
|
|
||||||
.window_resize = {}
|
|
||||||
});
|
|
||||||
|
|
||||||
mouse_inside_window = false;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.MOUSE_LEAVE => {
|
|
||||||
if (mouse_inside_window) {
|
|
||||||
try appendEvent(Event{
|
|
||||||
.mouse_leave = {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
mouse_inside_window = false;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.MOUSE_SCROLL => {
|
|
||||||
try appendEvent(Event{
|
|
||||||
.mouse_scroll = Vec2.init(e.scroll_x, e.scroll_y)
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.KEY_DOWN => {
|
|
||||||
try appendEvent(Event{
|
|
||||||
.key_pressed = .{
|
|
||||||
.code = @enumFromInt(@intFromEnum(e.key_code)),
|
|
||||||
.repeat = e.key_repeat
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.KEY_UP => {
|
|
||||||
try appendEvent(Event{
|
|
||||||
.key_released = @enumFromInt(@intFromEnum(e.key_code))
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.CHAR => {
|
|
||||||
try appendEvent(Event{
|
|
||||||
.char = @intCast(e.char_code)
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
.QUIT_REQUESTED => {
|
|
||||||
// TODO: handle quit request. Maybe show confirmation window in certain cases.
|
|
||||||
},
|
|
||||||
else => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn appendEvent(e: Event) !void {
|
|
||||||
event_queue.appendBounded(e) catch return error.EventQueueFull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn event(e_ptr: [*c]const sapp.Event) void {
|
export fn event(e_ptr: [*c]const sapp.Event) void {
|
||||||
const zone = tracy.initZone(@src(), .{ });
|
const zone = tracy.initZone(@src(), .{ });
|
||||||
defer zone.deinit();
|
defer zone.deinit();
|
||||||
|
|
||||||
if (Gfx.event(e_ptr)) {
|
const consumed_event = window.event(e_ptr) catch |e| switch (e) {
|
||||||
appendEvent(Event{
|
|
||||||
.mouse_leave = {}
|
|
||||||
}) catch {};
|
|
||||||
mouse_inside_window = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const consumed_event = appendToEventQueue(e_ptr) catch |e| switch (e) {
|
|
||||||
error.EventQueueFull => blk: {
|
error.EventQueueFull => blk: {
|
||||||
if (!event_queue_full_shown) {
|
if (!event_queue_full_shown) {
|
||||||
log.warn("Event queue is full! Frame is taking too long to process", .{});
|
log.warn("Event queue is full! Frame is taking too long to process", .{});
|
||||||
@ -272,13 +72,6 @@ export fn event(e_ptr: [*c]const sapp.Event) void {
|
|||||||
}
|
}
|
||||||
break :blk false;
|
break :blk false;
|
||||||
},
|
},
|
||||||
// else => blk: {
|
|
||||||
// log.err("Failed to append event to queue: {}", .{e});
|
|
||||||
// if (@errorReturnTrace()) |trace| {
|
|
||||||
// std.debug.dumpStackTrace(trace.*);
|
|
||||||
// }
|
|
||||||
// break :blk false;
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (consumed_event) {
|
if (consumed_event) {
|
||||||
@ -291,7 +84,6 @@ pub fn main() !void {
|
|||||||
var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
|
var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
|
||||||
defer _ = debug_allocator.deinit();
|
defer _ = debug_allocator.deinit();
|
||||||
|
|
||||||
var gpa: std.mem.Allocator = undefined;
|
|
||||||
if (builtin.mode == .ReleaseFast) {
|
if (builtin.mode == .ReleaseFast) {
|
||||||
gpa = std.heap.smp_allocator;
|
gpa = std.heap.smp_allocator;
|
||||||
} else {
|
} else {
|
||||||
@ -302,8 +94,6 @@ pub fn main() !void {
|
|||||||
|
|
||||||
tracy.setThreadName("Main");
|
tracy.setThreadName("Main");
|
||||||
|
|
||||||
try Window.init(&window, gpa);
|
|
||||||
|
|
||||||
var sa: std.posix.Sigaction = .{
|
var sa: std.posix.Sigaction = .{
|
||||||
.handler = .{ .handler = signalHandler },
|
.handler = .{ .handler = signalHandler },
|
||||||
.mask = std.posix.sigemptyset(),
|
.mask = std.posix.sigemptyset(),
|
||||||
@ -322,7 +112,7 @@ pub fn main() !void {
|
|||||||
.high_dpi = true,
|
.high_dpi = true,
|
||||||
.sample_count = 4,
|
.sample_count = 4,
|
||||||
.window_title = "Game",
|
.window_title = "Game",
|
||||||
.logger = sokol_logger,
|
.logger = .{ .func = Window.sokolLogCallback },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
280
src/window.zig
280
src/window.zig
@ -2,12 +2,20 @@ const std = @import("std");
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
const sokol = @import("sokol");
|
const sokol = @import("sokol");
|
||||||
|
const sapp = sokol.app;
|
||||||
|
|
||||||
|
const Gfx = @import("./graphics.zig");
|
||||||
|
|
||||||
const Math = @import("./math.zig");
|
const Math = @import("./math.zig");
|
||||||
const Vec2 = Math.Vec2;
|
const Vec2 = Math.Vec2;
|
||||||
|
const rgb = Math.rgb;
|
||||||
|
|
||||||
|
const Game = @import("./game.zig");
|
||||||
|
|
||||||
const Window = @This();
|
const Window = @This();
|
||||||
|
|
||||||
|
const log = std.log.scoped(.window);
|
||||||
|
|
||||||
pub const MouseButton = enum {
|
pub const MouseButton = enum {
|
||||||
left,
|
left,
|
||||||
right,
|
right,
|
||||||
@ -170,18 +178,282 @@ pub const Event = union(enum) {
|
|||||||
|
|
||||||
gpa: Allocator,
|
gpa: Allocator,
|
||||||
events: std.ArrayList(Event),
|
events: std.ArrayList(Event),
|
||||||
|
mouse_inside: bool = false,
|
||||||
|
last_frame_at_ns: i128,
|
||||||
|
frame_dt_ns: i128,
|
||||||
|
down_keys: std.EnumSet(KeyCode) = .initEmpty(),
|
||||||
|
game: Game,
|
||||||
|
|
||||||
pub fn init(self: *Window, gpa: Allocator) !void {
|
pub fn init(self: *Window, gpa: Allocator) !void {
|
||||||
|
var events: std.ArrayList(Event) = .empty;
|
||||||
|
errdefer events.deinit(gpa);
|
||||||
|
try events.ensureTotalCapacityPrecise(gpa, 50);
|
||||||
|
|
||||||
|
try Gfx.init(.{
|
||||||
|
.allocator = gpa,
|
||||||
|
.logger = .{ .func = sokolLogCallback }
|
||||||
|
});
|
||||||
|
|
||||||
|
var game = try Game.init();
|
||||||
|
errdefer game.deinit();
|
||||||
|
|
||||||
self.* = Window{
|
self.* = Window{
|
||||||
.gpa = gpa,
|
.gpa = gpa,
|
||||||
.events = .empty
|
.events = events,
|
||||||
// .last_frame_at_ns = std.time.nanoTimestamp(),
|
.last_frame_at_ns = std.time.nanoTimestamp(),
|
||||||
// .frame_arena = ArenaAllocator.init(gpa),
|
.frame_dt_ns = 0,
|
||||||
|
.game = game
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Window) void {
|
pub fn deinit(self: *Window) void {
|
||||||
const gpa = self.gpa;
|
const gpa = self.gpa;
|
||||||
_ = gpa; // autofix
|
|
||||||
|
|
||||||
|
self.game.deinit();
|
||||||
|
self.events.deinit(gpa);
|
||||||
|
|
||||||
|
Gfx.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn frame(self: *Window) !void {
|
||||||
|
const now = std.time.nanoTimestamp();
|
||||||
|
self.frame_dt_ns = now - self.last_frame_at_ns;
|
||||||
|
self.last_frame_at_ns = now;
|
||||||
|
|
||||||
|
Gfx.beginFrame();
|
||||||
|
defer Gfx.endFrame();
|
||||||
|
|
||||||
|
for (self.events.items) |e| {
|
||||||
|
switch (e) {
|
||||||
|
.key_pressed => |opts| {
|
||||||
|
if (!opts.repeat) {
|
||||||
|
self.down_keys.insert(opts.code);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.key_released => |key_code| {
|
||||||
|
self.down_keys.remove(key_code);
|
||||||
|
},
|
||||||
|
.mouse_leave => {
|
||||||
|
self.down_keys = .initEmpty();
|
||||||
|
},
|
||||||
|
else => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.events.clearRetainingCapacity();
|
||||||
|
|
||||||
|
const window_size: Vec2 = .init(sapp.widthf(), sapp.heightf());
|
||||||
|
const scale = @min(
|
||||||
|
window_size.x / self.game.canvas_size.x,
|
||||||
|
window_size.y / self.game.canvas_size.y,
|
||||||
|
);
|
||||||
|
|
||||||
|
const filler_size: Vec2 = Vec2.sub(window_size, self.game.canvas_size.multiplyScalar(scale)).multiplyScalar(0.5);
|
||||||
|
|
||||||
|
const input = self.game.getInput(self);
|
||||||
|
|
||||||
|
{
|
||||||
|
Gfx.pushTransform(filler_size, scale);
|
||||||
|
defer Gfx.popTransform();
|
||||||
|
|
||||||
|
try self.game.tick(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bg_color = rgb(0, 0, 0);
|
||||||
|
|
||||||
|
Gfx.drawRectangle(
|
||||||
|
.init(0, 0),
|
||||||
|
.init(window_size.x, filler_size.y),
|
||||||
|
bg_color
|
||||||
|
);
|
||||||
|
|
||||||
|
Gfx.drawRectangle(
|
||||||
|
.init(0, window_size.y - filler_size.y),
|
||||||
|
.init(window_size.x, filler_size.y),
|
||||||
|
bg_color
|
||||||
|
);
|
||||||
|
|
||||||
|
Gfx.drawRectangle(
|
||||||
|
.init(0, 0),
|
||||||
|
.init(filler_size.x, window_size.y),
|
||||||
|
bg_color
|
||||||
|
);
|
||||||
|
|
||||||
|
Gfx.drawRectangle(
|
||||||
|
.init(window_size.x - filler_size.x, 0),
|
||||||
|
.init(filler_size.x, window_size.y),
|
||||||
|
bg_color
|
||||||
|
);
|
||||||
|
|
||||||
|
try self.game.debug();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn appendEvent(self: *Window, e: Event) !void {
|
||||||
|
self.events.appendBounded(e) catch return error.EventQueueFull;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn event(self: *Window, e_ptr: [*c]const sapp.Event) !bool {
|
||||||
|
if (Gfx.event(e_ptr)) {
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.mouse_leave = {}
|
||||||
|
});
|
||||||
|
self.mouse_inside = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const e = e_ptr.*;
|
||||||
|
blk: switch (e.type) {
|
||||||
|
.MOUSE_DOWN => {
|
||||||
|
const mouse_button = Window.MouseButton.fromSokol(e.mouse_button) orelse break :blk;
|
||||||
|
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.mouse_pressed = .{
|
||||||
|
.button = mouse_button,
|
||||||
|
.position = Vec2.init(e.mouse_x, e.mouse_y)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
.MOUSE_UP => {
|
||||||
|
const mouse_button = MouseButton.fromSokol(e.mouse_button) orelse break :blk;
|
||||||
|
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.mouse_released = .{
|
||||||
|
.button = mouse_button,
|
||||||
|
.position = Vec2.init(e.mouse_x, e.mouse_y)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
.MOUSE_MOVE => {
|
||||||
|
if (!self.mouse_inside) {
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.mouse_enter = Vec2.init(e.mouse_x, e.mouse_y)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.mouse_move = Vec2.init(e.mouse_x, e.mouse_y)
|
||||||
|
});
|
||||||
|
|
||||||
|
self.mouse_inside = true;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
.MOUSE_ENTER => {
|
||||||
|
if (!self.mouse_inside) {
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.mouse_enter = Vec2.init(e.mouse_x, e.mouse_y)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
self.mouse_inside = true;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
.RESIZED => {
|
||||||
|
if (self.mouse_inside) {
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.mouse_leave = {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.window_resize = {}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.mouse_inside = false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
.MOUSE_LEAVE => {
|
||||||
|
if (self.mouse_inside) {
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.mouse_leave = {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
self.mouse_inside = false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
.MOUSE_SCROLL => {
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.mouse_scroll = Vec2.init(e.scroll_x, e.scroll_y)
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
.KEY_DOWN => {
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.key_pressed = .{
|
||||||
|
.code = @enumFromInt(@intFromEnum(e.key_code)),
|
||||||
|
.repeat = e.key_repeat
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
.KEY_UP => {
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.key_released = @enumFromInt(@intFromEnum(e.key_code))
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
.CHAR => {
|
||||||
|
try self.appendEvent(Event{
|
||||||
|
.char = @intCast(e.char_code)
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
.QUIT_REQUESTED => {
|
||||||
|
// TODO: handle quit request. Maybe show confirmation window in certain cases.
|
||||||
|
},
|
||||||
|
else => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cStrToZig(c_str: [*c]const u8) [:0]const u8 {
|
||||||
|
return std.mem.span(c_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sokolLogFmt(log_level: u32, comptime format: []const u8, args: anytype) void {
|
||||||
|
const log_sokol = std.log.scoped(.sokol);
|
||||||
|
|
||||||
|
if (log_level == 0) {
|
||||||
|
log_sokol.err(format, args);
|
||||||
|
} else if (log_level == 1) {
|
||||||
|
log_sokol.err(format, args);
|
||||||
|
} else if (log_level == 2) {
|
||||||
|
log_sokol.warn(format, args);
|
||||||
|
} else {
|
||||||
|
log_sokol.info(format, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sokolLogCallback(tag: [*c]const u8, log_level: u32, log_item: u32, message: [*c]const u8, line_nr: u32, filename: [*c]const u8, user_data: ?*anyopaque) callconv(.c) void {
|
||||||
|
_ = user_data;
|
||||||
|
|
||||||
|
if (filename != null) {
|
||||||
|
const format = "[{s}][id:{}] {s}:{}: {s}";
|
||||||
|
const args = .{
|
||||||
|
cStrToZig(tag orelse "-"),
|
||||||
|
log_item,
|
||||||
|
std.fs.path.basename(cStrToZig(filename orelse "-")),
|
||||||
|
line_nr,
|
||||||
|
cStrToZig(message orelse "")
|
||||||
|
};
|
||||||
|
|
||||||
|
sokolLogFmt(log_level, format, args);
|
||||||
|
} else {
|
||||||
|
const format = "[{s}][id:{}] {s}";
|
||||||
|
const args = .{
|
||||||
|
cStrToZig(tag orelse "-"),
|
||||||
|
log_item,
|
||||||
|
cStrToZig(message orelse "")
|
||||||
|
};
|
||||||
|
|
||||||
|
sokolLogFmt(log_level, format, args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user