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

Code before:
						disk.append(pos + edge * disk_size);
					}
					add_vertices(disk, path_tilt_material, Mesh::PRIMITIVE_LINE_STRIP);
				}
			}
		}

		if (handle_lines.size() > 1) {
			add_lines(handle_lines, path_thin_material);
		}

		if (tilt_handle_lines.size() > 1) {
			add_lines(tilt_handle_lines, path_tilt_material);
		}

		if (!Path3DEditorPlugin::singleton->curve_edit->is_pressed() && primary_handle_points.size()) {
			add_handles(primary_handle_points, handles_material);
		}
		if (secondary_handle_points.size()) {
			add_handles(secondary_handle_points, sec_handles_material, collected_secondary_handle_ids, false, true);
		}
		// Draw the gizmo plugin manually, because handles are registered. In which case, the caller code skips drawing the gizmo plugin.
		gizmo_plugin->redraw(this);
	}
}

void Path3DGizmo::_update_transform_gizmo() {
	Node3DEditor::get_singleton()->update_transform_gizmo();
}

Path3DGizmo::Path3DGizmo(Path3D *p_path, float p_disk_size) {
	path = p_path;
	disk_size = p_disk_size;
	set_node_3d(p_path);
	orig_in_length = 0;
	orig_out_length = 0;

	// Connecting to a signal once, rather than plaguing the implementation with calls to `Node3DEditor::update_transform_gizmo`.
	path->connect("curve_changed", callable_mp(this, &Path3DGizmo::_update_transform_gizmo));

	Path3DEditorPlugin::singleton->curve_edit->connect(SceneStringName(pressed), callable_mp(this, &Path3DGizmo::redraw));
	Path3DEditorPlugin::singleton->curve_edit_curve->connect(SceneStringName(pressed), callable_mp(this, &Path3DGizmo::redraw));
	Path3DEditorPlugin::singleton->curve_create->connect(SceneStringName(pressed), callable_mp(this, &Path3DGizmo::redraw));
	Path3DEditorPlugin::singleton->curve_del->connect(SceneStringName(pressed), callable_mp(this, &Path3DGizmo::redraw));
	Path3DEditorPlugin::singleton->curve_close->connect(SceneStringName(pressed), callable_mp(this, &Path3DGizmo::redraw));
}

EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) {
	if (!path) {
		return EditorPlugin::AFTER_GUI_INPUT_PASS;
	}

Review comment (performance):
```suggestion
			int *idx_ptr = idx.ptrw();
			for (int j = 0; j < pc; j++) {
				idx_ptr[j] = j;
```
More efficient version, avoids COW

Code after:
					PackedVector3Array disk;
					disk.append(pos);

					const int n = 36;
					for (int i = 0; i <= n; i++) {
						const float a = Math_TAU * i / n;
						const Vector3 edge = sin(a) * side + cos(a) * up;
						disk.append(pos + edge * disk_size);
					}
					add_vertices(disk, path_tilt_material, Mesh::PRIMITIVE_LINE_STRIP);
				}
			}
		}

		if (handle_lines.size() > 1) {
			add_lines(handle_lines, path_thin_material);
		}

		if (tilt_handle_lines.size() > 1) {
			add_lines(tilt_handle_lines, path_tilt_material);
		}

		if (!Path3DEditorPlugin::singleton->curve_edit->is_pressed() && primary_handle_points.size()) {
			// Need to define indices separately.
			// Point count.
			const int pc = primary_handle_points.size();
			Vector<int> idx;
			idx.resize(pc);
			int *idx_ptr = idx.ptrw();
			for (int j = 0; j < pc; j++) {
				idx_ptr[j] = j;
			}

			// Initialize arrays for first point.
			PackedVector3Array first_pt_handle_point;
			Vector<int> first_pt_id;
			first_pt_handle_point.append(primary_handle_points[0]);
			first_pt_id.append(idx[0]);

			// Initialize arrays and add handle for last point if needed.
			if (pc > 1) {
				PackedVector3Array last_pt_handle_point;
				Vector<int> last_pt_id;
				last_pt_handle_point.append(primary_handle_points[pc - 1]);
				last_pt_id.append(idx[pc - 1]);
				primary_handle_points.remove_at(pc - 1);
				idx.remove_at(pc - 1);
				add_handles(last_pt_handle_point, c->is_closed() ? handles_material : last_pt_handle_material, last_pt_id);
			}

			// Add handle for first point.