Actions are no longer hardcoded, dynamic bindings base.

This commit is contained in:
KikooDX 2021-01-30 16:13:06 +01:00
parent e54660228a
commit 3361e859ed
2 changed files with 176 additions and 52 deletions

113
src/actions.zig Normal file
View File

@ -0,0 +1,113 @@
// 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 std = @import("std");
const expect = std.testing.expect;
const movement = @import("movement.zig");
const Vec2 = @import("vec2.zig");
const Level = @import("level.zig");
pub const ActionCat = enum {
none, // do nothing
movement, // move and change selection
verb, // do stuff with selection
scale, // change draw scaling
};
pub const Action = struct {
category: ActionCat,
toggle: bool = false, // bool that can be passed to actions, i.e. exclusive for movement
// Only one of these should be set, and only one should be used.
function_move: fn (*Vec2, u32, bool) movement.SelectionUpdate = movement.move_left,
function_verb: fn (*Level) void = Level.action_delete,
};
pub const ActionsDef = .{
.none = Action{
.category = ActionCat.none,
},
// Movement.
// Left.
.move_left = Action{
.toggle = true,
.category = ActionCat.movement,
.function_move = movement.move_left,
},
.move_LEFT = Action{
.category = ActionCat.movement,
.function_move = movement.move_left,
},
// Right.
.move_right = Action{
.toggle = true,
.category = ActionCat.movement,
.function_move = movement.move_right,
},
.move_RIGHT = Action{
.category = ActionCat.movement,
.function_move = movement.move_right,
},
// Up.
.move_up = Action{
.toggle = true,
.category = ActionCat.movement,
.function_move = movement.move_up,
},
.move_UP = Action{
.category = ActionCat.movement,
.function_move = movement.move_up,
},
// Down.
.move_down = Action{
.toggle = true,
.category = ActionCat.movement,
.function_move = movement.move_down,
},
.move_DOWN = Action{
.category = ActionCat.movement,
.function_move = movement.move_down,
},
// Up-left.
.move_up_left = Action{
.toggle = true,
.category = ActionCat.movement,
.function_move = movement.move_up_left,
},
.move_UP_LEFT = Action{
.category = ActionCat.movement,
.function_move = movement.move_up_left,
},
// Up-right.
.move_up_right = Action{
.toggle = true,
.category = ActionCat.movement,
.function_move = movement.move_up_right,
},
.move_UP_RIGHT = Action{
.category = ActionCat.movement,
.function_move = movement.move_up_right,
},
// Down-left.
.move_down_left = Action{
.toggle = true,
.category = ActionCat.movement,
.function_move = movement.move_down_left,
},
.move_DOWN_LEFT = Action{
.category = ActionCat.movement,
.function_move = movement.move_up_left,
},
// Down-right.
.move_down_right = Action{
.toggle = true,
.category = ActionCat.movement,
.function_move = movement.move_down_right,
},
.move_DOWN_RIGHT = Action{
.category = ActionCat.movement,
.function_move = movement.move_down_right,
},
};

View File

@ -15,6 +15,11 @@ const maxInt = std.math.maxInt;
const Level = @import("level.zig");
const Vec2 = @import("vec2.zig");
const movement = @import("movement.zig");
const actions = @import("actions.zig");
const ActionsDef = actions.ActionsDef;
const ActionCat = actions.ActionCat;
const char_range = 255;
pub fn main() !void {
// Create allocator
@ -45,6 +50,26 @@ pub fn main() !void {
// 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
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;
// Create input buffer (ASCII).
const input_buffer_len = 255;
var input_buffer: [input_buffer_len]u32 = undefined;
@ -57,72 +82,58 @@ pub fn main() !void {
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;
{
// 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();
key = ray.GetCharPressed();
}
}
// Process buffer content.
// Read the buffer backwards. This is placeholder logic.
while (input_cursor > 0) {
input_cursor -= 1;
const action = input_buffer[input_cursor];
const key = if (input_buffer[input_cursor] <= char_range)
input_buffer[input_cursor]
else
0;
const movement_command = switch (action) {
'A'...'Z' => action - 'A' + 'a',
else => action,
};
const was_lowercase: bool = movement_command == action;
const action: actions.Action = bindings[key].*;
// Check for movement.
const selection_update: movement.SelectionUpdate = switch (movement_command) {
// Movement.
'h' => movement.move_left(&cursor, 1, was_lowercase),
'j' => movement.move_down(&cursor, 1, was_lowercase),
'k' => movement.move_up(&cursor, 1, was_lowercase),
'l' => movement.move_right(&cursor, 1, was_lowercase),
// Diagonals and rectangle selection.
'y' => movement.move_up_left(&cursor, 1, was_lowercase),
'u' => movement.move_up_right(&cursor, 1, was_lowercase),
'b' => movement.move_down_left(&cursor, 1, was_lowercase),
'n' => movement.move_down_right(&cursor, 1, was_lowercase),
else => blk: {
break :blk movement.SelectionUpdate{
.active = false,
.area = undefined,
.exclusive = undefined,
.state = undefined,
};
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);
}
},
};
if (selection_update.active) {
level.apply_selection_update(selection_update);
} else {
// If didn't input movement, check for action.
switch (action) {
// Actions.
'd' => level.action_delete(),
.verb => {
action.function_verb(&level);
},
.scale => {
// TODO: move this to functions, doesn't make any sense here
// Zoom (pog feature).
'-' => if (scale > 3) {
if (scale > 3) {
scale -= 1;
},
'+' => if (scale < comptime maxInt(scale_type)) {
}
if (scale < comptime maxInt(scale_type)) {
scale += 1;
},
}
// Reset zoom.
'=' => scale = scale_default,
else => log("No action for {} key.", .{action}),
}
scale = scale_default;
log("No action for {} key.", .{action});
},
}
}