Compare commits

...

6 Commits

Author SHA1 Message Date
SamratGhale 06664f9f67 Remove pointer index, fix memoery leak in glyph 2026-03-29 06:34:00 +05:45
SamratGhale c1b64e9066 Change Naming Convention, add scroll to microui 2026-03-28 13:42:24 +05:45
SamratGhale a74b46cd64 Fix double handle_input call 2026-03-28 06:57:40 +05:45
SamratGhale 41f679b32a Use OverlapShape instead of OvelapAABB 2026-03-28 06:48:15 +05:45
SamratGhale 3eb0c2555f Fix rendering current entity 2026-03-28 06:42:23 +05:45
SamratGhale be8c936e33 Fix position of new entities 2026-03-27 22:08:34 +05:45
12 changed files with 181 additions and 163 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ It's created using folloing tools
1. Odin programming language 1. Odin programming language
2. GLFW for input handling and graphics 2. GLFW for input handling and graphics
3. Dear ImGui for user interfaces 3. Microui for user interfaces
4. Box2d 4. Box2d
## Current Progress ## Current Progress
+1 -1
View File
@@ -174,7 +174,7 @@ DrawPointFcn :: proc "c" (
} }
//After initilizing draw //After initilizing draw
draw_configure_box2d :: proc(state: ^engine_state) draw_configure_box2d :: proc(state: ^Engine_State)
{ {
debug_draw := &state.debug_draw 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.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, nil)
} }
gl.Disable(gl.BLEND) gl.Disable(gl.BLEND)
gl.UseProgram(0) gl.UseProgram(0)
+60 -45
View File
@@ -22,12 +22,17 @@ import mu "vendor:microui"
//Only to be used inside the libarary //Only to be used inside the libarary
__e2d_interal : struct __e2d_interal : struct
{ {
viewport_changed : bool viewport_changed : bool,
mouse_scroll : [2]f64,
} }
/*
This engine is meant to be used by the game
All the stuffs internal should be stored in __e2d_internal
*/
engine_state :: struct Engine_State :: struct
{ {
window : glfw.WindowHandle, window : glfw.WindowHandle,
debug_draw : b2.DebugDraw, debug_draw : b2.DebugDraw,
@@ -39,21 +44,21 @@ engine_state :: struct
//Must be set before calling ion_init //Must be set before calling ion_init
width, height : i32, width, height : i32,
title : cstring, title : cstring,
time : f32,
tex_line : u32,
drop_callback : glfw.DropProc, drop_callback : glfw.DropProc,
input : input_state, input : Input_State,
mu_ctx : mu.Context, mu_ctx : mu.Context,
/* The opengl texture id created using mu.default_atlas_alpha */
mu_tex : u32, mu_tex : u32,
} }
MAX_KEYS :: 512 MAX_KEYS :: 512
input_state :: struct Input_State :: struct
{ {
mouse_wheel : [2]f64,
mouse : [2]f64, mouse : [2]f64,
mouse_prev : [2]f64, mouse_prev : [2]f64,
@@ -86,7 +91,7 @@ engine_check_types :: proc($Game: typeid)
level_engine_type := reflect.struct_field_by_name(level_map_type.value.id, "engine") 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.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") 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") entity_defs_type := reflect.struct_field_by_name(level_map_type.value.id, "entity_defs")
@@ -103,8 +108,8 @@ engine_check_types :: proc($Game: typeid)
assert(entity_engine.is_using, "Should be using") assert(entity_engine.is_using, "Should be using")
assert(defs_engine.is_using, "Should be using") assert(defs_engine.is_using, "Should be using")
assert(entity_engine.type.id == typeid_of(engine_entity)) 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 +119,16 @@ size_callback :: proc "c" (window: glfw.WindowHandle, width, height : i32)
__e2d_interal.viewport_changed = true __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 This will only be called once to initilize the engine
initilize graphics library, glfw, callbacks 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) engine_check_types(GameType)
@@ -134,9 +144,6 @@ engine_init :: proc($GameType : typeid, state: ^engine_state, font_path : strin
state.window = glfw.CreateWindow(state.width, state.height, state.title, nil, nil) 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) assert(state.window != nil)
glfw.MakeContextCurrent(state.window) glfw.MakeContextCurrent(state.window)
@@ -144,6 +151,7 @@ engine_init :: proc($GameType : typeid, state: ^engine_state, font_path : strin
gl.load_up_to(4, 5, glfw.gl_set_proc_address) gl.load_up_to(4, 5, glfw.gl_set_proc_address)
glfw.SetWindowSizeCallback(state.window, size_callback) glfw.SetWindowSizeCallback(state.window, size_callback)
glfw.SetScrollCallback( state.window, scroll_callback)
state.draw.cam = e2_draw.camera_init() state.draw.cam = e2_draw.camera_init()
@@ -157,13 +165,23 @@ engine_init :: proc($GameType : typeid, state: ^engine_state, font_path : strin
draw_configure_box2d(state) draw_configure_box2d(state)
cbor.tag_register_type({ cbor.tag_register_type({
marshal = proc(_: ^cbor.Tag_Implementation, e: cbor.Encoder, v: any) -> cbor.Marshal_Error {
marshal = proc(
_: ^cbor.Tag_Implementation,
e: cbor.Encoder, v: any) -> cbor.Marshal_Error
{
cbor._encode_u8(e.writer, 201, .Tag) or_return cbor._encode_u8(e.writer, 201, .Tag) or_return
return nil; return nil;
}, },
unmarshal = proc(_: ^cbor.Tag_Implementation, d: cbor.Decoder, _: cbor.Tag_Number, v: any) -> (cbor.Unmarshal_Error) {
unmarshal = proc(
_: ^cbor.Tag_Implementation,
d: cbor.Decoder, _: cbor.Tag_Number,
v: any) -> (cbor.Unmarshal_Error)
{
return nil return nil
}, },
}, 201, rawptr) }, 201, rawptr)
@@ -201,9 +219,9 @@ 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() glfw.PollEvents()
keyboard_update(state) keyboard_update(state)
@@ -211,6 +229,9 @@ update_frame :: proc(state: ^engine_state)
x, y:= glfw.GetCursorPos(state.window) x, y:= glfw.GetCursorPos(state.window)
mu.input_mouse_move(&state.mu_ctx, i32(x), i32(y)) 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 for key in key_map
{ {
@@ -221,7 +242,7 @@ update_frame :: proc(state: ^engine_state)
for key in mouse_map 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_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 +257,10 @@ update_frame :: proc(state: ^engine_state)
state.width , state.height = glfw.GetFramebufferSize(state.window) state.width , state.height = glfw.GetFramebufferSize(state.window)
gl.Viewport(0, 0, state.width, state.height) 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 //Microui
fb_x, fb_y := glfw.GetFramebufferSize(state.window) fb_x, fb_y := glfw.GetFramebufferSize(state.window)
@@ -260,6 +270,7 @@ end_frame :: proc(state: ^engine_state)
cmd: ^mu.Command cmd: ^mu.Command
draw := &state.draw draw := &state.draw
for mu.next_command(&state.mu_ctx, &cmd) for mu.next_command(&state.mu_ctx, &cmd)
{ {
#partial switch c in cmd.variant{ #partial switch c in cmd.variant{
@@ -300,29 +311,24 @@ end_frame :: proc(state: ^engine_state)
src_rect = normalize_rect(rect, mu.DEFAULT_ATLAS_WIDTH), 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)}, dst_rect = e2_draw.Rect{f32(c.rect.x), f32(c.rect.y), f32(rect.w), f32(rect.h)},
}) })
} }
} }
} }
glfw.SwapBuffers(state.window)
__e2d_interal.viewport_changed = false
} }
cleanup :: proc(state: ^engine_state) cleanup :: proc(state: ^Engine_State)
{ {
//imgui_impl_opengl3.Shutdown() //imgui_impl_opengl3.Shutdown()
//imgui_impl_glfw.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) return glfw.WindowShouldClose(state.window)
} }
keyboard_update :: proc(state: ^engine_state) keyboard_update :: proc(state: ^Engine_State)
{ {
state.input.mouse_prev = state.input.mouse state.input.mouse_prev = state.input.mouse
@@ -343,32 +349,41 @@ 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] 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] 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] return !state.input.curr[key] && state.input.prev[key]
} }
draw_flush :: proc(d: ^e2_draw.Draw) draw_flush :: proc(state: ^Engine_State)
{ {
d := &state.draw
if __e2d_interal.viewport_changed if __e2d_interal.viewport_changed
{ {
d.glyph.atlas_width = d.cam.width d.glyph.atlas_width = d.cam.width
d.glyph.atlas_height = d.cam.height d.glyph.atlas_height = d.cam.height
d.glyph.font_size_pt = 9 d.glyph.font_size_pt = 12
d.glyph.width = d.cam.width d.glyph.width = d.cam.width
d.glyph.height = d.cam.height d.glyph.height = d.cam.height
e2_glyph.glyph_init(&d.glyph, d.font_path) width, height := glfw.GetFramebufferSize(state.window)
state.width = width
state.height = height
e2_glyph.glyph_init(&d.glyph, d.font_path)
} }
e2_draw.draw_flush(d, __e2d_interal.viewport_changed) e2_draw.draw_flush(d, __e2d_interal.viewport_changed)
glfw.SwapBuffers(state.window)
__e2d_interal.viewport_changed = false
} }
+22 -25
View File
@@ -3,9 +3,9 @@ package edit2d
import b2 "vendor:box2d" import b2 "vendor:box2d"
import "core:fmt" import "core:fmt"
static_index :: i32 Static_Index :: i32
static_index_global :: struct Static_Index_Global :: struct
{ {
index : i32, index : i32,
level : string, 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, POLYGON_IS_BOX,
MULTI_BODIES, MULTI_BODIES,
CHAIN, CHAIN,
@@ -28,9 +28,9 @@ engine_entity_flags_enum :: enum u64 {
MULTI_SHAPES, 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, body_def : b2.BodyDef,
shape_def : b2.ShapeDef, shape_def : b2.ShapeDef,
shape_type : b2.ShapeType, shape_type : b2.ShapeType,
@@ -44,9 +44,9 @@ engine_entity_def :: struct {
vertices : [dynamic; b2.MAX_POLYGON_VERTICES]b2.Vec2, vertices : [dynamic; b2.MAX_POLYGON_VERTICES]b2.Vec2,
name_buf : [255]u8 `fmt:"-" cbor:"-"`, 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 //For chain bodies
//It will replicate itself to the body count and connect themselves with rev_joints //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, 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.body_def = b2.DefaultBodyDef()
ret.shape_def = b2.DefaultShapeDef() ret.shape_def = b2.DefaultShapeDef()
ret.shape_type = .polygonShape 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 ret := false
@@ -102,14 +102,11 @@ compare_engine_entity_def :: proc(a, b : engine_entity_def) -> bool
//ret &= a.vertices[:] == b.vertices[:] //ret &= a.vertices[:] == b.vertices[:]
ret &= a.name_buf == b.name_buf ret &= a.name_buf == b.name_buf
if a.entity_flags != b.entity_flags{
fmt.println("Hello world")
}
ret &= a.entity_flags == b.entity_flags ret &= a.entity_flags == b.entity_flags
ret &= a.index == b.index ret &= a.index == b.index
ret &= a.body_count == b.body_count ret &= a.body_count == b.body_count
ret &= a.rev_joint == b.rev_joint ret &= a.rev_joint == b.rev_joint
//ret &= a.link_length[:] == b.link_length[:] //ret &= a.link_length[:] == b.link_length[:]
return ret return ret
@@ -117,7 +114,7 @@ compare_engine_entity_def :: proc(a, b : engine_entity_def) -> bool
engine_entity :: struct { Engine_Entity :: struct {
body_id : b2.BodyId, body_id : b2.BodyId,
shape_id : b2.ShapeId, shape_id : b2.ShapeId,
@@ -125,24 +122,24 @@ engine_entity :: struct {
bodies : [dynamic]b2.BodyId, bodies : [dynamic]b2.BodyId,
shapes : [dynamic]b2.ShapeId, shapes : [dynamic]b2.ShapeId,
joints : [dynamic]b2.JointId, joints : [dynamic]b2.JointId,
entity_flags : engine_entity_flags, entity_flags : Engine_Entity_Flags,
index : ^static_index, index : ^Static_Index,
joint_id : b2.JointId, 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 def := def
new_entity : engine_entity new_entity : Engine_Entity
if def.index != 0 if def.index != 0
{ {
new_entity.index = new(static_index) new_entity.index = new(Static_Index)
new_entity.index^ = def.index new_entity.index^ = def.index
} }
@@ -270,10 +267,10 @@ engine_entity_single_body :: proc(def : ^engine_entity_def, world_id: b2.WorldId
} }
engine_create_chain_shape :: proc( engine_create_chain_shape :: proc(
def : ^engine_entity_def, def : ^Engine_Entity_Def,
world_id : b2.WorldId, world_id : b2.WorldId,
index : i32 index : i32
) -> engine_entity ) -> Engine_Entity
{ {
joint_def := def.rev_joint joint_def := def.rev_joint
orig_pos := def.body_def.position orig_pos := def.body_def.position
@@ -311,10 +308,10 @@ engine_create_chain_shape :: proc(
engine_create_entity :: proc( engine_create_entity :: proc(
def : ^engine_entity_def, def : ^Engine_Entity_Def,
world_id : b2.WorldId, world_id : b2.WorldId,
index : i32 index : i32
) -> engine_entity ) -> Engine_Entity
{ {
if .CHAIN not_in def.entity_flags if .CHAIN not_in def.entity_flags
+1 -1
View File
@@ -9,6 +9,6 @@ game_mode :: enum
engine_game :: struct { engine_game :: struct {
curr_level : string, curr_level : string,
interface : interface_state, interface : Interface_State,
mode : game_mode, mode : game_mode,
} }
+5 -2
View File
@@ -101,6 +101,9 @@ glyph_init :: proc(glyph: ^GlyphState, font_path : string = "")
if !os.exists(font_path) if !os.exists(font_path)
{ {
fmt.eprintln("Font not provided or not exist using default font") 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) font_data := #load("./mononoki-Regular.ttf", []byte)
stbtt.InitFont(&glyph.font_info, &font_data[0], 0) stbtt.InitFont(&glyph.font_info, &font_data[0], 0)
}else }else
@@ -123,7 +126,7 @@ glyph_draw_font :: proc(glyph_state: ^GlyphState, text: string, pos : [2]f32, co
text_color: [4]f32 = {f32( color.r)/ 255.0 ,f32(color.g)/255.0, f32(color.b)/255.0, f32(color.a)/255.0} text_color: [4]f32 = {f32( color.r)/ 255.0 ,f32(color.g)/255.0, f32(color.b)/255.0, f32(color.a)/255.0}
glyph_state.rect_buffer = make([dynamic]GlyphRectInstance, 0, 1000) //glyph_state.rect_buffer = make([dynamic]GlyphRectInstance, 0, 1000)
{ {
//put every glyph in text into rect_buffer //put every glyph in text into rect_buffer
@@ -144,7 +147,6 @@ glyph_draw_font :: proc(glyph_state: ^GlyphState, text: string, pos : [2]f32, co
prev_codepoint: rune = 0 prev_codepoint: rune = 0
delete(glyph_state.rect_buffer)
glyph_state.rect_buffer = make([dynamic]GlyphRectInstance, 0, 1000) glyph_state.rect_buffer = make([dynamic]GlyphRectInstance, 0, 1000)
glyph_state.curr = pos glyph_state.curr = pos
glyph_state.curr.y += math.round(baseline) glyph_state.curr.y += math.round(baseline)
@@ -326,4 +328,5 @@ glyph_draw_font :: proc(glyph_state: ^GlyphState, text: string, pos : [2]f32, co
gl.InvalidateBufferData(glyph_state.rect_instances_vbo) gl.InvalidateBufferData(glyph_state.rect_instances_vbo)
} }
delete(glyph_state.rect_buffer)
} }
+29 -13
View File
@@ -45,7 +45,7 @@ import draw "./draw"
*/ */
handle_entity_mode :: proc( handle_entity_mode :: proc(
$E : typeid, $E : typeid,
state : ^engine_state, state : ^Engine_State,
game_data : ^$G, game_data : ^$G,
) -> bool ) -> bool
{ {
@@ -70,25 +70,42 @@ handle_entity_mode :: proc(
input := &state.input input := &state.input
mpos := draw.camera_convert_screen_to_world(&state.draw.cam, input.mouse) 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 //Setlect entity
if is_key_pressed(state, glfw.MOUSE_BUTTON_LEFT) if is_key_pressed(state, glfw.MOUSE_BUTTON_LEFT)
{ {
aabb : b2.AABB = {mpos, mpos + 1} aabb : b2.AABB = {mpos, mpos + 1}
r := b2.World_OverlapAABB(level.engine.world_id, aabb, b2.DefaultQueryFilter(), click_query_filter, game)
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) else if is_key_pressed(state, glfw.MOUSE_BUTTON_RIGHT)
{ {
new_def := E { new_def := E {
engine = default_engine_entity_def(), engine = default_engine_entity_def(),
type = .NPC 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)) interface.selected_entity = i32(len(level.entity_defs))
append(&level.entity_defs, new_def) append(&level.entity_defs, new_def)
ret = true ret = true
} }
else{ else{
//Can only do these actions if a entity is selected //Can only do these actions if a entity is selected
if interface.selected_entity != -1 && len(level.entity_defs) > 0 if interface.selected_entity != -1 && len(level.entity_defs) > 0
{ {
@@ -126,12 +143,11 @@ handle_entity_mode :: proc(
def.body_def.position = mpos def.body_def.position = mpos
ret = true ret = true
} }
else if state.input.mouse_wheel.y != 0 else if __e2d_interal.mouse_scroll.y != 0
{ {
def.scale += f32(state.input.mouse_prev.y / 5) def.scale += f32( __e2d_interal.mouse_scroll.y / 5)
ret = true ret = true
} }
} }
@@ -143,7 +159,7 @@ handle_entity_mode :: proc(
handle_input :: proc( handle_input :: proc(
$E : typeid, $E : typeid,
state : ^engine_state, state : ^Engine_State,
game_data : ^$G, game_data : ^$G,
) -> bool ) -> bool
{ {
@@ -159,13 +175,13 @@ handle_input :: proc(
if is_key_pressed(state, glfw.KEY_E) if is_key_pressed(state, glfw.KEY_E)
{ {
interface := &game.interface 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 }else
{ {
new_val := int(interface.edit_mode) + 1 new_val := int(interface.edit_mode) + 1
interface.edit_mode = EditMode(new_val) interface.edit_mode = Edit_Mode(new_val)
} }
} }
@@ -181,17 +197,17 @@ handle_input :: proc(
ret := false
#partial switch game.interface.edit_mode #partial switch game.interface.edit_mode
{ {
case .ENTITY : handle_entity_mode(E, state, game_data) case .ENTITY : ret = handle_entity_mode(E, state, game_data)
// case .VERTICES : interface_handle_vertices_mode(state, game_data) // case .VERTICES : interface_handle_vertices_mode(state, game_data)
// case .OVERVIEW : interface_handle_overview_mode(state, game_data) // case .OVERVIEW : interface_handle_overview_mode(state, game_data)
// case .CHAIN : interface_handle_chain_mode(state, game_data) // case .CHAIN : interface_handle_chain_mode(state, game_data)
// case .JOINT : interface_handle_joint_mode(state, game_data) // case .JOINT : interface_handle_joint_mode(state, game_data)
} }
return false return ret
} }
+28 -50
View File
@@ -21,7 +21,7 @@ import b2 "vendor:box2d"
*/ */
Edit_Mode :: enum Edit_Mode :: enum
{ {
ENTITY, ENTITY,
VERTICES, VERTICES,
OVERVIEW, OVERVIEW,
@@ -30,23 +30,23 @@ EditMode :: enum
} }
Interface_State :: struct Interface_State :: struct
{ {
entity_defs : [dynamic]^Engine_Entity_Def, entity_defs : [dynamic]^Engine_Entity_Def,
entities : [dynamic]^engine_entity, entities : [dynamic]^Engine_Entity,
selected_entity : i32, selected_entity : i32,
world : ^Engine_World, world : ^Engine_World,
state : ^engine_state, state : ^Engine_State,
vertex_index : i32, vertex_index : i32,
chain_index : ^i32, chain_index : i32,
edit_mode : Edit_Mode, edit_mode : Edit_Mode,
curr_joint_index : i32, curr_joint_index : i32,
curr_joint_type : b2.JointType, curr_joint_type : b2.JointType,
curr_static_index : Static_Index_Global, curr_static_index : Static_Index_Global,
} }
@@ -94,43 +94,19 @@ 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.selected_entity = 0
interface.vertex_index = 0 interface.vertex_index = 0
interface.vertex_index^ = 0 interface.chain_index = 0
interface.chain_index = new(i32) }
interface.chain_index^ = 0
}
mu_interface_game_mode :: proc(state: ^Engine_State, interface: ^Interface_State) mu_interface_game_mode :: proc(state: ^Engine_State, interface: ^Interface_State)
interface_draw_options :: proc(state: ^engine_state) {
{
width :i32 = 250 width :i32 = 250
if mu.begin_window(&state.mu_ctx, "Edit Mode", {state.width - width, 0, width, 170})
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 for type in Edit_Mode
{ {
b : bool = interface.edit_mode == type b : bool = interface.edit_mode == type
if .CHANGE in mu.checkbox(&state.mu_ctx, fmt.tprint(type), &b) do interface.edit_mode = type if .CHANGE in mu.checkbox(&state.mu_ctx, fmt.tprint(type), &b) do interface.edit_mode = type
} }
@@ -139,9 +115,9 @@ 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", {0, 150, 200, 400}){ if mu.begin_window(&state.mu_ctx, "Options", {0, 150, 200, 400}){
debug_draw := &state.debug_draw debug_draw := &state.debug_draw
mu.label(&state.mu_ctx, "Zoom") mu.label(&state.mu_ctx, "Zoom")
mu.slider(&state.mu_ctx, &state.draw.cam.zoom,0, 100) mu.slider(&state.mu_ctx, &state.draw.cam.zoom,0, 100)
@@ -169,7 +145,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 ret := false
if interface.selected_entity <0 if interface.selected_entity <0
{ {
@@ -180,25 +156,27 @@ interface_all :: proc(interface: ^interface_state) -> bool
mu.begin(&state.mu_ctx) mu.begin(&state.mu_ctx)
mu_interface_draw_options(interface.state) mu_interface_draw_options(interface.state)
mu_interface_draw_options(interface.state)
mu_interface_game_mode(state, interface) mu_interface_game_mode(state, interface)
width : i32 = 250 width : i32 = 250
{ if mu.begin_window(&state.mu_ctx, "B2d Interface", {state.width - width, 170, width, 450}, { .NO_TITLE})
{
{ if interface.edit_mode == .ENTITY
{
if .ACTIVE in mu.header(&state.mu_ctx, "Entity", {.AUTO_SIZE}) if .ACTIVE in mu.header(&state.mu_ctx, "Entity", {.AUTO_SIZE})
} {
if interface_entity(interface) do ret = true
}
}
mu.end_window(&state.mu_ctx) mu.end_window(&state.mu_ctx)
} }
//if interface_joints(interface) do ret = true //if interface_joints(interface) do ret = true
mu.end(&state.mu_ctx) mu.end(&state.mu_ctx)
mu.end(&state.mu_ctx)
return ret return ret
return ret
} }
+18 -8
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 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 curr_index := &interface.curr_static_index
entity := interface.entities[interface.selected_entity] 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( mu_interface_shape_def_editor :: proc(
state : ^engine_state, state : ^Engine_State,
def : ^engine_entity_def) -> bool def : ^Engine_Entity_Def) -> bool
{ {
shape_def := &def.shape_def shape_def := &def.shape_def
@@ -371,10 +371,12 @@ 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 entity_selected := (interface.selected_entity != -1) && len(interface.entity_defs) > 0
ctx := &interface.state.mu_ctx
if entity_selected if entity_selected
{ {
def := interface.entity_defs[interface.selected_entity] def := interface.entity_defs[interface.selected_entity]
@@ -384,10 +386,18 @@ interface_entity :: proc(interface: ^interface_state) -> bool
//interface.edit_mode = .ENTITY //interface.edit_mode = .ENTITY
//Flags //Flags
for flag in engine_entity_flags_enum for flag in Engine_Entity_Flags_Enum
{ {
//contains := flag in def.entity_flags contains := flag in def.entity_flags
//if mu.checkbox(fmt.tprint(flag), &contains) do def.entity_flags ~= {flag} if .CHANGE in mu.checkbox(ctx, fmt.tprint(flag), &contains)
{
def.entity_flags ~= {flag}
}
}
//Draw circle on 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})
} }
+3 -3
View File
@@ -18,21 +18,21 @@ import draw "./draw"
joint_common :: struct joint_common :: struct
{ {
pivot : [2]f32, pivot : [2]f32,
entity_a, entity_b : static_index, entity_a, entity_b : Static_Index,
bodyIdA, bodyIdB : b2.BodyId, bodyIdA, bodyIdB : b2.BodyId,
} }
revolt_joint_def :: struct revolt_joint_def :: struct
{ {
pivot : [2]f32, pivot : [2]f32,
entity_a, entity_b : static_index, entity_a, entity_b : Static_Index,
using def : b2.RevoluteJointDef, using def : b2.RevoluteJointDef,
} }
distance_joint_def :: struct distance_joint_def :: struct
{ {
pivot : [2]f32, pivot : [2]f32,
entity_a, entity_b : static_index, entity_a, entity_b : Static_Index,
using def : b2.DistanceJointDef, using def : b2.DistanceJointDef,
} }
+12 -12
View File
@@ -18,13 +18,13 @@ import draw "./draw"
A Typical level code A Typical level code
*/ */
engine_world :: struct { Engine_World :: struct {
world_id : b2.WorldId, world_id : b2.WorldId,
//This in engine code? //This in engine code?
static_indexes : map[static_index]int `cbor:"-"`, static_indexes : map[Static_Index]int `cbor:"-"`,
relations : map[^static_index][dynamic]static_index_global `cbor:"-"`, relations : map[^Static_Index][dynamic]Static_Index_Global `cbor:"-"`,
relations_serializeable : map[ static_index][dynamic]static_index_global, relations_serializeable : map[ Static_Index][dynamic]Static_Index_Global,
/* /*
@@ -67,7 +67,7 @@ cbor_flags : cbor.Encoder_Flags :
level_load_from_files :: proc( level_load_from_files :: proc(
$G, $L, $E: typeid, $G, $L, $E: typeid,
game: ^G, game: ^G,
state: ^engine_state state: ^Engine_State
) )
{ {
files, err := os.read_all_directory_by_path("levels", context.allocator) files, err := os.read_all_directory_by_path("levels", context.allocator)
@@ -103,11 +103,11 @@ level_init_from_path :: proc(
$T, $E: typeid, $T, $E: typeid,
level_data : ^T, level_data : ^T,
path : string, path : string,
state: ^engine_state, state: ^Engine_State,
) -> (ret : bool) ) -> (ret : bool)
{ {
level := cast(^engine_world)level_data level := cast(^Engine_World)level_data
if os.is_file(path) if os.is_file(path)
{ {
@@ -118,7 +118,7 @@ level_init_from_path :: proc(
//? //?
level.relations = {} 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 if len(data) > 0
{ {
@@ -261,10 +261,10 @@ level_reload :: proc($T: typeid, $E: typeid, level: ^T)
If both hash is same the exits 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_path := fmt.tprintf("levels/%s.cbor", level.name)
level.cam = state.draw.cam 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 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] 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.entities)
clear(&interface.entity_defs) clear(&interface.entity_defs)