1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-04 12:00:25 +00:00

Path3D prefer control points for outward curve

This commit is contained in:
dugramen
2025-03-12 19:32:25 -04:00
parent 30bb49ec1f
commit 8bef789ca6
2 changed files with 32 additions and 1 deletions

View File

@@ -149,7 +149,31 @@ void Path3DGizmo::set_handle(int p_id, bool p_secondary, Camera3D *p_camera, con
local.snapf(snap); local.snapf(snap);
} }
if (info.type == HandleType::HANDLE_TYPE_IN) { // Determine if control points should be swapped based on delta movement.
// Only run on the next update after an overlap is detected, to get proper delta movement.
if (control_points_overlapped) {
control_points_overlapped = false;
Vector3 delta = local - (info.type == HANDLE_TYPE_IN ? c->get_point_in(idx) : c->get_point_out(idx));
Vector3 p0 = c->get_point_position(idx - 1) - base;
Vector3 p1 = c->get_point_position(idx + 1) - base;
HandleType new_type = Math::abs(delta.angle_to(p0)) < Math::abs(delta.angle_to(p1)) ? HANDLE_TYPE_IN : HANDLE_TYPE_OUT;
if (info.type != new_type) {
swapped_control_points_idx = idx;
}
}
// Detect control points overlap.
bool control_points_equal = c->get_point_in(idx).is_equal_approx(c->get_point_out(idx));
if (idx > 0 && idx < (c->get_point_count() - 1) && control_points_equal) {
control_points_overlapped = true;
}
HandleType control_type = info.type;
if (swapped_control_points_idx == idx) {
control_type = info.type == HANDLE_TYPE_IN ? HANDLE_TYPE_OUT : HANDLE_TYPE_IN;
}
if (control_type == HandleType::HANDLE_TYPE_IN) {
c->set_point_in(idx, local); c->set_point_in(idx, local);
if (Path3DEditorPlugin::singleton->mirror_angle_enabled()) { if (Path3DEditorPlugin::singleton->mirror_angle_enabled()) {
c->set_point_out(idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -local : (-local.normalized() * orig_out_length)); c->set_point_out(idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -local : (-local.normalized() * orig_out_length));
@@ -190,6 +214,9 @@ void Path3DGizmo::set_handle(int p_id, bool p_secondary, Camera3D *p_camera, con
} }
void Path3DGizmo::commit_handle(int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { void Path3DGizmo::commit_handle(int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) {
swapped_control_points_idx = -1;
control_points_overlapped = false;
Ref<Curve3D> c = path->get_curve(); Ref<Curve3D> c = path->get_curve();
if (c.is_null()) { if (c.is_null()) {
return; return;

View File

@@ -60,6 +60,10 @@ class Path3DGizmo : public EditorNode3DGizmo {
mutable float orig_out_length; mutable float orig_out_length;
mutable float disk_size = 0.8; mutable float disk_size = 0.8;
// Index that should have swapped control points for achieving an outwards curve.
int swapped_control_points_idx = -1;
bool control_points_overlapped = false;
// Cache information of secondary handles. // Cache information of secondary handles.
Vector<HandleInfo> _secondary_handles_info; Vector<HandleInfo> _secondary_handles_info;