package edit2d import b2 "vendor:box2d" //import im "shared:odin-imgui" import "core:fmt" import "vendor:glfw" import "base:runtime" import draw "./draw" /* Handling input Key Bindings Meta keys E -> Cycle thru interface edit mode CTRL + S -> Save level CTRL + C -> Copy entity CTRL + V -> Paste entity ALT + D -> Delete entity CTRL + Mouse left -> Move according to edit mode Mouse wheel -> Scale according to edit mode Mouse Left -> select entity Mouse Right -> create new entity TODO: Command mode? Different handling of keys for different modes */ /* Handle all keys when the editor is in entity mode Select Add Move Delete Copy paste Resize */ handle_entity_mode :: proc( $E : typeid, state : ^engine_state, game_data : ^$G, ) -> bool { ret := false click_query_filter :: proc "c" ( shape_id : b2.ShapeId, ctx : rawptr ) -> bool { context = runtime.default_context() game := cast(^engine_game)ctx index := i32(uintptr(b2.Shape_GetUserData(shape_id))) game.interface.selected_entity = index return true } game: ^engine_game = game_data interface := &game.interface level := &game_data.levels[game.curr_level] input := &state.input mpos := draw.camera_convert_screen_to_world(&state.draw.cam, input.mouse) if interface.selected_entity != -1 { def := &level.entity_defs[interface.selected_entity] { draw.solid_circle_add(&interface.state.draw.solid_circles, {p = def.body_def.position, q = {c = 1} }, 0.2, {1, 0, 0, 1}) } } //Setlect entity if is_key_pressed(state, glfw.MOUSE_BUTTON_LEFT) { aabb : b2.AABB = {mpos, mpos + 1} circle : b2.Circle = {center = mpos, radius = 0.2} proxy : b2.ShapeProxy = b2.MakeProxy({circle.center}, circle.radius) r := b2.World_OverlapShape(level.engine.world_id, proxy, b2.DefaultQueryFilter(), click_query_filter, game) } else if is_key_pressed(state, glfw.MOUSE_BUTTON_RIGHT) { new_def := E { engine = default_engine_entity_def(), type = .NPC } x_pos, y_pos := glfw.GetCursorPos(state.window) pos := draw.camera_convert_screen_to_world_32(&state.draw.cam, {f32(x_pos), f32(y_pos)}) new_def.body_def.position = pos interface.selected_entity = i32(len(level.entity_defs)) append(&level.entity_defs, new_def) ret = true } else{ //Can only do these actions if a entity is selected if interface.selected_entity != -1 && len(level.entity_defs) > 0 { def := &level.entity_defs[interface.selected_entity] //Copy paste if is_key_down( state, glfw.KEY_LEFT_CONTROL)\\ && is_key_pressed( state, glfw.KEY_C) { game_data.copied_def = def^ } else if is_key_down( state, glfw.KEY_LEFT_CONTROL) \\ && is_key_pressed( state, glfw.KEY_V) { //Paste the copied def on the mouse position interface.selected_entity = i32(len(level.entity_defs)) game_data.copied_def.body_def.position = mpos append(&level.entity_defs, game_data.copied_def) ret = true } else if is_key_down( state, glfw.KEY_LEFT_CONTROL) \\ && is_key_pressed( state, glfw.KEY_D) { //Remove the def unordered_remove(&level.entity_defs, interface.selected_entity) interface.selected_entity = -1 ret = true } else if is_key_down( state, glfw.KEY_LEFT_CONTROL) \\ && is_key_down( state, glfw.MOUSE_BUTTON_LEFT) { //move def def.body_def.position = mpos ret = true } else if state.input.mouse_wheel.y != 0 { def.scale += f32(state.input.mouse_prev.y / 5) ret = true } } } return ret } handle_input :: proc( $E : typeid, state : ^engine_state, game_data : ^$G, ) -> bool { game : ^engine_game = &game_data.engine /* Applies for all mode */ level := &game_data.levels[game.curr_level] if is_key_pressed(state, glfw.KEY_E) { interface := &game.interface if interface.edit_mode == max(EditMode) { interface.edit_mode = min(EditMode) }else { new_val := int(interface.edit_mode) + 1 interface.edit_mode = EditMode(new_val) } } if is_key_pressed(state, glfw.KEY_S) && \\ is_key_down(state, glfw.KEY_LEFT_CONTROL) { level_save_to_file(level, state) } //if im.GetIO().WantCaptureMouse do return false //if im.GetIO().WantCaptureKeyboard do return false ret := false #partial switch game.interface.edit_mode { case .ENTITY : ret = handle_entity_mode(E, state, game_data) // case .VERTICES : interface_handle_vertices_mode(state, game_data) // case .OVERVIEW : interface_handle_overview_mode(state, game_data) // case .CHAIN : interface_handle_chain_mode(state, game_data) // case .JOINT : interface_handle_joint_mode(state, game_data) } return ret }