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};