fixed input stack issue and removed old inputs implementation

This commit is contained in:
Peter Li 2025-04-24 19:44:13 -07:00
parent 6d1c2a4bd8
commit 481a8f411f
10 changed files with 189 additions and 44 deletions

View File

@ -1,6 +1,5 @@
const std = @import("std");
const logging = @import("logging.zig");
const input = @import("input.zig");
const engineObject = @import("engineObject.zig");
const time = @import("engineTime.zig");
const core = @import("core.zig");

View File

@ -1,6 +1,5 @@
const std = @import("std");
const logging = @import("logging.zig");
const input = @import("input.zig");
const p2 = @import("p2");
const engine_logs = logging.engine_logs;

View File

@ -1,20 +0,0 @@
// procedural functions to describe input primitives with which
// we can build on the rest of the engine.
const std = @import("std");
const engineObject = @import("engineObject.zig");
pub const InputSubsystem = struct {
const Self = @This();
pub var NeonObjectTable: engineObject.EngineObjectVTable = engineObject.EngineObjectVTable.from(Self);
allocator: std.mem.Allocator,
pub fn init(allocator: std.mem.Allocator) Self {
const self = Self{
.allocator = allocator,
};
return self;
}
};

View File

@ -11,6 +11,10 @@ pub fn convertEvent(event: *const sdl3.Event) ?IOEvent {
sdl3.events.key_down, sdl3.events.key_up => {
const scan: Key = @enumFromInt(event.key.scancode);
if (event.key.repeat) {
return null;
}
return IOEvent{
.key = .{
.key = scan,
@ -32,6 +36,11 @@ pub fn convertEvent(event: *const sdl3.Event) ?IOEvent {
},
};
},
sdl3.events.mouse_motion => {
const motion = core.Vector2f{ .x = event.motion.xrel, .y = event.motion.yrel };
return .{ .mouseRelative = motion };
},
else => {
return null;
},
@ -45,6 +54,7 @@ pub const IOEvent = union(enum(u8)) {
mousePosition: struct { x: f64, y: f64 },
scroll: struct { xoffset: f64, yoffset: f64 },
key: struct { key: Key, scancode: Key, action: ActionEvent, mods: c_int },
mouseRelative: core.Vector2f,
windowResize: struct { newSize: core.Vector2f },
codepoint: c_uint,
};
@ -105,7 +115,6 @@ fn BindingData(Listener: type, Func: type) type {
}
pub fn setKeyHeld(self: *@This(), key: Key) void {
// core.engine_log("repeating key {any}", .{key});
self.keysDown.push(.{ .key = key, .first = false }) catch unreachable;
}
@ -175,6 +184,8 @@ pub const Axis1dBinding = struct {
keys: std.ArrayListUnmanaged(AxisBindingKeyMagnitude) = .{},
magnitude: f32 = 0.0,
clampValue: ?f32 = 1.0,
pub const Listener = struct {
id: u32,
ctx: ?*anyopaque,
@ -197,6 +208,10 @@ pub const Axis1dBinding = struct {
gInputStack.active.addBindingByName(self.data.name, self) catch unreachable;
}
pub fn setClamp(self: *@This(), clampValue: ?f32) void {
self.clampValue = clampValue;
}
pub fn deactivate(self: *@This()) void {
gInputStack.active.removeBindingByName(self.data.name);
}
@ -220,8 +235,14 @@ pub const Axis2dBinding = struct {
yKeys: std.ArrayListUnmanaged(AxisBindingKeyMagnitude) = .{},
xKeys: std.ArrayListUnmanaged(AxisBindingKeyMagnitude) = .{},
// if mouseRelative is set to true then relative mouse movement values shall be passed to the listener
//
mouseRelative: bool = false,
magnitude: core.Vector2f = core.Vector2f.Zeroes,
clampValue: ?f32 = 1.0,
pub const Listener = struct {
id: u32,
ctx: ?*anyopaque,
@ -239,6 +260,19 @@ pub const Axis2dBinding = struct {
return self;
}
pub fn disableMouseRelative(self: *@This()) void {
self.mouseRelative = false;
}
pub fn enableMouseRelative(self: *@This()) void {
self.mouseRelative = true;
self.clampValue = null;
}
pub fn setClamp(self: *@This(), clampValue: ?f32) void {
self.clampValue = clampValue;
}
// pushes this binding to the active layer
pub fn activate(self: *@This()) void {
gInputStack.active.addBindingByName(self.data.name, self) catch unreachable;
@ -364,7 +398,9 @@ pub const Binding = union(BindingType) {
}
}
p.magnitude = std.math.clamp(p.magnitude, -1.0, 1.0);
if (p.clampValue) |clampValue| {
p.magnitude = std.math.clamp(p.magnitude, -clampValue, clampValue);
}
p.data.routed = routed;
// for (p.data.listeners.items) |listener| {
@ -388,8 +424,10 @@ pub const Binding = union(BindingType) {
}
}
p.magnitude.x = std.math.clamp(p.magnitude.x, -1.0, 1.0);
p.magnitude.y = std.math.clamp(p.magnitude.y, -1.0, 1.0);
if (p.clampValue) |clampValue| {
p.magnitude.x = std.math.clamp(p.magnitude.x, -clampValue, clampValue);
p.magnitude.y = std.math.clamp(p.magnitude.y, -clampValue, clampValue);
}
// core.engine_log(" >> {any} > routeBindingEvent magnitude {d} {d}", .{ key, p.magnitude.x, p.magnitude.y });
@ -583,11 +621,9 @@ pub const InputStack = struct {
if (event == .keyDown) {
binding.setKeyDown(key);
}
if (event == .keyHeld) {
} else if (event == .keyHeld) {
binding.setKeyHeld(key);
}
if (event == .keyUp) {
} else if (event == .keyUp) {
binding.setKeyUp(key);
}
@ -597,15 +633,39 @@ pub const InputStack = struct {
}
}
fn routeMouseRelative(self: *@This(), move: core.Vector2f) void {
if (self.active.bindingStack.items.len == 0) {
return;
}
var i: i32 = @intCast(self.active.bindingStack.items.len - 1);
// core.engine_log(" >> {any} > routeKeyEvent 2 binding count : {d}", .{ key, i });
while (i >= 0) : (i -= 1) {
const binding = self.active.bindingStack.items[@intCast(i)];
switch (binding) {
// only axis2d handles mouse relative right now,
.axis2d => |axis| {
if (axis.mouseRelative) {
axis.magnitude = axis.magnitude.add(move);
}
},
else => {},
}
}
}
pub fn routeEvent(self: *@This(), eventToRoute: IOEvent) void {
switch (eventToRoute) {
.key => |key| {
const keyEvent: ActionEvent = key.action; // @enumFromInt(@as(u8, @intCast(key.action)));
if (keyEvent != .keyHeld) {
// core.engine_log("converted: {any}", .{keyEvent});
self.routeKeyEvent(key.key, keyEvent);
self.routeKeyEvent(key.key, keyEvent); // do not route keyHelds
}
},
.mouseRelative => |rel| {
self.routeMouseRelative(rel);
},
else => {},
}
}

View File

@ -48,7 +48,7 @@ pub const Impl = struct {
//const renderpass = cmd.beginGPURenderPass(color_target_infos: [*c]const GPUColorTargetInfo, num_color_targets: u32, depth_stencil_target_info: [*c]const GPUDepthStencilTargetInfo);
var targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroes(gpu.GPUColorTargetInfo);
targetInfo.texture = rend.context().swapchainTexture;
targetInfo.texture = rend.context().swapchainTexture.?;
targetInfo.clear_color = .{ .r = 0.0, .g = 0.0, .b = 0.0, .a = 0.0 };
targetInfo.load_op = .loadopLoad;
targetInfo.store_op = .storeopStore;

View File

@ -15,12 +15,28 @@ pub const Module: core.ModuleDescription = .{
var gPlatformInstance: *windowing.PlatformInstance = undefined;
var gStartupParams: windowing.PlatformParams = .{};
pub fn context() *windowing.PlatformInstance {
return gPlatformInstance;
}
pub fn setWindowSettings(params: windowing.PlatformParams) void {
gStartupParams = params;
}
pub fn getCursorPosition() core.Vector2u {
gPlatformInstance.getCursorPosition();
pub fn getCursorPosition() core.Vector2f {
return gPlatformInstance.getCursorPosition();
}
pub fn setCursorVisible(visible: bool) void {
return gPlatformInstance.setCursorVisible(visible);
}
pub fn setMousePosition(pos: core.Vector2f) void {
gPlatformInstance.setMousePosition(pos);
}
pub fn setMouseRelativeMode(relativeMode: bool) void {
gPlatformInstance.setMouseRelativeMode(relativeMode);
}
pub fn start_module(comptime programSpec: anytype, args: anytype, allocator: std.mem.Allocator) !void {

View File

@ -69,6 +69,7 @@ pub const PlatformInstance = struct {
window: *sdl3.Window = undefined,
windowExtent: core.Vector2c,
extent: core.Vector2f,
windowName: [:0]u8,
iconPath: [:0]u8,
@ -104,12 +105,19 @@ pub const PlatformInstance = struct {
.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 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);
}
pub fn addSDLProcessFunction(self: *@This(), processFunc: *const fn (*sdl3.Event) void) !void {
try self.processFuncs.append(self.allocator, processFunc);
}
@ -117,6 +125,10 @@ pub const PlatformInstance = struct {
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 {
@ -136,6 +148,10 @@ pub const PlatformInstance = struct {
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 processEvents(ptr: *anyopaque, frameNumber: u64) core.EngineDataEventError!void {
_ = frameNumber;
@ -182,6 +198,15 @@ pub const PlatformInstance = struct {
pub fn isCursorEnabled(self: @This()) bool {
return self.cursorEnabled;
}
pub fn setCursorVisible(self: @This(), visible: bool) void {
_ = self;
if (visible) {
sdl3.showCursor();
} else {
sdl3.hideCursor();
}
}
};
pub const IOEvent = core.IOEvent;

View File

@ -46,7 +46,7 @@ pub const Renderer = struct {
debugDrawSys: *DebugDrawSystem = undefined,
// transients DO NOT TOUCH
swapchainTexture: *gpu.GPUTexture = undefined,
swapchainTexture: ?*gpu.GPUTexture = undefined,
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
@ -419,9 +419,14 @@ pub const Renderer = struct {
interface.func(interface.ptr, cmd);
}
if (cmd.waitAndAcquireGPUSwapchainTexture(self.window, &self.swapchainTexture, null, null)) {
if (cmd.waitAndAcquireGPUSwapchainTexture(self.window, @ptrCast(&self.swapchainTexture), null, null)) {
if (self.swapchainTexture == null) {
_ = cmd.submitGPUCommandBuffer();
return;
}
var targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroes(gpu.GPUColorTargetInfo);
targetInfo.texture = self.swapchainTexture;
targetInfo.texture = self.swapchainTexture.?;
targetInfo.clear_color = .{ .r = 0.1, .g = 0.1, .b = 0.1, .a = 1.0 };
targetInfo.load_op = .loadopClear;
targetInfo.store_op = .storeopStore;

View File

@ -52,6 +52,14 @@ pub fn getError() [*c]const u8 {
return c.SDL_GetError();
}
pub fn hideCursor() void {
_ = c.SDL_HideCursor();
}
pub fn showCursor() void {
_ = c.SDL_ShowCursor();
}
pub const gpu = @import("gpu.zig");
pub const Scancode = @import("scancode.zig").Scancode;
pub const shaderTypes = @import("shaderTypes");

View File

@ -7,14 +7,19 @@ cameraSpeed: f32 = 10.0,
moveInput: *core.Axis2dBinding = undefined,
moveVector: core.Vectorf = .{},
mouseMove: core.Vector2f = .{},
rotateAxis: f32 = 0.0,
rotateAxisPitch: f32 = 0.0,
sensitivity: f32 = 5.0,
verticalMove: f32 = 0.0,
yaw: f32 = 0.0,
pitch: f32 = 0.0,
mouseLook: bool = true,
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
pub fn init(allocator: std.mem.Allocator) !*@This() {
@ -62,6 +67,7 @@ pub fn prepare(self: *@This()) !void {
try script.runScriptFile("scripts/prepare.lua");
try assets.loadList(assetReferences);
platform.setMouseRelativeMode(true);
const exitInput = try core.ActionBinding.create(core.MakeName("exit"));
exitInput.addKey(.escape, .keyDown);
@ -140,19 +146,54 @@ pub fn prepare(self: *@This()) !void {
i.activate();
}
const verticalInput = try core.Axis1dBinding.create(core.MakeName("movementVertical"));
verticalInput.addKey(.e, 1.0);
verticalInput.addKey(.q, -1.0);
{
const verticalInput = try core.Axis1dBinding.create(core.MakeName("movementVertical"));
verticalInput.addKey(.e, 1.0);
verticalInput.addKey(.q, -1.0);
_ = verticalInput.data.addListener(self, verticalMovement);
verticalInput.activate();
_ = verticalInput.data.addListener(self, verticalMovement);
verticalInput.activate();
}
{
const mouseLook = try core.Axis2dBinding.create(core.MakeName("mouseLook"));
mouseLook.enableMouseRelative();
_ = mouseLook.data.addListener(self, onMouseLook);
mouseLook.activate();
}
{
const shaderReload = try core.ActionBinding.create(core.MakeName("shaderReload"));
shaderReload.addKey(.r, .keyDown);
_ = shaderReload.data.addListener(null, onShaderReload);
_ = shaderReload.data.addListener(self, onShaderReload);
shaderReload.activate();
}
{
const input = try core.ActionBinding.create(core.MakeName("toggleMouseLook"));
input.addKey(.t, .keyDown);
_ = input.data.addListener(self, toggleMouseLook);
input.activate();
}
}
fn onMouseLook(ctx: ?*anyopaque, axis: core.Vector2f) void {
const self: *@This() = @ptrCast(@alignCast(ctx));
self.mouseMove = axis;
}
fn toggleMouseLook(ctx: ?*anyopaque, action: core.ActionEvent) void {
const self: *@This() = @ptrCast(@alignCast(ctx));
_ = action;
self.mouseLook = !self.mouseLook;
self.updateMouseLook();
}
fn updateMouseLook(self: *@This()) void {
core.engine_log("{s}", .{if (self.mouseLook) "true" else "false"});
platform.setCursorVisible(self.mouseLook);
}
fn onShaderReload(ctx: ?*anyopaque, action: core.ActionEvent) void {
@ -201,17 +242,28 @@ pub fn onExit(ctx: ?*anyopaque, action: core.ActionEvent) void {
core.exitNow();
}
pub fn getMouseMovement(self: *@This()) core.Vector2f {
const rv = self.mouseMove;
self.mouseMove = .{};
return rv;
}
pub fn tick(self: *@This(), dt: f64) void {
const fdt: f32 = @floatCast(dt);
if (self.camera.fetch(core.Scene)) |scene| {
const vector = core.Vectorf{ .x = self.moveVector.x, .z = self.moveVector.z, .y = self.verticalMove };
const posRot = scene.getPosRot();
self.yaw += self.rotateAxis * fdt * 20;
self.pitch += self.rotateAxisPitch * fdt * 20;
const mouseMovement = self.getMouseMovement();
self.yaw += core.radians(mouseMovement.x * self.sensitivity);
self.pitch -= core.radians(mouseMovement.y * self.sensitivity);
self.cameraComponent.pitch = std.math.clamp(core.radians(self.pitch), core.radians(-90.0), core.radians(90.0));
posRot.rotation = core.Rotation.eulerY(core.radians(self.yaw));
const movement = scene.getPosRot().rotation.rotateVector(vector.fmul(self.cameraSpeed * fdt));
@ -247,6 +299,7 @@ pub fn main() anyerror!void {
const std = @import("std");
const backlog = @import("Backlog");
const assets = backlog.assets;
const platform = backlog.platform;
const core = backlog.core;
const ig = backlog.imgui.api;
const rend = backlog.rend;