samplegame is now compiling on windows in both debug and static build modes on 0.15

This commit is contained in:
peterino2 2025-10-19 23:35:28 -07:00
parent 7a6308454a
commit 02dff11242
39 changed files with 397 additions and 296 deletions

View File

@ -245,7 +245,7 @@ const DynamicDepList: []const struct { dep: []const u8, artifact: []const u8 } =
.{ .dep = "sdl3", .artifact = "SDL3" }, .{ .dep = "sdl3", .artifact = "SDL3" },
.{ .dep = "spng", .artifact = "spng_c" }, .{ .dep = "spng", .artifact = "spng_c" },
.{ .dep = "lua", .artifact = "luac" }, .{ .dep = "lua", .artifact = "luac" },
// .{ .dep = "miniaudio", .artifact = "miniaudio_c" }, .{ .dep = "miniaudio", .artifact = "miniaudio_c" },
.{ .dep = "zphysics", .artifact = "joltc" }, .{ .dep = "zphysics", .artifact = "joltc" },
// .{ .dep = "enet", .artifact = "enet_c" }, // .{ .dep = "enet", .artifact = "enet_c" },
.{ .dep = "ozz", .artifact = "ozz_cpp" }, .{ .dep = "ozz", .artifact = "ozz_cpp" },

View File

@ -117,8 +117,8 @@ pub fn getExtension(path: []const u8) ?[]const u8 {
pub fn generateCookFile(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []const u8) !void { pub fn generateCookFile(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []const u8) !void {
if (getExtension(path)) |extension| { if (getExtension(path)) |extension| {
if (gCookRegistry.typesByExt.get(extension)) |assetType| { if (gCookRegistry.typesByExt.get(extension)) |assetType| {
var cookFilePath = std.ArrayList(u8).init(allocator); var cookFilePath = std.ArrayList(u8){};
defer cookFilePath.deinit(); defer cookFilePath.deinit(allocator);
const generateFunction = gCookRegistry.generates.get(assetType).?; const generateFunction = gCookRegistry.generates.get(assetType).?;
var outPath: std.ArrayListUnmanaged(u8) = .{}; var outPath: std.ArrayListUnmanaged(u8) = .{};
@ -132,7 +132,10 @@ pub fn generateCookFile(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []c
const file = try dir.createFile(outPath.items, .{}); const file = try dir.createFile(outPath.items, .{});
defer file.close(); defer file.close();
try file.writeAll(cookFilePath.items); var writeBuf: [4096]u8 = undefined;
var writer = file.writer(&writeBuf);
try writer.interface.writeAll(cookFilePath.items);
} }
} }
} }

View File

@ -8,7 +8,7 @@ const Name = core.Name;
const AutoHashMapUnmanaged = std.AutoHashMapUnmanaged; const AutoHashMapUnmanaged = std.AutoHashMapUnmanaged;
const tracy = core.tracy; const tracy = core.tracy;
const ma = @import("miniaudio"); const ma = @import("miniaudio").c;
pub fn sound_log(comptime fmt: []const u8, args: anytype) void { pub fn sound_log(comptime fmt: []const u8, args: anytype) void {
core.printInner(core.defaultHighlight, "[SOUND ]: " ++ fmt ++ "\n", args); core.printInner(core.defaultHighlight, "[SOUND ]: " ++ fmt ++ "\n", args);

View File

@ -105,6 +105,8 @@ pub const shell = p2.shell;
pub const algorithm = @import("p2"); pub const algorithm = @import("p2");
pub const math = @import("math.zig"); pub const math = @import("math.zig");
pub const Rayf = math.Rayf;
pub const f32x4 = math.f32x4; // __m128_int pub const f32x4 = math.f32x4; // __m128_int
pub const f32x8 = math.f32x8; // __m256_int pub const f32x8 = math.f32x8; // __m256_int
pub const f32x16 = math.f32x16; // __m512_int pub const f32x16 = math.f32x16; // __m512_int
@ -163,6 +165,11 @@ pub const graphics_log = logging.graphics_log;
pub const engine_err = logging.engine_err; pub const engine_err = logging.engine_err;
pub const engine_errs = logging.engine_errs; pub const engine_errs = logging.engine_errs;
pub const printInner = logging.printInner;
pub const errorHighlight = logging.errorHighlight;
pub const defaultHighlight = logging.defaultHighlight;
pub const packer = @import("packer"); pub const packer = @import("packer");
pub const FileSystem = packer.PackerFS; pub const FileSystem = packer.PackerFS;
@ -398,6 +405,8 @@ pub fn exitNow() void {
} }
pub fn signalShutdown() void { pub fn signalShutdown() void {
// destroy all ecs entities first
ecs.destroyAllEntities();
gEngine.exit(); gEngine.exit();
} }

View File

@ -115,6 +115,22 @@ pub fn createEntity() !Entity {
return rv; return rv;
} }
pub fn destroyAllEntities() void {
const registry = getRegistry();
var elist = std.ArrayList(Entity){};
defer elist.deinit(registry.allocator);
core.engine_log("sparse set length {d}", .{registry.baseSet.dense.items.len});
for (registry.baseSet.dense.items) |dense| {
// TODO: shutdown allocator
elist.append(registry.allocator, Entity{ .handle = dense.sparseIndex }) catch {};
}
for (elist.items) |h| {
destroyEntity(h);
}
}
pub fn destroyEntity(e: Entity) void { pub fn destroyEntity(e: Entity) void {
core.engine_log("entity destroyed: {d}", .{e.handle.index}); core.engine_log("entity destroyed: {d}", .{e.handle.index});
const registry = getRegistry(); const registry = getRegistry();

View File

@ -75,7 +75,7 @@ pub const LoadedModule = struct {
} }
pub fn load(self: *@This(), allocator: std.mem.Allocator) !void { pub fn load(self: *@This(), allocator: std.mem.Allocator) !void {
core.engine_log("[ModuleLoader] loading module: ", .{}); core.engine_log("[ModuleLoader] loading module: {s}", .{self.moduleName});
self.lastLoad = std.time.microTimestamp(); self.lastLoad = std.time.microTimestamp();
try self.stageModule(allocator); try self.stageModule(allocator);

View File

@ -51,8 +51,8 @@ pub const GameObject = struct {
pub fn deinitECS(self: *@This(), handle: core.ObjectHandle) void { pub fn deinitECS(self: *@This(), handle: core.ObjectHandle) void {
_ = handle; _ = handle;
if (!self.destroyed) { if (!self.destroyed) {
self.destroyed = true;
self.objectRef.table.destroy(self.objectRef.ptr, core.get(GameObjectSystem).allocator); self.objectRef.table.destroy(self.objectRef.ptr, core.get(GameObjectSystem).allocator);
self.destroyed = true;
} }
} }
}; };

View File

@ -17,7 +17,7 @@ pub const LogBuffer = struct {
pub fn init(allocator: std.mem.Allocator) @This() { pub fn init(allocator: std.mem.Allocator) @This() {
return .{ return .{
.buffer = std.ArrayList(u8).init(allocator), .buffer = std.ArrayList(u8){},
.allocator = allocator, .allocator = allocator,
}; };
} }
@ -231,7 +231,7 @@ pub const LoggerSys = struct {
try core.dispatchJob(L{ .loggerSys = self }); try core.dispatchJob(L{ .loggerSys = self });
} else { } else {
//self.flushWriteBuffer(); try self.flushWriteBuffer();
} }
self.lock.unlock(); self.lock.unlock();
@ -252,6 +252,7 @@ pub const LoggerSys = struct {
} else { } else {
var writer = self.consoleFile.writer(self.writerBuffer); var writer = self.consoleFile.writer(self.writerBuffer);
try writer.interface.writeAll(self.writeOutBuffer.items); try writer.interface.writeAll(self.writeOutBuffer.items);
try writer.interface.flush();
} }
self.writeOutBuffer.clearRetainingCapacity(); self.writeOutBuffer.clearRetainingCapacity();
self.lock.unlock(); self.lock.unlock();
@ -266,6 +267,7 @@ pub const LoggerSys = struct {
var writer = self.consoleFile.writer(self.writerBuffer); var writer = self.consoleFile.writer(self.writerBuffer);
try writer.interface.writeAll(self.flushBuffer.items); try writer.interface.writeAll(self.flushBuffer.items);
try self.consoleFile.writeAll(""); try self.consoleFile.writeAll("");
try writer.interface.flush();
} }
self.flushBuffer.clearRetainingCapacity(); self.flushBuffer.clearRetainingCapacity();
self.lock.unlock(); self.lock.unlock();
@ -327,6 +329,7 @@ pub const LoggerSys = struct {
self.flushWriteBuffer() catch {}; self.flushWriteBuffer() catch {};
self.allocator.free(self.logFilePath); self.allocator.free(self.logFilePath);
self.logFile.close(); self.logFile.close();
self.allocator.free(self.writerBuffer);
self.writeOutBuffer.deinit(self.allocator); self.writeOutBuffer.deinit(self.allocator);
self.flushBuffer.deinit(self.allocator); self.flushBuffer.deinit(self.allocator);

View File

@ -1,4 +1,4 @@
buffer: core.LogBuffer = undefined, buffer: core.logging.LogBuffer = undefined,
allocator: std.mem.Allocator = undefined, allocator: std.mem.Allocator = undefined,
lastLength: usize = 0, lastLength: usize = 0,
consoleBuffer: [1024]u8 = std.mem.zeroes([1024]u8), consoleBuffer: [1024]u8 = std.mem.zeroes([1024]u8),
@ -10,7 +10,7 @@ pub fn init(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This()); const self = try allocator.create(@This());
self.* = .{ self.* = .{
.allocator = allocator, .allocator = allocator,
.buffer = core.LogBuffer.init(allocator), .buffer = core.logging.LogBuffer.init(allocator),
}; };
self.setup(); self.setup();

View File

@ -46,7 +46,7 @@ pub fn main() !void {
core.engine_log("Working Dir set: {s}", .{try std.fs.cwd().realpath(".", &BUFFER)}); core.engine_log("Working Dir set: {s}", .{try std.fs.cwd().realpath(".", &BUFFER)});
} }
panickers.attachSegfaultHandler(); // panickers.attachSegfaultHandler();
try realMain.main(); try realMain.main();
} }

View File

@ -262,7 +262,7 @@ pub fn parseConnectTarget(allocator: std.mem.Allocator, in: []const u8) !struct
p = try std.fmt.parseInt(u16, ps, 10); p = try std.fmt.parseInt(u16, ps, 10);
} }
return .{ .port = p, .address = try std.fmt.allocPrintZ(allocator, "{s}", .{base}) }; return .{ .port = p, .address = try std.fmt.allocPrintSentinel(allocator, "{s}", .{base}, 0) };
} }
pub fn createLink(self: *@This(), session: *net.Session) !*net.Link { pub fn createLink(self: *@This(), session: *net.Session) !*net.Link {

View File

@ -49,12 +49,12 @@ pub const TransportError = error{
}; };
pub fn ip2String(allocator: std.mem.Allocator, ip: u32) ![:0]u8 { pub fn ip2String(allocator: std.mem.Allocator, ip: u32) ![:0]u8 {
return try std.fmt.allocPrintZ(allocator, "{d}.{d}.{d}.{d}", .{ return try std.fmt.allocPrintSentinel(allocator, "{d}.{d}.{d}.{d}", .{
(ip >> 0) & 0xFF, (ip >> 0) & 0xFF,
(ip >> 8) & 0xFF, (ip >> 8) & 0xFF,
(ip >> 16) & 0xFF, (ip >> 16) & 0xFF,
(ip >> 24) & 0xFF, (ip >> 24) & 0xFF,
}); }, 0);
} }
pub const TransportRef = netEngine.TransportRef; pub const TransportRef = netEngine.TransportRef;

View File

@ -15,7 +15,12 @@ pub fn build(b: *std.Build) void {
const core_dep = b.dependency("core", .{ .target = target, .optimize = optimize, .static_build = static_build }); const core_dep = b.dependency("core", .{ .target = target, .optimize = optimize, .static_build = static_build });
const zphysics_dep = b.dependency("zphysics", .{ .target = target, .optimize = optimize, .static_build = static_build }); const zphysics_dep = b.dependency("zphysics", .{
.target = target,
.optimize = optimize,
.enable_cross_platform_determinism = false,
.static_build = static_build,
});
mod.addImport("core", core_dep.module("core")); mod.addImport("core", core_dep.module("core"));
mod.addImport("zphysics", zphysics_dep.module("root")); mod.addImport("zphysics", zphysics_dep.module("root"));

View File

@ -60,16 +60,9 @@ pub const IgnoreFixedBodiesFilter = extern struct {
}; };
const BroadPhaseLayerInterface = extern struct { const BroadPhaseLayerInterface = extern struct {
usingnamespace zphysics.BroadPhaseLayerInterface.Methods(@This()); broad_phase_layer_interface: zphysics.BroadPhaseLayerInterface = .init(@This()),
__v: *const zphysics.BroadPhaseLayerInterface.VTable = &vtable,
object_to_broad_phase: [ObjectLayers.len]zphysics.BroadPhaseLayer = undefined, object_to_broad_phase: [ObjectLayers.len]zphysics.BroadPhaseLayer = undefined,
const vtable = zphysics.BroadPhaseLayerInterface.VTable{
.getNumBroadPhaseLayers = _getNumBroadPhaseLayers,
.getBroadPhaseLayer = _getBroadPhaseLayer,
};
fn init() BroadPhaseLayerInterface { fn init() BroadPhaseLayerInterface {
var layer_interface: BroadPhaseLayerInterface = .{}; var layer_interface: BroadPhaseLayerInterface = .{};
layer_interface.object_to_broad_phase[ObjectLayers.non_moving] = BroadPhaseLayers.non_moving; layer_interface.object_to_broad_phase[ObjectLayers.non_moving] = BroadPhaseLayers.non_moving;
@ -77,26 +70,23 @@ const BroadPhaseLayerInterface = extern struct {
return layer_interface; return layer_interface;
} }
fn _getNumBroadPhaseLayers(_: *const zphysics.BroadPhaseLayerInterface) callconv(.c) u32 { pub fn getNumBroadPhaseLayers(_: *const zphysics.BroadPhaseLayerInterface) callconv(.c) u32 {
return BroadPhaseLayers.len; return BroadPhaseLayers.len;
} }
fn _getBroadPhaseLayer( pub fn getBroadPhaseLayer(
interface_self: *const zphysics.BroadPhaseLayerInterface, broad_phase_layer_interface: *const zphysics.BroadPhaseLayerInterface,
object_layer: zphysics.ObjectLayer, object_layer: zphysics.ObjectLayer,
) callconv(.c) zphysics.BroadPhaseLayer { ) callconv(.c) zphysics.BroadPhaseLayer {
const self: *const BroadPhaseLayerInterface = @ptrCast(interface_self); const self: *const BroadPhaseLayerInterface = @alignCast(@fieldParentPtr("broad_phase_layer_interface", broad_phase_layer_interface));
return self.object_to_broad_phase[object_layer]; return self.object_to_broad_phase[object_layer];
} }
}; };
const ObjectVsBroadPhaseLayerFilter = extern struct { const ObjectVsBroadPhaseLayerFilter = extern struct {
usingnamespace zphysics.ObjectVsBroadPhaseLayerFilter.Methods(@This()); object_vs_broad_phase_layer_filter: zphysics.ObjectVsBroadPhaseLayerFilter = .init(@This()),
__v: *const zphysics.ObjectVsBroadPhaseLayerFilter.VTable = &vtable,
const vtable = zphysics.ObjectVsBroadPhaseLayerFilter.VTable{ .shouldCollide = _shouldCollide }; pub fn shouldCollide(
fn _shouldCollide(
_: *const zphysics.ObjectVsBroadPhaseLayerFilter, _: *const zphysics.ObjectVsBroadPhaseLayerFilter,
object_layer: zphysics.ObjectLayer, object_layer: zphysics.ObjectLayer,
broad_phase_layer: zphysics.BroadPhaseLayer, broad_phase_layer: zphysics.BroadPhaseLayer,
@ -110,12 +100,9 @@ const ObjectVsBroadPhaseLayerFilter = extern struct {
}; };
const ObjectLayerPairFilter = extern struct { const ObjectLayerPairFilter = extern struct {
usingnamespace zphysics.ObjectLayerPairFilter.Methods(@This()); object_layer_pair_filter: zphysics.ObjectLayerPairFilter = .init(@This()),
__v: *const zphysics.ObjectLayerPairFilter.VTable = &vtable,
const vtable = zphysics.ObjectLayerPairFilter.VTable{ .shouldCollide = _shouldCollide }; pub fn shouldCollide(
fn _shouldCollide(
_: *const zphysics.ObjectLayerPairFilter, _: *const zphysics.ObjectLayerPairFilter,
a: zphysics.ObjectLayer, a: zphysics.ObjectLayer,
b: zphysics.ObjectLayer, b: zphysics.ObjectLayer,
@ -304,40 +291,40 @@ pub const ShapeSettings = union(enum(u8)) {
pub fn release(self: @This()) void { pub fn release(self: @This()) void {
switch (self) { switch (self) {
.convex => |x| { .convex => |x| {
x.release(); x.asShapeSettings().release();
}, },
.box => |x| { .box => |x| {
x.release(); x.asShapeSettings().release();
}, },
.sphere => |x| { .sphere => |x| {
x.release(); x.asShapeSettings().release();
}, },
.triangle => |x| { .triangle => |x| {
x.release(); x.asShapeSettings().release();
}, },
.capsule => |x| { .capsule => |x| {
x.release(); x.asShapeSettings().release();
}, },
.taperedCapsule => |x| { .taperedCapsule => |x| {
x.release(); x.asShapeSettings().release();
}, },
.cylinder => |x| { .cylinder => |x| {
x.release(); x.asShapeSettings().release();
}, },
.convexHull => |x| { .convexHull => |x| {
x.release(); x.asShapeSettings().release();
}, },
.heightField => |x| { .heightField => |x| {
x.release(); x.asShapeSettings().release();
}, },
.mesh => |x| { .mesh => |x| {
x.release(); x.asShapeSettings().release();
}, },
.decorated => |x| { .decorated => |x| {
x.release(); x.asShapeSettings().release();
}, },
.compound => |x| { .compound => |x| {
x.release(); x.asShapeSettings().release();
}, },
} }
} }
@ -345,40 +332,40 @@ pub const ShapeSettings = union(enum(u8)) {
pub fn createShape(self: @This()) !*zphysics.Shape { pub fn createShape(self: @This()) !*zphysics.Shape {
switch (self) { switch (self) {
.convex => |x| { .convex => |x| {
return try x.createShape(); return try x.asShapeSettings().createShape();
}, },
.box => |x| { .box => |x| {
return try x.createShape(); return try x.asShapeSettings().createShape();
}, },
.sphere => |x| { .sphere => |x| {
return try x.createShape(); return try x.asShapeSettings().createShape();
}, },
.triangle => |x| { .triangle => |x| {
return try x.createShape(); return try x.asShapeSettings().createShape();
}, },
.capsule => |x| { .capsule => |x| {
return try x.createShape(); return try x.asShapeSettings().createShape();
}, },
.taperedCapsule => |x| { .taperedCapsule => |x| {
return try x.createShape(); return try x.asShapeSettings().createShape();
}, },
.cylinder => |x| { .cylinder => |x| {
return try x.createShape(); return try x.asShapeSettings().createShape();
}, },
.convexHull => |x| { .convexHull => |x| {
return try x.createShape(); return try x.asShapeSettings().createShape();
}, },
.heightField => |x| { .heightField => |x| {
return try x.createShape(); return try x.asShapeSettings().createShape();
}, },
.mesh => |x| { .mesh => |x| {
return try x.createShape(); return try x.asShapeSettings().createShape();
}, },
.decorated => |x| { .decorated => |x| {
return try x.createShape(); return try x.asShapeSettings().createShape();
}, },
.compound => |x| { .compound => |x| {
return try x.createShape(); return try x.asShapeSettings().createShape();
}, },
} }
} }

View File

@ -73,8 +73,8 @@ pub fn getNormalRayFromScreen(
const width = platform.context().extent.x; const width = platform.context().extent.x;
const height = platform.context().extent.y; const height = platform.context().extent.y;
const sx = core.clamp(s.x, 0, width); const sx = core.math.clamp(s.x, 0, width);
const sy = core.clamp(s.y, 0, height); const sy = core.math.clamp(s.y, 0, height);
const vec = core.Vectorf{ const vec = core.Vectorf{
.x = ((2.0 / width) * sx) - 1.0, .x = ((2.0 / width) * sx) - 1.0,
@ -97,7 +97,7 @@ pub fn getNormalRayFromScreen(
} }
pub fn resolve(self: *@This()) void { pub fn resolve(self: *@This()) void {
const scene = self.entity.fetch(core.Scene).?; const scene = self.entity.fetch(core.Scene) orelse return;
self.updateProjections(); self.updateProjections();

View File

@ -37,7 +37,7 @@ pub fn loadIndexedMeshForPoolingGltf(allocator: std.mem.Allocator, meshName: cor
defer allocator.free(binaryPath); defer allocator.free(binaryPath);
core.engine_log("{s}", .{binaryPath}); core.engine_log("{s}", .{binaryPath});
binaryFile = try core.fs().loadFile(binaryPath); binaryFile = try core.fs().loadFile(binaryPath);
binaryBytes = binaryFile.?.bytes; binaryBytes = binaryFile.?.bytesNoEnd();
} }
defer if (binaryFile) |f| core.fs().unmap(f); defer if (binaryFile) |f| core.fs().unmap(f);
@ -231,7 +231,7 @@ pub fn loadIndexedMeshForPoolingGltf(allocator: std.mem.Allocator, meshName: cor
.y = texcoords.?[uvIndex + 1], .y = texcoords.?[uvIndex + 1],
} else core.Vector2f{}; } else core.Vector2f{};
const normal = if (normalIndex < normals.?.len) core.Vectorf{ const normal = if (normals != null and normalIndex < normals.?.len) core.Vectorf{
.x = normals.?[i], .x = normals.?[i],
.y = normals.?[i + 1], .y = normals.?[i + 1],
.z = normals.?[i + 2], .z = normals.?[i + 2],

View File

@ -329,7 +329,7 @@ pub const Renderer = struct {
// .address_mode_v = .sampleraddressmodeRepeat, // .address_mode_v = .sampleraddressmodeRepeat,
// .address_mode_w = .sampleraddressmodeRepeat, // .address_mode_w = .sampleraddressmodeRepeat,
// //
.mip_lod_bias = -1.0, .mip_lod_bias = 0.0,
.min_lod = 0, // Clamps the minimum of the computed LOD value. .min_lod = 0, // Clamps the minimum of the computed LOD value.
.max_lod = 10, // Clamps the maximum of the computed LOD value. .max_lod = 10, // Clamps the maximum of the computed LOD value.
.address_mode_u = .sampleraddressmodeRepeat, .address_mode_u = .sampleraddressmodeRepeat,

View File

@ -150,8 +150,8 @@ fn findRootDir(allocator: std.mem.Allocator) ![]u8 {
var current_dir = std.fs.cwd(); var current_dir = std.fs.cwd();
// Start from current directory and walk up // Start from current directory and walk up
var path_components = std.ArrayList([]const u8).init(allocator); var path_components = std.ArrayList([]const u8){};
defer path_components.deinit(); defer path_components.deinit(allocator);
// Try current directory first // Try current directory first
current_dir.access("content.txt", .{}) catch { current_dir.access("content.txt", .{}) catch {

View File

@ -376,10 +376,7 @@ pub const TextRenderer = struct {
item.destroy(self.allocator); item.destroy(self.allocator);
} }
for (self.deadList.items) |item| { self.deadList.deinit(self.allocator);
item.destroy(self.allocator);
}
self.geo.destroy(); self.geo.destroy();
self.linearBuffers.deinit(self.allocator); self.linearBuffers.deinit(self.allocator);
self.assignedBuffers.deinit(self.allocator); self.assignedBuffers.deinit(self.allocator);

View File

@ -11,6 +11,7 @@ const QuakeMap = @This();
worldspawn: Entity, worldspawn: Entity,
entities: std.ArrayList(Entity), entities: std.ArrayList(Entity),
allocator: std.mem.Allocator,
// uniqueMaterials: std.StringHashMap(u32), // counts for the number // uniqueMaterials: std.StringHashMap(u32), // counts for the number
// of times a material is used. // of times a material is used.
@ -28,7 +29,7 @@ pub fn deinit(self: *@This()) void {
pub fn read(allocator: Allocator, data: []const u8, error_info: *ErrorInfo) !QuakeMap { pub fn read(allocator: Allocator, data: []const u8, error_info: *ErrorInfo) !QuakeMap {
var worldspawn: ?Entity = null; var worldspawn: ?Entity = null;
var entities = std.ArrayList(Entity).init(allocator); var entities = std.ArrayList(Entity){};
var iter = std.mem.tokenizeAny(u8, data, "\r\n"); var iter = std.mem.tokenizeAny(u8, data, "\r\n");
error_info.line_number = 0; error_info.line_number = 0;
while (iter.next()) |line| { while (iter.next()) |line| {
@ -40,7 +41,7 @@ pub fn read(allocator: Allocator, data: []const u8, error_info: *ErrorInfo) !Qua
if (std.mem.eql(u8, entity.classname, "worldspawn")) { if (std.mem.eql(u8, entity.classname, "worldspawn")) {
worldspawn = entity; worldspawn = entity;
} else { } else {
try entities.append(entity); try entities.append(allocator, entity);
} }
}, },
else => { else => {
@ -53,6 +54,7 @@ pub fn read(allocator: Allocator, data: []const u8, error_info: *ErrorInfo) !Qua
return .{ return .{
.worldspawn = worldspawn orelse return error.WorldSpawnNotFound, .worldspawn = worldspawn orelse return error.WorldSpawnNotFound,
.entities = entities, .entities = entities,
.allocator = allocator,
}; };
} }
@ -66,20 +68,23 @@ pub const Entity = struct {
spawnflags: u32, spawnflags: u32,
properties: std.ArrayList(Property), properties: std.ArrayList(Property),
solids: std.ArrayList(Solid), solids: std.ArrayList(Solid),
allocator: std.mem.Allocator,
pub fn deinit(self: *@This()) void { pub fn deinit(self: *@This()) void {
for (self.solids.items) |*solid| { for (self.solids.items) |*solid| {
solid.faces.deinit(); solid.faces.deinit();
} }
self.properties.deinit(); self.solids.deinit(self.allocator);
self.properties.deinit(self.allocator);
} }
pub fn init(allocator: Allocator) Entity { pub fn init(allocator: Allocator) Entity {
return .{ return .{
.classname = &.{}, .classname = &.{},
.spawnflags = 0, .spawnflags = 0,
.properties = std.ArrayList(Property).init(allocator), .allocator = allocator,
.solids = std.ArrayList(Solid).init(allocator), .properties = std.ArrayList(Property){},
.solids = std.ArrayList(Solid){},
}; };
} }
@ -124,13 +129,14 @@ pub const Entity = struct {
pub const Solid = struct { pub const Solid = struct {
faces: std.ArrayList(Face), faces: std.ArrayList(Face),
allocator: std.mem.Allocator,
fn init(allocator: Allocator) Solid { fn init(allocator: Allocator) Solid {
return .{ .faces = std.ArrayList(Face).init(allocator) }; return .{ .faces = std.ArrayList(Face){}, .allocator = allocator };
} }
fn computeVertices(self: *Solid) !void { fn computeVertices(self: *Solid) !void {
const allocator = self.faces.allocator; const allocator = self.allocator;
var buffer: [64]Vec3d = undefined; var buffer: [64]Vec3d = undefined;
var vertices = std.ArrayListUnmanaged(Vec3d).initBuffer(buffer[0..32]); var vertices = std.ArrayListUnmanaged(Vec3d).initBuffer(buffer[0..32]);
var clipped = std.ArrayListUnmanaged(Vec3d).initBuffer(buffer[32..64]); var clipped = std.ArrayListUnmanaged(Vec3d).initBuffer(buffer[32..64]);
@ -272,10 +278,10 @@ fn readEntity(allocator: Allocator, iter: *TokenIterator(u8, .any), error_info:
} else if (std.mem.eql(u8, property.key, "spawnflags")) { } else if (std.mem.eql(u8, property.key, "spawnflags")) {
entity.spawnflags = try std.fmt.parseInt(u32, property.value, 10); entity.spawnflags = try std.fmt.parseInt(u32, property.value, 10);
} else { } else {
try entity.properties.append(property); try entity.properties.append(entity.allocator, property);
} }
}, },
'{' => try entity.solids.append(try readSolid(allocator, iter, error_info)), '{' => try entity.solids.append(entity.allocator, try readSolid(allocator, iter, error_info)),
'}' => break, '}' => break,
else => { else => {
std.debug.print("error in line: {s}\n", .{line}); std.debug.print("error in line: {s}\n", .{line});
@ -301,7 +307,7 @@ fn readSolid(allocator: Allocator, iter: *TokenIterator(u8, .any), error_info: *
error_info.line_number += 1; error_info.line_number += 1;
switch (line[0]) { switch (line[0]) {
'/' => continue, '/' => continue,
'(' => try solid.faces.append(try readFace(line)), '(' => try solid.faces.append(solid.allocator, try readFace(line)),
'}' => break, '}' => break,
else => { else => {

View File

@ -54,7 +54,7 @@ pub const TBMap = struct {
"Texture", "Texture",
textureName, textureName,
// TODO don't hardcode the root path // TODO don't hardcode the root path
.{ .path = try std.fmt.bufPrint(&fmtBuf2, "textures/{s}.png", .{textureRef}) }, .{ .path = try std.fmt.bufPrint(&fmtBuf2, "textures/{s}.png", .{textureRef}), .textureUseBlockySampler = false },
), ),
); );
} }
@ -92,7 +92,7 @@ pub const TBMap = struct {
vertexCount, vertexCount,
12, 12,
); );
defer settings.release(); defer settings.asShapeSettings().release();
// settings.setMaxConvexRadius(0.1); // settings.setMaxConvexRadius(0.1);
var nameBuffer: [256]u8 = undefined; var nameBuffer: [256]u8 = undefined;

View File

@ -43,8 +43,8 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
else => unreachable, else => unreachable,
}; };
pub usingnamespace switch (dimensions) { pub const DimensionImpl = switch (dimensions) {
2 => extern struct { 2 => struct {
/// Construct new vector. /// Construct new vector.
pub inline fn new(vx: T, vy: T) Self { pub inline fn new(vx: T, vy: T) Self {
return .{ .data = [2]T{ vx, vy } }; return .{ .data = [2]T{ vx, vy } };
@ -76,7 +76,7 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return Self.new(vec4.x(), vec4.y()); return Self.new(vec4.x(), vec4.y());
} }
}, },
3 => extern struct { 3 => struct {
/// Construct new vector. /// Construct new vector.
pub inline fn new(vx: T, vy: T, vz: T) Self { pub inline fn new(vx: T, vy: T, vz: T) Self {
return .{ .data = [3]T{ vx, vy, vz } }; return .{ .data = [3]T{ vx, vy, vz } };
@ -92,12 +92,12 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
/// Shorthand for (0, 0, 1). /// Shorthand for (0, 0, 1).
pub fn forward() Self { pub fn forward() Self {
return new(0, 0, 1); return Self.new(0, 0, 1);
} }
/// Shorthand for (0, 0, -1). /// Shorthand for (0, 0, -1).
pub fn back() Self { pub fn back() Self {
return forward().negate(); return Self.forward().negate();
} }
/// Construct the cross product (as vector) from two vectors. /// Construct the cross product (as vector) from two vectors.
@ -113,7 +113,7 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
const result_x = (y1 * z2) - (z1 * y2); const result_x = (y1 * z2) - (z1 * y2);
const result_y = (z1 * x2) - (x1 * z2); const result_y = (z1 * x2) - (x1 * z2);
const result_z = (x1 * y2) - (y1 * x2); const result_z = (x1 * y2) - (y1 * x2);
return new(result_x, result_y, result_z); return Self.new(result_x, result_y, result_z);
} }
pub inline fn toVec2(self: Self) GenericVector(2, T) { pub inline fn toVec2(self: Self) GenericVector(2, T) {
@ -132,7 +132,7 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return Self.new(vec4.x(), vec4.y(), vec4.z()); return Self.new(vec4.x(), vec4.y(), vec4.z());
} }
}, },
4 => extern struct { 4 => struct {
/// Construct new vector. /// Construct new vector.
pub inline fn new(vx: T, vy: T, vz: T, vw: T) Self { pub inline fn new(vx: T, vy: T, vz: T, vw: T) Self {
return .{ .data = [4]T{ vx, vy, vz, vw } }; return .{ .data = [4]T{ vx, vy, vz, vw } };
@ -140,12 +140,12 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
/// Shorthand for (0, 0, 1, 0). /// Shorthand for (0, 0, 1, 0).
pub fn forward() Self { pub fn forward() Self {
return new(0, 0, 1, 0); return Self.new(0, 0, 1, 0);
} }
/// Shorthand for (0, 0, -1, 0). /// Shorthand for (0, 0, -1, 0).
pub fn back() Self { pub fn back() Self {
return forward().negate(); return Self.forward().negate();
} }
pub inline fn z(self: Self) T { pub inline fn z(self: Self) T {
@ -183,6 +183,8 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
else => unreachable, else => unreachable,
}; };
pub const new = DimensionImpl.new;
pub inline fn x(self: Self) T { pub inline fn x(self: Self) T {
return self.data[0]; return self.data[0];
} }
@ -191,6 +193,9 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return self.data[1]; return self.data[1];
} }
pub const z = DimensionImpl.z;
pub const w = DimensionImpl.w;
pub inline fn xMut(self: *Self) *T { pub inline fn xMut(self: *Self) *T {
return &self.data[0]; return &self.data[0];
} }
@ -199,6 +204,9 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return &self.data[1]; return &self.data[1];
} }
pub const zMut = DimensionImpl.zMut;
pub const wMut = DimensionImpl.wMut;
/// Set all components to the same given value. /// Set all components to the same given value.
pub fn set(val: T) Self { pub fn set(val: T) Self {
const result: Data = @splat(val); const result: Data = @splat(val);
@ -245,6 +253,9 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return right().negate(); return right().negate();
} }
pub const forward = DimensionImpl.forward;
pub const back = DimensionImpl.back;
/// Negate the given vector. /// Negate the given vector.
pub fn negate(self: Self) Self { pub fn negate(self: Self) Self {
return self.scale(-1); return self.scale(-1);
@ -255,7 +266,7 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
pub fn cast(self: Self, comptime dest_type: type) GenericVector(dimensions, dest_type) { pub fn cast(self: Self, comptime dest_type: type) GenericVector(dimensions, dest_type) {
const dest_info = @typeInfo(dest_type); const dest_info = @typeInfo(dest_type);
if (dest_info != .Float and dest_info != .Int) { if (dest_info != .float and dest_info != .int) {
panic("Error, dest type should be integer or float.\n", .{}); panic("Error, dest type should be integer or float.\n", .{});
} }
@ -273,6 +284,14 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return .{ .data = result }; return .{ .data = result };
} }
pub const fromVec2 = DimensionImpl.fromVec2;
pub const fromVec3 = DimensionImpl.fromVec3;
pub const fromVec4 = DimensionImpl.fromVec4;
pub const toVec2 = DimensionImpl.toVec2;
pub const toVec3 = DimensionImpl.toVec3;
pub const toVec4 = DimensionImpl.toVec4;
/// Transform vector to array. /// Transform vector to array.
pub fn toArray(self: Self) [dimensions]T { pub fn toArray(self: Self) [dimensions]T {
return self.data; return self.data;
@ -290,12 +309,24 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return @sqrt(self.dot(self)); return @sqrt(self.dot(self));
} }
/// Return the length (magnitude) squared of given vector.
/// x^2 + y^2 + z^2 ...
pub fn lengthSq(self: Self) T {
return self.dot(self);
}
/// Return the distance between two points. /// Return the distance between two points.
/// [(x1 - x2)^2 + (y1 - y2)^2 + (z1 - z2)^2 ...] /// [(x1 - x2)^2 + (y1 - y2)^2 + (z1 - z2)^2 ...]
pub fn distance(first_vector: Self, second_vector: Self) T { pub fn distance(first_vector: Self, second_vector: Self) T {
return length(first_vector.sub(second_vector)); return length(first_vector.sub(second_vector));
} }
/// Return the distance squared between two points.
/// (x1 - x2)^2 + (y1 - y2)^2 + (z1 - z2)^2 ...
pub fn distanceSq(first_vector: Self, second_vector: Self) T {
return lengthSq(first_vector.sub(second_vector));
}
/// Construct new normalized vector from a given one. /// Construct new normalized vector from a given one.
pub fn norm(self: Self) Self { pub fn norm(self: Self) Self {
const l = self.length(); const l = self.length();
@ -329,6 +360,12 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return .{ .data = result }; return .{ .data = result };
} }
/// Component wise division betwen two given vector.
pub fn div(first_vector: Self, second_vector: Self) Self {
const result = first_vector.data / second_vector.data;
return .{ .data = result };
}
/// Construct vector from the max components in two vectors /// Construct vector from the max components in two vectors
pub fn max(first_vector: Self, second_vector: Self) Self { pub fn max(first_vector: Self, second_vector: Self) Self {
const result = @max(first_vector.data, second_vector.data); const result = @max(first_vector.data, second_vector.data);
@ -362,16 +399,41 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return .{ .data = result }; return .{ .data = result };
} }
pub const rotate = DimensionImpl.rotate;
pub const cross = DimensionImpl.cross;
pub fn swizzle(self: Self, comptime comps: []const u8) SwizzleType(comps.len) {
if (comps.len == 1) {
return self.data[@intFromEnum(@field(Component, &.{comps[0]}))];
}
var result = GenericVector(comps.len, T).zero();
inline for (comps, 0..) |comp, i| {
result.data[i] = self.data[@intFromEnum(@field(Component, &.{comp}))];
}
return result;
}
fn SwizzleType(comps_len: usize) type {
return switch (comps_len) {
1 => T,
else => GenericVector(comps_len, T),
};
}
/// Deprecated; use `swizzle` instead
pub inline fn swizzle2(self: Self, comptime vx: Component, comptime vy: Component) GenericVector(2, T) { pub inline fn swizzle2(self: Self, comptime vx: Component, comptime vy: Component) GenericVector(2, T) {
return GenericVector(2, T).new(self.data[@intFromEnum(vx)], self.data[@intFromEnum(vy)]); return self.swizzle(@tagName(vx) ++ @tagName(vy));
} }
/// Deprecated; use `swizzle` instead
pub inline fn swizzle3(self: Self, comptime vx: Component, comptime vy: Component, comptime vz: Component) GenericVector(3, T) { pub inline fn swizzle3(self: Self, comptime vx: Component, comptime vy: Component, comptime vz: Component) GenericVector(3, T) {
return GenericVector(3, T).new(self.data[@intFromEnum(vx)], self.data[@intFromEnum(vy)], self.data[@intFromEnum(vz)]); return self.swizzle(@tagName(vx) ++ @tagName(vy) ++ @tagName(vz));
} }
/// Deprecated; use `swizzle` instead
pub inline fn swizzle4(self: Self, comptime vx: Component, comptime vy: Component, comptime vz: Component, comptime vw: Component) GenericVector(4, T) { pub inline fn swizzle4(self: Self, comptime vx: Component, comptime vy: Component, comptime vz: Component, comptime vw: Component) GenericVector(4, T) {
return GenericVector(4, T).new(self.data[@intFromEnum(vx)], self.data[@intFromEnum(vy)], self.data[@intFromEnum(vz)], self.data[@intFromEnum(vw)]); return self.swizzle(@tagName(vx) ++ @tagName(vy) ++ @tagName(vz) ++ @tagName(vw));
} }
}; };
} }
@ -564,7 +626,7 @@ test "zalgebra.Vectors.length" {
} }
} }
test "zalgebra.Vectors.distance" { test "zalgebra.Vectors.distance/Sq" {
// Vec2 // Vec2
{ {
const a = Vec2.zero(); const a = Vec2.zero();
@ -572,7 +634,9 @@ test "zalgebra.Vectors.distance" {
const c = Vec2.new(0, 5); const c = Vec2.new(0, 5);
try expectEqual(a.distance(b), 1); try expectEqual(a.distance(b), 1);
try expectEqual(a.distanceSq(b), 1);
try expectEqual(a.distance(c), 5); try expectEqual(a.distance(c), 5);
try expectEqual(a.distanceSq(c), 25);
} }
// Vec3 // Vec3
@ -582,7 +646,9 @@ test "zalgebra.Vectors.distance" {
const c = Vec3.new(0, 5, 0); const c = Vec3.new(0, 5, 0);
try expectEqual(a.distance(b), 1); try expectEqual(a.distance(b), 1);
try expectEqual(a.distanceSq(b), 1);
try expectEqual(a.distance(c), 5); try expectEqual(a.distance(c), 5);
try expectEqual(a.distanceSq(c), 25);
} }
// Vec4 // Vec4
@ -592,7 +658,9 @@ test "zalgebra.Vectors.distance" {
const c = Vec4.new(0, 5, 0, 0); const c = Vec4.new(0, 5, 0, 0);
try expectEqual(a.distance(b), 1); try expectEqual(a.distance(b), 1);
try expectEqual(a.distanceSq(b), 1);
try expectEqual(a.distance(c), 5); try expectEqual(a.distance(c), 5);
try expectEqual(a.distanceSq(c), 25);
} }
} }
@ -886,50 +954,24 @@ test "vector conversions 4 -> 2" {
// Just touching every component // Just touching every component
// not testing every combination cause it's too many // not testing every combination cause it's too many
test "swizzle2" { test "swizzle" {
const v1 = Vec2.new(1, 2);
const x = v1.swizzle("x");
try expectEqual(1, x);
const v2 = Vec2.new(1, 2); const v2 = Vec2.new(1, 2);
const yx = v2.swizzle2(.y, .x); const yx = v2.swizzle("yx");
try expectEqual(Vec2.new(2, 1), yx); try expectEqual(Vec2.new(2, 1), yx);
const v3 = Vec3.new(1, 2, 3); const v3 = Vec3.new(1, 2, 3);
const zy = v3.swizzle2(.z, .y); const zy = v3.swizzle("zy");
const xx = v3.swizzle2(.x, .x); const xx = v3.swizzle("xx");
try expectEqual(Vec2.new(3, 2), zy); try expectEqual(Vec2.new(3, 2), zy);
try expectEqual(Vec2.new(1, 1), xx); try expectEqual(Vec2.new(1, 1), xx);
const v4 = Vec4.new(1, 2, 3, 4); const v4 = Vec4.new(1, 2, 3, 4);
const wz = v4.swizzle2(.w, .z); const wz = v4.swizzle("wz");
const xy = v4.swizzle2(.x, .y); const xy = v4.swizzle("xy");
try expectEqual(Vec2.new(4, 3), wz); try expectEqual(Vec2.new(4, 3), wz);
try expectEqual(Vec2.new(1, 2), xy); try expectEqual(Vec2.new(1, 2), xy);
} }
test "swizzle3" {
const v2 = Vec2.new(1, 2);
const yxy = v2.swizzle3(.y, .x, .y);
try expectEqual(Vec3.new(2, 1, 2), yxy);
const v3 = Vec3.new(1, 2, 3);
const zyx = v3.swizzle3(.z, .y, .x);
try expectEqual(Vec3.new(3, 2, 1), zyx);
const v4 = Vec4.new(1, 2, 3, 4);
const wzy = v4.swizzle3(.w, .z, .y);
const xxx = v4.swizzle3(.x, .x, .x);
try expectEqual(Vec3.new(4, 3, 2), wzy);
try expectEqual(Vec3.new(1, 1, 1), xxx);
}
test "swizzle4" {
const v2 = Vec2.new(1, 2);
const yxyx = v2.swizzle4(.y, .x, .y, .x);
try expectEqual(Vec4.new(2, 1, 2, 1), yxyx);
const v3 = Vec3.new(1, 2, 3);
const zyxz = v3.swizzle4(.z, .y, .x, .z);
try expectEqual(Vec4.new(3, 2, 1, 3), zyxz);
const v4 = Vec4.new(1, 2, 3, 4);
const wzyx = v4.swizzle4(.w, .z, .y, .x);
try expectEqual(Vec4.new(4, 3, 2, 1), wzyx);
}

View File

@ -4,16 +4,55 @@ const std = @import("std");
const expectEqual = std.testing.expectEqual; const expectEqual = std.testing.expectEqual;
const math = std.math; const math = std.math;
pub usingnamespace @import("generic_vector.zig"); const generic_vector = @import("generic_vector.zig");
pub usingnamespace @import("mat3.zig");
pub usingnamespace @import("mat4.zig"); pub const Vec2 = generic_vector.Vec2;
pub usingnamespace @import("quaternion.zig"); pub const Vec2_f64 = generic_vector.Vec2_f64;
pub const Vec2_i32 = generic_vector.Vec2_i32;
pub const Vec2_usize = generic_vector.Vec2_usize;
pub const Vec3 = generic_vector.Vec3;
pub const Vec3_f64 = generic_vector.Vec3_f64;
pub const Vec3_i32 = generic_vector.Vec3_i32;
pub const Vec3_usize = generic_vector.Vec3_usize;
pub const Vec4 = generic_vector.Vec4;
pub const Vec4_f64 = generic_vector.Vec4_f64;
pub const Vec4_i32 = generic_vector.Vec4_i32;
pub const Vec4_usize = generic_vector.Vec4_usize;
pub const GenericVector = generic_vector.GenericVector;
const mat3 = @import("mat3.zig");
pub const Mat3 = mat3.Mat3;
pub const Mat3_f64 = mat3.Mat3_f64;
pub const Mat3x3 = mat3.Mat3x3;
const mat4 = @import("mat4.zig");
pub const Mat4 = mat4.Mat4;
pub const Mat4_f64 = mat4.Mat4_f64;
pub const perspective = mat4.perspective;
pub const perspectiveReversedZ = mat4.perspectiveReversedZ;
pub const orthographic = mat4.orthographic;
pub const lookAt = mat4.lookAt;
pub const Mat4x4 = mat4.Mat4x4;
const quat = @import("quaternion.zig");
pub const Quat = quat.Quat;
pub const Quat_f64 = quat.Quaternion;
pub const Quaternion = quat.Quaternion;
/// Convert degrees to radians. /// Convert degrees to radians.
pub fn toRadians(degrees: anytype) @TypeOf(degrees) { pub fn toRadians(degrees: anytype) @TypeOf(degrees) {
const T = @TypeOf(degrees); const T = @TypeOf(degrees);
if (@typeInfo(T) != .Float) { if (@typeInfo(T) != .float) {
@compileError("Radians not implemented for " ++ @typeName(T)); @compileError("Radians not implemented for " ++ @typeName(T));
} }
@ -24,7 +63,7 @@ pub fn toRadians(degrees: anytype) @TypeOf(degrees) {
pub fn toDegrees(radians: anytype) @TypeOf(radians) { pub fn toDegrees(radians: anytype) @TypeOf(radians) {
const T = @TypeOf(radians); const T = @TypeOf(radians);
if (@typeInfo(T) != .Float) { if (@typeInfo(T) != .float) {
@compileError("Radians not implemented for " ++ @typeName(T)); @compileError("Radians not implemented for " ++ @typeName(T));
} }
@ -34,7 +73,7 @@ pub fn toDegrees(radians: anytype) @TypeOf(radians) {
/// Linear interpolation between two floats. /// Linear interpolation between two floats.
/// `t` is used to interpolate between `from` and `to`. /// `t` is used to interpolate between `from` and `to`.
pub fn lerp(comptime T: type, from: T, to: T, t: T) T { pub fn lerp(comptime T: type, from: T, to: T, t: T) T {
if (@typeInfo(T) != .Float) { if (@typeInfo(T) != .float) {
@compileError("Lerp not implemented for " ++ @typeName(T)); @compileError("Lerp not implemented for " ++ @typeName(T));
} }
@ -70,3 +109,10 @@ test "zalgebra.lerp" {
try expectEqual(lerp(f32, from, to, 0.5), 5); try expectEqual(lerp(f32, from, to, 0.5), 5);
try expectEqual(lerp(f32, from, to, 1), 10); try expectEqual(lerp(f32, from, to, 1), 10);
} }
test {
_ = generic_vector;
_ = mat3;
_ = mat4;
_ = quat;
}

View File

@ -19,10 +19,6 @@ pub const Mat3_f64 = Mat3x3(f64);
/// A column-major 3x3 matrix /// A column-major 3x3 matrix
/// Note: Column-major means accessing data like m.data[COLUMN][ROW]. /// Note: Column-major means accessing data like m.data[COLUMN][ROW].
pub fn Mat3x3(comptime T: type) type { pub fn Mat3x3(comptime T: type) type {
if (@typeInfo(T) != .Float) {
@compileError("Mat3x3 not implemented for " ++ @typeName(T));
}
const Vector3 = GenericVector(3, T); const Vector3 = GenericVector(3, T);
return extern struct { return extern struct {
@ -85,9 +81,8 @@ pub fn Mat3x3(comptime T: type) type {
return result; return result;
} }
/// Return a pointer to the inner data of the matrix. pub fn getSlice(self: *const Self) *const [3][3]T {
pub fn getData(self: *const Self) *const T { return self.data[0..3];
return @ptrCast(&self.data);
} }
/// Return true if two matrices are equals. /// Return true if two matrices are equals.
@ -105,6 +100,10 @@ pub fn Mat3x3(comptime T: type) type {
/// Construct a 3x3 matrix from given axis and angle (in degrees). /// Construct a 3x3 matrix from given axis and angle (in degrees).
pub fn fromRotation(angle_in_degrees: T, axis: Vector3) Self { pub fn fromRotation(angle_in_degrees: T, axis: Vector3) Self {
if (@typeInfo(T) != .float) {
@compileError("Mat3x3.fromRotation() not implemented for " ++ @typeName(T));
}
var result = Self.identity(); var result = Self.identity();
const norm_axis = axis.norm(); const norm_axis = axis.norm();
@ -133,6 +132,10 @@ pub fn Mat3x3(comptime T: type) type {
} }
pub fn rotate(self: Self, angle_in_degrees: T, axis: Vector3) Self { pub fn rotate(self: Self, angle_in_degrees: T, axis: Vector3) Self {
if (@typeInfo(T) != .float) {
@compileError("Mat3x3.rotate() not implemented for " ++ @typeName(T));
}
const rotation_mat = Self.fromRotation(angle_in_degrees, axis); const rotation_mat = Self.fromRotation(angle_in_degrees, axis);
return Self.mul(self, rotation_mat); return Self.mul(self, rotation_mat);
} }
@ -140,6 +143,10 @@ pub fn Mat3x3(comptime T: type) type {
/// Construct a rotation matrix from euler angles (X * Y * Z). /// Construct a rotation matrix from euler angles (X * Y * Z).
/// Order matters because matrix multiplication are NOT commutative. /// Order matters because matrix multiplication are NOT commutative.
pub fn fromEulerAngles(euler_angle: Vector3) Self { pub fn fromEulerAngles(euler_angle: Vector3) Self {
if (@typeInfo(T) != .float) {
@compileError("Mat3x3.fromEulerAngles() not implemented for " ++ @typeName(T));
}
const x = Self.fromRotation(euler_angle.x(), Vector3.right()); const x = Self.fromRotation(euler_angle.x(), Vector3.right());
const y = Self.fromRotation(euler_angle.y(), Vector3.up()); const y = Self.fromRotation(euler_angle.y(), Vector3.up());
const z = Self.fromRotation(euler_angle.z(), Vector3.forward()); const z = Self.fromRotation(euler_angle.z(), Vector3.forward());
@ -149,6 +156,10 @@ pub fn Mat3x3(comptime T: type) type {
/// Ortho normalize given matrix. /// Ortho normalize given matrix.
pub fn orthoNormalize(self: Self) Self { pub fn orthoNormalize(self: Self) Self {
if (@typeInfo(T) != .float) {
@compileError("Mat3x3.orthoNormalize() not implemented for " ++ @typeName(T));
}
const column_1 = Vector3.new(self.data[0][0], self.data[0][1], self.data[0][2]).norm(); const column_1 = Vector3.new(self.data[0][0], self.data[0][1], self.data[0][2]).norm();
const column_2 = Vector3.new(self.data[1][0], self.data[1][1], self.data[1][2]).norm(); const column_2 = Vector3.new(self.data[1][0], self.data[1][1], self.data[1][2]).norm();
const column_3 = Vector3.new(self.data[2][0], self.data[2][1], self.data[2][2]).norm(); const column_3 = Vector3.new(self.data[2][0], self.data[2][1], self.data[2][2]).norm();
@ -174,6 +185,10 @@ pub fn Mat3x3(comptime T: type) type {
/// Taken from Mike Day at Insomniac Games (and `glm` as the same function). /// Taken from Mike Day at Insomniac Games (and `glm` as the same function).
/// For more details: https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2012/07/euler-angles1.pdf /// For more details: https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2012/07/euler-angles1.pdf
pub fn extractEulerAngles(self: Self) Vector3 { pub fn extractEulerAngles(self: Self) Vector3 {
if (@typeInfo(T) != .float) {
@compileError("Mat3x3.extractEulerAngles() not implemented for " ++ @typeName(T));
}
const m = self.orthoNormalize(); const m = self.orthoNormalize();
const theta_x = math.atan2(m.data[1][2], m.data[2][2]); const theta_x = math.atan2(m.data[1][2], m.data[2][2]);
@ -259,27 +274,22 @@ pub fn Mat3x3(comptime T: type) type {
return inv_mat; return inv_mat;
} }
/// Print the 3x3 to stderr. pub fn format(
pub fn debugPrint(self: Self) void { self: Self,
const print = std.debug.print; comptime fmt: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = fmt;
_ = options;
print("({d}, {d}, {d})\n", .{ for (0..3) |i| {
self.data[0][0], try writer.print("({d:.2}, {d:.2}, {d:.2})\n", .{
self.data[1][0], self.data[0][i],
self.data[2][0], self.data[1][i],
}); self.data[2][i],
});
print("({d}, {d}, {d})\n", .{ }
self.data[0][1],
self.data[1][1],
self.data[2][1],
});
print("({d}, {d}, {d})\n", .{
self.data[0][2],
self.data[1][2],
self.data[2][2],
});
} }
/// Cast a type to another type. /// Cast a type to another type.
@ -287,7 +297,7 @@ pub fn Mat3x3(comptime T: type) type {
pub fn cast(self: Self, comptime dest_type: type) Mat3x3(dest_type) { pub fn cast(self: Self, comptime dest_type: type) Mat3x3(dest_type) {
const dest_info = @typeInfo(dest_type); const dest_info = @typeInfo(dest_type);
if (dest_info != .Float) { if (dest_info != .float) {
std.debug.panic("Error, dest type should be float.\n", .{}); std.debug.panic("Error, dest type should be float.\n", .{});
} }

View File

@ -23,7 +23,7 @@ pub const lookAt = Mat4.lookAt;
/// A column-major 4x4 matrix /// A column-major 4x4 matrix
/// Note: Column-major means accessing data like m.data[COLUMN][ROW]. /// Note: Column-major means accessing data like m.data[COLUMN][ROW].
pub fn Mat4x4(comptime T: type) type { pub fn Mat4x4(comptime T: type) type {
if (@typeInfo(T) != .Float) { if (@typeInfo(T) != .float) {
@compileError("Mat4x4 not implemented for " ++ @typeName(T)); @compileError("Mat4x4 not implemented for " ++ @typeName(T));
} }
@ -92,9 +92,8 @@ pub fn Mat4x4(comptime T: type) type {
return result; return result;
} }
/// Return a pointer to the inner data of the matrix. pub fn getSlice(self: *const Self) *const [4][4]T {
pub fn getData(self: *const Self) *const T { return self.data[0..4];
return @ptrCast(&self.data);
} }
/// Return true if two matrices are equals. /// Return true if two matrices are equals.
@ -114,12 +113,14 @@ pub fn Mat4x4(comptime T: type) type {
/// Construct 4x4 translation matrix by multiplying identity matrix and /// Construct 4x4 translation matrix by multiplying identity matrix and
/// given translation vector. /// given translation vector.
pub fn fromTranslate(axis: Vector3) Self { pub fn fromTranslate(axis: Vector3) Self {
var result = Self.identity(); return .{
result.data[3][0] = axis.data[0]; .data = .{
result.data[3][1] = axis.data[1]; .{ 1, 0, 0, 0 },
result.data[3][2] = axis.data[2]; .{ 0, 1, 0, 0 },
.{ 0, 0, 1, 0 },
return result; .{ axis.x(), axis.y(), axis.z(), 1 },
},
};
} }
/// Make a translation between the given matrix and the given axis. /// Make a translation between the given matrix and the given axis.
@ -217,13 +218,14 @@ pub fn Mat4x4(comptime T: type) type {
} }
pub fn fromScale(axis: Vector3) Self { pub fn fromScale(axis: Vector3) Self {
var result = Self.identity(); return .{
.data = .{
result.data[0][0] = axis.x(); .{ axis.x(), 0, 0, 0 },
result.data[1][1] = axis.y(); .{ 0, axis.y(), 0, 0 },
result.data[2][2] = axis.z(); .{ 0, 0, axis.z(), 0 },
.{ 0, 0, 0, 1 },
return result; },
};
} }
pub fn scale(self: Self, axis: Vector3) Self { pub fn scale(self: Self, axis: Vector3) Self {
@ -243,18 +245,17 @@ pub fn Mat4x4(comptime T: type) type {
/// Note: Field of view is given in degrees. /// Note: Field of view is given in degrees.
/// Also for more details https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml. /// Also for more details https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml.
pub fn perspective(fovy_in_degrees: T, aspect_ratio: T, z_near: T, z_far: T) Self { pub fn perspective(fovy_in_degrees: T, aspect_ratio: T, z_near: T, z_far: T) Self {
var result = Self.identity();
const f = 1 / @tan(root.toRadians(fovy_in_degrees) * 0.5); const f = 1 / @tan(root.toRadians(fovy_in_degrees) * 0.5);
const nf = 1 / (z_near - z_far);
result.data[0][0] = f / aspect_ratio; return .{
result.data[1][1] = f; .data = .{
result.data[2][2] = (z_near + z_far) / (z_near - z_far); .{ f / aspect_ratio, 0, 0, 0 },
result.data[2][3] = -1; .{ 0, f, 0, 0 },
result.data[3][2] = 2 * z_far * z_near / (z_near - z_far); .{ 0, 0, (z_near + z_far) * nf, -1 },
result.data[3][3] = 0; .{ 0, 0, 2 * z_near * z_far * nf, 0 },
},
return result; };
} }
/// Construct a perspective 4x4 matrix with reverse Z and infinite far plane. /// Construct a perspective 4x4 matrix with reverse Z and infinite far plane.
@ -262,18 +263,16 @@ pub fn Mat4x4(comptime T: type) type {
/// Also for more details https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml. /// Also for more details https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml.
/// For Reversed-Z details https://nlguillemot.wordpress.com/2016/12/07/reversed-z-in-opengl/ /// For Reversed-Z details https://nlguillemot.wordpress.com/2016/12/07/reversed-z-in-opengl/
pub fn perspectiveReversedZ(fovy_in_degrees: T, aspect_ratio: T, z_near: T) Self { pub fn perspectiveReversedZ(fovy_in_degrees: T, aspect_ratio: T, z_near: T) Self {
var result = Self.identity();
const f = 1 / @tan(root.toRadians(fovy_in_degrees) * 0.5); const f = 1 / @tan(root.toRadians(fovy_in_degrees) * 0.5);
result.data[0][0] = f / aspect_ratio; return .{
result.data[1][1] = f; .data = .{
result.data[2][2] = 0; .{ f / aspect_ratio, 0, 0, 0 },
result.data[2][3] = -1; .{ 0, f, 0, 0 },
result.data[3][2] = z_near; .{ 0, 0, 0, -1 },
result.data[3][3] = 0; .{ 0, 0, z_near, 0 },
},
return result; };
} }
/// Construct an orthographic 4x4 matrix. /// Construct an orthographic 4x4 matrix.
@ -440,37 +439,23 @@ pub fn Mat4x4(comptime T: type) type {
}; };
} }
/// Print the 4x4 to stderr. pub fn format(
pub fn debugPrint(self: Self) void { self: Self,
const print = std.debug.print; comptime fmt: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = fmt;
_ = options;
print("({d}, {d}, {d}, {d})\n", .{ for (0..4) |i| {
self.data[0][0], try writer.print("({d:.2}, {d:.2}, {d:.2}, {d:.2})\n", .{
self.data[1][0], self.data[0][i],
self.data[2][0], self.data[1][i],
self.data[3][0], self.data[2][i],
}); self.data[3][i],
});
print("({d}, {d}, {d}, {d})\n", .{ }
self.data[0][1],
self.data[1][1],
self.data[2][1],
self.data[3][1],
});
print("({d}, {d}, {d}, {d})\n", .{
self.data[0][2],
self.data[1][2],
self.data[2][2],
self.data[3][2],
});
print("({d}, {d}, {d}, {d})\n", .{
self.data[0][3],
self.data[1][3],
self.data[2][3],
self.data[3][3],
});
} }
/// Cast a type to another type. /// Cast a type to another type.
@ -478,7 +463,7 @@ pub fn Mat4x4(comptime T: type) type {
pub fn cast(self: Self, comptime dest_type: type) Mat4x4(dest_type) { pub fn cast(self: Self, comptime dest_type: type) Mat4x4(dest_type) {
const dest_info = @typeInfo(dest_type); const dest_info = @typeInfo(dest_type);
if (dest_info != .Float) { if (dest_info != .float) {
std.debug.panic("Error, dest type should be float.\n", .{}); std.debug.panic("Error, dest type should be float.\n", .{});
} }

View File

@ -24,7 +24,7 @@ pub const Quat_f64 = Quaternion(f64);
/// A Quaternion for 3D rotations. /// A Quaternion for 3D rotations.
pub fn Quaternion(comptime T: type) type { pub fn Quaternion(comptime T: type) type {
if (@typeInfo(T) != .Float) { if (@typeInfo(T) != .float) {
@compileError("Quaternion not implemented for " ++ @typeName(T)); @compileError("Quaternion not implemented for " ++ @typeName(T));
} }
@ -145,7 +145,7 @@ pub fn Quaternion(comptime T: type) type {
} }
/// Convert given quaternion to rotation 3x3 matrix. /// Convert given quaternion to rotation 3x3 matrix.
fn toMat3(self: Self) Mat3x3(T) { pub fn toMat3(self: Self) Mat3x3(T) {
var result: Mat3x3(T) = undefined; var result: Mat3x3(T) = undefined;
const normalized = self.norm(); const normalized = self.norm();
@ -378,7 +378,7 @@ pub fn Quaternion(comptime T: type) type {
pub fn cast(self: Self, comptime dest_type: type) Quaternion(dest_type) { pub fn cast(self: Self, comptime dest_type: type) Quaternion(dest_type) {
const dest_info = @typeInfo(dest_type); const dest_info = @typeInfo(dest_type);
if (dest_info != .Float) { if (dest_info != .float) {
std.debug.panic("Error, dest type should be float.\n", .{}); std.debug.panic("Error, dest type should be float.\n", .{});
} }

View File

@ -60,7 +60,7 @@ pub fn windowOpen(entry: *igutils.MenuEntry, dt: f64) void {
ig.textSlice(slice); ig.textSlice(slice);
} }
if (core.getEngineObject(core.EcsRegistry)) |ecsReg| { if (core.getEngineObject(core.ecs.EcsRegistry)) |ecsReg| {
ig.separator(); ig.separator();
for (ecsReg.containerNames.items, 0..) |*name, i| { for (ecsReg.containerNames.items, 0..) |*name, i| {

View File

@ -1,7 +1,6 @@
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
lastUpdateFrame: u64 = 0, lastUpdateFrame: u64 = 0,
arena: std.heap.ArenaAllocator,
bodyIds: std.ArrayList(physics.BodyId), bodyIds: std.ArrayList(physics.BodyId),
pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "extras.PhysicsObjectList"); pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "extras.PhysicsObjectList");
@ -11,8 +10,7 @@ pub fn create(allocator: std.mem.Allocator) !*@This() {
self.* = .{ self.* = .{
.allocator = allocator, .allocator = allocator,
.arena = std.heap.ArenaAllocator.init(allocator), .bodyIds = std.ArrayList(physics.BodyId){},
.bodyIds = std.ArrayList(physics.BodyId).init(allocator),
}; };
if (core.getEngineObject(igutils.TopBar)) |topbar| { if (core.getEngineObject(igutils.TopBar)) |topbar| {
@ -27,7 +25,7 @@ pub fn windowOpen(entry: *igutils.MenuEntry, dt: f64) void {
const self: *@This() = @ptrCast(@alignCast(entry.ctx)); const self: *@This() = @ptrCast(@alignCast(entry.ctx));
self.bodyIds.clearRetainingCapacity(); self.bodyIds.clearRetainingCapacity();
physics.context().system.getBodyIds(&self.bodyIds) catch return; physics.context().system.getBodyIds(self.allocator, &self.bodyIds) catch return;
if (ig.begin("Physics Objects", &entry.open, .{})) { if (ig.begin("Physics Objects", &entry.open, .{})) {
ig.textf("total Physics Objects count: {d}", .{self.bodyIds.items.len}); ig.textf("total Physics Objects count: {d}", .{self.bodyIds.items.len});
@ -39,8 +37,7 @@ pub fn windowOpen(entry: *igutils.MenuEntry, dt: f64) void {
} }
pub fn destroy(self: *@This()) void { pub fn destroy(self: *@This()) void {
self.arena.deinit(); self.bodyIds.deinit(self.allocator);
self.bodyIds.deinit();
self.allocator.destroy(self); self.allocator.destroy(self);
} }

View File

@ -28,7 +28,7 @@ pub fn setup(self: *@This()) void {
pub fn windowOpen(entry: *igu.MenuEntry, dt: f64) void { pub fn windowOpen(entry: *igu.MenuEntry, dt: f64) void {
const self: *@This() = @ptrCast(@alignCast(entry.ctx)); const self: *@This() = @ptrCast(@alignCast(entry.ctx));
core.rollingAverage(&self.dtAverage, dt, 50); core.math.rollingAverage(&self.dtAverage, dt, 50);
if (ig.begin("renderer debug", null, .{})) { if (ig.begin("renderer debug", null, .{})) {
if (self.dtAverage > 0.000001) { if (self.dtAverage > 0.000001) {

View File

@ -22,7 +22,7 @@ pub fn Browser(comptime T: type) type {
const self = try allocator.create(@This()); const self = try allocator.create(@This());
self.* = .{ self.* = .{
.browserName = try std.fmt.allocPrintZ(allocator, "Browser", .{}), .browserName = try std.fmt.allocPrintSentinel(allocator, "Browser", .{}, 0),
.allocator = allocator, .allocator = allocator,
}; };

View File

@ -57,7 +57,10 @@ pub fn setPosition(self: *@This(), position: core.Vectorf) void {
} }
pub fn getPosition(self: *@This()) core.Vectorf { pub fn getPosition(self: *@This()) core.Vectorf {
return self.camera.fetch(core.Scene).?.getPosition(); if (self.camera.fetch(core.Scene)) |scene| {
return scene.getPosition();
}
return .{};
} }
// movement value can be sourced from a mouse binding that has enableMouseRelative() on // movement value can be sourced from a mouse binding that has enableMouseRelative() on

View File

@ -555,10 +555,6 @@ pub fn SparseSetAdvanced(comptime T: type, comptime SparseSize: u32) type {
self.dense.deinit(self.allocator); self.dense.deinit(self.allocator);
} }
pub fn denseList(self: @This()) []const T {
return self.dense.items;
}
pub const EcsContainerInterfaceVTable = EcsContainerInterface.Implement(@This()); pub const EcsContainerInterfaceVTable = EcsContainerInterface.Implement(@This());
pub fn handleExists(self: @This(), handle: SetHandle) bool { pub fn handleExists(self: @This(), handle: SetHandle) bool {

View File

@ -48,8 +48,7 @@ pub fn build(b: *std.Build) void {
) orelse true, ) orelse true,
}; };
const static_build = b.option(bool, "static_build", "builds backlog dependencies for static linking") orelse false; const static_build = b.option(bool, "static_build", "builds backlog dependencies for static linking") orelse true;
_ = static_build;
const user_extensions = b.option( const user_extensions = b.option(
[]const std.Build.LazyPath, []const std.Build.LazyPath,
@ -74,14 +73,14 @@ pub fn build(b: *std.Build) void {
const joltc = b.addLibrary(.{ const joltc = b.addLibrary(.{
.name = "joltc", .name = "joltc",
.linkage = if (options.shared) .dynamic else .static, .linkage = if (!static_build) .dynamic else .static,
.root_module = b.createModule(.{ .root_module = b.createModule(.{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
}), }),
}); });
if (options.shared and target.result.os.tag == .windows) if (!static_build and target.result.os.tag == .windows)
joltc.root_module.addCMacro("JPC_API", "extern __declspec(dllexport)"); joltc.root_module.addCMacro("JPC_API", "extern __declspec(dllexport)");
b.installArtifact(joltc); b.installArtifact(joltc);

BIN
projects/content/meshes/fpsArms_magnum.fbx (Stored with Git LFS)

Binary file not shown.

View File

@ -111,7 +111,7 @@ pub fn testThing(self: *@This()) !void {
core.setBarrierCount(workerCount); core.setBarrierCount(workerCount);
for (0..workerCount) |i| { for (0..workerCount) |i| {
const name = try std.fmt.allocPrintZ(std.heap.c_allocator, "MultiJob{d}", .{i}); const name = try std.fmt.allocPrintSentinel(std.heap.c_allocator, "MultiJob{d}", .{i}, 0);
try core.dispatchJob(MultiJob{ .threadName = name, .threadId = @intCast(i) }); try core.dispatchJob(MultiJob{ .threadName = name, .threadId = @intCast(i) });
} }
} }

View File

@ -152,7 +152,7 @@ pub const ExternGameObject = struct {
} }
// change this into a parallel for // change this into a parallel for
for (0..300) |i| { for (0..1) |i| {
_ = try core.get(core.GameObjectSystem).spawnObject(BoxObject, "Box", .{ _ = try core.get(core.GameObjectSystem).spawnObject(BoxObject, "Box", .{
.posRot = .{ .posRot = .{
.position = .{ .x = core.itof32((i % 10)) * 2, .y = 15.0, .z = core.itof32(@divFloor(i, 10) * 2) }, .position = .{ .x = core.itof32((i % 10)) * 2, .y = 15.0, .z = core.itof32(@divFloor(i, 10) * 2) },

View File

@ -494,7 +494,7 @@ pub fn deinit(self: *@This()) void {
pub fn main() anyerror!void { pub fn main() anyerror!void {
var spec = try backlog.getSpec("sampleGame"); var spec = try backlog.getSpec("sampleGame");
// try spec.put("useGPA", .{ .boolean = false }); try spec.put("useGPA", .{ .boolean = true });
_ = backlog.startEngine(&NeonObjectTable, &spec); _ = backlog.startEngine(&NeonObjectTable, &spec);
// try backlog.initializeAndRunStandardProgram(@This(), .{ // try backlog.initializeAndRunStandardProgram(@This(), .{

View File

@ -225,7 +225,7 @@ fn loadFileAllocFromCwd(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []c
const filesize = (try file.stat()).size + 1; // add null byte const filesize = (try file.stat()).size + 1; // add null byte
const buffer: []u8 = try allocator.alloc(u8, filesize); const buffer: []u8 = try allocator.alloc(u8, filesize);
errdefer allocator.free(buffer); errdefer allocator.free(buffer);
try file.reader().readNoEof(buffer[0 .. buffer.len - 1]); _ = try file.read(buffer[0 .. buffer.len - 1]);
buffer[buffer.len - 1] = 0; buffer[buffer.len - 1] = 0;
return buffer; return buffer;
} }
@ -295,11 +295,8 @@ fn writeBuildZigFiles(self: *@This()) !void {
fn writeBuildZig(self: *@This(), workingDir: *std.fs.Dir) !void { fn writeBuildZig(self: *@This(), workingDir: *std.fs.Dir) !void {
const out_path = "build.zig"; const out_path = "build.zig";
var content = std.ArrayList(u8).init(self.allocator); var content = std.ArrayList(u8){};
defer content.deinit(); defer content.deinit(self.allocator);
var writer = content.writer();
const template = const template =
\\ const std = @import("std"); \\ const std = @import("std");
\\ const Backlog = @import("Backlog"); \\ const Backlog = @import("Backlog");
@ -315,7 +312,7 @@ fn writeBuildZig(self: *@This(), workingDir: *std.fs.Dir) !void {
\\ }}); \\ }});
; ;
try writer.print(template, .{self.engineRelative.?}); try content.print(self.allocator, template, .{self.engineRelative.?});
const template2 = const template2 =
\\ const program = blbuild.program(.{{ \\ const program = blbuild.program(.{{
@ -330,9 +327,9 @@ fn writeBuildZig(self: *@This(), workingDir: *std.fs.Dir) !void {
\\ }} \\ }}
; ;
try writer.print(template2, .{self.targetName.?}); try content.print(self.allocator, template2, .{self.targetName.?});
try writer.writeByte(0); try content.append(self.allocator, 0);
try self.writeZigFile(workingDir, out_path, content.items); try self.writeZigFile(workingDir, out_path, content.items);
} }
@ -348,13 +345,12 @@ const entries: []const struct { name: []const u8, path: []const u8 } = &.{
}; };
fn writeBuildZigZon(self: *@This(), workingDir: *std.fs.Dir) !void { fn writeBuildZigZon(self: *@This(), workingDir: *std.fs.Dir) !void {
var content = std.ArrayList(u8).init(self.allocator); var content = std.ArrayList(u8){};
defer content.deinit(); defer content.deinit(self.allocator);
var writer = content.writer(); try content.print(self.allocator, ".{{\n", .{});
try writer.print(".{{\n", .{});
try writer.print( try content.print(self.allocator,
\\ .name = .{s}, \\ .name = .{s},
\\ .version = "0.0.0", \\ .version = "0.0.0",
\\ .dependencies = .{{ \\ .dependencies = .{{
@ -362,34 +358,35 @@ fn writeBuildZigZon(self: *@This(), workingDir: *std.fs.Dir) !void {
, .{ std.fs.path.basename(self.targetDir.?), self.engineRelative.? }); , .{ std.fs.path.basename(self.targetDir.?), self.engineRelative.? });
for (entries) |entry| { for (entries) |entry| {
try writer.print(" .{s} = .{{ .path = \"{s}/{s}\" }},\n", .{ entry.name, self.engineRelative.?, entry.path }); try content.print(self.allocator, " .{s} = .{{ .path = \"{s}/{s}\" }},\n", .{ entry.name, self.engineRelative.?, entry.path });
} }
try writer.print( try content.print(self.allocator,
\\ }}, \\ }},
\\ \\
, .{}); , .{});
try writer.print( try content.print(self.allocator,
\\ .paths = .{{ "" }}, \\ .paths = .{{ "" }},
\\ \\
, .{}); , .{});
try writer.print( try content.print(self.allocator,
\\ .fingerprint = {s}, \\ .fingerprint = {s},
\\ \\
, .{self.fingerprint.?}); , .{self.fingerprint.?});
try writer.print("}}", .{}); try content.print(self.allocator, "}}", .{});
const file = try workingDir.createFile("build.zig.zon", .{}); const file = try workingDir.createFile("build.zig.zon", .{});
defer file.close(); defer file.close();
try file.writeAll(content.items); var writer = file.writer(&wbuf);
try writer.interface.writeAll(content.items);
} }
fn writeMainZig(self: *@This(), workingDir: *std.fs.Dir) !void { fn writeMainZig(self: *@This(), workingDir: *std.fs.Dir) !void {
var content = std.ArrayList(u8).init(self.allocator); var content = std.ArrayList(u8){};
defer content.deinit(); defer content.deinit(self.allocator);
const template = const template =
\\ pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "main"); \\ pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "main");
@ -435,10 +432,11 @@ fn writeMainZig(self: *@This(), workingDir: *std.fs.Dir) !void {
\\ \\
; ;
try content.appendSlice(template); const allocator = self.allocator;
try content.appendSlice(self.targetName.?); try content.appendSlice(allocator, template);
try content.appendSlice(template2); try content.appendSlice(allocator, self.targetName.?);
try content.append(0); try content.appendSlice(allocator, template2);
try content.append(allocator, 0);
const out_path = "src/main.zig"; const out_path = "src/main.zig";
@ -447,15 +445,17 @@ fn writeMainZig(self: *@This(), workingDir: *std.fs.Dir) !void {
try self.writeZigFile(workingDir, out_path, content.items); try self.writeZigFile(workingDir, out_path, content.items);
} }
var wbuf: [4096]u8 = undefined;
fn writeZigFile(self: *@This(), workingDir: *std.fs.Dir, out_path: []const u8, contents: []const u8) !void { fn writeZigFile(self: *@This(), workingDir: *std.fs.Dir, out_path: []const u8, contents: []const u8) !void {
var ast = try std.zig.Ast.parse(self.allocator, @as([:0]const u8, @ptrCast(contents[0 .. contents.len - 1])), .zig); var ast = try std.zig.Ast.parse(self.allocator, @as([:0]const u8, @ptrCast(contents[0 .. contents.len - 1])), .zig);
defer ast.deinit(self.allocator); defer ast.deinit(self.allocator);
const out = try ast.render(self.allocator); const out = try ast.renderAlloc(self.allocator);
const file = try workingDir.createFile(out_path, .{}); const file = try workingDir.createFile(out_path, .{});
defer file.close(); defer file.close();
try file.writeAll(out); var fw = file.writer(&wbuf);
try fw.interface.writeAll(out);
} }
fn updateFingerPrint(self: *@This(), zonEntry: []const u8) void { fn updateFingerPrint(self: *@This(), zonEntry: []const u8) void {

View File

@ -107,8 +107,8 @@ fn findRootDir(allocator: std.mem.Allocator) ![]u8 {
var current_dir = std.fs.cwd(); var current_dir = std.fs.cwd();
// Start from current directory and walk up // Start from current directory and walk up
var path_components = std.ArrayList([]const u8).init(allocator); var path_components = std.ArrayList([]const u8){};
defer path_components.deinit(); defer path_components.deinit(allocator);
// Try current directory first // Try current directory first
current_dir.access("content.txt", .{}) catch { current_dir.access("content.txt", .{}) catch {