package edit2d import "core:fmt" import b2 "vendor:box2d" //import im "shared:odin-imgui" import draw "./draw" /* TODO: Delete joints Angles in degree */ /* All joints have bodyIdA and bodyIdB */ joint_common :: struct { pivot : [2]f32, entity_a, entity_b : Static_Index, bodyIdA, bodyIdB : b2.BodyId, } revolt_joint_def :: struct { pivot : [2]f32, entity_a, entity_b : Static_Index, using def : b2.RevoluteJointDef, } distance_joint_def :: struct { pivot : [2]f32, entity_a, entity_b : Static_Index, using def : b2.DistanceJointDef, } /* 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]] draw.points_add(&interface.state.draw.points, entity_a.body_def.position, 20.0, {200, 240, 200, 200}) } if joint_def.entity_b in level.static_indexes{ entity_b := interface.entity_defs[level.static_indexes[joint_def.entity_b]] draw.points_add(&interface.state.draw.points, entity_b.body_def.position, 20.0, {200, 240, 200, 200}) } } /* Set body A and Body B on the basis of static index so that it can pesist after restart */ ret := false 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) { joint_def.entity_a = i ret = true } } im.EndCombo() } im.Separator() if im.BeginCombo("Index B", fmt.ctprint(joint_def.entity_b)) { for i in level.static_indexes { //Set pivot if im.Selectable(fmt.ctprint(i), i == joint_def.entity_b) { joint_def.entity_b = i //Get the body's position and set it as default pivot joint_def.pivot = interface.entity_defs[level.static_indexes[i]].body_def.position ret = true } } im.EndCombo() } return ret } mu_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]] draw.points_add(&interface.state.draw.points, entity_a.body_def.position, 20.0, {200, 240, 200, 200}) } if joint_def.entity_b in level.static_indexes{ entity_b := interface.entity_defs[level.static_indexes[joint_def.entity_b]] draw.points_add(&interface.state.draw.points, entity_b.body_def.position, 20.0, {200, 240, 200, 200}) } } ret := 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)) } if im.Button("Delete current join") { unordered_remove(&level.distant_joint_defs, interface.curr_joint_index) return true } //Select index { if im.BeginCombo("Select joint", fmt.ctprint(interface.curr_joint_index)) { for i in 0..= 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_rev_joint_minimal :: proc(joint_def: ^b2.RevoluteJointDef) { im.SliderFloat2("localAnchorA", &joint_def.localAnchorA, -5, 5) im.SliderFloat2("localAnchorB", &joint_def.localAnchorB, -5, 5) reference_angle := draw.RAD2DEG * joint_def.referenceAngle if im.SliderFloat("Reference Angle", &reference_angle, 0, 359) { joint_def.referenceAngle = draw.DEG2RAD * reference_angle } target_angle := draw.RAD2DEG * joint_def.targetAngle if im.SliderFloat("Target Angle", &target_angle, 0, 359) { joint_def.targetAngle = draw.DEG2RAD * target_angle } im.Checkbox("Enable Spring", &joint_def.enableSpring) im.InputFloat("Hertz ", &joint_def.hertz) im.InputFloat("Damping Ratio", &joint_def.dampingRatio) lower_angle := draw.RAD2DEG * joint_def.lowerAngle if im.SliderFloat("Lower Angle", &lower_angle, 0, 359) { joint_def.lowerAngle = draw.DEG2RAD * lower_angle } upper_angle := draw.RAD2DEG * joint_def.upperAngle if im.SliderFloat("Upper Angle", &upper_angle, 0, 359) { joint_def.upperAngle = draw.DEG2RAD * upper_angle } 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) } 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)) } if im.Button("Delete current join") { unordered_remove(&level.revolute_joint_defs, interface.curr_joint_index) return true } //Select index if im.BeginCombo("Select joint", fmt.ctprint(interface.curr_joint_index)) { for i in 0..= 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) { //Set body_a := interface.entities[level.static_indexes[joint_def.entity_a]].body_id body_b := interface.entities[level.static_indexes[joint_def.entity_b]].body_id joint_def.localAnchorA = b2.Body_GetLocalPoint(body_a, joint_def.pivot) joint_def.localAnchorB = b2.Body_GetLocalPoint(body_b, joint_def.pivot) return true } /* Highlight the bodies here */ //Assuming pivot is always body b's position //Edit pivot if im.SliderFloat2("Pivot", &joint_def.pivot, -500, 500) { body_a := interface.entities[level.static_indexes[joint_def.entity_a]].body_id body_b := interface.entities[level.static_indexes[joint_def.entity_b]].body_id joint_def.localAnchorA = b2.Body_GetLocalPoint(body_a, joint_def.pivot) joint_def.localAnchorB = b2.Body_GetLocalPoint(body_b, joint_def.pivot) } interface_edit_rev_joint_minimal(joint_def) return old_def != joint_def^ } interface_joints :: proc(interface: ^interface_state) -> bool { ret := false //interface.edit_mode = .JOINT ctx := &interface.state.mu_ctx if .ACTIVE in mu.begin_treenode(ctx, "Joint Type") { for type in b2.JointType { state := interface.curr_joint_type == type if .CHANGE in mu.checkbox(ctx, fmt.tprint(type), &state) { interface.curr_joint_type = type } } mu.end_treenode(ctx) } if interface.curr_joint_type == .distanceJoint { ret |= interface_edit_distance_joint(interface) } if interface.curr_joint_type == .revoluteJoint { ret |= interface_edit_revolute_joint(interface) } return ret } */