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 = "spng", .artifact = "spng_c" },
.{ .dep = "lua", .artifact = "luac" },
// .{ .dep = "miniaudio", .artifact = "miniaudio_c" },
.{ .dep = "miniaudio", .artifact = "miniaudio_c" },
.{ .dep = "zphysics", .artifact = "joltc" },
// .{ .dep = "enet", .artifact = "enet_c" },
.{ .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 {
if (getExtension(path)) |extension| {
if (gCookRegistry.typesByExt.get(extension)) |assetType| {
var cookFilePath = std.ArrayList(u8).init(allocator);
defer cookFilePath.deinit();
var cookFilePath = std.ArrayList(u8){};
defer cookFilePath.deinit(allocator);
const generateFunction = gCookRegistry.generates.get(assetType).?;
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, .{});
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 tracy = core.tracy;
const ma = @import("miniaudio");
const ma = @import("miniaudio").c;
pub fn sound_log(comptime fmt: []const u8, args: anytype) void {
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 math = @import("math.zig");
pub const Rayf = math.Rayf;
pub const f32x4 = math.f32x4; // __m128_int
pub const f32x8 = math.f32x8; // __m256_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_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 FileSystem = packer.PackerFS;
@ -398,6 +405,8 @@ pub fn exitNow() void {
}
pub fn signalShutdown() void {
// destroy all ecs entities first
ecs.destroyAllEntities();
gEngine.exit();
}

View File

@ -115,6 +115,22 @@ pub fn createEntity() !Entity {
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 {
core.engine_log("entity destroyed: {d}", .{e.handle.index});
const registry = getRegistry();

View File

@ -75,7 +75,7 @@ pub const LoadedModule = struct {
}
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();
try self.stageModule(allocator);

View File

@ -51,8 +51,8 @@ pub const GameObject = struct {
pub fn deinitECS(self: *@This(), handle: core.ObjectHandle) void {
_ = handle;
if (!self.destroyed) {
self.destroyed = true;
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() {
return .{
.buffer = std.ArrayList(u8).init(allocator),
.buffer = std.ArrayList(u8){},
.allocator = allocator,
};
}
@ -231,7 +231,7 @@ pub const LoggerSys = struct {
try core.dispatchJob(L{ .loggerSys = self });
} else {
//self.flushWriteBuffer();
try self.flushWriteBuffer();
}
self.lock.unlock();
@ -252,6 +252,7 @@ pub const LoggerSys = struct {
} else {
var writer = self.consoleFile.writer(self.writerBuffer);
try writer.interface.writeAll(self.writeOutBuffer.items);
try writer.interface.flush();
}
self.writeOutBuffer.clearRetainingCapacity();
self.lock.unlock();
@ -266,6 +267,7 @@ pub const LoggerSys = struct {
var writer = self.consoleFile.writer(self.writerBuffer);
try writer.interface.writeAll(self.flushBuffer.items);
try self.consoleFile.writeAll("");
try writer.interface.flush();
}
self.flushBuffer.clearRetainingCapacity();
self.lock.unlock();
@ -327,6 +329,7 @@ pub const LoggerSys = struct {
self.flushWriteBuffer() catch {};
self.allocator.free(self.logFilePath);
self.logFile.close();
self.allocator.free(self.writerBuffer);
self.writeOutBuffer.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,
lastLength: usize = 0,
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());
self.* = .{
.allocator = allocator,
.buffer = core.LogBuffer.init(allocator),
.buffer = core.logging.LogBuffer.init(allocator),
};
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)});
}
panickers.attachSegfaultHandler();
// panickers.attachSegfaultHandler();
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);
}
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 {

View File

@ -49,12 +49,12 @@ pub const TransportError = error{
};
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 >> 8) & 0xFF,
(ip >> 16) & 0xFF,
(ip >> 24) & 0xFF,
});
}, 0);
}
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 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("zphysics", zphysics_dep.module("root"));

View File

@ -60,16 +60,9 @@ pub const IgnoreFixedBodiesFilter = extern struct {
};
const BroadPhaseLayerInterface = extern struct {
usingnamespace zphysics.BroadPhaseLayerInterface.Methods(@This());
__v: *const zphysics.BroadPhaseLayerInterface.VTable = &vtable,
broad_phase_layer_interface: zphysics.BroadPhaseLayerInterface = .init(@This()),
object_to_broad_phase: [ObjectLayers.len]zphysics.BroadPhaseLayer = undefined,
const vtable = zphysics.BroadPhaseLayerInterface.VTable{
.getNumBroadPhaseLayers = _getNumBroadPhaseLayers,
.getBroadPhaseLayer = _getBroadPhaseLayer,
};
fn init() BroadPhaseLayerInterface {
var layer_interface: BroadPhaseLayerInterface = .{};
layer_interface.object_to_broad_phase[ObjectLayers.non_moving] = BroadPhaseLayers.non_moving;
@ -77,26 +70,23 @@ const BroadPhaseLayerInterface = extern struct {
return layer_interface;
}
fn _getNumBroadPhaseLayers(_: *const zphysics.BroadPhaseLayerInterface) callconv(.c) u32 {
pub fn getNumBroadPhaseLayers(_: *const zphysics.BroadPhaseLayerInterface) callconv(.c) u32 {
return BroadPhaseLayers.len;
}
fn _getBroadPhaseLayer(
interface_self: *const zphysics.BroadPhaseLayerInterface,
pub fn getBroadPhaseLayer(
broad_phase_layer_interface: *const zphysics.BroadPhaseLayerInterface,
object_layer: zphysics.ObjectLayer,
) 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];
}
};
const ObjectVsBroadPhaseLayerFilter = extern struct {
usingnamespace zphysics.ObjectVsBroadPhaseLayerFilter.Methods(@This());
__v: *const zphysics.ObjectVsBroadPhaseLayerFilter.VTable = &vtable,
object_vs_broad_phase_layer_filter: zphysics.ObjectVsBroadPhaseLayerFilter = .init(@This()),
const vtable = zphysics.ObjectVsBroadPhaseLayerFilter.VTable{ .shouldCollide = _shouldCollide };
fn _shouldCollide(
pub fn shouldCollide(
_: *const zphysics.ObjectVsBroadPhaseLayerFilter,
object_layer: zphysics.ObjectLayer,
broad_phase_layer: zphysics.BroadPhaseLayer,
@ -110,12 +100,9 @@ const ObjectVsBroadPhaseLayerFilter = extern struct {
};
const ObjectLayerPairFilter = extern struct {
usingnamespace zphysics.ObjectLayerPairFilter.Methods(@This());
__v: *const zphysics.ObjectLayerPairFilter.VTable = &vtable,
object_layer_pair_filter: zphysics.ObjectLayerPairFilter = .init(@This()),
const vtable = zphysics.ObjectLayerPairFilter.VTable{ .shouldCollide = _shouldCollide };
fn _shouldCollide(
pub fn shouldCollide(
_: *const zphysics.ObjectLayerPairFilter,
a: zphysics.ObjectLayer,
b: zphysics.ObjectLayer,
@ -304,40 +291,40 @@ pub const ShapeSettings = union(enum(u8)) {
pub fn release(self: @This()) void {
switch (self) {
.convex => |x| {
x.release();
x.asShapeSettings().release();
},
.box => |x| {
x.release();
x.asShapeSettings().release();
},
.sphere => |x| {
x.release();
x.asShapeSettings().release();
},
.triangle => |x| {
x.release();
x.asShapeSettings().release();
},
.capsule => |x| {
x.release();
x.asShapeSettings().release();
},
.taperedCapsule => |x| {
x.release();
x.asShapeSettings().release();
},
.cylinder => |x| {
x.release();
x.asShapeSettings().release();
},
.convexHull => |x| {
x.release();
x.asShapeSettings().release();
},
.heightField => |x| {
x.release();
x.asShapeSettings().release();
},
.mesh => |x| {
x.release();
x.asShapeSettings().release();
},
.decorated => |x| {
x.release();
x.asShapeSettings().release();
},
.compound => |x| {
x.release();
x.asShapeSettings().release();
},
}
}
@ -345,40 +332,40 @@ pub const ShapeSettings = union(enum(u8)) {
pub fn createShape(self: @This()) !*zphysics.Shape {
switch (self) {
.convex => |x| {
return try x.createShape();
return try x.asShapeSettings().createShape();
},
.box => |x| {
return try x.createShape();
return try x.asShapeSettings().createShape();
},
.sphere => |x| {
return try x.createShape();
return try x.asShapeSettings().createShape();
},
.triangle => |x| {
return try x.createShape();
return try x.asShapeSettings().createShape();
},
.capsule => |x| {
return try x.createShape();
return try x.asShapeSettings().createShape();
},
.taperedCapsule => |x| {
return try x.createShape();
return try x.asShapeSettings().createShape();
},
.cylinder => |x| {
return try x.createShape();
return try x.asShapeSettings().createShape();
},
.convexHull => |x| {
return try x.createShape();
return try x.asShapeSettings().createShape();
},
.heightField => |x| {
return try x.createShape();
return try x.asShapeSettings().createShape();
},
.mesh => |x| {
return try x.createShape();
return try x.asShapeSettings().createShape();
},
.decorated => |x| {
return try x.createShape();
return try x.asShapeSettings().createShape();
},
.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 height = platform.context().extent.y;
const sx = core.clamp(s.x, 0, width);
const sy = core.clamp(s.y, 0, height);
const sx = core.math.clamp(s.x, 0, width);
const sy = core.math.clamp(s.y, 0, height);
const vec = core.Vectorf{
.x = ((2.0 / width) * sx) - 1.0,
@ -97,7 +97,7 @@ pub fn getNormalRayFromScreen(
}
pub fn resolve(self: *@This()) void {
const scene = self.entity.fetch(core.Scene).?;
const scene = self.entity.fetch(core.Scene) orelse return;
self.updateProjections();

View File

@ -37,7 +37,7 @@ pub fn loadIndexedMeshForPoolingGltf(allocator: std.mem.Allocator, meshName: cor
defer allocator.free(binaryPath);
core.engine_log("{s}", .{binaryPath});
binaryFile = try core.fs().loadFile(binaryPath);
binaryBytes = binaryFile.?.bytes;
binaryBytes = binaryFile.?.bytesNoEnd();
}
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],
} 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],
.y = normals.?[i + 1],
.z = normals.?[i + 2],

View File

@ -329,7 +329,7 @@ pub const Renderer = struct {
// .address_mode_v = .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.
.max_lod = 10, // Clamps the maximum of the computed LOD value.
.address_mode_u = .sampleraddressmodeRepeat,

View File

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

View File

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

View File

@ -11,6 +11,7 @@ const QuakeMap = @This();
worldspawn: Entity,
entities: std.ArrayList(Entity),
allocator: std.mem.Allocator,
// uniqueMaterials: std.StringHashMap(u32), // counts for the number
// 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 {
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");
error_info.line_number = 0;
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")) {
worldspawn = entity;
} else {
try entities.append(entity);
try entities.append(allocator, entity);
}
},
else => {
@ -53,6 +54,7 @@ pub fn read(allocator: Allocator, data: []const u8, error_info: *ErrorInfo) !Qua
return .{
.worldspawn = worldspawn orelse return error.WorldSpawnNotFound,
.entities = entities,
.allocator = allocator,
};
}
@ -66,20 +68,23 @@ pub const Entity = struct {
spawnflags: u32,
properties: std.ArrayList(Property),
solids: std.ArrayList(Solid),
allocator: std.mem.Allocator,
pub fn deinit(self: *@This()) void {
for (self.solids.items) |*solid| {
solid.faces.deinit();
}
self.properties.deinit();
self.solids.deinit(self.allocator);
self.properties.deinit(self.allocator);
}
pub fn init(allocator: Allocator) Entity {
return .{
.classname = &.{},
.spawnflags = 0,
.properties = std.ArrayList(Property).init(allocator),
.solids = std.ArrayList(Solid).init(allocator),
.allocator = allocator,
.properties = std.ArrayList(Property){},
.solids = std.ArrayList(Solid){},
};
}
@ -124,13 +129,14 @@ pub const Entity = struct {
pub const Solid = struct {
faces: std.ArrayList(Face),
allocator: std.mem.Allocator,
fn init(allocator: Allocator) Solid {
return .{ .faces = std.ArrayList(Face).init(allocator) };
return .{ .faces = std.ArrayList(Face){}, .allocator = allocator };
}
fn computeVertices(self: *Solid) !void {
const allocator = self.faces.allocator;
const allocator = self.allocator;
var buffer: [64]Vec3d = undefined;
var vertices = std.ArrayListUnmanaged(Vec3d).initBuffer(buffer[0..32]);
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")) {
entity.spawnflags = try std.fmt.parseInt(u32, property.value, 10);
} 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,
else => {
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;
switch (line[0]) {
'/' => continue,
'(' => try solid.faces.append(try readFace(line)),
'(' => try solid.faces.append(solid.allocator, try readFace(line)),
'}' => break,
else => {

View File

@ -54,7 +54,7 @@ pub const TBMap = struct {
"Texture",
textureName,
// 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,
12,
);
defer settings.release();
defer settings.asShapeSettings().release();
// settings.setMaxConvexRadius(0.1);
var nameBuffer: [256]u8 = undefined;

View File

@ -43,8 +43,8 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
else => unreachable,
};
pub usingnamespace switch (dimensions) {
2 => extern struct {
pub const DimensionImpl = switch (dimensions) {
2 => struct {
/// Construct new vector.
pub inline fn new(vx: T, vy: T) Self {
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());
}
},
3 => extern struct {
3 => struct {
/// Construct new vector.
pub inline fn new(vx: T, vy: T, vz: T) Self {
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).
pub fn forward() Self {
return new(0, 0, 1);
return Self.new(0, 0, 1);
}
/// Shorthand for (0, 0, -1).
pub fn back() Self {
return forward().negate();
return Self.forward().negate();
}
/// 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_y = (z1 * x2) - (x1 * z2);
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) {
@ -132,7 +132,7 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return Self.new(vec4.x(), vec4.y(), vec4.z());
}
},
4 => extern struct {
4 => struct {
/// Construct new vector.
pub inline fn new(vx: T, vy: T, vz: T, vw: T) Self {
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).
pub fn forward() Self {
return new(0, 0, 1, 0);
return Self.new(0, 0, 1, 0);
}
/// Shorthand for (0, 0, -1, 0).
pub fn back() Self {
return forward().negate();
return Self.forward().negate();
}
pub inline fn z(self: Self) T {
@ -183,6 +183,8 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
else => unreachable,
};
pub const new = DimensionImpl.new;
pub inline fn x(self: Self) T {
return self.data[0];
}
@ -191,6 +193,9 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return self.data[1];
}
pub const z = DimensionImpl.z;
pub const w = DimensionImpl.w;
pub inline fn xMut(self: *Self) *T {
return &self.data[0];
}
@ -199,6 +204,9 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return &self.data[1];
}
pub const zMut = DimensionImpl.zMut;
pub const wMut = DimensionImpl.wMut;
/// Set all components to the same given value.
pub fn set(val: T) Self {
const result: Data = @splat(val);
@ -245,6 +253,9 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
return right().negate();
}
pub const forward = DimensionImpl.forward;
pub const back = DimensionImpl.back;
/// Negate the given vector.
pub fn negate(self: Self) Self {
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) {
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", .{});
}
@ -273,6 +284,14 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
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.
pub fn toArray(self: Self) [dimensions]T {
return self.data;
@ -290,12 +309,24 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
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.
/// [(x1 - x2)^2 + (y1 - y2)^2 + (z1 - z2)^2 ...]
pub fn distance(first_vector: Self, second_vector: Self) T {
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.
pub fn norm(self: Self) Self {
const l = self.length();
@ -329,6 +360,12 @@ pub fn GenericVector(comptime dimensions: comptime_int, comptime T: type) type {
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
pub fn max(first_vector: Self, second_vector: Self) Self {
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 };
}
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) {
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) {
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) {
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
{
const a = Vec2.zero();
@ -572,7 +634,9 @@ test "zalgebra.Vectors.distance" {
const c = Vec2.new(0, 5);
try expectEqual(a.distance(b), 1);
try expectEqual(a.distanceSq(b), 1);
try expectEqual(a.distance(c), 5);
try expectEqual(a.distanceSq(c), 25);
}
// Vec3
@ -582,7 +646,9 @@ test "zalgebra.Vectors.distance" {
const c = Vec3.new(0, 5, 0);
try expectEqual(a.distance(b), 1);
try expectEqual(a.distanceSq(b), 1);
try expectEqual(a.distance(c), 5);
try expectEqual(a.distanceSq(c), 25);
}
// Vec4
@ -592,7 +658,9 @@ test "zalgebra.Vectors.distance" {
const c = Vec4.new(0, 5, 0, 0);
try expectEqual(a.distance(b), 1);
try expectEqual(a.distanceSq(b), 1);
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
// 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 yx = v2.swizzle2(.y, .x);
const yx = v2.swizzle("yx");
try expectEqual(Vec2.new(2, 1), yx);
const v3 = Vec3.new(1, 2, 3);
const zy = v3.swizzle2(.z, .y);
const xx = v3.swizzle2(.x, .x);
const zy = v3.swizzle("zy");
const xx = v3.swizzle("xx");
try expectEqual(Vec2.new(3, 2), zy);
try expectEqual(Vec2.new(1, 1), xx);
const v4 = Vec4.new(1, 2, 3, 4);
const wz = v4.swizzle2(.w, .z);
const xy = v4.swizzle2(.x, .y);
const wz = v4.swizzle("wz");
const xy = v4.swizzle("xy");
try expectEqual(Vec2.new(4, 3), wz);
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 math = std.math;
pub usingnamespace @import("generic_vector.zig");
pub usingnamespace @import("mat3.zig");
pub usingnamespace @import("mat4.zig");
pub usingnamespace @import("quaternion.zig");
const generic_vector = @import("generic_vector.zig");
pub const Vec2 = generic_vector.Vec2;
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.
pub fn toRadians(degrees: anytype) @TypeOf(degrees) {
const T = @TypeOf(degrees);
if (@typeInfo(T) != .Float) {
if (@typeInfo(T) != .float) {
@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) {
const T = @TypeOf(radians);
if (@typeInfo(T) != .Float) {
if (@typeInfo(T) != .float) {
@compileError("Radians not implemented for " ++ @typeName(T));
}
@ -34,7 +73,7 @@ pub fn toDegrees(radians: anytype) @TypeOf(radians) {
/// Linear interpolation between two floats.
/// `t` is used to interpolate between `from` and `to`.
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));
}
@ -70,3 +109,10 @@ test "zalgebra.lerp" {
try expectEqual(lerp(f32, from, to, 0.5), 5);
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
/// Note: Column-major means accessing data like m.data[COLUMN][ROW].
pub fn Mat3x3(comptime T: type) type {
if (@typeInfo(T) != .Float) {
@compileError("Mat3x3 not implemented for " ++ @typeName(T));
}
const Vector3 = GenericVector(3, T);
return extern struct {
@ -85,9 +81,8 @@ pub fn Mat3x3(comptime T: type) type {
return result;
}
/// Return a pointer to the inner data of the matrix.
pub fn getData(self: *const Self) *const T {
return @ptrCast(&self.data);
pub fn getSlice(self: *const Self) *const [3][3]T {
return self.data[0..3];
}
/// 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).
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();
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 {
if (@typeInfo(T) != .float) {
@compileError("Mat3x3.rotate() not implemented for " ++ @typeName(T));
}
const rotation_mat = Self.fromRotation(angle_in_degrees, axis);
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).
/// Order matters because matrix multiplication are NOT commutative.
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 y = Self.fromRotation(euler_angle.y(), Vector3.up());
const z = Self.fromRotation(euler_angle.z(), Vector3.forward());
@ -149,6 +156,10 @@ pub fn Mat3x3(comptime T: type) type {
/// Ortho normalize given matrix.
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_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();
@ -174,6 +185,10 @@ pub fn Mat3x3(comptime T: type) type {
/// 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
pub fn extractEulerAngles(self: Self) Vector3 {
if (@typeInfo(T) != .float) {
@compileError("Mat3x3.extractEulerAngles() not implemented for " ++ @typeName(T));
}
const m = self.orthoNormalize();
const theta_x = math.atan2(m.data[1][2], m.data[2][2]);
@ -259,35 +274,30 @@ pub fn Mat3x3(comptime T: type) type {
return inv_mat;
}
/// Print the 3x3 to stderr.
pub fn debugPrint(self: Self) void {
const print = std.debug.print;
pub fn format(
self: Self,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = fmt;
_ = options;
print("({d}, {d}, {d})\n", .{
self.data[0][0],
self.data[1][0],
self.data[2][0],
});
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],
for (0..3) |i| {
try writer.print("({d:.2}, {d:.2}, {d:.2})\n", .{
self.data[0][i],
self.data[1][i],
self.data[2][i],
});
}
}
/// Cast a type to another type.
/// It's like builtins: @intCast, @floatCast, @floatFromInt, @intFromFloat.
pub fn cast(self: Self, comptime dest_type: type) Mat3x3(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", .{});
}

View File

@ -23,7 +23,7 @@ pub const lookAt = Mat4.lookAt;
/// A column-major 4x4 matrix
/// Note: Column-major means accessing data like m.data[COLUMN][ROW].
pub fn Mat4x4(comptime T: type) type {
if (@typeInfo(T) != .Float) {
if (@typeInfo(T) != .float) {
@compileError("Mat4x4 not implemented for " ++ @typeName(T));
}
@ -92,9 +92,8 @@ pub fn Mat4x4(comptime T: type) type {
return result;
}
/// Return a pointer to the inner data of the matrix.
pub fn getData(self: *const Self) *const T {
return @ptrCast(&self.data);
pub fn getSlice(self: *const Self) *const [4][4]T {
return self.data[0..4];
}
/// 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
/// given translation vector.
pub fn fromTranslate(axis: Vector3) Self {
var result = Self.identity();
result.data[3][0] = axis.data[0];
result.data[3][1] = axis.data[1];
result.data[3][2] = axis.data[2];
return result;
return .{
.data = .{
.{ 1, 0, 0, 0 },
.{ 0, 1, 0, 0 },
.{ 0, 0, 1, 0 },
.{ axis.x(), axis.y(), axis.z(), 1 },
},
};
}
/// 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 {
var result = Self.identity();
result.data[0][0] = axis.x();
result.data[1][1] = axis.y();
result.data[2][2] = axis.z();
return result;
return .{
.data = .{
.{ axis.x(), 0, 0, 0 },
.{ 0, axis.y(), 0, 0 },
.{ 0, 0, axis.z(), 0 },
.{ 0, 0, 0, 1 },
},
};
}
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.
/// 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 {
var result = Self.identity();
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;
result.data[1][1] = f;
result.data[2][2] = (z_near + z_far) / (z_near - z_far);
result.data[2][3] = -1;
result.data[3][2] = 2 * z_far * z_near / (z_near - z_far);
result.data[3][3] = 0;
return result;
return .{
.data = .{
.{ f / aspect_ratio, 0, 0, 0 },
.{ 0, f, 0, 0 },
.{ 0, 0, (z_near + z_far) * nf, -1 },
.{ 0, 0, 2 * z_near * z_far * nf, 0 },
},
};
}
/// 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.
/// 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 {
var result = Self.identity();
const f = 1 / @tan(root.toRadians(fovy_in_degrees) * 0.5);
result.data[0][0] = f / aspect_ratio;
result.data[1][1] = f;
result.data[2][2] = 0;
result.data[2][3] = -1;
result.data[3][2] = z_near;
result.data[3][3] = 0;
return result;
return .{
.data = .{
.{ f / aspect_ratio, 0, 0, 0 },
.{ 0, f, 0, 0 },
.{ 0, 0, 0, -1 },
.{ 0, 0, z_near, 0 },
},
};
}
/// Construct an orthographic 4x4 matrix.
@ -440,45 +439,31 @@ pub fn Mat4x4(comptime T: type) type {
};
}
/// Print the 4x4 to stderr.
pub fn debugPrint(self: Self) void {
const print = std.debug.print;
pub fn format(
self: Self,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = fmt;
_ = options;
print("({d}, {d}, {d}, {d})\n", .{
self.data[0][0],
self.data[1][0],
self.data[2][0],
self.data[3][0],
});
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],
for (0..4) |i| {
try writer.print("({d:.2}, {d:.2}, {d:.2}, {d:.2})\n", .{
self.data[0][i],
self.data[1][i],
self.data[2][i],
self.data[3][i],
});
}
}
/// Cast a type to another type.
/// It's like builtins: @intCast, @floatCast, @floatFromInt, @intFromFloat.
pub fn cast(self: Self, comptime dest_type: type) Mat4x4(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", .{});
}

View File

@ -24,7 +24,7 @@ pub const Quat_f64 = Quaternion(f64);
/// A Quaternion for 3D rotations.
pub fn Quaternion(comptime T: type) type {
if (@typeInfo(T) != .Float) {
if (@typeInfo(T) != .float) {
@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.
fn toMat3(self: Self) Mat3x3(T) {
pub fn toMat3(self: Self) Mat3x3(T) {
var result: Mat3x3(T) = undefined;
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) {
const dest_info = @typeInfo(dest_type);
if (dest_info != .Float) {
if (dest_info != .float) {
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);
}
if (core.getEngineObject(core.EcsRegistry)) |ecsReg| {
if (core.getEngineObject(core.ecs.EcsRegistry)) |ecsReg| {
ig.separator();
for (ecsReg.containerNames.items, 0..) |*name, i| {

View File

@ -1,7 +1,6 @@
allocator: std.mem.Allocator,
lastUpdateFrame: u64 = 0,
arena: std.heap.ArenaAllocator,
bodyIds: std.ArrayList(physics.BodyId),
pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "extras.PhysicsObjectList");
@ -11,8 +10,7 @@ pub fn create(allocator: std.mem.Allocator) !*@This() {
self.* = .{
.allocator = allocator,
.arena = std.heap.ArenaAllocator.init(allocator),
.bodyIds = std.ArrayList(physics.BodyId).init(allocator),
.bodyIds = std.ArrayList(physics.BodyId){},
};
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));
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, .{})) {
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 {
self.arena.deinit();
self.bodyIds.deinit();
self.bodyIds.deinit(self.allocator);
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 {
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 (self.dtAverage > 0.000001) {

View File

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

View File

@ -57,7 +57,10 @@ pub fn setPosition(self: *@This(), position: core.Vectorf) void {
}
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

View File

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

View File

@ -48,8 +48,7 @@ pub fn build(b: *std.Build) void {
) orelse true,
};
const static_build = b.option(bool, "static_build", "builds backlog dependencies for static linking") orelse false;
_ = static_build;
const static_build = b.option(bool, "static_build", "builds backlog dependencies for static linking") orelse true;
const user_extensions = b.option(
[]const std.Build.LazyPath,
@ -74,14 +73,14 @@ pub fn build(b: *std.Build) void {
const joltc = b.addLibrary(.{
.name = "joltc",
.linkage = if (options.shared) .dynamic else .static,
.linkage = if (!static_build) .dynamic else .static,
.root_module = b.createModule(.{
.target = target,
.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)");
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);
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) });
}
}

View File

@ -152,7 +152,7 @@ pub const ExternGameObject = struct {
}
// change this into a parallel for
for (0..300) |i| {
for (0..1) |i| {
_ = try core.get(core.GameObjectSystem).spawnObject(BoxObject, "Box", .{
.posRot = .{
.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 {
var spec = try backlog.getSpec("sampleGame");
// try spec.put("useGPA", .{ .boolean = false });
try spec.put("useGPA", .{ .boolean = true });
_ = backlog.startEngine(&NeonObjectTable, &spec);
// 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 buffer: []u8 = try allocator.alloc(u8, filesize);
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;
return buffer;
}
@ -295,11 +295,8 @@ fn writeBuildZigFiles(self: *@This()) !void {
fn writeBuildZig(self: *@This(), workingDir: *std.fs.Dir) !void {
const out_path = "build.zig";
var content = std.ArrayList(u8).init(self.allocator);
defer content.deinit();
var writer = content.writer();
var content = std.ArrayList(u8){};
defer content.deinit(self.allocator);
const template =
\\ const std = @import("std");
\\ 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 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);
}
@ -348,13 +345,12 @@ const entries: []const struct { name: []const u8, path: []const u8 } = &.{
};
fn writeBuildZigZon(self: *@This(), workingDir: *std.fs.Dir) !void {
var content = std.ArrayList(u8).init(self.allocator);
defer content.deinit();
var content = std.ArrayList(u8){};
defer content.deinit(self.allocator);
var writer = content.writer();
try writer.print(".{{\n", .{});
try content.print(self.allocator, ".{{\n", .{});
try writer.print(
try content.print(self.allocator,
\\ .name = .{s},
\\ .version = "0.0.0",
\\ .dependencies = .{{
@ -362,34 +358,35 @@ fn writeBuildZigZon(self: *@This(), workingDir: *std.fs.Dir) !void {
, .{ std.fs.path.basename(self.targetDir.?), self.engineRelative.? });
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 = .{{ "" }},
\\
, .{});
try writer.print(
try content.print(self.allocator,
\\ .fingerprint = {s},
\\
, .{self.fingerprint.?});
try writer.print("}}", .{});
try content.print(self.allocator, "}}", .{});
const file = try workingDir.createFile("build.zig.zon", .{});
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 {
var content = std.ArrayList(u8).init(self.allocator);
defer content.deinit();
var content = std.ArrayList(u8){};
defer content.deinit(self.allocator);
const template =
\\ 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);
try content.appendSlice(self.targetName.?);
try content.appendSlice(template2);
try content.append(0);
const allocator = self.allocator;
try content.appendSlice(allocator, template);
try content.appendSlice(allocator, self.targetName.?);
try content.appendSlice(allocator, template2);
try content.append(allocator, 0);
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);
}
var wbuf: [4096]u8 = undefined;
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);
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, .{});
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 {

View File

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