Many editor improvements

This commit is contained in:
sergeypdev 2025-01-04 00:06:55 +04:00
parent 686d034b06
commit aa0f945b0c
2 changed files with 152 additions and 20 deletions

View File

@ -15,6 +15,9 @@
package game
import "assets"
import "core:c"
import "core:fmt"
import "core:log"
import "core:math"
import "core:math/linalg"
import rl "vendor:raylib"
@ -62,6 +65,7 @@ Editor_State :: struct {
point_selection: map[int]bool,
track_edit_state: Track_Edit_State,
move_axis: Move_Axis,
total_movement_world: rl.Vector3,
initial_point_pos: rl.Vector3,
}
@ -218,17 +222,25 @@ update_editor :: proc() {
if is_point_selected() {
if rl.IsKeyPressed(.X) {
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) {
es.track_edit_state = .Move
es.move_axis = .None
es.total_movement_world = {}
// es.initial_point_pos = g_mem.track.points[es.selected_track_point]
}
}
@ -297,6 +309,8 @@ update_editor :: proc() {
for k in es.point_selection {
get_world().track.points[k] += movement_world
}
es.total_movement_world += movement_world
}
}
}
@ -380,6 +394,12 @@ draw :: proc() {
// road_uvs.allocator = context.temp_allocator
// road_indices.allocator = context.temp_allocator
interpolated_points := calculate_spline_interpolated_points(
points[:],
context.temp_allocator,
)
{
// Debug draw spline road
{
@ -388,11 +408,6 @@ draw :: proc() {
rlgl.Color3f(1, 0, 0)
interpolated_points := calculate_spline_interpolated_points(
points[:],
context.temp_allocator,
)
debug_draw_spline(interpolated_points)
debug_draw_spline_mesh(interpolated_points)
}
@ -432,6 +447,18 @@ draw :: proc() {
if g_mem.editor {
rl.DrawText("Editor", 5, 5, 8, rl.ORANGE)
switch g_mem.es.track_edit_state {
case .Select:
case .Move:
rl.DrawText(
fmt.ctprintf("%v %v", g_mem.es.move_axis, g_mem.es.total_movement_world),
5,
16,
8,
rl.ORANGE,
)
}
}
}
@ -441,8 +468,67 @@ draw :: proc() {
points := &get_world().track.points
points_len := len(points)
if points_len > 0 {
// Add point before first
{
tangent: rl.Vector3
if points_len > 1 {
tangent = linalg.normalize0(points[1] - points[0])
} else {
tangent = rl.Vector3{-1, 0, 0}
}
new_point_pos := points[0] - tangent * 4
if (spline_handle(
new_point_pos,
camera,
false,
rl.GuiIconName.ICON_TARGET_POINT,
)) {
inject_at(&get_world().track.points, 0, new_point_pos)
log.debugf("add point before 0")
}
}
// Add point after last
{
tangent: rl.Vector3
if points_len > 1 {
tangent = linalg.normalize0(points[points_len - 1] - points[points_len - 2])
} else {
tangent = rl.Vector3{-1, 0, 0}
}
new_point_pos := points[points_len - 1] + tangent * 4
if (spline_handle(
new_point_pos,
camera,
false,
rl.GuiIconName.ICON_TARGET_POINT,
)) {
inject_at(&get_world().track.points, points_len - 1 + 1, new_point_pos)
log.debugf("add point before 0")
}
}
}
selected_point := false
for i in 0 ..< points_len {
if i < points_len - 1 {
t := (f32(i) + 0.5) / f32(points_len)
middle_pos := sample_spline(points[:], t)
if (spline_handle(middle_pos, camera, false, rl.GuiIconName.ICON_TARGET_POINT)) {
inject_at(&get_world().track.points, i + 1, middle_pos)
log.debugf("add point after %d", i)
}
}
if spline_handle(get_world().track.points[i], camera, es.point_selection[i]) {
if !rl.IsKeyDown(.LEFT_CONTROL) {
clear(&g_mem.es.point_selection)
@ -485,6 +571,8 @@ spline_handle :: proc(
world_pos: rl.Vector3,
camera: rl.Camera,
selected: bool,
icon := rl.GuiIconName.ICON_NONE,
size := f32(20),
) -> (
clicked: bool,
) {
@ -492,18 +580,28 @@ spline_handle :: proc(
return
}
pos := rl.GetWorldToScreen(world_pos, camera)
size := rl.Vector2{10, 10}
min, max := pos - size, pos + size
mouse_pos := rl.GetMousePosition()
is_hover :=
mouse_pos.x >= min.x &&
(mouse_pos.x >= min.x &&
mouse_pos.y >= min.y &&
mouse_pos.x <= max.x &&
mouse_pos.y <= max.y
mouse_pos.y <= max.y)
rl.DrawRectangleV(pos, size, selected ? rl.BLUE : (is_hover ? rl.ORANGE : rl.WHITE))
rl.DrawCircleV(pos, size / 2, selected ? rl.BLUE : (is_hover ? rl.ORANGE : rl.WHITE))
if icon != .ICON_NONE {
rl.GuiDrawIcon(
icon,
c.int(pos.x) - 7,
c.int(pos.y) - 7,
1,
selected || is_hover ? rl.WHITE : rl.BLACK,
)
}
// rl.DrawRectangleV(pos, size, selected ? rl.BLUE : (is_hover ? rl.ORANGE : rl.WHITE))
return rl.IsMouseButtonPressed(.LEFT) && is_hover
}

View File

@ -1,5 +1,7 @@
package game
import "base:builtin"
import "core:math"
import lg "core:math/linalg"
import rl "vendor:raylib"
import "vendor:raylib/rlgl"
@ -39,6 +41,39 @@ Interpolated_Point :: struct {
normal: rl.Vector3,
}
sample_spline :: proc(points: []rl.Vector3, t: f32) -> rl.Vector3 {
points_len := len(points)
if points_len >= 2 {
t_mul_len := math.saturate(t) * f32(len(points))
i := int(t_mul_len)
frac_t := t_mul_len - f32(i)
extended_start := points[0] + (points[0] - points[1])
extended_end := points[points_len - 1] + points[points_len - 1] - points[points_len - 2]
extended_end2 := extended_end + points[points_len - 1] - points[points_len - 2]
prev := i > 0 ? points[i - 1] : extended_start
current := points[i]
next := i < points_len - 1 ? points[i + 1] : extended_end
next2 := i < points_len - 2 ? points[i + 2] : extended_end2
a, b, c, d := catmull_rom_coefs(
prev,
current,
next,
next2,
CATMULL_ROM_ALPHA,
CATMULL_ROM_TENSION,
)
return catmull_rom(a, b, c, d, frac_t)
} else if len(points) == 1 {
return points[0]
}
return {}
}
calculate_spline_interpolated_points :: proc(
points: []rl.Vector3,
allocator := context.allocator,
@ -47,7 +82,6 @@ calculate_spline_interpolated_points :: proc(
ctrl_rotations := calculate_spline_ctrl_rotations(points, context.temp_allocator)
if points_len >= 2 {
interpolated_points := make(
[]Interpolated_Point,