Backlog/engine/core/src/engineObject.zig

163 lines
5.6 KiB
Zig

const std = @import("std");
const logging = @import("logging.zig");
const input = @import("input.zig");
const p2 = @import("p2");
const engine_logs = logging.engine_logs;
const ObjectHandle = p2.ObjectHandle;
const Name = p2.Name;
const MakeName = p2.MakeName;
const ArrayList = std.ArrayList;
const AutoHashMap = std.AutoHashMap;
const ArrayListUnmanaged = std.ArrayListUnmanaged;
const AutoHashMapUnmanaged = std.AutoHashMapUnmanaged;
pub fn InterfaceRef(comptime Vtable: type) type {
return struct {
ptr: *anyopaque,
vtable: *const Vtable,
};
}
pub fn MakeTypeName(comptime TargetType: type) Name {
const hashedName = comptime std.fmt.comptimePrint("{s}_{d}", .{ @typeName(TargetType), @sizeOf(TargetType) });
return MakeName(hashedName);
}
// todo.. engineObject is not the right word for this
pub const EngineDataEventError = error{
UnknownStatePanic,
BadInit,
UnknownError,
OutOfMemory,
};
pub const EngineObjectVTable = struct {
typeName: []const u8,
typeSize: usize,
typeAlign: usize,
init_func: *const fn (std.mem.Allocator) EngineDataEventError!*anyopaque,
tick_func: ?*const fn (*anyopaque, f64) void = null,
engineDraw_func: ?*const fn (*anyopaque, f64) void = null,
preTick_func: ?*const fn (*anyopaque, f64) EngineDataEventError!void = null,
deinit_func: ?*const fn (*anyopaque) void = null,
postInit_func: ?*const fn (*anyopaque) EngineDataEventError!void = null,
processEvents: ?*const fn (*anyopaque, u64) EngineDataEventError!void = null,
exitSignal_func: ?*const fn (*anyopaque) EngineDataEventError!void = null,
readyToExit_func: ?*const fn (*anyopaque) bool = null,
pub fn from(comptime TargetType: type) EngineObjectVTable {
const wrappedInit = struct {
const funcFind: @TypeOf(@field(TargetType, "init")) = @field(TargetType, "init");
pub fn func(allocator: std.mem.Allocator) EngineDataEventError!*anyopaque {
const newObject = funcFind(allocator) catch return error.BadInit;
return @as(*anyopaque, @ptrCast(newObject));
}
};
var self = EngineObjectVTable{
.typeName = @typeName(TargetType),
.typeSize = @sizeOf(TargetType),
.typeAlign = @alignOf(TargetType),
.init_func = wrappedInit.func,
};
if (@hasDecl(TargetType, "postInit")) {
const wrappedPostInit = struct {
pub fn func(pointer: *anyopaque) EngineDataEventError!void {
var ptr = @as(*TargetType, @ptrCast(@alignCast(pointer)));
try ptr.postInit();
}
};
self.postInit_func = wrappedPostInit.func;
}
if (@hasDecl(TargetType, "preTick")) {
const Wrapped = struct {
pub fn func(pointer: *anyopaque, deltaTime: f64) EngineDataEventError!void {
var ptr = @as(*TargetType, @ptrCast(@alignCast(pointer)));
ptr.preTick(deltaTime) catch return error.UnknownStatePanic;
}
};
self.preTick_func = Wrapped.func;
}
if (@hasDecl(TargetType, "engineDraw")) {
const Wrapped = struct {
pub fn func(pointer: *anyopaque, deltaTime: f64) void {
var ptr = @as(*TargetType, @ptrCast(@alignCast(pointer)));
ptr.engineDraw(deltaTime);
}
};
self.engineDraw_func = Wrapped.func;
}
if (@hasDecl(TargetType, "tick")) {
const Wrapped = struct {
pub fn func(pointer: *anyopaque, deltaTime: f64) void {
var ptr = @as(*TargetType, @ptrCast(@alignCast(pointer)));
ptr.tick(deltaTime);
}
};
self.tick_func = Wrapped.func;
}
if (@hasDecl(TargetType, "processEvents")) {
const wrappedProcessEvents = struct {
pub fn func(pointer: *anyopaque, frameNumber: u64) EngineDataEventError!void {
var ptr = @as(*TargetType, @ptrCast(@alignCast(pointer)));
try ptr.processEvents(frameNumber);
}
};
self.processEvents = wrappedProcessEvents.func;
}
if (@hasDecl(TargetType, "onExitSignal")) {
if (!@hasDecl(TargetType, "readyToExit")) {
@compileError("engine object implemented onExitSignal but did not implement fn readyToExit() bool");
}
const wrappedProcessEvents = struct {
pub fn onExitSignal(pointer: *anyopaque) EngineDataEventError!void {
var ptr = @as(*TargetType, @ptrCast(@alignCast(pointer)));
try ptr.onExitSignal();
}
pub fn readyToExit(pointer: *anyopaque) bool {
var ptr = @as(*TargetType, @ptrCast(@alignCast(pointer)));
return ptr.readyToExit();
}
};
self.exitSignal_func = wrappedProcessEvents.onExitSignal;
self.readyToExit_func = wrappedProcessEvents.readyToExit;
}
if (@hasDecl(TargetType, "deinit")) {
const wrappedDeinit = struct {
pub fn func(pointer: *anyopaque) void {
var ptr = @as(*TargetType, @ptrCast(@alignCast(pointer)));
ptr.deinit();
}
};
self.deinit_func = wrappedDeinit.func;
}
return self;
}
};
pub const EngineObjectRef = InterfaceRef(EngineObjectVTable);