// SPDX-License-Identifier: MIT // Copyright (c) 2021 KikooDX // This file is part of [KBLE](https://sr.ht/~kikoodx/kble), which is // MIT licensed. The MIT license requires this copyright notice to be // included in all copies and substantial portions of the software. const ray = @cImport({ @cInclude("raylib.h"); }); const std = @import("std"); const assert = std.debug.assert; const format = std.fmt.format; const log = std.log.default.debug; const maxInt = std.math.maxInt; const Level = @import("level.zig"); const Vec2 = @import("vec2.zig"); const movement = @import("movement.zig"); const scaling = @import("scaling.zig"); const actions = @import("actions.zig"); const ActionsDef = actions.ActionsDef; const ActionCat = actions.ActionCat; const char_range = 255; pub fn main() !void { // Create allocator var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); const allocator = &arena.allocator; // Create window. ray.SetConfigFlags(ray.FLAG_WINDOW_RESIZABLE); ray.InitWindow(640, 480, "KBLE"); defer ray.CloseWindow(); // Limit FPS for performance. ray.SetTargetFPS(60); // Create level. var level: Level = try Level.init(allocator, 16, 16); defer level.deinit(allocator); // Create camera. var camera: Vec2 = Vec2.init(0, 0); // Init scale, used by drawing code. var scale: scaling.scale_type = scaling.scale_default; // Create cursor. var cursor: Vec2 = Vec2.init(0, 0); // Create binding "table". var bindings = [_]*const actions.Action{&actions.ActionsDef.none} ** char_range; // Set default bindings. // Movement. bindings['h'] = &ActionsDef.move_left; bindings['H'] = &ActionsDef.move_LEFT; bindings['j'] = &ActionsDef.move_down; bindings['J'] = &ActionsDef.move_DOWN; bindings['k'] = &ActionsDef.move_up; bindings['K'] = &ActionsDef.move_UP; bindings['l'] = &ActionsDef.move_right; bindings['L'] = &ActionsDef.move_RIGHT; bindings['y'] = &ActionsDef.move_up_left; bindings['Y'] = &ActionsDef.move_UP_LEFT; bindings['u'] = &ActionsDef.move_up_right; bindings['U'] = &ActionsDef.move_UP_RIGHT; bindings['b'] = &ActionsDef.move_down_left; bindings['B'] = &ActionsDef.move_DOWN_LEFT; bindings['n'] = &ActionsDef.move_down_right; bindings['N'] = &ActionsDef.move_DOWN_RIGHT; // Scale. bindings['='] = &ActionsDef.scale_reset; bindings['+'] = &ActionsDef.scale_up; bindings['-'] = &ActionsDef.scale_down; // Create input buffer. const input_buffer_len = 255; var input_buffer: [input_buffer_len]u32 = undefined; comptime { var i: u8 = 0; while (i < input_buffer_len) : (i += 1) { input_buffer[i] = 0; } } var input_cursor: u8 = 0; while (!ray.WindowShouldClose()) { { // Get keyboard input. var key = ray.GetCharPressed(); // Check if more characters have been pressed. while (key != 0) { // Add key to buffer. input_buffer[input_cursor] = @intCast(u32, key); input_cursor += 1; // Avoid writing out of memory. if (input_cursor >= input_buffer_len) input_cursor = input_buffer_len - 1; key = ray.GetCharPressed(); } } // Process buffer content. // Read the buffer backwards. This is placeholder logic. while (input_cursor > 0) { input_cursor -= 1; const key = if (input_buffer[input_cursor] <= char_range) input_buffer[input_cursor] else 0; const action: actions.Action = bindings[key].*; switch (action.category) { .none => {}, .movement => { const selection_update: movement.SelectionUpdate = action.function_move(&cursor, 1, action.toggle); if (selection_update.active) { level.apply_selection_update(selection_update); } }, .verb => { action.function_verb(&level); }, .scale => { scale = action.function_scale(scale); }, } } ray.BeginDrawing(); defer ray.EndDrawing(); ray.ClearBackground(ray.BLACK); level.draw(scale, camera); level.draw_selection(scale, camera); //ray.DrawFPS(0, 0); } }