Repository: godotengine/godot
File: editor/plugins/path_3d_editor_plugin.cpp (C++)

Code before:
	if (handles.size()) {
		p_gizmo->add_vertices(handles, handle_material, Mesh::PRIMITIVE_POINTS);
	}
}

int Path3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const {
	Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d());
	ERR_FAIL_NULL_V(path, -1);
	Ref<Curve3D> curve = path->get_curve();
	ERR_FAIL_COND_V(curve.is_null(), -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;
			}
		}
	}
	return -1;
}

Vector<int> Path3DGizmoPlugin::subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const {
	Vector<int> contained_points;

	Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d());
	ERR_FAIL_NULL_V(path, contained_points);
	Ref<Curve3D> curve = path->get_curve();
	ERR_FAIL_COND_V(curve.is_null(), contained_points);

	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));
			bool is_contained_in_frustum = true;
			for (int i = 0; i < p_frustum.size(); ++i) {
				if (p_frustum[i].distance_to(pos) > 0) {
					is_contained_in_frustum = false;
					break;
				}
			}

			if (is_contained_in_frustum) {
				contained_points.push_back(idx);
			}
		}
	}

	return contained_points;
}

Transform3D Path3DGizmoPlugin::get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const {

Review comment (suggestion):
Same as above:

```suggestion
	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));
```

Code after:
	Node3DEditor::get_singleton()->add_control_to_menu_panel(topmenu_bar);
}

Ref<EditorNode3DGizmo> Path3DGizmoPlugin::create_gizmo(Node3D *p_spatial) {
	Ref<Path3DGizmo> ref;

	Path3D *path = Object::cast_to<Path3D>(p_spatial);
	if (path) {
		ref = Ref<Path3DGizmo>(memnew(Path3DGizmo(path, disk_size)));
	}

	return ref;
}

bool Path3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
	return Object::cast_to<Path3D>(p_spatial) != nullptr;
}

String Path3DGizmoPlugin::get_gizmo_name() const {
	return "Path3D";
}

void Path3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
	Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d());
	ERR_FAIL_NULL(path);

	Ref<Curve3D> curve = path->get_curve();

	Ref<StandardMaterial3D> handle_material = get_material("handles", 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);

	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));

	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);
		}
	}

	if (handles.size()) {
		// Point count.
		const int pc = handles.size();