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
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)
+61 -46
View File
@@ -22,12 +22,17 @@ import mu "vendor:microui"
//Only to be used inside the libarary
__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,
debug_draw : b2.DebugDraw,
@@ -39,21 +44,21 @@ engine_state :: struct
//Must be set before calling ion_init
width, height : i32,
title : cstring,
time : f32,
tex_line : u32,
drop_callback : glfw.DropProc,
input : input_state,
input : Input_State,
mu_ctx : mu.Context,
/* The opengl texture id created using mu.default_atlas_alpha */
mu_tex : u32,
}
MAX_KEYS :: 512
input_state :: struct
Input_State :: struct
{
mouse_wheel : [2]f64,
mouse : [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")
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")
@@ -103,8 +108,8 @@ engine_check_types :: proc($Game: typeid)
assert(entity_engine.is_using, "Should be using")
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(entity_engine.type.id == typeid_of(Engine_Entity))
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
}
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 +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)
//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 +151,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()
@@ -157,13 +165,23 @@ engine_init :: proc($GameType : typeid, state: ^engine_state, font_path : strin
draw_configure_box2d(state)
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
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
},
}, 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()
keyboard_update(state)
@@ -211,6 +229,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
{
@@ -236,21 +257,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)
@@ -260,6 +270,7 @@ end_frame :: proc(state: ^engine_state)
cmd: ^mu.Command
draw := &state.draw
for mu.next_command(&state.mu_ctx, &cmd)
{
#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),
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_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
@@ -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]
}
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(d: ^e2_draw.Draw)
draw_flush :: proc(state: ^Engine_State)
{
d := &state.draw
if __e2d_interal.viewport_changed
{
d.glyph.atlas_width = d.cam.width
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.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)
glfw.SwapBuffers(state.window)
__e2d_interal.viewport_changed = false
}
+20 -23
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
@@ -102,9 +102,6 @@ compare_engine_entity_def :: proc(a, b : engine_entity_def) -> bool
//ret &= a.vertices[:] == b.vertices[:]
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.index == b.index
@@ -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,
shape_id : b2.ShapeId,
@@ -125,24 +122,24 @@ 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
new_entity : engine_entity
new_entity : Engine_Entity
if def.index != 0
{
new_entity.index = new(static_index)
new_entity.index = new(Static_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(
def : ^engine_entity_def,
def : ^Engine_Entity_Def,
world_id : b2.WorldId,
index : i32
) -> engine_entity
) -> Engine_Entity
{
joint_def := def.rev_joint
orig_pos := def.body_def.position
@@ -311,10 +308,10 @@ 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
) -> Engine_Entity
{
if .CHAIN not_in def.entity_flags
+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,
}
+5 -2
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
@@ -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}
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
@@ -144,7 +147,6 @@ glyph_draw_font :: proc(glyph_state: ^GlyphState, text: string, pos : [2]f32, co
prev_codepoint: rune = 0
delete(glyph_state.rect_buffer)
glyph_state.rect_buffer = make([dynamic]GlyphRectInstance, 0, 1000)
glyph_state.curr = pos
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)
}
delete(glyph_state.rect_buffer)
}
+29 -13
View File
@@ -45,7 +45,7 @@ import draw "./draw"
*/
handle_entity_mode :: proc(
$E : typeid,
state : ^engine_state,
state : ^Engine_State,
game_data : ^$G,
) -> bool
{
@@ -70,25 +70,42 @@ handle_entity_mode :: proc(
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}
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)
{
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
{
@@ -126,12 +143,11 @@ handle_entity_mode :: proc(
def.body_def.position = mpos
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
}
}
@@ -143,7 +159,7 @@ handle_entity_mode :: proc(
handle_input :: proc(
$E : typeid,
state : ^engine_state,
state : ^Engine_State,
game_data : ^$G,
) -> bool
{
@@ -159,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)
}
}
@@ -181,17 +197,17 @@ handle_input :: proc(
ret := false
#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 .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 false
return ret
}
+26 -48
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,
selected_entity : i32,
entities : [dynamic]^Engine_Entity,
selected_entity : i32,
world : ^Engine_World,
state : ^engine_state,
state : ^Engine_State,
vertex_index : i32,
chain_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,43 +94,19 @@ mui_text_height :: proc(font: mu.Font) -> i32
interface_get_default :: proc(interface: ^Interface_State)
{
{
interface.selected_entity = 0
interface.vertex_index = 0
interface.vertex_index^ = 0
interface.chain_index = new(i32)
interface.chain_index^ = 0
}
interface.chain_index = 0
}
mu_interface_game_mode :: proc(state: ^Engine_State, interface: ^Interface_State)
interface_draw_options :: proc(state: ^engine_state)
{
{
width :i32 = 250
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", {state.width - width, 0, width, 170})
{
for type in Edit_Mode
{
for type in EditMode
{
{
b : bool = 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)
{
{
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.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
{
{
ret := false
if interface.selected_entity <0
{
@@ -180,25 +156,27 @@ interface_all :: proc(interface: ^interface_state) -> bool
mu.begin(&state.mu_ctx)
mu_interface_draw_options(interface.state)
mu_interface_draw_options(interface.state)
mu_interface_game_mode(state, interface)
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 interface_entity(interface) do ret = true
}
}
mu.end_window(&state.mu_ctx)
}
//if interface_joints(interface) do ret = true
mu.end(&state.mu_ctx)
mu.end(&state.mu_ctx)
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
@@ -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,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
ctx := &interface.state.mu_ctx
if entity_selected
{
def := interface.entity_defs[interface.selected_entity]
@@ -384,10 +386,18 @@ 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 mu.checkbox(fmt.tprint(flag), &contains) do def.entity_flags ~= {flag}
contains := flag in def.entity_flags
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
{
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)