Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Path3D prefer control points for outward curve #104058

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion editor/plugins/path_3d_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,37 @@ void Path3DGizmo::set_handle(int p_id, bool p_secondary, Camera3D *p_camera, con
}

Vector3 local = gi.xform(inters) - base;

if (Node3DEditor::get_singleton()->is_snap_enabled()) {
float snap = Node3DEditor::get_singleton()->get_translate_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 = abs(delta.angle_to(p0)) < 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);
if (Path3DEditorPlugin::singleton->mirror_angle_enabled()) {
c->set_point_out(idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -local : (-local.normalized() * orig_out_length));
Expand Down Expand Up @@ -190,6 +215,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) {
swapped_control_points_idx = -1;
control_points_overlapped = false;

Ref<Curve3D> c = path->get_curve();
if (c.is_null()) {
return;
Expand Down
4 changes: 4 additions & 0 deletions editor/plugins/path_3d_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ class Path3DGizmo : public EditorNode3DGizmo {
mutable float orig_out_length;
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.
Vector<HandleInfo> _secondary_handles_info;

Expand Down
Loading