Change Naming Convention, add scroll to microui

This commit is contained in:
SamratGhale
2026-03-28 13:42:24 +05:45
parent a74b46cd64
commit c1b64e9066
12 changed files with 90 additions and 97 deletions
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
-1
View File
@@ -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)
+30 -36
View File
@@ -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)
+16 -16
View File
@@ -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
+1 -1
View File
@@ -9,6 +9,6 @@ game_mode :: enum
engine_game :: struct {
curr_level : string,
interface : interface_state,
interface : Interface_State,
mode : game_mode,
}
+3
View File
@@ -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
+5 -8
View File
@@ -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)
}
}
+12 -12
View File
@@ -21,7 +21,7 @@ import b2 "vendor:box2d"
*/
Edit_Mode :: enum
{
{
ENTITY,
VERTICES,
OVERVIEW,
@@ -30,23 +30,23 @@ EditMode :: enum
}
Interface_State :: struct
{
{
entity_defs : [dynamic]^Engine_Entity_Def,
entities : [dynamic]^engine_entity,
entities : [dynamic]^engine_entity,
selected_entity : i32,
world : ^Engine_World,
state : ^engine_state,
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,
}
}
@@ -94,7 +94,7 @@ mui_text_height :: proc(font: mu.Font) -> i32
interface_get_default :: proc(interface: ^Interface_State)
{
{
interface.selected_entity = 0
interface.vertex_index = new(i32)
interface.vertex_index^ = 0
@@ -126,11 +126,11 @@ interface_draw_options :: proc(state: ^engine_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 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)
{
{
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
{
{
ret := false
if interface.selected_entity <0
{
+6 -6
View File
@@ -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)
+3 -3
View File
@@ -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,
}
+12 -12
View File
@@ -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)