This commit is contained in:
SamratGhale
2026-03-12 12:54:13 +05:45
parent d23c934662
commit 8ed94fac32
4 changed files with 222 additions and 28 deletions
+16 -7
View File
@@ -17,20 +17,24 @@ static_index_global :: struct
Don't put game's logic here
*/
joint_common :: struct
{
entity_a, entity_b : static_index,
bodyIdA, bodyIdB : b2.BodyId,
}
revolt_joint_def :: struct
{
using def : b2.RevoluteJointDef,
//Everything else can be stored in the def
entity_a, entity_b : static_index,
using def : b2.RevoluteJointDef,
}
distance_joint_def :: struct
{
using def : b2.DistanceJointDef,
//Everything else can be stored in the def
entity_a, entity_b : static_index,
using def : b2.DistanceJointDef,
}
engine_world :: struct
@@ -42,10 +46,15 @@ engine_world :: struct
relations : map[^static_index][dynamic]static_index_global `cbor:"-"`,
relations_serializeable : map[ static_index][dynamic]static_index_global,
/*
Seems okay to put the joint defs in engine rather than in game because
we don't add more attributes in joints in the game
Can be changed later without requireing refactor
*/
revolute_joint_defs : [dynamic]revolt_joint_def,
distant_joint_defs : [dynamic]distance_joint_def,
revolute_joints : [dynamic]b2.JointId,
joints : [dynamic]b2.JointId `cbor:"-"`,
}
engine_entity_flags_enum :: enum u64 {
+40 -16
View File
@@ -1,16 +1,18 @@
package ion
import "base:runtime"
import "core:slice"
import "core:container/small_array"
import "core:fmt"
import im "shared:odin-imgui"
import "vendor:glfw"
import b2 "vendor:box2d"
/*
This library will only account for box2d's entities editing
It only deals with one world_id, which means typically one level
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
*/
EditMode :: enum
@@ -18,22 +20,22 @@ EditMode :: enum
ENTITY,
VERTICES,
OVERVIEW,
JOINT,
}
interface_state :: struct
{
entity_defs: [dynamic]^engine_entity_def,
entities: [dynamic]^engine_entity,
selected_entity: ^i32,
world: ^engine_world,
state: ^engine_state,
entity_defs : [dynamic]^engine_entity_def,
entities : [dynamic]^engine_entity,
selected_entity : ^i32,
world : ^engine_world,
state : ^engine_state,
vertex_index : ^i32,
edit_mode : EditMode,
curr_revolt_joint : revolt_joint_def,
curr_joint_joint : distance_joint_def,
curr_joint_index : i32,
curr_joint_type : b2.JointType,
curr_static_index : static_index_global,
}
@@ -251,15 +253,15 @@ interface_edit_static_index :: proc(interface:^interface_state, def: ^engine_ent
return false
}
/*
interface_edit_revolute_joint :: proc(interface: ^interface_state) -> bool
{
//Select static index and then get bodyId from it
//If chain shapre then allow choosing index
level := interface.world
joint_def := &interface.curr_revolt_joint
joint_def := interface.curr_revolt_joint
if im.BeginCombo("Index A", fmt.ctprint(joint_def.entity_a))
{
@@ -317,13 +319,14 @@ interface_edit_revolute_joint :: proc(interface: ^interface_state) -> bool
if im.Button("Add joint")
{
append(&level.revolute_joint_defs, interface.curr_revolt_joint)
//append(&level.revolute_joint_defs, interface.curr_revolt_joint)
return true
}
return false
}
*/
interface_entity :: proc(interface: ^interface_state) -> bool
@@ -340,7 +343,7 @@ interface_entity :: proc(interface: ^interface_state) -> bool
if im.BeginTabItem("Entity", nil, {.Leading})
{
interface.edit_mode = .ENTITY
//Flags
for flag in engine_entity_flags_enum
{
@@ -375,12 +378,26 @@ interface_entity :: proc(interface: ^interface_state) -> bool
if im.BeginTabItem("Joints", nil , {})
{
interface.edit_mode = .JOINT
if im.CollapsingHeader("Revolute Joints")
if im.BeginCombo("Joint type", fmt.ctprint(interface.curr_joint_type))
{
for type in b2.JointType
{
if im.Selectable(fmt.ctprint(type), type == interface.curr_joint_type) do interface.curr_joint_type = type
}
im.EndCombo()
}
if interface.curr_joint_type == .distanceJoint
{
ret |= interface_edit_distance_joint(interface)
}
if interface.curr_joint_type == .revoluteJoint
{
ret |= interface_edit_revolute_joint(interface)
}
im.EndTabItem()
}
@@ -407,3 +424,10 @@ interface_all :: proc(interface: ^interface_state) -> bool
im.End()
return ret
}
+162
View File
@@ -0,0 +1,162 @@
package ion
import "core:fmt"
import b2 "vendor:box2d"
import im "shared:odin-imgui"
/*
TODO:
Delete joints
Angles in degree
*/
/*
All joints have bodyIdA and bodyIdB
*/
interface_edit_joint_common :: proc(joint_def : ^joint_common, interface: ^interface_state) -> bool
{
level := interface.world
{
if joint_def.entity_a in level.static_indexes{
entity_a := interface.entity_defs[level.static_indexes[joint_def.entity_a]]
points_add(&interface.state.draw.points, entity_a.body_def.position, 20.0, b2.HexColor.Plum)
}
if joint_def.entity_b in level.static_indexes{
entity_b := interface.entity_defs[level.static_indexes[joint_def.entity_b]]
points_add(&interface.state.draw.points, entity_b.body_def.position, 20.0, b2.HexColor.Plum)
}
}
/*
Set body A and Body B on the basis of static index so that it can pesist after restart
*/
if im.BeginCombo("Index A", fmt.ctprint(joint_def.entity_a))
{
for i in level.static_indexes
{
if im.Selectable(fmt.ctprint(i), i == joint_def.entity_a) do joint_def.entity_a = i
}
im.EndCombo()
}
im.Separator()
if im.BeginCombo("Index B", fmt.ctprint(joint_def.entity_b))
{
for i in level.static_indexes
{
if im.Selectable(fmt.ctprint(i), i == joint_def.entity_b) do joint_def.entity_b = i
}
im.EndCombo()
}
return false
}
interface_edit_distance_joint :: proc( interface : ^interface_state ) -> bool
{
level := interface.world
interface.curr_joint_type = .distanceJoint
if len(level.distant_joint_defs) == 0 do im.Text("No distance joint created, Click add to create new")
if im.Button("Create new joint")
{
append(&level.distant_joint_defs, distance_joint_def{def = b2.DefaultDistanceJointDef()})
interface.curr_joint_index = i32(len(level.distant_joint_defs))
}
//Select index
{
if im.BeginCombo("Select joint", fmt.ctprint(interface.curr_joint_index))
{
for i in 0..<len(level.distant_joint_defs){
if im.Selectable(fmt.ctprint(i), i32(i) == interface.curr_joint_index) do interface.curr_joint_index = i32(i)
}
im.EndCombo()
}
}
if interface.curr_joint_index >= i32(len(level.distant_joint_defs)) do return false
joint_def := &level.distant_joint_defs[interface.curr_joint_index]
old_def := joint_def^
if interface_edit_joint_common(cast(^joint_common)joint_def, interface) do return true
/*
Highlight the bodies here
*/
im.SliderFloat2("localAnchorA", &joint_def.localAnchorA, -5, 5)
im.SliderFloat2("localAnchorB", &joint_def.localAnchorB, -5, 5)
im.SliderFloat("Rest length", &joint_def.length, 0, 100)
im.Checkbox("Enable Spring", &joint_def.enableSpring)
im.InputFloat("Hertz ", &joint_def.hertz)
im.InputFloat("Damping Ratio", &joint_def.dampingRatio)
im.Checkbox("Enable Limit", &joint_def.enableLimit)
im.InputFloat("Min length", &joint_def.minLength)
im.InputFloat("Max length", &joint_def.maxLength)
im.Checkbox("Enable Motor", &joint_def.enableMotor)
im.InputFloat("Moror Torque", &joint_def.maxMotorForce)
im.InputFloat("Moror Speed", &joint_def.motorSpeed)
im.Checkbox("Collide Connected", &joint_def.collideConnected)
return old_def != joint_def^
}
interface_edit_revolute_joint :: proc( interface : ^interface_state ) -> bool
{
level := interface.world
interface.curr_joint_type = .revoluteJoint
if len(level.revolute_joint_defs) == 0 do im.Text("No revolute joint created, Click add to create new")
if im.Button("Create new joint")
{
append(&level.revolute_joint_defs, revolt_joint_def{def = b2.DefaultRevoluteJointDef()})
interface.curr_joint_index = i32(len(level.revolute_joint_defs))
}
//Select index
if im.BeginCombo("Select joint", fmt.ctprint(interface.curr_joint_index))
{
for i in 0..<len(level.revolute_joint_defs){
if im.Selectable(fmt.ctprint(i), i32(i) == interface.curr_joint_index) do interface.curr_joint_index = i32(i)
}
im.EndCombo()
}
if interface.curr_joint_index >= i32(len(level.revolute_joint_defs)) do return false
joint_def := &level.revolute_joint_defs[interface.curr_joint_index]
old_def := joint_def^
if interface_edit_joint_common(cast(^joint_common)joint_def, interface) do return true
/*
Highlight the bodies here
*/
im.SliderFloat2("localAnchorA", &joint_def.localAnchorA, -5, 5)
im.SliderFloat2("localAnchorB", &joint_def.localAnchorB, -5, 5)
im.SliderFloat("Refresh angle", &joint_def.referenceAngle, 0, 100)
im.SliderFloat("Target angle", &joint_def.targetAngle, 0, 100)
im.Checkbox("Enable Spring", &joint_def.enableSpring)
im.InputFloat("Hertz ", &joint_def.hertz)
im.InputFloat("Damping Ratio", &joint_def.dampingRatio)
im.InputFloat("Lower Angle", &joint_def.lowerAngle)
im.InputFloat("Upper Angle", &joint_def.upperAngle)
im.InputFloat("Max Motor Limit", &joint_def.maxMotorTorque)
im.InputFloat("Motor Speed", &joint_def.motorSpeed)
im.InputFloat("Draw Size", &joint_def.drawSize)
im.Checkbox("Enable Motor", &joint_def.enableMotor)
im.Checkbox("Enable Limit", &joint_def.enableLimit)
im.Checkbox("Collide Connected", &joint_def.collideConnected)
return old_def != joint_def^
}
-1
View File
@@ -40,7 +40,6 @@ input_state :: struct
/*
This will only be called once to initilize the engine
initilize graphics library, glfw, callbacks
*/
engine_init :: proc(state: ^engine_state)