hadean-zig/src/Engine.zig

145 lines
4.2 KiB
Zig

const std = @import("std");
const Recti = @import("geometry/Recti.zig");
const Matrix4f = @import("geometry/Matrix4f.zig");
const shaders = @import("shaders.zig");
const Texture = @import("Texture.zig");
const Sprite = @import("Sprite.zig");
const Layer = @import("Layer.zig");
const Color = @import("Color.zig");
const Scene = @import("Scene.zig");
const assets = @import("assets.zig");
const c = @cImport({
@cInclude("glad/glad.h");
@cInclude("GLFW/glfw3.h");
});
const AutoHashMap = std.AutoHashMap;
const Error = error {
WindowNotInitialized,
WindowAlreadyInitialized,
NoScene,
AlreadyRunning
};
var window: ?*c.GLFWwindow = null;
var current_scene: ?Scene = null;
var next_scene: ?Scene = null;
var projection: Matrix4f = undefined;
fn glfw_on_error(err: c_int, desc_c: [*c]const u8) callconv(.C) void {
const desc: *const u8 = @ptrCast(desc_c);
std.log.err("[Engine:glfw_on_error] glfw error {x:0>8}: {s}", .{ err, desc });
}
fn glfw_on_resize (_: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void {
std.debug.print("[Engine:glfw_on_resize] {?}: {d} x {d}\n", .{ window, width, height });
c.glViewport(0, 0, width, height);
projection = Matrix4f.orthographic(0, @floatFromInt(width), @floatFromInt(height), 0, 0, 100);
shaders.set_projection_matrix(&projection);
if (current_scene != null) current_scene.?.resize(width, height);
}
fn get_size() struct { i32, i32 } {
var width: c_int = undefined;
var height: c_int = undefined;
c.glfwGetFramebufferSize(window, @ptrCast(&width), @ptrCast(&height));
return .{ width, height };
}
pub fn setup() !void {
if (window != null) return Error.WindowAlreadyInitialized;
// in case of errors, set callback early!
// for some reason this returns an error function as well??
_ = c.glfwSetErrorCallback(glfw_on_error);
// initialize glfw capabilities & cleanup
if (c.glfwInit() != 1) {
std.log.err("Failed to init glfw", .{});
return error.Initialization;
}
// ensure glfw knows what we're about
// c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MAJOR, 3);
c.glfwDefaultWindowHints();
c.glfwWindowHint(c.GLFW_SAMPLES, 4);
// c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MINOR, 3);
// c.glfwWindowHint(c.GLFW_OPENGL_PROFILE, c.GLFW_OPENGL_CORE_PROFILE);
// create the window & cleanup
window = c.glfwCreateWindow(1920, 1080, "My Title", null, null) orelse {
std.log.err("Failed to open window", .{});
return error.Initialization;
};
// load opengl into the window
c.glfwMakeContextCurrent(window);
if (c.gladLoadGL() != 1) {
std.log.err("Failed to load GL context", .{});
return error.Initialization;
}
// configure the context!
c.glfwSwapInterval(1);
// compile shaders...
try shaders.load();
try assets.load();
_ = c.glfwSetWindowSizeCallback(window, glfw_on_resize);
const clearBrightness: f32 = 0.09;
c.glClearColor(clearBrightness, clearBrightness, clearBrightness, 1.0);
// c.glEnable(c.GL_MULTISAMPLE);
c.glDisable(c.GL_MULTISAMPLE);
c.glEnable(c.GL_BLEND);
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
c.glEnable(c.GL_DEPTH_TEST);
c.glDepthFunc(c.GL_LEQUAL);
c.glDepthMask(c.GL_TRUE);
const width, const height = get_size();
c.glViewport(0, 0, width, height);
projection = Matrix4f.orthographic(0, @floatFromInt(width), @floatFromInt(height), 0, 0, 100);
shaders.set_projection_matrix(&projection);
}
pub fn destroy() void {
c.glfwDestroyWindow(window);
c.glfwTerminate();
}
pub fn set_scene(scene: Scene) void {
next_scene = scene;
}
pub fn run() Error!void {
if (window == null) return Error.WindowNotInitialized;
if (current_scene != null) return Error.AlreadyRunning;
if (next_scene == null) return Error.NoScene;
// run the main loop
while (c.glfwWindowShouldClose(window) == 0) {
// switch scenes if need be
if (next_scene != null) {
if (current_scene != null) current_scene.?.destroy();
current_scene = next_scene;
next_scene = null;
// start our scene
try current_scene.?.start();
// and send it the appropriate resize.
const width, const height = get_size();
current_scene.?.resize(width, height);
}
// setup for drawing
c.glClear(c.GL_COLOR_BUFFER_BIT | c.GL_DEPTH_BUFFER_BIT);
current_scene.?.draw();
c.glfwSwapBuffers(window);
c.glfwPollEvents();
current_scene.?.update(0.0042);
}
}