Refactor draw to be separate and handle ortho draw

This commit is contained in:
2026-03-23 13:32:46 +05:45
parent 157f04060e
commit 739a806493
6 changed files with 637 additions and 267 deletions
+291 -217
View File
File diff suppressed because it is too large Load Diff
+110 -8
View File
@@ -1,23 +1,26 @@
package edit2d package edit2d
import "core:fmt"
import "base:intrinsics" import "base:intrinsics"
import "core:encoding/cbor" import "core:encoding/cbor"
import b2 "vendor:box2d"
import "base:runtime" import "base:runtime"
import im "shared:odin-imgui" import im "shared:odin-imgui"
import "shared:odin-imgui/imgui_impl_glfw" import "shared:odin-imgui/imgui_impl_glfw"
import "shared:odin-imgui/imgui_impl_opengl3" import "shared:odin-imgui/imgui_impl_opengl3"
import gl "vendor:OpenGL" import gl "vendor:OpenGL"
import "vendor:glfw" import "vendor:glfw"
import draw "shared:Edit2D/draw" import e2_draw "shared:Edit2D/draw"
import "core:reflect" import "core:reflect"
import mu "vendor:microui"
engine_state :: struct engine_state :: struct
{ {
window : glfw.WindowHandle, window : glfw.WindowHandle,
draw : draw.Draw, draw : e2_draw.Draw,
restart, pause : bool, restart, pause : bool,
substep_count : u32, substep_count : u32,
@@ -30,6 +33,7 @@ engine_state :: struct
input : input_state, input : input_state,
mu_ctx : mu.Context,
} }
MAX_KEYS :: 512 MAX_KEYS :: 512
@@ -95,18 +99,25 @@ engine_check_types :: proc($Game: typeid)
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) engine_init :: proc($GameType : typeid, state: ^engine_state, font_path : string="")
{ {
engine_check_types(GameType) engine_check_types(GameType)
assert(glfw.Init() == true) assert(glfw.Init() == true)
glfw.WindowHint(glfw.SCALE_TO_MONITOR, 1) glfw.WindowHint(glfw.SCALE_TO_MONITOR, 1)
glfw.WindowHint(glfw.CONTEXT_VERSION_MAJOR, 4)
glfw.WindowHint(glfw.OPENGL_DEBUG_CONTEXT, true)
glfw.WindowHint(glfw.CONTEXT_VERSION_MINOR, 5)
glfw.WindowHint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
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)
@@ -139,7 +150,7 @@ engine_init :: proc($GameType : typeid, state: ^engine_state)
imgui_impl_glfw.InitForOpenGL(state.window, true) imgui_impl_glfw.InitForOpenGL(state.window, true)
imgui_impl_opengl3.Init("#version 150") imgui_impl_opengl3.Init("#version 150")
state.draw.cam = draw.camera_init() state.draw.cam = e2_draw.camera_init()
display_w, display_h := glfw.GetFramebufferSize(state.window) display_w, display_h := glfw.GetFramebufferSize(state.window)
state.draw.cam.width = display_w state.draw.cam.width = display_w
@@ -147,7 +158,7 @@ engine_init :: proc($GameType : typeid, state: ^engine_state)
state.draw.cam.zoom = 15 state.draw.cam.zoom = 15
state.draw.show_ui = true state.draw.show_ui = true
draw.draw_create(&state.draw, &state.draw.cam) e2_draw.draw_create(&state.draw, &state.draw.cam, font_path)
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 {
@@ -159,6 +170,16 @@ engine_init :: proc($GameType : typeid, state: ^engine_state)
}, },
}, 201, rawptr) }, 201, rawptr)
//Glyph and microui
{
mu.init(&state.mu_ctx)
state.mu_ctx.style.font = cast(mu.Font)&state.draw.glyph
state.mu_ctx.text_width = mui_text_width
state.mu_ctx.text_height = mui_text_height
}
} }
@@ -169,6 +190,25 @@ update_frame :: proc(state: ^engine_state)
keyboard_update(state) keyboard_update(state)
x, y:= glfw.GetCursorPos(state.window)
mu.input_mouse_move(&state.mu_ctx, i32(x), i32(y))
{
for key in key_map
{
if is_key_pressed(state, key) do mu.input_key_down(&state.mu_ctx, key_map[key])
if is_key_released(state, key) do mu.input_key_up(&state.mu_ctx, key_map[key])
}
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])
}
}
gl.ClearColor(0.4, 0.5, 0.6, 1.0) gl.ClearColor(0.4, 0.5, 0.6, 1.0)
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
@@ -187,6 +227,68 @@ end_frame :: proc(state: ^engine_state)
{ {
im.Render() im.Render()
imgui_impl_opengl3.RenderDrawData(im.GetDrawData()) imgui_impl_opengl3.RenderDrawData(im.GetDrawData())
//Microui
{
cmd: ^mu.Command
draw := &state.draw
for mu.next_command(&state.mu_ctx, &cmd)
{
#partial switch c in cmd.variant{
case ^mu.Command_Text:
{
color := c.color
append(&draw.texts, e2_draw.TextItem{c.str, {f32(c.pos.x), f32(c.pos.y)}, {c.color.r, color.g, color.b, color.a}})
}
case ^mu.Command_Rect:
{
rect := c.rect
pos :[2]f32= {f32(rect.x), f32(rect.y)}
wh :[2]f32= {f32(rect.w), f32(rect.h)}
w, h := wh.x, wh.y
points : [4][2]f32 = {
{pos.x + w, pos.y},
{pos.x, pos.y},
{pos.x, pos.y + h},
{pos.x + w, pos.y + h},
}
for &p, i in &points do points[i] = e2_draw.camera_convert_screen_to_world(&draw.cam, p)
color := c.color
hex_color := e2_draw.make_hex_color({color.r, color.g, color.b, color.a})
e2_draw.solid_polygon_add(&draw.polygons, {q = b2.Rot{c = 1}}, &points[0], 4, 0, hex_color)
}
case ^mu.Command_Clip:
{
rect := c.rect
gl.Scissor(rect.x, state.height - (rect.y + rect.h), rect.w, rect.h)
}
case ^mu.Command_Icon:{
if c.id == .CHECK
{
pos :[2]f32= {f32(c.rect.x), f32(c.rect.y)}
pos.x += f32(c.rect.w)/2.0
pos.y += f32(c.rect.h)/2.0
pos = e2_draw.camera_convert_screen_to_world(&draw.cam, pos)
e2_draw.solid_circle_add(&draw.solid_circles,{p = pos, q = b2.Rot{c = 1}} , 0.1,{255, 255, 255, 255})
}else{
fmt.println(c.id)
}
}
}
}
}
glfw.SwapBuffers(state.window) glfw.SwapBuffers(state.window)
} }
@@ -236,9 +338,9 @@ is_key_released :: #force_inline proc(state: ^engine_state, key : i32) -> bool{
} }
draw_flush :: proc(d: ^draw.Draw) draw_flush :: proc(d: ^e2_draw.Draw)
{ {
draw.draw_flush(d) e2_draw.draw_flush(d)
} }
+30 -13
View File
@@ -1,5 +1,6 @@
package e2glyph package e2glyph
import "core:fmt"
/* /*
Provides text rendering using glfw, stb_truetype for the engine Provides text rendering using glfw, stb_truetype for the engine
@@ -52,11 +53,13 @@ GlyphState :: struct {
} }
glyph_init :: proc(glyph: ^GlyphState, filepath : string) { glyph_init :: proc(glyph: ^GlyphState, font_path : string = "") {
ok : bool ok : bool
glyph.program_id, ok = gl.load_shaders_source(#load("./shaders/font_vert.glsl"), #load("./shaders/font_frag.glsl"), ) glyph.program_id, ok = gl.load_shaders_source(#load("./shaders/font_vert.glsl"), #load("./shaders/font_frag.glsl"), )
gl.UseProgram(glyph.program_id)
gl.CreateBuffers(1, &glyph.rect_instances_vbo) gl.CreateBuffers(1, &glyph.rect_instances_vbo)
gl.CreateVertexArrays(1, &glyph.vao) gl.CreateVertexArrays(1, &glyph.vao)
@@ -82,9 +85,18 @@ glyph_init :: proc(glyph: ^GlyphState, filepath : string) {
gl.CreateTextures(gl.TEXTURE_RECTANGLE, 1, &glyph.atlas_texture) gl.CreateTextures(gl.TEXTURE_RECTANGLE, 1, &glyph.atlas_texture)
gl.TextureStorage2D(glyph.atlas_texture, 1, gl.RGB8, glyph.atlas_width, glyph.atlas_height) gl.TextureStorage2D(glyph.atlas_texture, 1, gl.RGB8, glyph.atlas_width, glyph.atlas_height)
font_data, _ := os.read_entire_file_from_path(filepath, context.allocator)
stbtt.InitFont(&glyph.font_info, &font_data[0], 0) if !os.exists(font_path)
{
fmt.eprintln("Font not provided or not exist using default font")
font_data := #load("./mononoki-Regular.ttf", []byte)
stbtt.InitFont(&glyph.font_info, &font_data[0], 0)
}else
{
font_data, _ := os.read_entire_file_from_path(font_path, context.allocator)
stbtt.InitFont(&glyph.font_info, &font_data[0], 0)
}
gl.UseProgram(0) gl.UseProgram(0)
} }
@@ -98,6 +110,7 @@ glyph_draw_font :: proc(glyph_state: ^GlyphState, text: string, pos : [2]f32, co
coverage_adjustment: f32 = 0.0 coverage_adjustment: f32 = 0.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} 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
@@ -138,13 +151,15 @@ glyph_draw_font :: proc(glyph_state: ^GlyphState, text: string, pos : [2]f32, co
glyph_state.curr.y += math.round(line_height) glyph_state.curr.y += math.round(line_height)
} else if c == '\t' { } else if c == '\t' {
glyph_state.curr.x += 2 * glyph_state.font_size_pt glyph_state.curr.x += 2 * glyph_state.font_size_pt
} else { } else {
horizontal_filter_padding, subpixel_positioning_left_padding: i32 = 1, 1 horizontal_filter_padding, subpixel_positioning_left_padding: i32 = 1, 1
assert(codepoint <= 127) if codepoint >= 127{
return
}
assert(codepoint < 127)
glyph_atlas := glyph_state.atlas_items[codepoint] glyph_atlas := glyph_state.atlas_items[codepoint]
if !glyph_atlas.filled if !glyph_atlas.filled
@@ -283,17 +298,19 @@ glyph_draw_font :: proc(glyph_state: ^GlyphState, text: string, pos : [2]f32, co
gl.Enable(gl.BLEND) gl.Enable(gl.BLEND)
gl.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC1_COLOR) gl.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC1_COLOR)
gl.BindVertexArray(glyph_state.vao) gl.UseProgram( glyph_state.program_id)
gl.UseProgram(glyph_state.program_id) gl.BindVertexArray( glyph_state.vao)
gl.ProgramUniform2f(glyph_state.program_id, 0, f32(glyph_state.width) / 2.0, f32(glyph_state.height) / 2.0) gl.ProgramUniform2f( glyph_state.program_id, 0, f32(glyph_state.width) / 2.0, f32(glyph_state.height) / 2.0)
gl.ProgramUniform1ui(glyph_state.program_id, 1, u32(coverage_adjustment)) gl.ProgramUniform1ui( glyph_state.program_id, 1, u32(coverage_adjustment))
gl.ProgramUniform1ui(glyph_state.program_id, 2, 0) gl.ProgramUniform1ui( glyph_state.program_id, 2, 0)
gl.BindTextureUnit(0, glyph_state.atlas_texture) gl.BindTextureUnit(0, glyph_state.atlas_texture)
gl.DrawArraysInstanced(gl.TRIANGLES, 0, 6, i32(len(glyph_state.rect_buffer))) gl.DrawArraysInstanced(gl.TRIANGLES, 0, 6, i32(len(glyph_state.rect_buffer)))
gl.Disable(gl.BLEND)
gl.UseProgram(0)
gl.BindVertexArray(0) //gl.UseProgram(0)
//gl.BindVertexArray(0)
gl.InvalidateBufferData(glyph_state.rect_instances_vbo) gl.InvalidateBufferData(glyph_state.rect_instances_vbo)
} }
Binary file not shown.
+115 -25
View File
@@ -1,15 +1,23 @@
#+feature dynamic-literals
package edit2d
import im "shared:odin-imgui" import im "shared:odin-imgui"
import mu "vendor:microui" import mu "vendor:microui"
import e2_glyph "./glyph"
import "core:fmt"
import "vendor:glfw" import "vendor:glfw"
import b2 "vendor:box2d"
/* /*
This library will only account for box2d's entities editing This library will only account for box2d's entities editing
This library will only account for box2d's entities editing
It only deals with one world_id, which means typically one level It only deals with one world_id, which means typically one level
It only deals with one world_id, which means typically one level
All the interface follows a pattern All the interface follows a pattern
All the interface follows a pattern i.e. It takes interface_state pointer and returns a boolean indicating weather the world needs to be reloaded
i.e. It takes interface_state pointer and returns a boolean indicating weather the world needs to be reloaded
Interface should handle microui
*/ */
EditMode :: enum EditMode :: enum
@@ -41,6 +49,51 @@ interface_state :: struct
} }
key_map : map[i32]mu.Key = {
glfw.KEY_LEFT_SHIFT = .SHIFT,
glfw.KEY_RIGHT_SHIFT = .SHIFT,
glfw.KEY_LEFT_CONTROL = .CTRL,
glfw.KEY_RIGHT = .CTRL,
glfw.KEY_LEFT_ALT = .ALT,
glfw.KEY_RIGHT_ALT = .ALT,
glfw.KEY_BACKSPACE = .BACKSPACE,
glfw.KEY_DELETE = .DELETE,
glfw.KEY_ENTER = .RETURN,
glfw.KEY_LEFT = .LEFT,
glfw.KEY_RIGHT = .RIGHT,
glfw.KEY_HOME = .HOME,
glfw.KEY_END = .END,
glfw.KEY_A = .A,
glfw.KEY_X = .X,
glfw.KEY_C = .C,
glfw.KEY_V = .V
}
mouse_map : map[i32]mu.Mouse = {
glfw.MOUSE_BUTTON_LEFT = .LEFT,
glfw.MOUSE_BUTTON_RIGHT = .RIGHT,
glfw.MOUSE_BUTTON_MIDDLE= .MIDDLE,
}
//interface_get_font
mui_text_width :: proc(font: mu.Font, str: string) -> i32
{
glyph := cast(^e2_glyph.GlyphState)font
return i32(len(str)) * i32(glyph.font_size_pt)
}
mui_text_height :: proc(font: mu.Font) -> i32
{
glyph := cast(^e2_glyph.GlyphState)font
return i32(glyph.font_size_pt)
}
interface_get_default :: proc(interface: ^interface_state)
{ {
interface.selected_entity = 0 interface.selected_entity = 0
interface.vertex_index = new(i32) interface.vertex_index = new(i32)
@@ -50,7 +103,8 @@ interface_get_default :: proc(interface: ^interface_state)
} }
interface_draw_options :: proc(state: ^engine_state) interface_draw_options :: proc(state: ^engine_state)
interface_draw_options :: proc(state: ^engine_state) { {
debug_draw := &state.draw.debug_draw
im.SliderFloat("Zoom", &state.draw.cam.zoom, 0, 100) im.SliderFloat("Zoom", &state.draw.cam.zoom, 0, 100)
im.Checkbox("Shapes", &debug_draw.drawShapes) im.Checkbox("Shapes", &debug_draw.drawShapes)
@@ -70,6 +124,48 @@ 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", {1700, 0, 250, 170})
{
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
}
mu.end_window(&state.mu_ctx)
}
}
mu_interface_draw_options :: proc(state: ^engine_state)
{
if mu.begin_window(&state.mu_ctx, "Options", {200, 150, 200, 400}){
debug_draw := &state.draw.debug_draw
mu.label(&state.mu_ctx, "Zoom")
mu.slider(&state.mu_ctx, &state.draw.cam.zoom,0, 100)
mu.checkbox(&state.mu_ctx, "Shapes", &debug_draw.drawShapes)
mu.checkbox(&state.mu_ctx, "Joints", &debug_draw.drawJoints)
mu.checkbox(&state.mu_ctx, "Joint Extras", &debug_draw.drawJointExtras)
mu.checkbox(&state.mu_ctx, "Bounds", &debug_draw.drawBounds)
mu.checkbox(&state.mu_ctx, "Contact Points", &debug_draw.drawContacts)
mu.checkbox(&state.mu_ctx, "Contact Normals", &debug_draw.drawContactNormals)
mu.checkbox(&state.mu_ctx, "Contact Inpulses", &debug_draw.drawContactImpulses)
mu.checkbox(&state.mu_ctx, "Contact Features", &debug_draw.drawContactFeatures)
mu.checkbox(&state.mu_ctx, "Friction Inpulses", &debug_draw.drawFrictionImpulses)
mu.checkbox(&state.mu_ctx, "Mass ", &debug_draw.drawMass)
mu.checkbox(&state.mu_ctx, "Body Names", &debug_draw.drawBodyNames)
mu.checkbox(&state.mu_ctx, "Graph Colors", &debug_draw.drawGraphColors)
mu.checkbox(&state.mu_ctx, "Islands ", &debug_draw.drawIslands)
mu.label(&state.mu_ctx, "Rotation")
mu.slider(&state.mu_ctx, &state.draw.cam.rotation, 0, 360)
mu.end_window(&state.mu_ctx)
}
}
interface_all :: proc(interface: ^interface_state) -> bool interface_all :: proc(interface: ^interface_state) -> bool
{ {
ret := false ret := false
@@ -79,27 +175,26 @@ interface_all :: proc(interface: ^interface_state) -> bool
} }
state := interface.state state := interface.state
if im.Begin("Edit Mode", nil) mu.begin(&state.mu_ctx)
{
for type in EditMode //test_window(&state.mu_ctx)
{ mu_interface_draw_options(interface.state)
if im.RadioButton(fmt.ctprint(type), interface.edit_mode == type) mu_interface_game_mode(state, interface)
{
interface.edit_mode = type
}
}
}
im.End()
if im.Begin("Box2d interface") if im.Begin("Box2d interface")
{ {
if im.BeginTabBar("Tabs") if im.BeginTabBar("Tabs")
{ {
if mu.begin_window(&state.mu_ctx, "B2d Interface", {1700, 150, 250, 250}) if mu.begin_window(&state.mu_ctx, "B2d Interface", {1700, 150, 250, 250})
if im.BeginTabItem("Entity", nil, {.Leading}) {
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 {
im.EndTabItem() if interface_entity(interface) do ret = true
}
mu.end_window(&state.mu_ctx)
}
if im.BeginTabItem("Joints", nil, {}) if im.BeginTabItem("Joints", nil, {})
{ {
@@ -108,15 +203,10 @@ interface_all :: proc(interface: ^interface_state) -> bool
} }
im.EndTabBar() im.EndTabBar()
if im.BeginTabItem("Draw Options", nil, {})
{
interface_draw_options(interface.state)
im.EndTabItem()
}
} }
} }
mu.end(&state.mu_ctx) mu.end(&state.mu_ctx)
im.End()
return ret return ret
} }
+89 -2
View File
@@ -2,6 +2,7 @@ package edit2d
import b2 "vendor:box2d" import b2 "vendor:box2d"
import im "shared:odin-imgui" import im "shared:odin-imgui"
import mu "vendor:microui"
import "core:slice" import "core:slice"
import draw "./draw" import draw "./draw"
import "core:fmt" import "core:fmt"
@@ -122,6 +123,92 @@ interface_edit_static_index :: proc(interface:^interface_state, def: ^engine_ent
return false return false
} }
mu_interface_shape_def_editor :: proc(
state : ^engine_state,
def : ^engine_entity_def) -> bool
{
shape_def := &def.shape_def
mu.label(&state.mu_ctx, "Shape Type")
for type in b2.ShapeType
{
b := def.shape_type == type
if .CHANGE in mu.checkbox(&state.mu_ctx, fmt.tprint(type), &b) do def.shape_type = type
}
switch def.shape_type
{
case .circleShape:{
mu.label(&state.mu_ctx, "Radius")
mu.slider(&state.mu_ctx, &def.radius, 0, 40)
}
case .polygonShape:{
mu.label(&state.mu_ctx, "Size")
mu.slider(&state.mu_ctx, &def.size[0], -500, 500)
mu.slider(&state.mu_ctx, &def.size[1], -500, 500)
}
case .capsuleShape:{
mu.label(&state.mu_ctx, "Center 1")
mu.slider(&state.mu_ctx, &def.centers[0][0], -100, 100)
mu.slider(&state.mu_ctx, &def.centers[0][1], -100, 100)
mu.label(&state.mu_ctx, "Center 2")
mu.slider(&state.mu_ctx, &def.centers[1][0], -100, 100)
mu.slider(&state.mu_ctx, &def.centers[1][1], -100, 100)
mu.label(&state.mu_ctx, "Radius")
mu.slider(&state.mu_ctx, &def.radius, 0, 40)
}
case .chainSegmentShape:{
mu.checkbox(&state.mu_ctx, "Is Loop", &def.is_loop)
}
case .segmentShape:{
}
}
mu.label(&state.mu_ctx, "Density")
mu.slider(&state.mu_ctx, &def.shape_def.density, 0, 100)
if .SUBMIT in mu.button(&state.mu_ctx, "Flip horizontally") do flip_points(def.vertices[:], .Horizontal)
if .SUBMIT in mu.button(&state.mu_ctx, "Flip Vertically ") do flip_points(def.vertices[:], .Vertical)
if .ACTIVE in mu.begin_treenode(&state.mu_ctx, "Events and contacts")
{
mu.checkbox(&state.mu_ctx, "Is sensor", &def.shape_def.isSensor)
mu.checkbox(&state.mu_ctx, "Enable Sensor Events", &def.shape_def.enableSensorEvents)
mu.checkbox(&state.mu_ctx, "Enable Contact Events", &def.shape_def.enableContactEvents)
mu.checkbox(&state.mu_ctx, "Enable Hit Events", &def.shape_def.enableHitEvents)
mu.checkbox(&state.mu_ctx, "Enable Presolve Events", &def.shape_def.enablePreSolveEvents)
mu.checkbox(&state.mu_ctx, "Invoke contact Creation", &def.shape_def.invokeContactCreation)
mu.checkbox(&state.mu_ctx, "Update body mass ", &def.shape_def.updateBodyMass)
mu.end_treenode(&state.mu_ctx)
}
if .ACTIVE in mu.begin_treenode(&state.mu_ctx, "Material")
{
mu.label(&state.mu_ctx, "Friction")
mu.slider(&state.mu_ctx, &def.shape_def.material.friction, 0, 1)
mu.label(&state.mu_ctx, "Restitution")
mu.slider(&state.mu_ctx, &def.shape_def.material.restitution, 0, 1)
mu.label(&state.mu_ctx, "Rolling Resistance")
mu.slider(&state.mu_ctx, &def.shape_def.material.rollingResistance, 0, 1)
mu.label(&state.mu_ctx, "Tangent Speed")
mu.slider(&state.mu_ctx, &def.shape_def.material.tangentSpeed, 0, 1)
//if .ACTIVE in mu.begin_treenode(&state.mu_ctx, "Color")
mu.end_treenode(&state.mu_ctx)
}
return false
}
interface_shape_def_editor :: proc(def: ^engine_entity_def) -> bool interface_shape_def_editor :: proc(def: ^engine_entity_def) -> bool
{ {
@@ -211,7 +298,6 @@ interface_shape_def_editor :: proc(def: ^engine_entity_def) -> bool
im.Separator() im.Separator()
im.TreePop() im.TreePop()
} }
return false return false
} }
@@ -238,8 +324,9 @@ interface_entity :: proc(interface: ^interface_state) -> bool
if im.CollapsingHeader("Shape Edit") if im.CollapsingHeader("Shape Edit")
{ {
interface_shape_def_editor(def) //interface_shape_def_editor(def)
} }
mu_interface_shape_def_editor(interface.state, def)
im.Separator() im.Separator()