diff --git a/README.md b/README.md index 5d1604b..731cdf0 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ It's created using folloing tools 1. Odin programming language 2. GLFW for input handling and graphics -3. Dear ImGui for user interfaces +3. Microui for user interfaces 4. Box2d ## Current Progress diff --git a/box2d_draw.odin b/box2d_draw.odin index aaf1f62..44e1417 100644 --- a/box2d_draw.odin +++ b/box2d_draw.odin @@ -174,7 +174,7 @@ DrawPointFcn :: proc "c" ( } //After initilizing draw -draw_configure_box2d :: proc(state: ^engine_state) +draw_configure_box2d :: proc(state: ^Engine_State) { debug_draw := &state.debug_draw diff --git a/draw/draw.odin b/draw/draw.odin index aaa5cc3..105410b 100644 --- a/draw/draw.odin +++ b/draw/draw.odin @@ -1566,7 +1566,6 @@ textures_flush :: proc(d: ^Draw) gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, nil) - } gl.Disable(gl.BLEND) gl.UseProgram(0) diff --git a/edit2d.odin b/edit2d.odin index 998fb47..0a98ce3 100644 --- a/edit2d.odin +++ b/edit2d.odin @@ -12,6 +12,7 @@ import "shared:odin-imgui/imgui_impl_glfw" import "shared:odin-imgui/imgui_impl_opengl3" **/ +import "core:fmt" import gl "vendor:OpenGL" import "vendor:glfw" import e2_draw "shared:Edit2D/draw" @@ -22,12 +23,13 @@ import mu "vendor:microui" //Only to be used inside the libarary __e2d_interal : struct { - viewport_changed : bool + viewport_changed : bool, + mouse_scroll : [2]f64, } -engine_state :: struct +Engine_State :: struct { window : glfw.WindowHandle, debug_draw : b2.DebugDraw, @@ -43,7 +45,7 @@ engine_state :: struct tex_line : u32, drop_callback : glfw.DropProc, - input : input_state, + input : Input_State, mu_ctx : mu.Context, mu_tex : u32, @@ -51,7 +53,7 @@ engine_state :: struct MAX_KEYS :: 512 -input_state :: struct +Input_State :: struct { mouse_wheel : [2]f64, mouse : [2]f64, @@ -86,7 +88,7 @@ engine_check_types :: proc($Game: typeid) level_engine_type := reflect.struct_field_by_name(level_map_type.value.id, "engine") assert(level_engine_type.is_using, "Should be using engine") - assert(level_engine_type.type.id == typeid_of(engine_world), "Should be using engine") + assert(level_engine_type.type.id == typeid_of(Engine_World), "Should be using engine") entities_type := reflect.struct_field_by_name(level_map_type.value.id, "entities") entity_defs_type := reflect.struct_field_by_name(level_map_type.value.id, "entity_defs") @@ -104,7 +106,7 @@ engine_check_types :: proc($Game: typeid) assert(defs_engine.is_using, "Should be using") assert(entity_engine.type.id == typeid_of(engine_entity)) - assert(defs_engine.type.id == typeid_of(engine_entity_def)) + assert(defs_engine.type.id == typeid_of(Engine_Entity_Def)) } @@ -114,11 +116,16 @@ size_callback :: proc "c" (window: glfw.WindowHandle, width, height : i32) __e2d_interal.viewport_changed = true } +scroll_callback :: proc "c" (window : glfw.WindowHandle, x, y : f64) +{ + __e2d_interal.mouse_scroll = {x, y} +} + /* This will only be called once to initilize the engine initilize graphics library, glfw, callbacks */ -engine_init :: proc($GameType : typeid, state: ^engine_state, font_path : string="") +engine_init :: proc($GameType : typeid, state: ^Engine_State, font_path : string="") { engine_check_types(GameType) @@ -134,9 +141,6 @@ engine_init :: proc($GameType : typeid, state: ^engine_state, font_path : strin state.window = glfw.CreateWindow(state.width, state.height, state.title, nil, nil) - - //gl.DebugMessageControl(gl.DONT_CARE, gl.DONT_CARE, gl.DONT_CARE, 0, nil, gl.TRUE); - assert(state.window != nil) glfw.MakeContextCurrent(state.window) @@ -144,6 +148,7 @@ engine_init :: proc($GameType : typeid, state: ^engine_state, font_path : strin gl.load_up_to(4, 5, glfw.gl_set_proc_address) glfw.SetWindowSizeCallback(state.window, size_callback) + glfw.SetScrollCallback( state.window, scroll_callback) state.draw.cam = e2_draw.camera_init() @@ -152,7 +157,7 @@ engine_init :: proc($GameType : typeid, state: ^engine_state, font_path : strin state.draw.cam.height = display_h state.draw.cam.zoom = 15 state.draw.show_ui = true - + e2_draw.draw_create(&state.draw, &state.draw.cam, font_path) draw_configure_box2d(state) @@ -201,9 +206,10 @@ normalize_rect :: proc(rect : mu.Rect, size : i32) -> e2_draw.Rect } -update_frame :: proc(state: ^engine_state) +update_frame :: proc(state: ^Engine_State) { state.input.mouse_wheel = {} + __e2d_interal.mouse_scroll = {} glfw.PollEvents() keyboard_update(state) @@ -211,6 +217,9 @@ update_frame :: proc(state: ^engine_state) x, y:= glfw.GetCursorPos(state.window) mu.input_mouse_move(&state.mu_ctx, i32(x), i32(y)) + + wheel := __e2d_interal.mouse_scroll + mu.input_scroll(&state.mu_ctx, i32(wheel.x) * 10, i32(wheel.y) * -20) { for key in key_map { @@ -221,7 +230,7 @@ update_frame :: proc(state: ^engine_state) for key in mouse_map { if is_key_pressed(state, key) do mu.input_mouse_down(&state.mu_ctx, i32(x), i32(y), mouse_map[key]) - if is_key_released(state, key) do mu.input_mouse_up(&state.mu_ctx,i32(x), i32(y), mouse_map[key]) + if is_key_released(state, key) do mu.input_mouse_up( &state.mu_ctx,i32(x), i32(y), mouse_map[key]) } } @@ -236,21 +245,10 @@ update_frame :: proc(state: ^engine_state) state.width , state.height = glfw.GetFramebufferSize(state.window) gl.Viewport(0, 0, state.width, state.height) - /* - imgui_impl_opengl3.NewFrame() - imgui_impl_glfw.NewFrame() - im.NewFrame() - */ } -end_frame :: proc(state: ^engine_state) +end_frame :: proc(state: ^Engine_State) { - /* - im.Render() - imgui_impl_opengl3.RenderDrawData(im.GetDrawData()) - */ - - //Microui fb_x, fb_y := glfw.GetFramebufferSize(state.window) @@ -300,27 +298,24 @@ end_frame :: proc(state: ^engine_state) src_rect = normalize_rect(rect, mu.DEFAULT_ATLAS_WIDTH), dst_rect = e2_draw.Rect{f32(c.rect.x), f32(c.rect.y), f32(rect.w), f32(rect.h)}, }) - } } - } - } -cleanup :: proc(state: ^engine_state) +cleanup :: proc(state: ^Engine_State) { //imgui_impl_opengl3.Shutdown() //imgui_impl_glfw.Shutdown() } -engine_should_close :: proc(state : ^engine_state) -> b32 +engine_should_close :: proc(state : ^Engine_State) -> b32 { return glfw.WindowShouldClose(state.window) } -keyboard_update :: proc(state: ^engine_state) +keyboard_update :: proc(state: ^Engine_State) { state.input.mouse_prev = state.input.mouse @@ -341,20 +336,20 @@ keyboard_update :: proc(state: ^engine_state) } } -is_key_down :: #force_inline proc(state: ^engine_state, key : i32) -> bool{ +is_key_down :: #force_inline proc(state: ^Engine_State, key : i32) -> bool{ return state.input.curr[key] } -is_key_pressed :: #force_inline proc(state: ^engine_state, key : i32) -> bool{ +is_key_pressed :: #force_inline proc(state: ^Engine_State, key : i32) -> bool{ return state.input.curr[key] && !state.input.prev[key] } -is_key_released :: #force_inline proc(state: ^engine_state, key : i32) -> bool{ +is_key_released :: #force_inline proc(state: ^Engine_State, key : i32) -> bool{ return !state.input.curr[key] && state.input.prev[key] } -draw_flush :: proc(state: ^engine_state) +draw_flush :: proc(state: ^Engine_State) { d := &state.draw if __e2d_interal.viewport_changed @@ -366,7 +361,6 @@ draw_flush :: proc(state: ^engine_state) d.glyph.height = d.cam.height e2_glyph.glyph_init(&d.glyph, d.font_path) - } e2_draw.draw_flush(d, __e2d_interal.viewport_changed) diff --git a/entity.odin b/entity.odin index f69ad1d..2212687 100644 --- a/entity.odin +++ b/entity.odin @@ -3,9 +3,9 @@ package edit2d import b2 "vendor:box2d" import "core:fmt" -static_index :: i32 +Static_Index :: i32 -static_index_global :: struct +Static_Index_Global :: struct { index : i32, level : string, @@ -20,7 +20,7 @@ static_index_global :: struct */ -engine_entity_flags_enum :: enum u64 { +Engine_Entity_Flags_Enum :: enum u64 { POLYGON_IS_BOX, MULTI_BODIES, CHAIN, @@ -28,9 +28,9 @@ engine_entity_flags_enum :: enum u64 { MULTI_SHAPES, } -engine_entity_flags :: bit_set[engine_entity_flags_enum] +Engine_Entity_Flags :: bit_set[Engine_Entity_Flags_Enum] -engine_entity_def :: struct { +Engine_Entity_Def :: struct { body_def : b2.BodyDef, shape_def : b2.ShapeDef, shape_type : b2.ShapeType, @@ -44,9 +44,9 @@ engine_entity_def :: struct { vertices : [dynamic; b2.MAX_POLYGON_VERTICES]b2.Vec2, name_buf : [255]u8 `fmt:"-" cbor:"-"`, - entity_flags : engine_entity_flags, + entity_flags : Engine_Entity_Flags, - index : static_index, + index : Static_Index, //For chain bodies //It will replicate itself to the body count and connect themselves with rev_joints @@ -58,9 +58,9 @@ engine_entity_def :: struct { link_length_array : [dynamic]b2.Vec2, } -default_engine_entity_def :: proc() -> engine_entity_def +default_engine_entity_def :: proc() -> Engine_Entity_Def { - ret : engine_entity_def + ret : Engine_Entity_Def ret.body_def = b2.DefaultBodyDef() ret.shape_def = b2.DefaultShapeDef() ret.shape_type = .polygonShape @@ -85,7 +85,7 @@ default_engine_entity_def :: proc() -> engine_entity_def } -compare_engine_entity_def :: proc(a, b : engine_entity_def) -> bool +compare_engine_entity_def :: proc(a, b : Engine_Entity_Def) -> bool { ret := false @@ -122,14 +122,14 @@ engine_entity :: struct { bodies : [dynamic]b2.BodyId, shapes : [dynamic]b2.ShapeId, joints : [dynamic]b2.JointId, - entity_flags : engine_entity_flags, - index : ^static_index, + entity_flags : Engine_Entity_Flags, + index : ^Static_Index, joint_id : b2.JointId, } -engine_entity_single_body :: proc(def : ^engine_entity_def, world_id: b2.WorldId, index : i32) -> engine_entity +engine_entity_single_body :: proc(def : ^Engine_Entity_Def, world_id: b2.WorldId, index : i32) -> engine_entity { def := def @@ -139,7 +139,7 @@ engine_entity_single_body :: proc(def : ^engine_entity_def, world_id: b2.WorldId if def.index != 0 { - new_entity.index = new(static_index) + new_entity.index = new(Static_Index) new_entity.index^ = def.index } @@ -267,7 +267,7 @@ engine_entity_single_body :: proc(def : ^engine_entity_def, world_id: b2.WorldId } engine_create_chain_shape :: proc( - def : ^engine_entity_def, + def : ^Engine_Entity_Def, world_id : b2.WorldId, index : i32 ) -> engine_entity @@ -308,7 +308,7 @@ engine_create_chain_shape :: proc( engine_create_entity :: proc( - def : ^engine_entity_def, + def : ^Engine_Entity_Def, world_id : b2.WorldId, index : i32 ) -> engine_entity diff --git a/game.odin b/game.odin index 15138a2..6b3636f 100644 --- a/game.odin +++ b/game.odin @@ -9,6 +9,6 @@ game_mode :: enum engine_game :: struct { curr_level : string, - interface : interface_state, + interface : Interface_State, mode : game_mode, } diff --git a/glyph/glyph.odin b/glyph/glyph.odin index 54a9b71..54c24ec 100644 --- a/glyph/glyph.odin +++ b/glyph/glyph.odin @@ -101,6 +101,9 @@ glyph_init :: proc(glyph: ^GlyphState, font_path : string = "") if !os.exists(font_path) { fmt.eprintln("Font not provided or not exist using default font") + + /* TODO: use microui's font when no font's provided */ + font_data := #load("./mononoki-Regular.ttf", []byte) stbtt.InitFont(&glyph.font_info, &font_data[0], 0) }else diff --git a/handle_input.odin b/handle_input.odin index 2b24696..2bcf059 100644 --- a/handle_input.odin +++ b/handle_input.odin @@ -2,7 +2,6 @@ package edit2d import b2 "vendor:box2d" //import im "shared:odin-imgui" -import "core:fmt" import "vendor:glfw" import "base:runtime" import draw "./draw" @@ -46,7 +45,7 @@ import draw "./draw" */ handle_entity_mode :: proc( $E : typeid, - state : ^engine_state, + state : ^Engine_State, game_data : ^$G, ) -> bool { @@ -107,7 +106,6 @@ handle_entity_mode :: proc( ret = true } else{ - //Can only do these actions if a entity is selected if interface.selected_entity != -1 && len(level.entity_defs) > 0 { @@ -150,7 +148,6 @@ handle_entity_mode :: proc( def.scale += f32(state.input.mouse_prev.y / 5) ret = true } - } @@ -162,7 +159,7 @@ handle_entity_mode :: proc( handle_input :: proc( $E : typeid, - state : ^engine_state, + state : ^Engine_State, game_data : ^$G, ) -> bool { @@ -178,13 +175,13 @@ handle_input :: proc( if is_key_pressed(state, glfw.KEY_E) { interface := &game.interface - if interface.edit_mode == max(EditMode) + if interface.edit_mode == max(Edit_Mode) { - interface.edit_mode = min(EditMode) + interface.edit_mode = min(Edit_Mode) }else { new_val := int(interface.edit_mode) + 1 - interface.edit_mode = EditMode(new_val) + interface.edit_mode = Edit_Mode(new_val) } } diff --git a/interface.odin b/interface.odin index 1c8f855..adba3b5 100644 --- a/interface.odin +++ b/interface.odin @@ -21,7 +21,7 @@ import b2 "vendor:box2d" */ -EditMode :: enum +Edit_Mode :: enum { ENTITY, VERTICES, @@ -30,23 +30,23 @@ EditMode :: enum JOINT, } -interface_state :: struct +Interface_State :: struct { - entity_defs : [dynamic]^engine_entity_def, + entity_defs : [dynamic]^Engine_Entity_Def, entities : [dynamic]^engine_entity, selected_entity : i32, - world : ^engine_world, - state : ^engine_state, + world : ^Engine_World, + state : ^Engine_State, vertex_index : ^i32, chain_index : ^i32, - edit_mode : EditMode, + edit_mode : Edit_Mode, curr_joint_index : i32, curr_joint_type : b2.JointType, - curr_static_index : static_index_global, + curr_static_index : Static_Index_Global, } @@ -94,7 +94,7 @@ mui_text_height :: proc(font: mu.Font) -> i32 } -interface_get_default :: proc(interface: ^interface_state) +interface_get_default :: proc(interface: ^Interface_State) { interface.selected_entity = 0 interface.vertex_index = new(i32) @@ -126,11 +126,11 @@ interface_draw_options :: proc(state: ^engine_state) } */ -mu_interface_game_mode :: proc(state: ^engine_state, interface: ^interface_state) +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 EditMode + 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 @@ -139,7 +139,7 @@ mu_interface_game_mode :: proc(state: ^engine_state, interface: ^interface_state } } -mu_interface_draw_options :: proc(state: ^engine_state) +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 @@ -169,7 +169,7 @@ mu_interface_draw_options :: proc(state: ^engine_state) } -interface_all :: proc($E: typeid, interface: ^interface_state, game_data : $G) -> bool +interface_all :: proc($E: typeid, interface: ^Interface_State, game_data : $G) -> bool { ret := false if interface.selected_entity <0 diff --git a/interface_entity.odin b/interface_entity.odin index ad5126e..f6991fa 100644 --- a/interface_entity.odin +++ b/interface_entity.odin @@ -62,7 +62,7 @@ interface_body_def_editor :: proc(def: ^engine_entity_def) } */ -mu_interface_body_def_editor :: proc(interface: ^interface_state, def : ^engine_entity_def) +mu_interface_body_def_editor :: proc(interface: ^Interface_State, def : ^Engine_Entity_Def) { ctx := &interface.state.mu_ctx @@ -170,7 +170,7 @@ interface_edit_static_index :: proc(interface:^interface_state, def: ^engine_ent } */ -mu_interface_edit_static_index :: proc(interface: ^interface_state, def : ^engine_entity_def) -> bool +mu_interface_edit_static_index :: proc(interface: ^Interface_State, def : ^Engine_Entity_Def) -> bool { curr_index := &interface.curr_static_index entity := interface.entities[interface.selected_entity] @@ -192,8 +192,8 @@ mu_interface_edit_static_index :: proc(interface: ^interface_state, def : ^engin } mu_interface_shape_def_editor :: proc( - state : ^engine_state, - def : ^engine_entity_def) -> bool + state : ^Engine_State, + def : ^Engine_Entity_Def) -> bool { shape_def := &def.shape_def @@ -371,7 +371,7 @@ interface_shape_def_editor :: proc(def: ^engine_entity_def) -> bool } */ -interface_entity :: proc(interface: ^interface_state) -> bool +interface_entity :: proc(interface: ^Interface_State) -> bool { entity_selected := (interface.selected_entity != -1) && len(interface.entity_defs) > 0 @@ -386,7 +386,7 @@ interface_entity :: proc(interface: ^interface_state) -> bool //interface.edit_mode = .ENTITY //Flags - for flag in engine_entity_flags_enum + for flag in Engine_Entity_Flags_Enum { contains := flag in def.entity_flags if .CHANGE in mu.checkbox(ctx, fmt.tprint(flag), &contains) diff --git a/interface_joints.odin b/interface_joints.odin index b2948bd..9179099 100644 --- a/interface_joints.odin +++ b/interface_joints.odin @@ -18,21 +18,21 @@ import draw "./draw" joint_common :: struct { pivot : [2]f32, - entity_a, entity_b : static_index, + entity_a, entity_b : Static_Index, bodyIdA, bodyIdB : b2.BodyId, } revolt_joint_def :: struct { pivot : [2]f32, - entity_a, entity_b : static_index, + entity_a, entity_b : Static_Index, using def : b2.RevoluteJointDef, } distance_joint_def :: struct { pivot : [2]f32, - entity_a, entity_b : static_index, + entity_a, entity_b : Static_Index, using def : b2.DistanceJointDef, } diff --git a/level.odin b/level.odin index 1830528..a7b4e56 100644 --- a/level.odin +++ b/level.odin @@ -18,13 +18,13 @@ import draw "./draw" A Typical level code */ -engine_world :: struct { +Engine_World :: struct { world_id : b2.WorldId, //This in engine code? - static_indexes : map[static_index]int `cbor:"-"`, - relations : map[^static_index][dynamic]static_index_global `cbor:"-"`, - relations_serializeable : map[ static_index][dynamic]static_index_global, + static_indexes : map[Static_Index]int `cbor:"-"`, + relations : map[^Static_Index][dynamic]Static_Index_Global `cbor:"-"`, + relations_serializeable : map[ Static_Index][dynamic]Static_Index_Global, /* @@ -67,7 +67,7 @@ cbor_flags : cbor.Encoder_Flags : level_load_from_files :: proc( $G, $L, $E: typeid, game: ^G, - state: ^engine_state + state: ^Engine_State ) { files, err := os.read_all_directory_by_path("levels", context.allocator) @@ -103,11 +103,11 @@ level_init_from_path :: proc( $T, $E: typeid, level_data : ^T, path : string, - state: ^engine_state, + state: ^Engine_State, ) -> (ret : bool) { - level := cast(^engine_world)level_data + level := cast(^Engine_World)level_data if os.is_file(path) { @@ -118,7 +118,7 @@ level_init_from_path :: proc( //? level.relations = {} - level.relations = make(map[^static_index][dynamic]static_index_global) + level.relations = make(map[^Static_Index][dynamic]Static_Index_Global) if len(data) > 0 { @@ -261,10 +261,10 @@ level_reload :: proc($T: typeid, $E: typeid, level: ^T) If both hash is same the exits */ -level_save_to_file :: proc(level_data: ^$T, state: ^engine_state) +level_save_to_file :: proc(level_data: ^$T, state: ^Engine_State) { - level := cast(^engine_world)level_data + level := cast(^Engine_World)level_data level_path := fmt.tprintf("levels/%s.cbor", level.name) level.cam = state.draw.cam @@ -370,11 +370,11 @@ level_save_to_file :: proc(level_data: ^$T, state: ^engine_state) /* The engine assumes that it has attribute entities */ -game_to_engine_entities :: proc($Game: typeid, game_data: ^Game, state: ^engine_state) +game_to_engine_entities :: proc($Game: typeid, game_data: ^Game, state: ^Engine_State) { level := &game_data.levels[game_data.curr_level] - interface : ^interface_state = &game_data.interface + interface : ^Interface_State = &game_data.interface clear(&interface.entities) clear(&interface.entity_defs)