odin_editor/src/core/core.odin

171 lines
4.9 KiB
Plaintext

package core
import "core:runtime"
import "core:fmt"
import "vendor:raylib"
import "../plugin"
Mode :: enum {
Normal,
Insert,
}
Window :: struct {
input_map: InputMap,
draw: plugin.WindowDrawProc,
free_user_data: plugin.WindowFreeProc,
get_buffer: plugin.WindowGetBufferProc,
// TODO: create hook for when mode changes happen
user_data: rawptr,
}
request_window_close :: proc(state: ^State) {
state.should_close_window = true;
}
close_window_and_free :: proc(state: ^State) {
if state.window != nil {
if state.window.free_user_data != nil {
state.window.free_user_data(state.plugin_vtable, state.window.user_data);
}
delete_input_map(&state.window.input_map);
free(state.window);
state.window = nil;
state.current_input_map = &state.input_map;
}
}
State :: struct {
ctx: runtime.Context,
mode: Mode,
should_close: bool,
screen_height: int,
screen_width: int,
font: raylib.Font,
directory: string,
source_font_width: int,
source_font_height: int,
line_number_padding: int,
current_buffer: int,
buffers: [dynamic]FileBuffer,
window: ^Window,
should_close_window: bool,
input_map: InputMap,
current_input_map: ^InputMap,
plugins: [dynamic]plugin.Interface,
plugin_vtable: plugin.Plugin,
highlighters: map[string]plugin.OnColorBufferProc,
hooks: map[plugin.Hook][dynamic]plugin.OnHookProc,
}
add_hook :: proc(state: ^State, hook: plugin.Hook, hook_proc: plugin.OnHookProc) {
if _, exists := state.hooks[hook]; !exists {
state.hooks[hook] = make([dynamic]plugin.OnHookProc);
}
runtime.append(&state.hooks[hook], hook_proc);
}
PluginEditorAction :: proc "c" (plugin: plugin.Plugin);
EditorAction :: proc(state: ^State);
InputGroup :: union {PluginEditorAction, EditorAction, InputMap}
Action :: struct {
action: InputGroup,
description: string,
}
InputMap :: struct {
key_actions: map[raylib.KeyboardKey]Action,
ctrl_key_actions: map[raylib.KeyboardKey]Action,
}
new_input_map :: proc() -> InputMap {
input_map := InputMap {
key_actions = make(map[raylib.KeyboardKey]Action),
ctrl_key_actions = make(map[raylib.KeyboardKey]Action),
}
return input_map;
}
delete_input_map :: proc(input_map: ^InputMap) {
delete(input_map.key_actions);
delete(input_map.ctrl_key_actions);
}
// NOTE(pcleavelin): might be a bug in the compiler where it can't coerce
// `EditorAction` to `InputGroup` when given as a proc parameter, that is why there
// are two functions
register_plugin_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, action: PluginEditorAction, description: string = "") {
if ok := key in input_map.key_actions; ok {
// TODO: log that key is already registered
fmt.eprintln("plugin key already registered with single action", key);
}
input_map.key_actions[key] = Action {
action = action,
description = description,
};
}
register_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, action: EditorAction, description: string = "") {
if ok := key in input_map.key_actions; ok {
// TODO: log that key is already registered
fmt.eprintln("key already registered with single action", key);
}
input_map.key_actions[key] = Action {
action = action,
description = description,
};
}
register_key_action_group :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, input_group: InputGroup, description: string = "") {
if ok := key in input_map.key_actions; ok {
// TODO: log that key is already registered
fmt.eprintln("key already registered with single action", key);
}
input_map.key_actions[key] = Action {
action = input_group,
description = description,
};
}
register_ctrl_key_action_single :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, action: EditorAction, description: string = "") {
if ok := key in input_map.key_actions; ok {
// TODO: log that key is already registered
fmt.eprintln("key already registered with single action", key);
}
input_map.ctrl_key_actions[key] = Action {
action = action,
description = description,
};
}
register_ctrl_key_action_group :: proc(input_map: ^InputMap, key: raylib.KeyboardKey, input_group: InputGroup, description: string = "") {
if ok := key in input_map.key_actions; ok {
// TODO: log that key is already registered
fmt.eprintln("key already registered with single action", key);
}
input_map.ctrl_key_actions[key] = Action {
action = input_group,
description = description,
};
}
register_key_action :: proc{register_plugin_key_action_single, register_key_action_single, register_key_action_group};
register_ctrl_key_action :: proc{register_ctrl_key_action_single, register_ctrl_key_action_group};