Repository: godotengine/godot
File: scene/resources/curve.h (C/C++)

Code before:

	real_t get_baked_length() const;
	Vector2 sample_baked(real_t p_offset, bool p_cubic = false) const;
	Transform2D sample_baked_with_rotation(real_t p_offset, bool p_cubic = false) const;
	PackedVector2Array get_baked_points() const; //useful for going through
	Vector2 get_closest_point(const Vector2 &p_to_point) const;
	real_t get_closest_offset(const Vector2 &p_to_point) const;

	PackedVector2Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; //useful for display
	PackedVector2Array tessellate_even_length(int p_max_stages = 5, real_t p_length = 20.0) const; // Useful for baking.

	Curve2D();
};

class Curve3D : public Resource {
	GDCLASS(Curve3D, Resource);

	struct Point {
		Vector3 in;
		Vector3 out;
		Vector3 position;
		real_t tilt = 0.0;
	};

	Vector<Point> points;

	mutable bool baked_cache_dirty = false;
	mutable PackedVector3Array baked_point_cache;
	mutable Vector<real_t> baked_tilt_cache;
	mutable PackedVector3Array baked_up_vector_cache;
	mutable PackedVector3Array baked_forward_vector_cache;
	mutable Vector<real_t> baked_dist_cache;
	mutable real_t baked_max_ofs = 0.0;

	void mark_dirty();

	static Vector3 _calculate_tangent(const Vector3 &p_begin, const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t);
	void _bake() const;

	struct Interval {
		int idx;
		real_t frac;
	};
	Interval _find_interval(real_t p_offset) const;
	Vector3 _sample_baked(Interval p_interval, bool p_cubic) const;
	real_t _sample_baked_tilt(Interval p_interval) const;
	Basis _sample_posture(Interval p_interval, bool p_apply_tilt = false) const;

	real_t bake_interval = 0.2;
	bool up_vector_enabled = true;


Review comment (performance):
I assume `points_in_cache` and `get_point_baked_posture()` should be implemented on the EditorPlugin to begin with. You should add the `"curve_baked"` signal to `Curve3D::_bake()` and calculate it on the EditorPlugin side with connecting Curve3D's curve_baked signal to `Path3DEditor::_curve_baked()`.

Code after:

	real_t get_baked_length() const;
	Vector2 sample_baked(real_t p_offset, bool p_cubic = false) const;
	Transform2D sample_baked_with_rotation(real_t p_offset, bool p_cubic = false) const;
	PackedVector2Array get_baked_points() const; //useful for going through
	Vector2 get_closest_point(const Vector2 &p_to_point) const;
	real_t get_closest_offset(const Vector2 &p_to_point) const;

	PackedVector2Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; //useful for display
	PackedVector2Array tessellate_even_length(int p_max_stages = 5, real_t p_length = 20.0) const; // Useful for baking.

	Curve2D();
};

class Curve3D : public Resource {
	GDCLASS(Curve3D, Resource);

	struct Point {
		Vector3 in;
		Vector3 out;
		Vector3 position;
		real_t tilt = 0.0;
	};

	Vector<Point> points;
#ifdef TOOLS_ENABLED
	// For Path3DGizmo.
	mutable Vector<size_t> points_in_cache;
#endif

	mutable bool baked_cache_dirty = false;
	mutable PackedVector3Array baked_point_cache;
	mutable Vector<real_t> baked_tilt_cache;
	mutable PackedVector3Array baked_up_vector_cache;
	mutable PackedVector3Array baked_forward_vector_cache;
	mutable Vector<real_t> baked_dist_cache;
	mutable real_t baked_max_ofs = 0.0;

	void mark_dirty();

	static Vector3 _calculate_tangent(const Vector3 &p_begin, const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t);
	void _bake() const;

	struct Interval {
		int idx;
		real_t frac;
	};
	Interval _find_interval(real_t p_offset) const;
	Vector3 _sample_baked(Interval p_interval, bool p_cubic) const;
	real_t _sample_baked_tilt(Interval p_interval) const;
	Basis _sample_posture(Interval p_interval, bool p_apply_tilt = false) const;