allocator: std.mem.Allocator, objectList: *core.GameObjectList, windowOpen: bool = true, spawnFuncs: std.ArrayListUnmanaged(SpawnEntry) = .{}, spawnPosition: core.Vectorf = .{}, spawnRotation: core.Rotation = .{}, pub const SpawnEntry = struct { typeName: []const u8, spawnFunc: core.GameObjectList.SpawnFunc, opts: Options, }; pub const Options = struct { absoluteSpawnposition: bool = false, // if set, won't move the object to where the spawn rotation and position is }; pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "extras.objectSpawner"); pub fn create(allocator: std.mem.Allocator) !*@This() { const self = try allocator.create(@This()); self.* = .{ .allocator = allocator, .objectList = try core.GameObjectList.create(allocator), }; return self; } pub fn objectSpawnOptions(self: *@This()) void { for (self.spawnFuncs.items) |entry| { if (ig.smallButton(entry.typeName.ptr)) { if (entry.spawnFunc(self.objectList)) |new| { const entity = new.vtable.getEntity.?(new.ptr); if (!entry.opts.absoluteSpawnposition) { self.prepareEntity(entity); } } } } } fn spawnedObjectsList(self: *@This()) void { for (self.objectList.objects.items, 0..) |interface, i| { ig.textFmt("{s}", .{interface.vtable.objectName}) catch {}; ig.sameLine(0.0, 2.0); ig.pushID_Int(@intCast(i)); if (ig.smallButton("delete me")) { interface.vtable.destroy(interface.ptr); } ig.popID(); } } pub fn tick(self: *@This(), dt: f64) void { self.objectList.tick(dt); if (self.windowOpen) { if (ig.begin("object Spawner", null, .{})) { self.objectSpawnOptions(); self.spawnedObjectsList(); } ig.end(); } } pub fn addSpawnFunction(self: *@This(), comptime name: []const u8, comptime T: type) !void { var opts: Options = .{}; if (@hasDecl(T, "SpawnOptions")) { opts = T.SpawnOptions; } try self.spawnFuncs.append(self.allocator, .{ .typeName = name, .spawnFunc = core.GameObjectList.spawnObjectFunction(T), .opts = opts }); } pub fn prepareEntity(self: *@This(), entity: core.Entity) void { if (entity.fetch(core.Scene)) |scene| { scene.setPosition(self.spawnPosition); scene.setRotation(scene.getRotation().add(self.spawnRotation)); _ = scene.getAndResolveTransform(); } } pub fn destroy(self: *@This()) void { self.spawnFuncs.deinit(self.allocator); self.objectList.destroy(); self.allocator.destroy(self); } const std = @import("std"); const backlog = @import("Backlog"); const core = backlog.core; const rend = backlog.rend; const ig = backlog.imgui.api;