aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
parent2374e1f1a11d62ee579d25a39b24312a68e7387e (diff)
downloadparticle-sim-0dc97d45f1b228f6f3b9feb1773b972eca343766.tar.gz
Added load / save feature with simple CSV parsing
Diffstat (limited to 'src')
-rw-r--r--src/imgui.zig26
-rw-r--r--src/main.zig11
-rw-r--r--src/particle.zig47
-rw-r--r--src/rules.zig76
4 files changed, 100 insertions, 60 deletions
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 => " ",
+ };
+}