give up on this repo, rewrite on v2 without hot code reload
This commit is contained in:
parent
39c311e225
commit
5e9b4b43a9
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
zig-out
|
zig-out
|
||||||
|
zig-pkg
|
||||||
.zig-cache
|
.zig-cache
|
||||||
|
|||||||
@ -48,9 +48,6 @@ pub fn init(outer_builder: *std.Build, opts: InitOptions) void {
|
|||||||
build_options.addOption(bool, "code_dynamic_linking", code_dynamic_linking);
|
build_options.addOption(bool, "code_dynamic_linking", code_dynamic_linking);
|
||||||
build_options.addOption(bool, "code_static_linking", code_static_linking);
|
build_options.addOption(bool, "code_static_linking", code_static_linking);
|
||||||
build_options.addOption(bool, "asset_hot_reload", asset_hot_reload);
|
build_options.addOption(bool, "asset_hot_reload", asset_hot_reload);
|
||||||
if (asset_hot_reload) {
|
|
||||||
build_options.addOptionPath("asset_dir", opts.asset_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
const engine_lib = b.createModule(.{
|
const engine_lib = b.createModule(.{
|
||||||
.root_source_file = b.path("src/game_lib/root.zig")
|
.root_source_file = b.path("src/game_lib/root.zig")
|
||||||
@ -140,13 +137,17 @@ pub fn init(outer_builder: *std.Build, opts: InitOptions) void {
|
|||||||
});
|
});
|
||||||
const install_game_lib = b.addInstallArtifact(game_lib, .{});
|
const install_game_lib = b.addInstallArtifact(game_lib, .{});
|
||||||
|
|
||||||
run_cmd.addArg("--game-lib-path");
|
run_cmd.addArg("--dynamic-lib-path");
|
||||||
run_cmd.addArg(b.getInstallPath(.lib, game_lib.out_lib_filename));
|
run_cmd.addArg(b.getInstallPath(.lib, game_lib.out_lib_filename));
|
||||||
run_cmd.step.dependOn(&install_game_lib.step);
|
run_cmd.step.dependOn(&install_game_lib.step);
|
||||||
|
|
||||||
var game_lib_step = outer_builder.step("game-lib", "Build game dynamic library");
|
var game_lib_step = outer_builder.step("game-lib", "Build game dynamic library");
|
||||||
game_lib_step.dependOn(&install_game_lib.step);
|
game_lib_step.dependOn(&install_game_lib.step);
|
||||||
}
|
}
|
||||||
|
if (asset_hot_reload) {
|
||||||
|
run_cmd.addArg("--assets-path");
|
||||||
|
run_cmd.addFileArg(opts.asset_dir);
|
||||||
|
}
|
||||||
run_cmd_step = &run_cmd.step;
|
run_cmd_step = &run_cmd.step;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,15 +106,16 @@ fn processEvent(self: *Environment, event: Input.Event) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stateInit(self: *Environment, initial: Init) void {
|
pub fn stateInit(self: *Environment, initial: Init, assets: Lib.Asset.List) void {
|
||||||
assert(self.frame == null);
|
assert(self.frame == null);
|
||||||
const opts = Lib.Init{
|
const opts = Lib.Init{
|
||||||
.gpa = self.gpa,
|
.gpa = self.gpa,
|
||||||
.seed = initial.seed,
|
.seed = initial.seed,
|
||||||
|
.assets = assets
|
||||||
};
|
};
|
||||||
self.state = self.callbacks.init(&opts);
|
self.state = self.callbacks.init(&opts);
|
||||||
|
|
||||||
self.frame = .init(self.gpa, initial.screen_size);
|
self.frame = .init(self.gpa, initial.screen_size, assets);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stateDeinit(self: *Environment) void {
|
pub fn stateDeinit(self: *Environment) void {
|
||||||
|
|||||||
@ -58,6 +58,18 @@ const Texture = struct {
|
|||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
rgba: [*]u8,
|
rgba: [*]u8,
|
||||||
|
|
||||||
|
pub fn clone(self: Data, allocator: std.mem.Allocator) !Data {
|
||||||
|
const pixel_count = self.width*self.height;
|
||||||
|
const rgba = try allocator.dupe(u8, self.rgba[0..(pixel_count * 4)]);
|
||||||
|
errdefer allocator.free(rgba);
|
||||||
|
|
||||||
|
return Data{
|
||||||
|
.width = self.width,
|
||||||
|
.height = self.height,
|
||||||
|
.rgba = rgba.ptr,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn destroy(self: *Texture) void {
|
fn destroy(self: *Texture) void {
|
||||||
@ -103,6 +115,9 @@ scissor_stack: std.ArrayList(Rect) = .empty,
|
|||||||
sokol_state: ?SokolState,
|
sokol_state: ?SokolState,
|
||||||
sokol_options: SokolOptions,
|
sokol_options: SokolOptions,
|
||||||
|
|
||||||
|
deferred_textures_arena: std.heap.ArenaAllocator,
|
||||||
|
deferred_textures: std.AutoArrayHashMapUnmanaged(Lib.Texture.Id, Texture.Data) = .empty,
|
||||||
|
|
||||||
const Options = struct {
|
const Options = struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
logger: sg.Logger = .{},
|
logger: sg.Logger = .{},
|
||||||
@ -113,6 +128,7 @@ pub fn init(options: Options) !Graphics {
|
|||||||
return Graphics{
|
return Graphics{
|
||||||
.gpa = options.allocator,
|
.gpa = options.allocator,
|
||||||
.sokol_state = null,
|
.sokol_state = null,
|
||||||
|
.deferred_textures_arena = std.heap.ArenaAllocator.init(options.allocator),
|
||||||
.sokol_options = .{
|
.sokol_options = .{
|
||||||
.logger = options.logger,
|
.logger = options.logger,
|
||||||
.imgui_font = options.imgui_font,
|
.imgui_font = options.imgui_font,
|
||||||
@ -198,6 +214,13 @@ pub fn setupSokol(self: *Graphics) !void {
|
|||||||
.nearest_sampler = nearest_sampler,
|
.nearest_sampler = nearest_sampler,
|
||||||
.font_context = font_context,
|
.font_context = font_context,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var iter = self.deferred_textures.iterator();
|
||||||
|
while (iter.next()) |entry| {
|
||||||
|
try self.setTextureData(entry.key_ptr.*, entry.value_ptr.*);
|
||||||
|
}
|
||||||
|
_ = self.deferred_textures_arena.reset(.free_all);
|
||||||
|
self.deferred_textures = .empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Graphics, gpa: std.mem.Allocator) void {
|
pub fn deinit(self: *Graphics, gpa: std.mem.Allocator) void {
|
||||||
@ -525,7 +548,9 @@ pub fn removeTexture(self: *Graphics, id: Lib.Texture.Id) void {
|
|||||||
|
|
||||||
pub fn setTextureData(self: *Graphics, id: Lib.Texture.Id, data: Texture.Data) !void {
|
pub fn setTextureData(self: *Graphics, id: Lib.Texture.Id, data: Texture.Data) !void {
|
||||||
if (self.sokol_state == null) {
|
if (self.sokol_state == null) {
|
||||||
return error.SokolNotSetup;
|
const arena = self.deferred_textures_arena.allocator();
|
||||||
|
try self.deferred_textures.put(arena, id, try data.clone(arena));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const texture = self.textures.get(.fromInt(@intFromEnum(id))) orelse return;
|
const texture = self.textures.get(.fromInt(@intFromEnum(id))) orelse return;
|
||||||
|
|||||||
@ -36,14 +36,126 @@ const Environment = @import("environment.zig");
|
|||||||
|
|
||||||
const Engine = @This();
|
const Engine = @This();
|
||||||
|
|
||||||
|
const IniReader = struct {
|
||||||
|
reader: *std.Io.Reader,
|
||||||
|
|
||||||
|
const Tag = union(enum) {
|
||||||
|
section: []const u8,
|
||||||
|
option: struct {
|
||||||
|
key: []const u8,
|
||||||
|
value: []const u8
|
||||||
|
},
|
||||||
|
|
||||||
|
pub fn isOption(self: Tag, key: []const u8) ?[]const u8 {
|
||||||
|
if (self == .option and std.mem.eql(u8, self.option.key, key)) {
|
||||||
|
return self.option.value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn next(self: *IniReader) !?Tag {
|
||||||
|
while (true) {
|
||||||
|
var line = self.reader.takeDelimiterInclusive('\n') catch |e| switch (e) {
|
||||||
|
error.EndOfStream => break,
|
||||||
|
else => return e
|
||||||
|
};
|
||||||
|
line = @constCast(std.mem.trim(u8, line, &std.ascii.whitespace));
|
||||||
|
if (std.mem.startsWith(u8, line, "#")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (line.len == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std.mem.startsWith(u8, line, "[") and std.mem.endsWith(u8, line, "]")) {
|
||||||
|
const section_name = line[1..(line.len-1)];
|
||||||
|
return Tag{
|
||||||
|
.section = std.mem.trim(u8, section_name, &std.ascii.whitespace)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (std.mem.indexOfScalar(u8, line, '=')) |equals_index| {
|
||||||
|
const key = line[0..equals_index];
|
||||||
|
const value = line[(equals_index+1)..];
|
||||||
|
|
||||||
|
return Tag{
|
||||||
|
.option = .{
|
||||||
|
.key = std.mem.trim(u8, key, &std.ascii.whitespace),
|
||||||
|
.value = std.mem.trim(u8, value, &std.ascii.whitespace),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return error.InvalidLine;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const LoadOptions = struct {
|
||||||
|
asset_dir: std.fs.Dir,
|
||||||
|
ini_reader: *IniReader,
|
||||||
|
arena: *std.heap.ArenaAllocator
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const AssetSystem = struct {
|
||||||
|
assets: std.ArrayList(Lib.Asset),
|
||||||
|
|
||||||
|
pub fn register(self: AssetSystem) void {
|
||||||
|
_ = self; // autofix
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Subsystems = struct {
|
||||||
|
graphics: *Graphics,
|
||||||
|
audio: *Audio,
|
||||||
|
assets: *AssetSystem,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ImageAsset = struct {
|
||||||
|
pub fn load(subsystems: Subsystems, opts: LoadOptions) !void {
|
||||||
|
const ini_reader = opts.ini_reader;
|
||||||
|
const arena = opts.arena;
|
||||||
|
const dir = opts.asset_dir;
|
||||||
|
|
||||||
|
var maybe_image_path: ?[]const u8 = null;
|
||||||
|
while (try ini_reader.next()) |tag| {
|
||||||
|
if (tag.isOption("path")) |opt| {
|
||||||
|
maybe_image_path = try arena.allocator().dupe(u8, opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maybe_image_path) |image_path| {
|
||||||
|
const image_data = try readFileAll(arena.allocator(), dir, image_path);
|
||||||
|
const image = try STBImage.load(image_data);
|
||||||
|
defer image.deinit();
|
||||||
|
std.debug.print("{s}\n", .{image_path});
|
||||||
|
const texture_id = try subsystems.graphics.addTexture();
|
||||||
|
try subsystems.graphics.setTextureData(texture_id, .{
|
||||||
|
.width = image.width,
|
||||||
|
.height = image.height,
|
||||||
|
.rgba = image.rgba8_pixels,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// subsystems.assets.register("icon");
|
||||||
|
// try subsystems.assets.append(self.assets_arena.allocator(), Lib.Asset{
|
||||||
|
// .id = @enumFromInt(self.assets.items.len),
|
||||||
|
// .key = try self.assets_arena.allocator().dupe(u8, asset_id),
|
||||||
|
// .data = &[_]u8{}
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
graphics: Graphics,
|
graphics: Graphics,
|
||||||
audio: Audio,
|
audio: Audio,
|
||||||
|
|
||||||
seed: u64,
|
seed: u64,
|
||||||
// game_linking: GameLinking,
|
|
||||||
environment: Environment,
|
environment: Environment,
|
||||||
|
|
||||||
|
assets_arena: std.heap.ArenaAllocator,
|
||||||
|
assets: std.ArrayList(Lib.Asset),
|
||||||
|
|
||||||
queued_events: std.ArrayList(Input.Event),
|
queued_events: std.ArrayList(Input.Event),
|
||||||
is_mouse_inside: bool,
|
is_mouse_inside: bool,
|
||||||
|
|
||||||
@ -51,28 +163,23 @@ debug: DebugSystem,
|
|||||||
|
|
||||||
pub const RunOptions = struct {
|
pub const RunOptions = struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
game_library_path: ?[]const u8 = null,
|
|
||||||
do_recording: bool = (builtin.mode == .Debug),
|
do_recording: bool = (builtin.mode == .Debug),
|
||||||
screen_width: u32 = 640,
|
screen_width: u32 = 640,
|
||||||
screen_height: u32 = 480,
|
screen_height: u32 = 480,
|
||||||
|
|
||||||
|
dynamic_library_path: ?[]const u8 = null,
|
||||||
|
assets_path: ?[]const u8 = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn run(self: *Engine, opts: RunOptions) !void {
|
pub fn run(self: *Engine, opts: RunOptions) !void {
|
||||||
// var game_linking: GameLinking = undefined;
|
|
||||||
// if (opts.game_library_path) |game_library_path| {
|
|
||||||
// game_linking = try .initDynamic(opts.allocator, game_library_path);
|
|
||||||
// } else {
|
|
||||||
// game_linking = try .initStatic();
|
|
||||||
// }
|
|
||||||
|
|
||||||
var debug_system = DebugSystem.init(opts.allocator);
|
var debug_system = DebugSystem.init(opts.allocator);
|
||||||
|
|
||||||
var maybe_callbacks: ?GameCallbacks = null;
|
var maybe_callbacks: ?GameCallbacks = null;
|
||||||
if (build_options.code_static_linking) {
|
if (build_options.code_static_linking) {
|
||||||
maybe_callbacks = GameLinking.getStatic();
|
maybe_callbacks = GameLinking.getStatic();
|
||||||
}
|
}
|
||||||
if (build_options.code_dynamic_linking and opts.game_library_path != null) {
|
if (build_options.code_dynamic_linking and opts.dynamic_library_path != null) {
|
||||||
var dynamic = try GameLinking.Dynamic.init(opts.allocator, opts.game_library_path.?);
|
var dynamic = try GameLinking.Dynamic.init(opts.allocator, opts.dynamic_library_path.?);
|
||||||
maybe_callbacks = try dynamic.getCallbacks();
|
maybe_callbacks = try dynamic.getCallbacks();
|
||||||
debug_system.dynamic_linking = dynamic;
|
debug_system.dynamic_linking = dynamic;
|
||||||
}
|
}
|
||||||
@ -105,10 +212,62 @@ pub fn run(self: *Engine, opts: RunOptions) !void {
|
|||||||
.queued_events = .empty,
|
.queued_events = .empty,
|
||||||
.seed = initial.seed,
|
.seed = initial.seed,
|
||||||
.is_mouse_inside = false,
|
.is_mouse_inside = false,
|
||||||
.debug = debug_system
|
.debug = debug_system,
|
||||||
|
.assets = .empty,
|
||||||
|
.assets_arena = std.heap.ArenaAllocator.init(opts.allocator)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.environment.stateInit(initial);
|
if (opts.assets_path) |assets_path| {
|
||||||
|
var temp_arena = std.heap.ArenaAllocator.init(opts.allocator);
|
||||||
|
defer temp_arena.deinit();
|
||||||
|
|
||||||
|
var result_arena = std.heap.ArenaAllocator.init(opts.allocator);
|
||||||
|
defer result_arena.deinit();
|
||||||
|
|
||||||
|
var dir = try std.fs.openDirAbsolute(assets_path, .{ .iterate = false });
|
||||||
|
defer dir.close();
|
||||||
|
|
||||||
|
const result = try listFilesRecursively(assets_path, temp_arena.allocator(), result_arena.allocator(), ".ini");
|
||||||
|
for (result.items) |path| {
|
||||||
|
const path_without_ini = path[0..(path.len-4)];
|
||||||
|
const index_of_dot = std.mem.lastIndexOfScalar(u8, path_without_ini, '.') orelse continue;
|
||||||
|
const asset_type = path_without_ini[(index_of_dot+1)..];
|
||||||
|
const asset_id = path_without_ini[0..index_of_dot];
|
||||||
|
|
||||||
|
std.debug.print("{s} {s}\n", .{asset_id, asset_type});
|
||||||
|
if (std.mem.eql(u8, asset_type, "image")) {
|
||||||
|
const f = try dir.openFile(path, .{ });
|
||||||
|
defer f.close();
|
||||||
|
|
||||||
|
var reader_buffer: [Math.bytes_per_kib * 4]u8 = undefined;
|
||||||
|
var file_reader = f.reader(&reader_buffer);
|
||||||
|
var ini_reader = IniReader{ .reader = &file_reader.interface };
|
||||||
|
|
||||||
|
var asset_system = AssetSystem{
|
||||||
|
.assets = .empty
|
||||||
|
};
|
||||||
|
try ImageAsset.load(.{
|
||||||
|
.audio = &self.audio,
|
||||||
|
.graphics = &self.graphics,
|
||||||
|
.assets = &asset_system
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.arena = &temp_arena,
|
||||||
|
.ini_reader = &ini_reader,
|
||||||
|
.asset_dir = dir
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// for (result)
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.assets.append(self.allocator, Lib.Asset{
|
||||||
|
.data = &.{}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.environment.stateInit(initial, .{
|
||||||
|
.items = self.assets.items
|
||||||
|
});
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// if (opts.do_recording) {
|
// if (opts.do_recording) {
|
||||||
@ -169,6 +328,30 @@ pub fn run(self: *Engine, opts: RunOptions) !void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn listFilesRecursively(
|
||||||
|
absolute_path: []const u8,
|
||||||
|
temp_allocator: std.mem.Allocator,
|
||||||
|
result_arena: std.mem.Allocator,
|
||||||
|
extension: []const u8
|
||||||
|
) !std.ArrayList([]u8) {
|
||||||
|
var result: std.ArrayList([]u8) = .empty;
|
||||||
|
var dir = try std.fs.openDirAbsolute(absolute_path, .{ .iterate = true });
|
||||||
|
defer dir.close();
|
||||||
|
|
||||||
|
var walker = try dir.walk(temp_allocator);
|
||||||
|
defer walker.deinit();
|
||||||
|
|
||||||
|
while (try walker.next()) |entry| {
|
||||||
|
if (entry.kind == .file) {
|
||||||
|
if (std.mem.endsWith(u8, entry.path, extension)) {
|
||||||
|
try result.append(result_arena, try result_arena.dupe(u8, entry.path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
fn readFileAll(gpa: std.mem.Allocator, dir: std.fs.Dir, sub_path: []const u8) ![]u8 {
|
fn readFileAll(gpa: std.mem.Allocator, dir: std.fs.Dir, sub_path: []const u8) ![]u8 {
|
||||||
const f = try dir.openFile(sub_path, .{});
|
const f = try dir.openFile(sub_path, .{});
|
||||||
defer f.close();
|
defer f.close();
|
||||||
@ -206,6 +389,7 @@ fn sokolCleanup(self: *Engine) void {
|
|||||||
self.audio.deinit();
|
self.audio.deinit();
|
||||||
self.graphics.deinit(self.allocator);
|
self.graphics.deinit(self.allocator);
|
||||||
self.debug.deinit();
|
self.debug.deinit();
|
||||||
|
self.assets_arena.deinit();
|
||||||
// TODO:
|
// TODO:
|
||||||
// self.game_linking.deinit(self.allocator);
|
// self.game_linking.deinit(self.allocator);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -270,6 +270,27 @@ pub const KeyState = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Asset = struct {
|
||||||
|
data: []const u8,
|
||||||
|
// type: *std.builtin.Type,
|
||||||
|
|
||||||
|
pub const Id = u16;
|
||||||
|
|
||||||
|
pub const List = struct {
|
||||||
|
items: []Asset,
|
||||||
|
|
||||||
|
pub fn get(self: List, comptime T: type, id: Id) *const T {
|
||||||
|
if (id >= self.items.len) {
|
||||||
|
@panic("foo");
|
||||||
|
}
|
||||||
|
if (@sizeOf(T) != self.items[id].data.len) {
|
||||||
|
@panic("foo");
|
||||||
|
}
|
||||||
|
return @ptrCast(@alignCast(self.items[id].data.ptr));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
pub const Frame = struct {
|
pub const Frame = struct {
|
||||||
arena: std.heap.ArenaAllocator,
|
arena: std.heap.ArenaAllocator,
|
||||||
time_ns: Nanoseconds,
|
time_ns: Nanoseconds,
|
||||||
@ -288,9 +309,12 @@ pub const Frame = struct {
|
|||||||
screen_size: Vec2,
|
screen_size: Vec2,
|
||||||
clear_color: Vec4,
|
clear_color: Vec4,
|
||||||
|
|
||||||
|
assets: Asset.List,
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(
|
||||||
gpa: std.mem.Allocator,
|
gpa: std.mem.Allocator,
|
||||||
screen_size: Vec2
|
screen_size: Vec2,
|
||||||
|
assets: Asset.List,
|
||||||
) Frame {
|
) Frame {
|
||||||
return Frame{
|
return Frame{
|
||||||
.arena = std.heap.ArenaAllocator.init(gpa),
|
.arena = std.heap.ArenaAllocator.init(gpa),
|
||||||
@ -306,6 +330,7 @@ pub const Frame = struct {
|
|||||||
.audio_commands = .empty,
|
.audio_commands = .empty,
|
||||||
.hide_cursor = false,
|
.hide_cursor = false,
|
||||||
.screen_size = screen_size,
|
.screen_size = screen_size,
|
||||||
|
.assets = assets
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,6 +498,7 @@ pub const Frame = struct {
|
|||||||
pub const Init = struct {
|
pub const Init = struct {
|
||||||
gpa: std.mem.Allocator,
|
gpa: std.mem.Allocator,
|
||||||
seed: u64,
|
seed: u64,
|
||||||
|
assets: Asset.List,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Callbacks = struct {
|
pub const Callbacks = struct {
|
||||||
|
|||||||
@ -29,6 +29,9 @@ pub fn main() !void {
|
|||||||
var game_library_path: ?[]const u8 = null;
|
var game_library_path: ?[]const u8 = null;
|
||||||
defer if (game_library_path) |str| allocator.free(str);
|
defer if (game_library_path) |str| allocator.free(str);
|
||||||
|
|
||||||
|
var assets_path: ?[]const u8 = null;
|
||||||
|
defer if (assets_path) |str| allocator.free(str);
|
||||||
|
|
||||||
// var asset_loading: Engine.RunOptions.AssetLoading = undefined;
|
// var asset_loading: Engine.RunOptions.AssetLoading = undefined;
|
||||||
// if (!build_options.asset_hot_reload) {
|
// if (!build_options.asset_hot_reload) {
|
||||||
// asset_loading = .{
|
// asset_loading = .{
|
||||||
@ -53,12 +56,21 @@ pub fn main() !void {
|
|||||||
var opt_game_lib_path: ?CLI.Option.Id = null;
|
var opt_game_lib_path: ?CLI.Option.Id = null;
|
||||||
if (build_options.code_dynamic_linking) {
|
if (build_options.code_dynamic_linking) {
|
||||||
opt_game_lib_path = try cli.addOption(.{
|
opt_game_lib_path = try cli.addOption(.{
|
||||||
.long_name = "game-lib-path",
|
.long_name = "dynamic-lib-path",
|
||||||
.description = "Load game code from dynamic library",
|
.description = "Load game code from dynamic library",
|
||||||
.kind = .single_argument
|
.kind = .single_argument
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var opt_assets_path: ?CLI.Option.Id = null;
|
||||||
|
if (build_options.asset_hot_reload) {
|
||||||
|
opt_assets_path = try cli.addOption(.{
|
||||||
|
.long_name = "assets-path",
|
||||||
|
.description = "Load assets from folder at runtime",
|
||||||
|
.kind = .single_argument
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const cmd_version = try cli.addCommand(.{
|
const cmd_version = try cli.addCommand(.{
|
||||||
.name = "version",
|
.name = "version",
|
||||||
.description = "Show semantic version and build options"
|
.description = "Show semantic version and build options"
|
||||||
@ -85,6 +97,12 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opt_assets_path) |opt| {
|
||||||
|
if (parsed.getOptionArgument(opt)) |arg| {
|
||||||
|
assets_path = try allocator.dupe(u8, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const command = parsed.command orelse cmd_launch;
|
const command = parsed.command orelse cmd_launch;
|
||||||
if (command == cmd_version) {
|
if (command == cmd_version) {
|
||||||
cli.stdout.write("Version: {s}\n", .{ "TODO:" });
|
cli.stdout.write("Version: {s}\n", .{ "TODO:" });
|
||||||
@ -102,8 +120,8 @@ pub fn main() !void {
|
|||||||
|
|
||||||
try engine.run(.{
|
try engine.run(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.game_library_path = game_library_path,
|
.dynamic_library_path = game_library_path,
|
||||||
// .asset_loading = asset_loading
|
.assets_path = assets_path
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
src/assets/icon.image.ini
Normal file
4
src/assets/icon.image.ini
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[asdf]
|
||||||
|
path = ./icon.png
|
||||||
|
|
||||||
|
# afd
|
||||||
24
src/game.zig
24
src/game.zig
@ -14,6 +14,22 @@ const State = struct {
|
|||||||
player: Vec2,
|
player: Vec2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const AssetId = enum {
|
||||||
|
icon
|
||||||
|
};
|
||||||
|
|
||||||
|
const Image = struct {
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
rgba: []const u8,
|
||||||
|
|
||||||
|
pub const nil = Image{
|
||||||
|
.width = 0,
|
||||||
|
.height = 0,
|
||||||
|
.rgba = &.{ }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
pub fn init(opts: *const Engine.Init) callconv(.c) *anyopaque {
|
pub fn init(opts: *const Engine.Init) callconv(.c) *anyopaque {
|
||||||
const gpa = opts.gpa;
|
const gpa = opts.gpa;
|
||||||
|
|
||||||
@ -23,6 +39,14 @@ pub fn init(opts: *const Engine.Init) callconv(.c) *anyopaque {
|
|||||||
.player = .init(50, 50),
|
.player = .init(50, 50),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// var icon = opts.assets.get(ImageAsset, "icon");
|
||||||
|
// icon.id
|
||||||
|
// icon.rgba
|
||||||
|
// icon.texture_id
|
||||||
|
|
||||||
|
// std.debug.print("{}\n", .{opts.assets});
|
||||||
|
// const icon = opts.assets.get(Image, @intFromEnum(AssetId.icon));
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user