Highlight selected points in Path3DEditor

This commit is contained in:
Silc Lizard (Tokage) Renew 2026-01-13 19:16:52 +09:00
parent 56f3e2611d
commit 163b498d39
2 changed files with 54 additions and 43 deletions

View file

@ -245,6 +245,10 @@ void Path3DGizmo::commit_handle(int p_id, bool p_secondary, const Variant &p_res
return;
}
if (!Path3DEditorPlugin::singleton) {
return;
}
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
// Primary handles: position.
@ -765,6 +769,12 @@ EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_3d_gui_input(Camera3D *p
return EditorPlugin::AFTER_GUI_INPUT_PASS;
}
void Path3DEditorPlugin::update_handles() {
if (_edit.gizmo.is_valid()) {
callable_mp(_edit.gizmo.ptr(), &Path3DGizmo::redraw).call_deferred();
}
}
void Path3DEditorPlugin::edit(Object *p_object) {
path = Object::cast_to<Path3D>(p_object);
_update_toolbar();
@ -1117,54 +1127,41 @@ void Path3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Ref<StandardMaterial3D> first_pt_handle_material = get_material("first_pt_handle", p_gizmo);
Ref<StandardMaterial3D> last_pt_handle_material = get_material("last_pt_handle", p_gizmo);
Ref<StandardMaterial3D> closed_pt_handle_material = get_material("closed_pt_handle", p_gizmo);
Ref<StandardMaterial3D> selected_pt_handle_material = get_material("selected_pt_handle", p_gizmo);
first_pt_handle_material->set_albedo(Color(0.2, 1.0, 0.0));
last_pt_handle_material->set_albedo(Color(1.0, 0.2, 0.0));
closed_pt_handle_material->set_albedo(Color(1.0, 0.8, 0.0));
selected_pt_handle_material->set_albedo(Color(0.2, 0.5, 1.0));
PackedVector3Array handles;
if (Path3DEditorPlugin::singleton->curve_edit->is_pressed()) {
for (int idx = 0; idx < curve->get_point_count(); ++idx) {
// Collect handles.
const Vector3 pos = curve->get_point_position(idx);
handles.append(pos);
PackedInt32Array selected_points = p_gizmo->get_subgizmo_selection();
PackedVector3Array first_pt;
PackedVector3Array last_pt;
PackedVector3Array common_pt;
PackedVector3Array selected_pt;
int last = curve->get_point_count() - 1;
for (int i = 0; i <= last; i++) {
if (selected_points.has(i)) {
selected_pt.push_back(curve->get_point_position(i));
} else if (i == 0) {
first_pt.push_back(curve->get_point_position(i));
} else if (i == last) {
last_pt.push_back(curve->get_point_position(i));
} else {
common_pt.push_back(curve->get_point_position(i));
}
}
if (handles.size()) {
// Point count.
const int pc = handles.size();
// Initialize arrays for first point.
PackedVector3Array first_pt;
first_pt.append(handles[0]);
// Initialize arrays and add handle for last point if needed.
if (pc > 1) {
PackedVector3Array last_pt;
last_pt.append(handles[handles.size() - 1]);
handles.remove_at(handles.size() - 1);
if (curve->is_closed()) {
p_gizmo->add_vertices(last_pt, handle_material, Mesh::PRIMITIVE_POINTS);
} else {
p_gizmo->add_vertices(last_pt, last_pt_handle_material, Mesh::PRIMITIVE_POINTS);
}
}
// Add handle for first point.
handles.remove_at(0);
if (curve->is_closed()) {
p_gizmo->add_vertices(first_pt, closed_pt_handle_material, Mesh::PRIMITIVE_POINTS);
} else {
p_gizmo->add_vertices(first_pt, first_pt_handle_material, Mesh::PRIMITIVE_POINTS);
}
// Add handles for remaining intermediate points.
if (!handles.is_empty()) {
p_gizmo->add_vertices(handles, handle_material, Mesh::PRIMITIVE_POINTS);
}
if (first_pt.size()) {
p_gizmo->add_vertices(first_pt, curve->is_closed() ? closed_pt_handle_material : first_pt_handle_material, Mesh::PRIMITIVE_POINTS);
}
if (last_pt.size()) {
p_gizmo->add_vertices(last_pt, curve->is_closed() ? handle_material : last_pt_handle_material, Mesh::PRIMITIVE_POINTS);
}
if (common_pt.size()) {
p_gizmo->add_vertices(common_pt, handle_material, Mesh::PRIMITIVE_POINTS);
}
if (selected_pt.size()) {
p_gizmo->add_vertices(selected_pt, selected_pt_handle_material, Mesh::PRIMITIVE_POINTS);
}
}
@ -1174,15 +1171,22 @@ int Path3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo,
Ref<Curve3D> curve = path->get_curve();
ERR_FAIL_COND_V(curve.is_null(), -1);
int ret = -1;
if (Path3DEditorPlugin::singleton->curve_edit->is_pressed()) {
for (int idx = 0; idx < curve->get_point_count(); ++idx) {
Vector3 pos = path->get_global_transform().xform(curve->get_point_position(idx));
if (p_camera->unproject_position(pos).distance_to(p_point) < 20) {
return idx;
ret = idx;
break;
}
}
}
return -1;
if (Path3DEditorPlugin::singleton) {
Path3DEditorPlugin::singleton->update_handles();
}
return ret;
}
Vector<int> Path3DGizmoPlugin::subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const {
@ -1210,6 +1214,10 @@ Vector<int> Path3DGizmoPlugin::subgizmos_intersect_frustum(const EditorNode3DGiz
}
}
if (Path3DEditorPlugin::singleton) {
Path3DEditorPlugin::singleton->update_handles();
}
return contained_points;
}
@ -1283,5 +1291,6 @@ Path3DGizmoPlugin::Path3DGizmoPlugin() {
create_handle_material("first_pt_handle", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorPathSmoothHandle"), EditorStringName(EditorIcons)));
create_handle_material("last_pt_handle", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorPathSmoothHandle"), EditorStringName(EditorIcons)));
create_handle_material("closed_pt_handle", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorPathSmoothHandle"), EditorStringName(EditorIcons)));
create_handle_material("selected_pt_handle", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorPathSmoothHandle"), EditorStringName(EditorIcons)));
create_handle_material("sec_handles", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorCurveHandle"), EditorStringName(EditorIcons)));
}

View file

@ -169,6 +169,8 @@ protected:
public:
Path3D *get_edited_path() { return path; }
void update_handles();
inline static Path3DEditorPlugin *singleton = nullptr;
virtual EditorPlugin::AfterGUIInput forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) override;