gutter_runner/game/editor.odin

185 lines
4.6 KiB
Odin

package game
import "core:fmt"
import lg "core:math/linalg"
import "game:physics/collision"
import "game:ui"
import rl "libs:raylib"
update_editor :: proc(es: ^Editor_State, dt: f32) {
free_camera_update(&es.camera)
did_undo_redo := false
if rl.IsKeyPressed(.Z) && rl.IsKeyDown(.LEFT_CONTROL) {
world_stack_pop(&es.world_stack)
did_undo_redo = true
}
if !did_undo_redo {
switch es.track_edit_state {
case .Select:
{
if rl.IsKeyPressed(.F) {
world_stack_push(&es.world_stack)
add_track_spline_point()
}
if is_point_selected() {
if rl.IsKeyPressed(.X) {
world_stack_push(&es.world_stack)
if len(es.point_selection) <= 1 {
for i in es.point_selection {
ordered_remove(&get_world().track.points, i)
}
} else {
#reverse for _, i in get_world().track.points {
if i in es.point_selection {
ordered_remove(&get_world().track.points, i)
}
}
}
clear(&es.point_selection)
}
if rl.IsKeyPressed(.G) {
track := &world_stack_current(&es.world_stack).track
selected_count := 0
es.move_initial_pos = 0
for k in es.point_selection {
es.move_initial_pos += track.points[k]
selected_count += 1
}
if selected_count > 0 {
es.move_initial_pos /= f32(selected_count)
es.track_edit_state = .Move
es.move_axis = .None
es.total_movement_world = {}
world_stack_push(&es.world_stack)
}
}
}
}
case .Move:
{
if rl.IsKeyPressed(.ESCAPE) {
es.track_edit_state = .Select
// g_mem.track.points[es.selected_track_point] = es.initial_point_pos
break
}
if (rl.IsMouseButtonPressed(.LEFT)) {
es.track_edit_state = .Select
break
}
if !es.mouse_captured {
// Blender style movement
if rl.IsKeyDown(.LEFT_SHIFT) {
if rl.IsKeyPressed(.X) {
es.move_axis = .YZ
}
if rl.IsKeyPressed(.Y) {
es.move_axis = .XZ
}
if rl.IsKeyPressed(.Z) {
es.move_axis = .XY
}
} else {
if rl.IsKeyPressed(.X) {
es.move_axis = .X
}
if rl.IsKeyPressed(.Y) {
es.move_axis = .Y
}
if rl.IsKeyPressed(.Z) {
es.move_axis = .Z
}
}
// log.debugf("Move axis %v", es.move_axis)
camera := game_camera_3d()
mouse_pos := rl.GetMousePosition()
prev_mouse_pos := es.prev_mouse_pos
prev_ray := rl.GetScreenToWorldRay(prev_mouse_pos, camera)
ray := rl.GetScreenToWorldRay(mouse_pos, camera)
axes_buf: [2]rl.Vector3
colors_buf: [2]rl.Color
axes, _ := get_movement_axes(es.move_axis, &axes_buf, &colors_buf)
movement_world: rl.Vector3
if len(axes) == 2 {
normal := lg.normalize0(lg.cross(axes[0], axes[1]))
plane := collision.plane_from_point_normal(es.move_initial_pos, normal)
_, pos1 := collision.intersect_ray_plane(
prev_ray.position,
prev_ray.direction,
plane,
)
_, pos2 := collision.intersect_ray_plane(
ray.position,
ray.direction,
plane,
)
world_delta := pos2 - pos1
world_delta -= lg.dot(world_delta, plane.normal) * plane.normal
movement_world += world_delta
} else if len(axes) == 1 {
for axis in axes {
tangent := lg.cross(es.move_initial_pos - camera.position, axis)
normal := lg.normalize0(lg.cross(axis, tangent))
plane := collision.plane_from_point_normal(es.move_initial_pos, normal)
_, pos1 := collision.intersect_ray_plane(
prev_ray.position,
prev_ray.direction,
plane,
)
_, pos2 := collision.intersect_ray_plane(
ray.position,
ray.direction,
plane,
)
world_delta := pos2 - pos1
movement_world += lg.dot(axis, world_delta) * axis
}
}
for k in es.point_selection {
get_world().track.points[k] += movement_world
}
es.total_movement_world += movement_world
}
}
}
}
es.prev_mouse_pos = rl.GetMousePosition()
ui_ctx := &g_mem.ui_context
if ui.window(ui_ctx, "Editor", ui.Rect{x = 500, y = 0, w = 500, h = 600}) {
cnt := ui.get_current_container(ui_ctx)
cnt.rect.w = max(cnt.rect.w, 500)
cnt.rect.h = max(cnt.rect.h, 600)
if .ACTIVE in ui.header(ui_ctx, "Details", {.EXPANDED}) {
ui.layout_row(ui_ctx, {100, -1})
ui.label(ui_ctx, "mov")
ui.label(ui_ctx, fmt.tprintf("%v", es.move_initial_pos))
}
}
world := world_stack_current(&es.world_stack)
config := World_Update_Config {
commit_physics = false,
}
update_world(world, dt, config)
}