233 lines
7.2 KiB
Zig
233 lines
7.2 KiB
Zig
const std = @import("std");
|
|
const core = @import("core");
|
|
const platform = @import("platform.zig");
|
|
|
|
const RingQueue = core.RingQueue;
|
|
pub const sdl3 = @import("sdl3");
|
|
const tracy = core.tracy;
|
|
|
|
pub const InputListenerError = error{
|
|
UnknownError,
|
|
};
|
|
|
|
pub const RawInputListenerInterface = struct {
|
|
|
|
// required functions
|
|
OnIoEvent: *const fn (*anyopaque, event: IOEvent) InputListenerError!void,
|
|
|
|
pub fn from(comptime TargetType: type) @This() {
|
|
const Wrapped = struct {
|
|
pub fn OnIoEvent(pointer: *anyopaque, event: IOEvent) InputListenerError!void {
|
|
var ptr = @as(*TargetType, @ptrCast(@alignCast(pointer)));
|
|
try ptr.OnIoEvent(event);
|
|
}
|
|
};
|
|
|
|
return .{
|
|
.OnIoEvent = Wrapped.OnIoEvent,
|
|
};
|
|
}
|
|
};
|
|
|
|
pub const RawInputObjectRef = struct {
|
|
ptr: *anyopaque,
|
|
vtable: *const RawInputListenerInterface,
|
|
|
|
pub fn from(target: anytype) @This() {
|
|
const vtable = &(@TypeOf(target.*)).RawInputListenerVTable;
|
|
|
|
return .{
|
|
.ptr = target,
|
|
.vtable = vtable,
|
|
};
|
|
}
|
|
};
|
|
|
|
// We are having some serious issues with this events pump.
|
|
pub const PlatformParams = struct {
|
|
extent: core.Vector2c = .{ .x = 1600, .y = 900 },
|
|
windowName: []const u8,
|
|
icon: []const u8 = "textures/icon.png",
|
|
hasVideo: bool = true,
|
|
|
|
pub fn init() @This() {
|
|
const rv = @This(){
|
|
.extent = .{
|
|
.x = core.configVar(c_int, "platform.window.width", 1600),
|
|
.y = core.configVar(c_int, "platform.window.height", 900),
|
|
},
|
|
.windowName = core.configVar([]const u8, "platform.window.name", "Backlog Engine"),
|
|
.icon = core.configVar([]const u8, "platform.window.icon", "textures/icon.png"),
|
|
};
|
|
|
|
core.engine_log("platform settings {any}", .{rv});
|
|
return rv;
|
|
}
|
|
};
|
|
|
|
// For windows and linux computers this is a glfw instance
|
|
pub const PlatformInstance = struct {
|
|
allocator: std.mem.Allocator,
|
|
|
|
cursorEnabled: bool = true,
|
|
newCursorEnabled: bool = true,
|
|
hasVideo: bool = false,
|
|
|
|
window: *sdl3.Window = undefined,
|
|
|
|
windowExtent: core.Vector2c = undefined,
|
|
extent: core.Vector2f = undefined,
|
|
|
|
windowName: [:0]u8 = undefined,
|
|
iconPath: [:0]u8 = undefined,
|
|
|
|
enableImguiEvents: bool = true,
|
|
imguiVisible: bool = true,
|
|
|
|
windowDestroyed: bool = false,
|
|
|
|
processFuncs: std.ArrayListUnmanaged(*const fn (*sdl3.Event) void) = .{},
|
|
|
|
cursorPos: core.Vector2f = .{},
|
|
|
|
pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "platform.Instance");
|
|
|
|
pub fn deinit(self: *@This()) void {
|
|
self.allocator.free(self.windowName);
|
|
self.allocator.free(self.iconPath);
|
|
self.processFuncs.deinit(self.allocator);
|
|
// shutdown
|
|
}
|
|
|
|
pub fn onExitSignal(self: *@This()) !void {
|
|
sdl3.c.SDL_DestroyWindow(self.window);
|
|
self.windowDestroyed = true;
|
|
}
|
|
|
|
pub fn readyToExit(self: *@This()) bool {
|
|
return self.windowDestroyed;
|
|
}
|
|
|
|
pub fn init(
|
|
allocator: std.mem.Allocator,
|
|
) !*@This() {
|
|
const self = try allocator.create(@This());
|
|
self.* = .{
|
|
.allocator = allocator,
|
|
//.windowName = try allocator.dupeZ(u8, params.windowName),
|
|
//.iconPath = try allocator.dupeZ(u8, params.icon),
|
|
//.windowExtent = params.extent,
|
|
//.extent = .{ .x = @floatFromInt(params.extent.x), .y = @floatFromInt(params.extent.y) },
|
|
//.hasVideo = params.hasVideo,
|
|
};
|
|
|
|
return self;
|
|
}
|
|
|
|
pub fn setParams(self: *@This(), params: PlatformParams) !void {
|
|
self.windowName = try self.allocator.dupeZ(u8, params.windowName);
|
|
self.iconPath = try self.allocator.dupeZ(u8, params.icon);
|
|
self.windowExtent = params.extent;
|
|
self.extent = .{ .x = @floatFromInt(params.extent.x), .y = @floatFromInt(params.extent.y) };
|
|
self.hasVideo = params.hasVideo;
|
|
}
|
|
|
|
pub fn setMouseRelativeMode(self: *@This(), relativeMode: bool) void {
|
|
// _ = sdl3.c.SDL_SetHint(sdl3.c.SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, "1");
|
|
_ = sdl3.c.SDL_SetWindowRelativeMouseMode(self.window, relativeMode);
|
|
_ = sdl3.c.SDL_SetWindowMouseRect(self.window, null);
|
|
|
|
self.cursorEnabled = !relativeMode;
|
|
|
|
self.enableImguiEvents = !relativeMode;
|
|
}
|
|
|
|
pub fn addSDLProcessFunction(self: *@This(), processFunc: *const fn (*sdl3.Event) void) !void {
|
|
try self.processFuncs.append(self.allocator, processFunc);
|
|
}
|
|
|
|
pub fn setupWindow(self: *@This()) core.EngineDataEventError!void {
|
|
sdl3.init(.{ .video = true, .gamepad = true }) catch return error.BadInit;
|
|
self.window = sdl3.c.SDL_CreateWindow(self.windowName, self.windowExtent.x, self.windowExtent.y, 0).?; // resizeable
|
|
self.extent = .{
|
|
.x = @floatFromInt(self.windowExtent.x),
|
|
.y = @floatFromInt(self.windowExtent.y),
|
|
};
|
|
}
|
|
|
|
pub fn registerFuncs(self: *@This()) !void {
|
|
core.setupEnginePlatform(self, enginePoll, procEvents);
|
|
}
|
|
|
|
// runs pinned on io thread.
|
|
// old glfw needed to do it's polling here.
|
|
pub fn enginePoll(opaqueSelf: *anyopaque) core.EngineDataEventError!void {
|
|
_ = opaqueSelf;
|
|
// this polling event should probably be used for IO, now that we have a free thread for doing w.e
|
|
// var self: *@This() = @alignCast(@ptrCast(opaqueSelf));
|
|
// self.pollEvents();
|
|
}
|
|
|
|
pub fn installListener(self: *@This(), listener: anytype) !void {
|
|
try self.listeners.append(RawInputObjectRef.from(listener));
|
|
}
|
|
|
|
pub fn setMousePosition(self: *@This(), pos: core.Vector2f) void {
|
|
sdl3.c.SDL_WarpMouseInWindow(self.window, pos.x, pos.y);
|
|
}
|
|
|
|
pub fn procEvents(ptr: *anyopaque, frameNumber: u64) core.EngineDataEventError!void {
|
|
_ = frameNumber;
|
|
|
|
const self: *@This() = @ptrCast(@alignCast(ptr));
|
|
|
|
// const self: *@This() = @ptrCast(@alignCast(ptr));
|
|
var t1 = tracy.ZoneN(@src(), "Pumping Events");
|
|
defer t1.End();
|
|
|
|
const inputStack = core.getInputStack();
|
|
inputStack.updatePreviousInputs();
|
|
while (sdl3.pollEvent()) |event| {
|
|
if (event.type == sdl3.events.mouse_motion) {
|
|
sdl3.getMouseState(&self.cursorPos.x, &self.cursorPos.y);
|
|
}
|
|
|
|
if (core.inputs.convertEvent(event)) |converted| {
|
|
inputStack.routeEvent(converted);
|
|
}
|
|
|
|
for (self.processFuncs.items) |func| {
|
|
func(@ptrCast(event));
|
|
}
|
|
|
|
switch (event.type) {
|
|
sdl3.events.quit => {
|
|
core.exitNow();
|
|
},
|
|
else => {},
|
|
}
|
|
}
|
|
|
|
inputStack.sendAxisUpdates();
|
|
}
|
|
|
|
pub fn getCursorPosition(self: *@This()) core.Vector2f {
|
|
return self.cursorPos;
|
|
}
|
|
|
|
pub fn isCursorEnabled(self: @This()) bool {
|
|
return self.cursorEnabled;
|
|
}
|
|
|
|
pub fn setCursorVisible(self: @This(), visible: bool) void {
|
|
self.cursorEnabled = visible;
|
|
if (visible) {
|
|
sdl3.showCursor();
|
|
} else {
|
|
sdl3.hideCursor();
|
|
}
|
|
}
|
|
};
|
|
|
|
pub const IOEvent = core.IOEvent;
|