aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNic Gaffney <gaffney_nic@protonmail.com>2024-06-20 00:44:24 -0500
committerNic Gaffney <gaffney_nic@protonmail.com>2024-06-20 00:44:24 -0500
commit0dc97d45f1b228f6f3b9feb1773b972eca343766 (patch)
tree3d133ce030dbd23632759edb31ab4c1878d20517
parent2374e1f1a11d62ee579d25a39b24312a68e7387e (diff)
downloadparticle-sim-0dc97d45f1b228f6f3b9feb1773b972eca343766.tar.gz
Added load / save feature with simple CSV parsing
-rw-r--r--.gitignore1
-rw-r--r--build.zig4
-rw-r--r--imgui.ini10
-rw-r--r--src/imgui.zig26
-rw-r--r--src/main.zig11
-rw-r--r--src/particle.zig47
-rw-r--r--src/rules.zig76
7 files changed, 103 insertions, 72 deletions
diff --git a/.gitignore b/.gitignore
index ee7098f..d93a0a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
zig-out/
zig-cache/
+imgui.ini
diff --git a/build.zig b/build.zig
index 5306693..8c5f1fe 100644
--- a/build.zig
+++ b/build.zig
@@ -6,7 +6,7 @@ pub fn build(b: *std.Build) !void {
const exe = b.addExecutable(.{
.name = "particle-sim",
- .root_source_file = .{ .path = "src/main.zig" },
+ .root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
@@ -27,7 +27,7 @@ pub fn build(b: *std.Build) !void {
});
exe.root_module.addImport("zgui", zgui.module("root"));
exe.linkLibrary(zgui.artifact("imgui"));
- exe.addIncludePath(.{ .path = "vendor/zgui/libs/imgui" });
+ exe.addIncludePath(b.path("vendor/zgui/libs/imgui"));
const rlimgui = b.dependency("rlimgui", .{
.target = target,
diff --git a/imgui.ini b/imgui.ini
deleted file mode 100644
index 3ec33f2..0000000
--- a/imgui.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[Window][Debug##Default]
-Pos=0,0
-Size=400,400
-Collapsed=0
-
-[Window][Configuration]
-Pos=-1,0
-Size=1102,376
-Collapsed=1
-
diff --git a/src/imgui.zig b/src/imgui.zig
index b6def48..163ee0f 100644
--- a/src/imgui.zig
+++ b/src/imgui.zig
@@ -1,7 +1,7 @@
const std = @import("std");
const rl = @import("raylib");
const z = @import("zgui");
-const part = @import("particle.zig");
+const rul = @import("rules.zig");
const cfg = @import("config.zig");
const c = @cImport({
@@ -9,7 +9,7 @@ const c = @cImport({
@cInclude("rlImGui.h");
});
-pub fn update() !void {
+pub fn update(alloc: std.mem.Allocator, buf: [:0]u8) !void {
c.rlImGuiBegin();
defer c.rlImGuiEnd();
@@ -28,12 +28,6 @@ pub fn update() !void {
_ = z.sliderFloat("Minimum Distance", .{ .v = &cfg.minDistance, .min = 1.0, .max = 100.0 });
}
if (z.collapsingHeader("Ruleset", .{ .default_open = true })) {
- // comptime var string: [:0]const u8 = "";
- // comptime for (0..cfg.colors.len) |cols| {
- // string = string ++ part.colorToString(cols) ++ "\t\t\t\t\t";
- // };
- //
- // z.text("{s:<}", .{string});
_ = z.beginTable("Rules", .{
.column = cfg.colorAmnt + 1,
.flags = .{},
@@ -46,13 +40,13 @@ pub fn update() !void {
z.text("Rules", .{});
for (0..cfg.colorAmnt) |i| {
_ = z.tableNextColumn();
- z.text("{s}", .{part.colorToString(i)});
+ z.text("{s}", .{rul.colorToString(i)});
}
for (&cfg.rules, 0..) |*row, i| {
_ = z.tableNextRow(.{});
_ = z.tableSetColumnIndex(0);
- z.text("{s}", .{part.colorToString(i)});
+ z.text("{s}", .{rul.colorToString(i)});
_ = z.tableNextColumn();
for (row, 0..) |*cols, j| {
var id: [2:0]u8 = undefined;
@@ -65,4 +59,16 @@ pub fn update() !void {
}
}
}
+ if (z.collapsingHeader("Load / Save", .{ .default_open = true })) {
+ _ = z.inputText("Save Path", .{ .buf = buf });
+ if (z.button("Save", .{})) {
+ const path = buf;
+ _ = rul.saveRules(path) catch void;
+ }
+ _ = z.inputText("Load Path", .{ .buf = buf });
+ if (z.button("Load", .{})) {
+ const path = buf;
+ _ = rul.loadRules(alloc, path) catch void;
+ }
+ }
}
diff --git a/src/main.zig b/src/main.zig
index 02830e5..118609a 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -4,6 +4,7 @@ const z = @import("zgui");
const part = @import("particle.zig");
const cfg = @import("config.zig");
const img = @import("imgui.zig");
+const rules = @import("rules.zig");
const c = @cImport({
@cDefine("NO_FONT_AWESOME", "1");
@@ -11,8 +12,8 @@ const c = @cImport({
});
pub fn main() !void {
- cfg.rules = part.ruleMatrix();
- part.printRules(cfg.rules);
+ cfg.rules = rules.ruleMatrix();
+ rules.printRules(cfg.rules);
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
@@ -35,6 +36,10 @@ pub fn main() !void {
var particles = try part.initParticles(gpa.allocator(), cfg.initialParticles);
defer particles.deinit(gpa.allocator());
+ const buf = try gpa.allocator().allocSentinel(u8, 128, 0);
+ std.mem.copyForwards(u8, buf, "Absolute File Path" ++ .{0});
+ defer gpa.allocator().free(buf);
+
while (!rl.windowShouldClose()) {
if (particles.items(.x).len < cfg.particleCount) {
for (0..@intCast(cfg.particleCount - @as(i32, @intCast(particles.items(.x).len)))) |_| {
@@ -54,6 +59,6 @@ pub fn main() !void {
part.updateVelocities(particles, cfg.rules);
part.updatePosition(particles);
part.draw(particles);
- try img.update();
+ try img.update(gpa.allocator(), buf);
}
}
diff --git a/src/particle.zig b/src/particle.zig
index e0cb789..bf36cfb 100644
--- a/src/particle.zig
+++ b/src/particle.zig
@@ -2,53 +2,6 @@ const cfg = @import("config.zig");
const std = @import("std");
const rl = @import("raylib");
-/// Generate the set of rules the particles will abide by
-pub fn ruleMatrix() [cfg.colorAmnt][cfg.colorAmnt]f32 {
- const seed = @as(u64, @truncate(@as(u128, @bitCast(std.time.nanoTimestamp()))));
- var prng = std.rand.DefaultPrng.init(seed);
- var rules: [cfg.colorAmnt][cfg.colorAmnt]f32 = undefined;
- for (0..cfg.colorAmnt) |i| {
- for (0..cfg.colorAmnt) |j| {
- var val = prng.random().float(f32);
- const isNeg = prng.random().uintAtMost(u8, 1);
- if (isNeg == 1) val = 0 - val;
- rules[i][j] = val;
- }
- }
- return rules;
-}
-
-/// Prints rules generated from ruleMatrix()
-pub fn printRules(rules: [cfg.colorAmnt][cfg.colorAmnt]f32) void {
- std.debug.print("\n| {s:^7} ", .{"Rules"});
- for (0..cfg.colors.len) |c|
- std.debug.print("| {s:^7} ", .{colorToString(c)});
-
- std.debug.print("|\n", .{});
- for (rules, 0..) |row, i| {
- std.debug.print("| {s:^7} ", .{colorToString(i)});
- for (row) |col|
- std.debug.print("| {d:^7.1} ", .{col});
-
- std.debug.print("|\n", .{});
- }
-}
-
-/// Convert the color index to a string
-pub fn colorToString(c: usize) []const u8 {
- return switch (c) {
- 0 => "Red",
- 1 => "Green",
- 2 => "Blue",
- 3 => "Yellow",
- 4 => "Magenta",
- 5 => "Brown",
- 6 => "Orange",
- 7 => "Gray",
- else => " ",
- };
-}
-
/// Initialize a MultiArrayList of size amnt with particles created by createParticle
pub fn initParticles(allocator: std.mem.Allocator, amnt: u32) !std.MultiArrayList(particle) {
var particles = std.MultiArrayList(particle){};
diff --git a/src/rules.zig b/src/rules.zig
new file mode 100644
index 0000000..2a2f1d3
--- /dev/null
+++ b/src/rules.zig
@@ -0,0 +1,76 @@
+const cfg = @import("config.zig");
+const std = @import("std");
+
+/// Generate the set of rules the particles will abide by
+pub fn ruleMatrix() [cfg.colorAmnt][cfg.colorAmnt]f32 {
+ const seed = @as(u64, @truncate(@as(u128, @bitCast(std.time.nanoTimestamp()))));
+ var prng = std.rand.DefaultPrng.init(seed);
+ var rules: [cfg.colorAmnt][cfg.colorAmnt]f32 = undefined;
+ for (0..cfg.colorAmnt) |i| {
+ for (0..cfg.colorAmnt) |j| {
+ var val = prng.random().float(f32);
+ const isNeg = prng.random().uintAtMost(u8, 1);
+ if (isNeg == 1) val = 0 - val;
+ rules[i][j] = val;
+ }
+ }
+ return rules;
+}
+
+/// Prints rules generated from ruleMatrix()
+pub fn printRules(rules: [cfg.colorAmnt][cfg.colorAmnt]f32) void {
+ std.debug.print("\n| {s:^7} ", .{"Rules"});
+ for (0..cfg.colors.len) |c|
+ std.debug.print("| {s:^7} ", .{colorToString(c)});
+
+ std.debug.print("|\n", .{});
+ for (rules, 0..) |row, i| {
+ std.debug.print("| {s:^7} ", .{colorToString(i)});
+ for (row) |col|
+ std.debug.print("| {d:^7.1} ", .{col});
+
+ std.debug.print("|\n", .{});
+ }
+}
+
+pub fn loadRules(allocator: std.mem.Allocator, absolutePath: [:0]u8) !void {
+ const file = try std.fs.openFileAbsoluteZ(absolutePath, .{ .mode = .read_only });
+ defer file.close();
+ var reader = file.reader();
+ for (&cfg.rules) |*row| {
+ std.debug.print("Row\n", .{});
+ for (row) |*col| {
+ const buf = try reader.readUntilDelimiterAlloc(allocator, ',', 16);
+ defer allocator.free(buf);
+ col.* = try std.fmt.parseFloat(f32, buf);
+ }
+ try reader.skipBytes(1, .{});
+ }
+}
+
+pub fn saveRules(absolutePath: [:0]u8) !void {
+ const file = try std.fs.createFileAbsoluteZ(absolutePath, .{ .read = true });
+ defer file.close();
+ var writer = file.writer();
+ for (cfg.rules) |row| {
+ for (row) |col| {
+ try writer.print("{d:.3},", .{col});
+ }
+ _ = try writer.write("\n");
+ }
+}
+
+/// Convert the color index to a string
+pub fn colorToString(c: usize) []const u8 {
+ return switch (c) {
+ 0 => "Red",
+ 1 => "Green",
+ 2 => "Blue",
+ 3 => "Yellow",
+ 4 => "Magenta",
+ 5 => "Brown",
+ 6 => "Orange",
+ 7 => "Gray",
+ else => " ",
+ };
+}