#ifndef PROC_NODES_PROC_CURVES_H
#define PROC_NODES_PROC_CURVES_H
#include "attribute_storage.h"
#include "offset_indices.h"
#include <godot_cpp/classes/ref_counted.hpp>
#include <godot_cpp/variant/packed_float32_array.hpp>
#include <godot_cpp/variant/packed_int32_array.hpp>
#include <godot_cpp/variant/packed_vector3_array.hpp>
namespace godot {
enum class CurveType : int32_t {
Poly = 0,
CatmullRom = 1,
Bezier = 2,
};
class ProcCurves : public RefCounted {
GDCLASS(ProcCurves, RefCounted);
protected:
static void _bind_methods();
public:
// All control points, contiguous (grouped by curve via curve_offsets)
PackedVector3Array positions;
PackedFloat32Array radii;
PackedFloat32Array tilts;
PackedInt32Array curve_offsets; // OffsetIndices raw data
PackedInt32Array curve_types; // Per-curve CurveType
// PER-CURVE CYCLIC FLAG. Blender's Curve Circle is a closed loop of
// `resolution` points; without this the only way to spell that was to
// repeat the first point, which is one point more than Blender for the same
// resolution and leaves a seam where the duplicate sits. Absent or 0 means
// open, so every curve that existed before behaves as it did.
PackedInt32Array curve_cyclic;
AttributeStorage point_attrs;
AttributeStorage curve_attrs;
int point_count() const { return positions.size(); }
int curve_count() const;
int domain_size(AttrDomain p_domain) const;
OffsetIndices get_offset_indices() const { return OffsetIndices(curve_offsets); }
Ref<ProcCurves> duplicate_curves() const;
// Evaluate position at parameter t (0..1) on curve index p_curve
Vector3 evaluate_position(int p_curve, float p_t) const;
Vector3 evaluate_position_cyclic(int p_curve, float p_t) const;
// Sample a curve at `count` points spaced evenly BY ARC LENGTH, both ends
// included. Blender resamples by length, not by parameter, and the two
// agree only when every segment is the same length -- which is why a line
// and a regular circle matched while a bezier did not.
PackedVector3Array sample_uniform(int p_curve, int p_count) const;
bool is_cyclic(int p_curve) const {
return p_curve >= 0 && p_curve < curve_cyclic.size() && curve_cyclic[p_curve] != 0;
}
// Evaluate tangent at parameter t (0..1) on curve index p_curve
Vector3 evaluate_tangent(int p_curve, float p_t) const;
// Get total arc length of a curve (approximated by summing segment lengths)
float approximate_length(int p_curve, int p_samples = 32) const;
ProcCurves() = default;
};
} // namespace godot
#endif // PROC_NODES_PROC_CURVES_H