272 lines
6.1 KiB
Odin
272 lines
6.1 KiB
Odin
package edit2d
|
|
|
|
import b2 "vendor:box2d"
|
|
import im "shared:odin-imgui"
|
|
import "core:slice"
|
|
import draw "./draw"
|
|
import "core:fmt"
|
|
|
|
|
|
/*
|
|
This is mostly stable
|
|
|
|
Handles
|
|
1. Body Defination
|
|
2. Shape defination
|
|
3. Static index
|
|
|
|
TODO:
|
|
Handle multiple shapes?
|
|
Could use more tweaks on min and max values
|
|
*/
|
|
|
|
|
|
/*
|
|
We don't need to return bool from this function because we can see the difference
|
|
By doing comparasion on def
|
|
*/
|
|
|
|
interface_body_def_editor :: proc(def: ^engine_entity_def)
|
|
{
|
|
if im.BeginCombo("Body Type", fmt.ctprint(def.body_def.type))
|
|
{
|
|
for type in b2.BodyType
|
|
{
|
|
if im.Selectable(fmt.ctprint(type), def.body_def.type == type) do def.body_def.type = type
|
|
}
|
|
im.EndCombo()
|
|
}
|
|
|
|
im.SliderFloat2("Position", &def.body_def.position, -50, 50)
|
|
|
|
angle := draw.RAD2DEG * b2.Rot_GetAngle(def.body_def.rotation)
|
|
|
|
if im.SliderFloat("Rotation", &angle, 0, 359)
|
|
{
|
|
def.body_def.rotation = b2.MakeRot(draw.DEG2RAD * angle)
|
|
}
|
|
|
|
im.SliderFloat2("Linear velocity", &def.body_def.linearVelocity, 0, 500)
|
|
im.SliderFloat( "Angular velocity", &def.body_def.angularVelocity, 0, 500)
|
|
im.SliderFloat( "Linear Damping", &def.body_def.linearDamping, 0, 500)
|
|
im.SliderFloat( "Angular Damping", &def.body_def.angularDamping, 0, 500)
|
|
im.SliderFloat( "Gravity Scale", &def.body_def.gravityScale, 0, 100)
|
|
im.Checkbox( "Fixed rotation", &def.body_def.fixedRotation)
|
|
|
|
if im.InputText("Body Name", cstring(&def.name_buf[0]), 255)
|
|
{
|
|
def.body_def.name = cstring(&def.name_buf[0])
|
|
}
|
|
}
|
|
|
|
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]
|
|
|
|
level := interface.world
|
|
|
|
|
|
if level.relations[entity.index] == nil
|
|
{
|
|
level.relations[entity.index] = {}
|
|
}
|
|
|
|
indexes := &level.relations[entity.index]
|
|
|
|
if im.InputInt("Index Value", &def.index) do return true
|
|
|
|
ret := false
|
|
|
|
if def.index != 0
|
|
{
|
|
//For now only select from current room
|
|
|
|
if im.BeginCombo("Edit Select index", fmt.ctprint(curr_index.index))
|
|
{
|
|
for index in level.static_indexes
|
|
{
|
|
if im.Selectable(fmt.ctprint(index), curr_index.index == index)
|
|
{
|
|
curr_index.index = index
|
|
}
|
|
}
|
|
im.EndCombo()
|
|
}
|
|
if curr_index.index != 0
|
|
{
|
|
if indexes != nil
|
|
{
|
|
if im.Button("Add relation")
|
|
{
|
|
if !slice.contains(indexes[:], interface.curr_static_index)
|
|
{
|
|
append(indexes, interface.curr_static_index)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if indexes != nil{
|
|
for val, i in indexes
|
|
{
|
|
im.Text("%d", val.index)
|
|
im.SameLine()
|
|
if im.Button("Delete") {
|
|
ordered_remove(indexes, i)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
|
|
interface_shape_def_editor :: proc(def: ^engine_entity_def) -> bool
|
|
{
|
|
shape_def := &def.shape_def
|
|
|
|
|
|
if im.BeginCombo("Shape Type", fmt.ctprint(def.shape_type)) {
|
|
|
|
for type in b2.ShapeType
|
|
{
|
|
if im.Selectable(fmt.ctprint(type), def.shape_type == type)
|
|
{
|
|
def.shape_type = type
|
|
}
|
|
}
|
|
|
|
im.EndCombo()
|
|
}
|
|
|
|
switch def.shape_type {
|
|
|
|
case .circleShape:
|
|
{
|
|
im.SliderFloat("radius", &def.radius, 0, 40)
|
|
}
|
|
|
|
case .polygonShape:
|
|
{
|
|
im.SliderFloat2("Size", &def.size, -500, 500)
|
|
}
|
|
|
|
case .capsuleShape:
|
|
{
|
|
im.SliderFloat2("Center 1", &def.centers[0], -100, 100)
|
|
im.SliderFloat2("Center 2", &def.centers[1], -100, 100)
|
|
im.SliderFloat("Radius", &def.radius, 0, 40)
|
|
}
|
|
|
|
case .chainSegmentShape:
|
|
{
|
|
im.Checkbox("is loop", &def.is_loop)
|
|
}
|
|
|
|
case .segmentShape:
|
|
{
|
|
//TODO
|
|
}
|
|
|
|
}
|
|
|
|
im.SliderFloat("Density", &def.shape_def.density, 0, 100)
|
|
|
|
if im.Button("Flip horizontally") do flip_points(def.vertices[:], .Horizontal)
|
|
if im.Button("Flip Vertically ") do flip_points(def.vertices[:], .Vertical)
|
|
|
|
if im.TreeNode("Events and contacts") {
|
|
im.Checkbox("Is sensor", &def.shape_def.isSensor)
|
|
im.Checkbox("Enable Sensor Events", &def.shape_def.enableSensorEvents)
|
|
im.Checkbox("Enable Contact Events", &def.shape_def.enableContactEvents)
|
|
im.Checkbox("Enable Hit Events", &def.shape_def.enableHitEvents)
|
|
im.Checkbox("Enable Presolve Events", &def.shape_def.enablePreSolveEvents)
|
|
im.Checkbox("Invoke contact Creation", &def.shape_def.invokeContactCreation)
|
|
im.Checkbox("Update body mass ", &def.shape_def.updateBodyMass)
|
|
im.TreePop()
|
|
}
|
|
|
|
if im.TreeNode("Material") {
|
|
im.Separator()
|
|
|
|
im.SliderFloat("Friction", &def.shape_def.material.friction, 0, 1)
|
|
im.SliderFloat("Restitution", &def.shape_def.material.restitution, 0, 1)
|
|
im.SliderFloat("Rolling Resistance", &def.shape_def.material.rollingResistance, 0, 1)
|
|
im.SliderFloat("Tangent Speed", &def.shape_def.material.tangentSpeed, 0, 1)
|
|
im.InputInt("User material id", &def.shape_def.material.userMaterialId)
|
|
|
|
//Colorpicker
|
|
|
|
if im.TreeNode("Color") {
|
|
color_f32 := u32_to_float4(def.shape_def.material.customColor)
|
|
|
|
if im.ColorPicker4("Custom Color", &color_f32, {.Uint8, .InputRGB}) {
|
|
def.shape_def.material.customColor = float4_to_u32(color_f32)
|
|
}
|
|
im.TreePop()
|
|
}
|
|
|
|
im.Separator()
|
|
im.TreePop()
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
interface_entity :: proc(interface: ^interface_state) -> bool
|
|
{
|
|
entity_selected := (interface.selected_entity != -1) && len(interface.entity_defs) > 0
|
|
|
|
if entity_selected
|
|
{
|
|
def := interface.entity_defs[interface.selected_entity]
|
|
def_old := def^
|
|
|
|
ret := false
|
|
|
|
//interface.edit_mode = .ENTITY
|
|
//Flags
|
|
for flag in engine_entity_flags_enum
|
|
{
|
|
contains := flag in def.entity_flags
|
|
if im.Checkbox(fmt.ctprint(flag), &contains) do def.entity_flags ~= {flag}
|
|
}
|
|
|
|
im.Separator()
|
|
|
|
if im.CollapsingHeader("Shape Edit")
|
|
{
|
|
interface_shape_def_editor(def)
|
|
}
|
|
|
|
im.Separator()
|
|
|
|
if im.CollapsingHeader("Body Edit")
|
|
{
|
|
interface_body_def_editor(def)
|
|
}
|
|
|
|
if im.CollapsingHeader("Static Index")
|
|
{
|
|
ret |= interface_edit_static_index(interface, def)
|
|
}
|
|
|
|
if .CHAIN in def.entity_flags
|
|
{
|
|
im.InputInt("Body Count", &def.body_count)
|
|
//im.SliderFloat2("Half Link Length", &def.link_length, -10, 10)
|
|
|
|
if im.CollapsingHeader("Chain joint def")
|
|
{
|
|
interface_edit_rev_joint_minimal(&def.rev_joint)
|
|
}
|
|
}
|
|
|
|
return !compare_engine_entity_def(def^, def_old) || ret
|
|
}
|
|
|
|
return false
|
|
}
|