mach: ResourceManager: implement auto convertion of files into assets based on given info
This commit is contained in:
parent
b0a00c5581
commit
71b25dc2a6
1 changed files with 37 additions and 13 deletions
|
|
@ -5,28 +5,41 @@ const ResourceManager = @This();
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
paths: []const []const u8,
|
paths: []const []const u8,
|
||||||
resource_types: []const ResourceType,
|
// TODO: Use comptime hash map for resource_types
|
||||||
|
resource_map: std.StringArrayHashMapUnmanaged(ResourceType) = .{},
|
||||||
resources: std.StringHashMapUnmanaged(Resource) = .{},
|
resources: std.StringHashMapUnmanaged(Resource) = .{},
|
||||||
cwd: std.fs.Dir,
|
cwd: std.fs.Dir,
|
||||||
|
context: ?*anyopaque = null,
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, paths: []const []const u8, resource_types: []const ResourceType) !ResourceManager {
|
pub fn init(allocator: std.mem.Allocator, paths: []const []const u8, resource_types: []const ResourceType) !ResourceManager {
|
||||||
var cwd = try std.fs.openDirAbsolute(try std.fs.selfExeDirPathAlloc(allocator), .{});
|
var cwd = try std.fs.openDirAbsolute(try std.fs.selfExeDirPathAlloc(allocator), .{});
|
||||||
errdefer cwd.close();
|
errdefer cwd.close();
|
||||||
|
|
||||||
|
var resource_map: std.StringArrayHashMapUnmanaged(ResourceType) = .{};
|
||||||
|
for (resource_types) |res| {
|
||||||
|
try resource_map.put(allocator, res.name, res);
|
||||||
|
}
|
||||||
|
|
||||||
return ResourceManager{
|
return ResourceManager{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.paths = paths,
|
.paths = paths,
|
||||||
.resource_types = resource_types,
|
.resource_map = resource_map,
|
||||||
.cwd = cwd,
|
.cwd = cwd,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ResourceType = struct {
|
pub const ResourceType = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
load: fn (context: *anyopaque, mem: []const u8) error{ InvalidResource, CorruptData }!*anyopaque,
|
load: fn (context: ?*anyopaque, mem: []const u8) error{ InvalidResource, CorruptData }!*anyopaque,
|
||||||
unload: fn (context: *anyopaque, resource: *anyopaque) void,
|
unload: fn (context: ?*anyopaque, resource: *anyopaque) void,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub fn setLoadContext(self: *ResourceManager, ctx: anytype) void {
|
||||||
|
var context = self.allocator.create(@TypeOf(ctx)) catch unreachable;
|
||||||
|
context.* = ctx;
|
||||||
|
self.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn getResource(self: *ResourceManager, uri: []const u8) !Resource {
|
pub fn getResource(self: *ResourceManager, uri: []const u8) !Resource {
|
||||||
if (self.resources.get(uri)) |res|
|
if (self.resources.get(uri)) |res|
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -46,22 +59,33 @@ pub fn getResource(self: *ResourceManager, uri: []const u8) !Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file) |f| {
|
if (file) |f| {
|
||||||
var data = try f.reader().readAllAlloc(self.allocator, std.math.maxInt(usize));
|
if (self.resource_map.get(uri_data.scheme)) |res_type| {
|
||||||
errdefer self.allocator.free(data);
|
var data = try f.reader().readAllAlloc(self.allocator, std.math.maxInt(usize));
|
||||||
|
errdefer self.allocator.free(data);
|
||||||
|
|
||||||
const res = Resource{
|
const resource = try res_type.load(self.context, data);
|
||||||
.uri = try self.allocator.dupe(u8, uri),
|
errdefer res_type.unload(self.context, resource);
|
||||||
.resource = @ptrCast(*anyopaque, &data.ptr),
|
|
||||||
.size = data.len,
|
const res = Resource{
|
||||||
};
|
.uri = try self.allocator.dupe(u8, uri),
|
||||||
try self.resources.putNoClobber(self.allocator, uri, res);
|
.resource = resource,
|
||||||
return res;
|
.size = data.len,
|
||||||
|
};
|
||||||
|
try self.resources.putNoClobber(self.allocator, uri, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return error.UnknownResourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
return error.ResourceNotFound;
|
return error.ResourceNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unloadResource(self: *ResourceManager, res: Resource) void {
|
pub fn unloadResource(self: *ResourceManager, res: Resource) void {
|
||||||
|
const uri_data = uri_parser.parseUri(res.uri) catch unreachable;
|
||||||
|
if (self.resource_map.get(uri_data.scheme)) |res_type| {
|
||||||
|
res_type.unload(self.context, res.resource);
|
||||||
|
}
|
||||||
|
|
||||||
_ = self.resources.remove(res.uri);
|
_ = self.resources.remove(res.uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue