137 lines
4.4 KiB
Zig
137 lines
4.4 KiB
Zig
const std = @import("std");
|
|
const rl = @import("raylib");
|
|
|
|
const e = @import("../errors.zig");
|
|
const st = @import("../common/structures.zig");
|
|
const ut = @import("../common/utils.zig");
|
|
const Road = @import("road.zig").Road;
|
|
const Node = @import("node.zig").Node;
|
|
|
|
pub const RoadManager = struct {
|
|
next_id: usize,
|
|
roads: std.ArrayList(*Road),
|
|
|
|
pub fn init() RoadManager {
|
|
return .{
|
|
.next_id = 0,
|
|
.roads = .empty,
|
|
};
|
|
}
|
|
|
|
/// Deinitialises every road (pointer) and then the list itself
|
|
pub fn deinit(self: *RoadManager, allocator: std.mem.Allocator) void {
|
|
for (self.roads.items) |road| {
|
|
road.deinit(allocator);
|
|
}
|
|
self.roads.deinit(allocator);
|
|
}
|
|
|
|
/// Draws all the roads in the list, sends the information ahead whether the road drawn should be highlighted
|
|
pub fn draw(self: *const RoadManager, highlighted_road: ?*Road, display_info: bool) void {
|
|
for (self.roads.items) |road| {
|
|
const is_highlighted = if (highlighted_road) |h_road| road == h_road else false;
|
|
road.draw(is_highlighted, display_info);
|
|
}
|
|
}
|
|
|
|
/// Function which creates the road object, its pointer, adds it to the list
|
|
/// and then also references that same road to the bounding nodes
|
|
pub fn addRoad(self: *RoadManager, allocator: std.mem.Allocator, start: *Node, end: *Node) !void {
|
|
const road_ptr = try allocator.create(Road);
|
|
road_ptr.* = Road.init(self.getNextID(), start, end);
|
|
try self.roads.append(allocator, road_ptr);
|
|
|
|
const ref = self.roads.items[self.roads.items.len - 1];
|
|
try start.referenceRoad(allocator, ref);
|
|
try end.referenceRoad(allocator, ref);
|
|
}
|
|
|
|
/// Returns the id, and increases it by one; used for generating ID's for new entities
|
|
fn getNextID(self: *RoadManager) usize {
|
|
const id = self.next_id;
|
|
self.next_id += 1;
|
|
|
|
return id;
|
|
}
|
|
|
|
/// Deinits all the roads, clears them but not deiniting the list itself; also resets the next ID var
|
|
pub fn clear(self: *RoadManager, allocator: std.mem.Allocator) void {
|
|
for (self.roads.items) |road| {
|
|
road.deinit(allocator);
|
|
}
|
|
self.roads.clearRetainingCapacity();
|
|
self.next_id = 0;
|
|
}
|
|
|
|
/// Removes the references of the road, from the nodes that bound that road
|
|
///
|
|
/// Then it deinitialises the road and removes it from the list
|
|
///
|
|
/// Will return an error if the road itself is not present in the list
|
|
pub fn deleteRoad(self: *RoadManager, allocator: std.mem.Allocator, road_to_delete: *Road) !void {
|
|
// unreference the road from its bounding functions
|
|
road_to_delete.unreferenceNodes() catch |err| {
|
|
std.debug.panic("Failed to unreference the road from its nodes: {}\n", .{err});
|
|
};
|
|
|
|
for (0..self.roads.items.len) |i| {
|
|
if (self.roads.items[i] != road_to_delete) continue;
|
|
|
|
road_to_delete.deinit(allocator);
|
|
_ = self.roads.swapRemove(i);
|
|
return;
|
|
}
|
|
|
|
return e.Entity.NotFound;
|
|
}
|
|
|
|
/// Returns if pos is pointing at a road, or null if it isn't at any
|
|
pub fn getHighlightedRoad(self: *const RoadManager, pos: Vector2) ?*Road {
|
|
for (self.roads.items) |road| {
|
|
if (road.collides(pos)) return road;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const Vector2 = @import("raylib").Vector2;
|
|
const expect = std.testing.expect;
|
|
|
|
test "id tracking" {
|
|
var gpa: std.heap.DebugAllocator(.{}) = .init;
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
var road_man: RoadManager = .init();
|
|
defer road_man.deinit(allocator);
|
|
const n = 5;
|
|
|
|
const start: Node = .init(0, .{.x = 0, .y = 0});
|
|
const start_ptr = try allocator.create(Node);
|
|
start_ptr.* = start;
|
|
|
|
const end: Node = .init(1, .{.x = 100, .y = 100});
|
|
const end_ptr = try allocator.create(Node);
|
|
end_ptr.* = end;
|
|
|
|
defer {
|
|
start_ptr.deinit(allocator);
|
|
end_ptr.deinit(allocator);
|
|
|
|
allocator.destroy(start_ptr);
|
|
allocator.destroy(end_ptr);
|
|
}
|
|
|
|
for (0..n) |_| {
|
|
try road_man.addRoad(allocator, start_ptr, end_ptr);
|
|
}
|
|
|
|
try expect(road_man.next_id == n);
|
|
try expect(road_man.roads.items.len == n);
|
|
}
|
|
|
|
// TODO tests
|
|
// force resize pointer test
|
|
// add, remove road
|
|
// destroy road and then verify the nodes do not have a pointer to it |