ona/source/ona/ona.zig
kayomn 07a515a81f
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Tidy up and fix data structures
2023-06-02 21:43:53 +00:00

139 lines
3.7 KiB
Zig
Executable File

const builtin = @import("builtin");
const canvas = @import("./canvas.zig");
const coral = @import("coral");
const ext = @import("./ext.zig");
pub const file = @import("./file.zig");
pub const heap = @import("./heap.zig");
const kym = @import("./kym.zig");
const AppManifest = struct {
title: [255:0]u8 = [_:0]u8{0} ** 255,
width: u16 = 640,
height: u16 = 480,
pub fn load_script(self: *AppManifest, env: *kym.Environment, fs: file.System, file_path: []const u8) !void {
const manifest = try env.execute_file(fs, file.Path.from(&.{file_path}));
defer env.discard(manifest);
const manifest_ref = manifest.as_ref();
{
const title = try env.get_field(manifest_ref, try env.intern("title"));
defer env.discard(title);
const title_string = try env.string_cast(title.as_ref());
try env.check(title_string.len <= self.title.len, "`title` cannot exceed 255 bytes in length");
coral.io.copy(&self.title, title_string);
}
const u16_int = @typeInfo(u16).Int;
{
const width = try env.get_field(manifest_ref, try env.intern("width"));
errdefer env.discard(width);
self.width = try coral.math.checked_cast(u16_int, try env.to_integer(width.as_ref()));
}
{
const height = try env.get_field(manifest_ref, try env.intern("height"));
errdefer env.discard(height);
self.width = try coral.math.checked_cast(u16_int, try env.to_integer(height.as_ref()));
}
}
};
pub fn run_app(base_file_system: file.System) void {
const Logger = struct {
const Self = @This();
fn log(_: *const Self, message: []const u8) void {
ext.SDL_LogError(ext.SDL_LOG_CATEGORY_APPLICATION, "%.*s", message.len, message.ptr);
}
};
var script_environment = kym.Environment.init(heap.allocator, .{
.values_max = 512,
.calls_max = 512,
.reporter = kym.Environment.Reporter.bind(Logger, &.{}, Logger.log),
}) catch {
return ext.SDL_LogError(ext.SDL_LOG_CATEGORY_APPLICATION, "failed to initialize Kym vm\n");
};
defer script_environment.deinit();
const app_file_name = "app.ona";
var app_manifest = AppManifest{};
app_manifest.load_script(&script_environment, base_file_system, app_file_name) catch {
return ext.SDL_LogError(ext.SDL_LOG_CATEGORY_APPLICATION, "failed to load %s\n", app_file_name);
};
if (ext.SDL_Init(ext.SDL_INIT_EVERYTHING) != 0) {
return ext.SDL_LogError(ext.SDL_LOG_CATEGORY_APPLICATION, "%s\n", ext.SDL_GetError());
}
defer ext.SDL_Quit();
{
const base_prefix = ext.SDL_GetBasePath() orelse {
return ext.SDL_LogError(ext.SDL_LOG_CATEGORY_APPLICATION, "%s\n", ext.SDL_GetError());
};
defer ext.SDL_free(base_prefix);
const window_flags = 0;
const window_pos = ext.SDL_WINDOWPOS_CENTERED;
const window = ext.SDL_CreateWindow(&app_manifest.title, window_pos, window_pos, app_manifest.width, app_manifest.height, window_flags) orelse {
return ext.SDL_LogError(ext.SDL_LOG_CATEGORY_APPLICATION, "%s\n", ext.SDL_GetError());
};
defer ext.SDL_DestroyWindow(window);
const renderer_flags = 0;
const renderer = ext.SDL_CreateRenderer(window, -1, renderer_flags) orelse {
return ext.SDL_LogError(ext.SDL_LOG_CATEGORY_APPLICATION, "%s\n", ext.SDL_GetError());
};
defer ext.SDL_DestroyRenderer(renderer);
while (true) {
// TODO: Delta timing.
var event = @as(ext.SDL_Event, undefined);
while (ext.SDL_PollEvent(&event) != 0) {
switch (event.type) {
ext.SDL_QUIT => return,
else => {},
}
}
if (ext.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0) != 0) {
return ext.SDL_LogError(ext.SDL_LOG_CATEGORY_APPLICATION, "%s\n", ext.SDL_GetError());
}
if (ext.SDL_RenderClear(renderer) != 0) {
return ext.SDL_LogError(ext.SDL_LOG_CATEGORY_APPLICATION, "%s\n", ext.SDL_GetError());
}
// TODO: Render here.
ext.SDL_RenderPresent(renderer);
}
}
}