#+feature dynamic-literals package edit2d //import im "shared:odin-imgui" import mu "vendor:microui" import e2_glyph "./glyph" import "core:fmt" import "vendor:glfw" import b2 "vendor:box2d" /* This library will only account for box2d's entities editing It only deals with one world_id, which means typically one level All the interface follows a pattern i.e. It takes interface_state pointer and returns a boolean indicating weather the world needs to be reloaded Interface should handle microui */ Edit_Mode :: enum { ENTITY, VERTICES, OVERVIEW, CHAIN, JOINT, } Interface_State :: struct { entity_defs : [dynamic]^Engine_Entity_Def, entities : [dynamic]^engine_entity, selected_entity : i32, world : ^Engine_World, state : ^Engine_State, vertex_index : ^i32, chain_index : ^i32, edit_mode : Edit_Mode, curr_joint_index : i32, curr_joint_type : b2.JointType, curr_static_index : Static_Index_Global, } key_map : map[i32]mu.Key = { glfw.KEY_LEFT_SHIFT = .SHIFT, glfw.KEY_RIGHT_SHIFT = .SHIFT, glfw.KEY_LEFT_CONTROL = .CTRL, glfw.KEY_RIGHT = .CTRL, glfw.KEY_LEFT_ALT = .ALT, glfw.KEY_RIGHT_ALT = .ALT, glfw.KEY_BACKSPACE = .BACKSPACE, glfw.KEY_DELETE = .DELETE, glfw.KEY_ENTER = .RETURN, glfw.KEY_LEFT = .LEFT, glfw.KEY_RIGHT = .RIGHT, glfw.KEY_HOME = .HOME, glfw.KEY_END = .END, glfw.KEY_A = .A, glfw.KEY_X = .X, glfw.KEY_C = .C, glfw.KEY_V = .V } mouse_map : map[i32]mu.Mouse = { glfw.MOUSE_BUTTON_LEFT = .LEFT, glfw.MOUSE_BUTTON_RIGHT = .RIGHT, glfw.MOUSE_BUTTON_MIDDLE= .MIDDLE, } //interface_get_font mui_text_width :: proc(font: mu.Font, str: string) -> i32 { glyph := cast(^e2_glyph.GlyphState)font return i32(len(str)) * i32(glyph.font_size_pt) } mui_text_height :: proc(font: mu.Font) -> i32 { glyph := cast(^e2_glyph.GlyphState)font return i32(glyph.font_size_pt) } interface_get_default :: proc(interface: ^Interface_State) { interface.selected_entity = 0 interface.vertex_index = new(i32) interface.vertex_index^ = 0 interface.chain_index = new(i32) interface.chain_index^ = 0 } /* interface_draw_options :: proc(state: ^engine_state) { debug_draw := &state.debug_draw im.SliderFloat("Zoom", &state.draw.cam.zoom, 0, 100) im.Checkbox("Shapes", &debug_draw.drawShapes) im.Checkbox("Joints", &debug_draw.drawJoints) im.Checkbox("Joint Extras", &debug_draw.drawJointExtras) im.Checkbox("Bounds", &debug_draw.drawBounds) im.Checkbox("Contact Points", &debug_draw.drawContacts) im.Checkbox("Contact Normals", &debug_draw.drawContactNormals) im.Checkbox("Contact Inpulses", &debug_draw.drawContactImpulses) im.Checkbox("Contact Features", &debug_draw.drawContactFeatures) im.Checkbox("Friction Inpulses", &debug_draw.drawFrictionImpulses) im.Checkbox("Mass ", &debug_draw.drawMass) im.Checkbox("Body Names", &debug_draw.drawBodyNames) im.Checkbox("Graph Colors", &debug_draw.drawGraphColors) im.Checkbox("Islands ", &debug_draw.drawIslands) im.SliderFloat("Rotation", &state.draw.cam.rotation, 0, 360) } */ mu_interface_game_mode :: proc(state: ^Engine_State, interface: ^Interface_State) { if mu.begin_window(&state.mu_ctx, "Edit Mode", {1630, 0, 250, 170}) { for type in Edit_Mode { b : bool = interface.edit_mode == type if .CHANGE in mu.checkbox(&state.mu_ctx, fmt.tprint(type), &b) do interface.edit_mode = type } mu.end_window(&state.mu_ctx) } } mu_interface_draw_options :: proc(state: ^Engine_State) { if mu.begin_window(&state.mu_ctx, "Options", {200, 150, 200, 400}){ debug_draw := &state.debug_draw mu.label(&state.mu_ctx, "Zoom") mu.slider(&state.mu_ctx, &state.draw.cam.zoom,0, 100) mu.checkbox(&state.mu_ctx, "Shapes", &debug_draw.drawShapes) mu.checkbox(&state.mu_ctx, "Joints", &debug_draw.drawJoints) mu.checkbox(&state.mu_ctx, "Joint Extras", &debug_draw.drawJointExtras) mu.checkbox(&state.mu_ctx, "Bounds", &debug_draw.drawBounds) mu.checkbox(&state.mu_ctx, "Contact Points", &debug_draw.drawContacts) mu.checkbox(&state.mu_ctx, "Contact Normals", &debug_draw.drawContactNormals) mu.checkbox(&state.mu_ctx, "Contact Inpulses", &debug_draw.drawContactImpulses) mu.checkbox(&state.mu_ctx, "Contact Features", &debug_draw.drawContactFeatures) mu.checkbox(&state.mu_ctx, "Friction Inpulses", &debug_draw.drawFrictionImpulses) mu.checkbox(&state.mu_ctx, "Mass ", &debug_draw.drawMass) mu.checkbox(&state.mu_ctx, "Body Names", &debug_draw.drawBodyNames) mu.checkbox(&state.mu_ctx, "Graph Colors", &debug_draw.drawGraphColors) mu.checkbox(&state.mu_ctx, "Islands ", &debug_draw.drawIslands) mu.label(&state.mu_ctx, "Rotation") mu.slider(&state.mu_ctx, &state.draw.cam.rotation, 0, 360) mu.end_window(&state.mu_ctx) } } interface_all :: proc($E: typeid, interface: ^Interface_State, game_data : $G) -> bool { ret := false if interface.selected_entity <0 { interface.selected_entity = 0 } //if handle_input(E, interface.state, game_data) do return true state := interface.state mu.begin(&state.mu_ctx) //test_window(&state.mu_ctx) mu_interface_draw_options(interface.state) mu_interface_game_mode(state, interface) if mu.begin_window(&state.mu_ctx, "B2d Interface", {1630, 170, 250, 450}) { if interface.edit_mode == .ENTITY { if .ACTIVE in mu.header(&state.mu_ctx, "Entity", {.AUTO_SIZE}) { if interface_entity(interface) do ret = true } } mu.end_window(&state.mu_ctx) } //if interface_joints(interface) do ret = true mu.end(&state.mu_ctx) //im.End() return ret }