// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
#pragma once
#include "../Actor.h"
#include "Engine/Animations/Curve.h"
///
/// Spline shape actor that defines spatial curve with utility functions for general purpose usage.
///
API_CLASS(Attributes="ActorContextMenu(\"New/Other/Spline\"), ActorToolbox(\"Other\")")
class FLAXENGINE_API Spline : public Actor
{
DECLARE_SCENE_OBJECT(Spline);
typedef BezierCurveKeyframe Keyframe;
private:
bool _loop = false;
BoundingBox _localBounds;
public:
///
/// The spline bezier curve points represented as series of transformations in 3D space (with tangents). Points are stored in local-space of the actor.
///
/// Ensure to call UpdateSpline() after editing curve to reflect the changes.
BezierCurve Curve;
///
/// Whether to use spline as closed loop. In that case, ensure to place start and end at the same location.
///
API_PROPERTY(Attributes="EditorOrder(0), EditorDisplay(\"Spline\")")
bool GetIsLoop() const;
///
/// Whether to use spline as closed loop. In that case, ensure to place start and end at the same location.
///
API_PROPERTY() void SetIsLoop(bool value);
public:
///
/// Evaluates the spline curve at the given time and calculates the point location in 3D (world-space).
///
/// The time value. Can be negative or larger than curve length (curve will loop or clamp).
/// The calculated curve point location (world-space).
API_FUNCTION() Vector3 GetSplinePoint(float time) const;
///
/// Evaluates the spline curve at the given time and calculates the point location in 3D (local-space).
///
/// The time value. Can be negative or larger than curve length (curve will loop or clamp).
/// The calculated curve point location (local-space).
API_FUNCTION() Vector3 GetSplineLocalPoint(float time) const;
///
/// Evaluates the spline curve at the given time and calculates the point rotation in 3D (world-space).
///
/// The time value. Can be negative or larger than curve length (curve will loop or clamp).
/// The calculated curve point rotation (world-space).
API_FUNCTION() Quaternion GetSplineOrientation(float time) const;
///
/// Evaluates the spline curve at the given time and calculates the point rotation in 3D (local-space).
///
/// The time value. Can be negative or larger than curve length (curve will loop or clamp).
/// The calculated curve point rotation (local-space).
API_FUNCTION() Quaternion GetSplineLocalOrientation(float time) const;
///
/// Evaluates the spline curve at the given time and calculates the point scale in 3D (world-space).
///
/// The time value. Can be negative or larger than curve length (curve will loop or clamp).
/// The calculated curve point scale (world-space).
API_FUNCTION() Vector3 GetSplineScale(float time) const;
///
/// Evaluates the spline curve at the given time and calculates the point scale in 3D (local-space).
///
/// The time value. Can be negative or larger than curve length (curve will loop or clamp).
/// The calculated curve point scale (local-space).
API_FUNCTION() Vector3 GetSplineLocalScale(float time) const;
///
/// Evaluates the spline curve at the given time and calculates the transformation in 3D (world-space).
///
/// The time value. Can be negative or larger than curve length (curve will loop or clamp).
/// The calculated curve point transformation (world-space).
API_FUNCTION() Transform GetSplineTransform(float time) const;
///
/// Evaluates the spline curve at the given time and calculates the transformation in 3D (local-space).
///
/// The time value. Can be negative or larger than curve length (curve will loop or clamp).
/// The calculated curve point transformation (local-space).
API_FUNCTION() Transform GetSplineLocalTransform(float time) const;
///
/// Evaluates the spline curve direction (forward vector, aka position 1st derivative) at the given time in 3D (world-space).
///
/// The time value. Can be negative or larger than curve length (curve will loop or clamp).
/// The calculated curve direction (world-space).
API_FUNCTION() Vector3 GetSplineDirection(float time) const;
///
/// Evaluates the spline curve direction (forward vector, aka position 1st derivative) at the given time in 3D (local-space).
///
/// The time value. Can be negative or larger than curve length (curve will loop or clamp).
/// The calculated curve direction (local-space).
API_FUNCTION() Vector3 GetSplineLocalDirection(float time) const;
///
/// Evaluates the spline curve at the given index (world-space).
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The curve point location (world-space).
API_FUNCTION() Vector3 GetSplinePoint(int32 index) const;
///
/// Evaluates the spline curve at the given index (local-space).
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The curve point location (local-space).
API_FUNCTION() Vector3 GetSplineLocalPoint(int32 index) const;
///
/// Evaluates the spline curve at the given index (world-space).
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The curve point transformation (world-space).
API_FUNCTION() Transform GetSplineTransform(int32 index) const;
///
/// Evaluates the spline curve at the given index (local-space).
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The curve point transformation (local-space).
API_FUNCTION() Transform GetSplineLocalTransform(int32 index) const;
///
/// Gets the spline curve point tangent at the given index (world-space).
///
/// Tangents are stored relative to the curve point but this methods converts them to be in world-space.
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// True if get arrive tangent, otherwise gets leave tangent (in or out).
/// The transformation of the tangent to set (world-space).
API_FUNCTION() Transform GetSplineTangent(int32 index, bool isIn);
///
/// Gets the spline curve point tangent at the given index (local-space).
///
/// Tangents are stored relative to the curve point but this methods converts them to be in local-space of the actor.
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// True if get arrive tangent, otherwise gets leave tangent (in or out).
/// The transformation of the tangent to set (world-space).
API_FUNCTION() Transform GetSplineLocalTangent(int32 index, bool isIn);
///
/// Gets the amount of points in the spline.
///
API_PROPERTY() int32 GetSplinePointsCount() const;
///
/// Gets the total duration of the spline curve (time of the last point).
///
API_PROPERTY() float GetSplineDuration() const;
///
/// Gets the total length of the spline curve (distance between all the points).
///
API_PROPERTY() float GetSplineLength() const;
///
/// Gets the length of the spline segment (distance between pair of two points).
///
/// The index of the segment end index. Zero-based, smaller than GetSplinePointsCount().
/// The spline segment length.
API_FUNCTION() float GetSplineSegmentLength(int32 index) const;
///
/// Gets the time of the spline keyframe.
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The spline time.
API_FUNCTION() float GetSplineTime(int32 index) const;
///
/// Calculates the closest point to the given location and returns the spline time at that point.
///
/// The point in world-space to find the spline point that is closest to it.
/// The spline time.
API_FUNCTION() float GetSplineTimeClosestToPoint(const Vector3& point) const;
///
/// Calculates the closest point to the given location.
///
/// The point in world-space to find the spline point that is closest to it.
/// The spline position.
API_FUNCTION() Vector3 GetSplinePointClosestToPoint(const Vector3& point) const;
///
/// Gets the spline curve points list (world-space).
///
/// The result points collection.
API_FUNCTION() void GetSplinePoints(API_PARAM(Out) Array& points) const;
///
/// Gets the spline curve points list (local-space).
///
/// The result points collection.
API_FUNCTION() void GetSplineLocalPoints(API_PARAM(Out) Array& points) const;
///
/// Gets the spline curve points list (world-space).
///
/// The result points collection.
API_FUNCTION() void GetSplinePoints(API_PARAM(Out) Array& points) const;
///
/// Gets the spline curve points list (local-space).
///
/// The result points collection.
API_FUNCTION() void GetSplineLocalPoints(API_PARAM(Out) Array& points) const;
public:
///
/// Clears the spline to be empty.
///
API_FUNCTION() void ClearSpline();
///
/// Removes the spline curve point at the given index.
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// True if update spline after removing the point, otherwise false.
API_FUNCTION() void RemoveSplinePoint(int32 index, bool updateSpline = true);
///
/// Sets the spline curve at the given index (world-space).
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The location of the point to set (world-space).
/// True if update spline after editing the point, otherwise false.
API_FUNCTION() void SetSplinePoint(int32 index, const Vector3& point, bool updateSpline = true);
///
/// Sets the spline curve at the given index (local-space).
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The location of the point to set (local-space).
/// True if update spline after editing the point, otherwise false.
API_FUNCTION() void SetSplineLocalPoint(int32 index, const Vector3& point, bool updateSpline = true);
///
/// Sets the spline curve at the given index (world-space).
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The transformation of the point to set (world-space).
/// True if update spline after editing the point, otherwise false.
API_FUNCTION() void SetSplineTransform(int32 index, const Transform& point, bool updateSpline = true);
///
/// Sets the spline curve at the given index (local-space).
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The transformation of the point to set (local-space).
/// True if update spline after editing the point, otherwise false.
API_FUNCTION() void SetSplineLocalTransform(int32 index, const Transform& point, bool updateSpline = true);
///
/// Sets the spline curve point tangent at the given index (world-space).
///
/// Tangents are stored relative to the curve point but this methods converts them to be in world-space.
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The transformation of the tangent to set (world-space).
/// True if set arrive tangent, otherwise sets leave tangent (in or out).
/// True if update spline after editing the point, otherwise false.
API_FUNCTION() void SetSplineTangent(int32 index, const Transform& point, bool isIn, bool updateSpline = true);
///
/// Sets the spline curve point tangent at the given index (local-space).
///
/// Tangents are stored relative to the curve point but this methods converts them to be in local-space of the actor.
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The transformation of the tangent to set (local-space).
/// True if set arrive tangent, otherwise sets leave tangent (in or out).
/// True if update spline after editing the point, otherwise false.
API_FUNCTION() void SetSplineLocalTangent(int32 index, const Transform& point, bool isIn, bool updateSpline = true);
///
/// Sets the spline curve point time at the given index (world-space).
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The time to set.
/// True if update spline after editing the point, otherwise false.
API_FUNCTION() void SetSplinePointTime(int32 index, float time, bool updateSpline = true);
///
/// Adds the point to the spline curve (at the end).
///
/// The location of the point to add to the curve (world-space).
/// True if update spline after editing the point, otherwise false.
API_FUNCTION() void AddSplinePoint(const Vector3& point, bool updateSpline = true);
///
/// Adds the point to the spline curve (at the end).
///
/// The location of the point to add to the curve (local-space).
/// True if update spline after adding the point, otherwise false.
API_FUNCTION() void AddSplineLocalPoint(const Vector3& point, bool updateSpline = true);
///
/// Adds the point to the spline curve (at the end).
///
/// The transformation of the point to add to the curve (world-space).
/// True if update spline after adding the point, otherwise false.
API_FUNCTION() void AddSplinePoint(const Transform& point, bool updateSpline = true);
///
/// Adds the point to the spline curve (at the end).
///
/// The transformation of the point to add to the curve (local-space).
/// True if update spline after adding the point, otherwise false.
API_FUNCTION() void AddSplineLocalPoint(const Transform& point, bool updateSpline = true);
///
/// Inserts the spline curve point at the given index (world-space).
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The time value.
/// The location of the point to add to the curve (world-space).
/// True if update spline after removing the point, otherwise false.
API_FUNCTION() void InsertSplinePoint(int32 index, float time, const Transform& point, bool updateSpline = true);
///
/// Inserts the spline curve point at the given index (local-space).
///
/// The curve keyframe index. Zero-based, smaller than GetSplinePointsCount().
/// The time value.
/// The location of the point to add to the curve (local-space).
/// True if update spline after removing the point, otherwise false.
API_FUNCTION() void InsertSplineLocalPoint(int32 index, float time, const Transform& point, bool updateSpline = true);
///
/// Updates the curve tangent points to make curve linear.
///
API_FUNCTION() void SetTangentsLinear();
///
/// Updates the curve tangent points to make curve smooth.
///
API_FUNCTION() void SetTangentsSmooth();
public:
///
/// Called when spline gets updated (eg. after curve modification).
///
API_EVENT() Action SplineUpdated;
///
/// Updates the spline after it was modified. Recreates the collision and/or any cached state that depends on the spline type.
///
API_FUNCTION() virtual void UpdateSpline();
protected:
#if USE_EDITOR
// Spline color getter for debug drawing, can be overriden by custom spline types.
virtual Color GetSplineColor()
{
return Color::White;
}
#endif
private:
// Internal bindings
#if !COMPILE_WITHOUT_CSHARP
API_FUNCTION(NoProxy) void GetKeyframes(MArray* data);
API_FUNCTION(NoProxy) void SetKeyframes(MArray* data, int32 keySize);
#endif
public:
// [Actor]
#if USE_EDITOR
void OnDebugDraw() override;
void OnDebugDrawSelected() override;
#endif
void OnTransformChanged() override;
void Initialize() override;
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
};