292 lines
8.4 KiB
C++
292 lines
8.4 KiB
C++
#pragma once
|
|
|
|
#include "animation/animation.h"
|
|
#include "engine/array.h"
|
|
#include "engine/math.h"
|
|
#include "engine/stream.h"
|
|
#include "engine/string.h"
|
|
|
|
// Runtime part of animation nodes
|
|
// For editor part of animation nodes see editor_nodes.h
|
|
|
|
namespace Lumix {
|
|
|
|
struct Model;
|
|
struct Pose;
|
|
|
|
namespace anim {
|
|
|
|
struct Controller;
|
|
|
|
enum class NodeType : u32 {
|
|
ANIMATION,
|
|
BLEND1D,
|
|
LAYERS,
|
|
NONE,
|
|
SELECT,
|
|
BLEND2D,
|
|
TREE,
|
|
OUTPUT,
|
|
INPUT,
|
|
SWITCH,
|
|
CMP_EQ,
|
|
CMP_NEQ,
|
|
CMP_LT,
|
|
CMP_GT,
|
|
CMP_LTE,
|
|
CMP_GTE,
|
|
MUL,
|
|
DIV,
|
|
ADD,
|
|
SUB,
|
|
CONSTANT,
|
|
AND,
|
|
OR,
|
|
PLAYRATE,
|
|
IK
|
|
};
|
|
|
|
struct Node {
|
|
static Node* create(NodeType type, Controller& controller);
|
|
|
|
virtual ~Node() {}
|
|
virtual NodeType type() const = 0;
|
|
virtual void serialize(OutputMemoryStream& stream) const = 0;
|
|
virtual void deserialize(InputMemoryStream& stream, Controller& ctrl, u32 version) = 0;
|
|
};
|
|
|
|
void serializeNode(OutputMemoryStream& blob, const Node& node);
|
|
Node* deserializeNode(InputMemoryStream& blob, Controller& ctrl, u32 version);
|
|
|
|
struct PoseNode : Node {
|
|
virtual void update(RuntimeContext& ctx) const = 0;
|
|
virtual void enter(RuntimeContext& ctx) = 0;
|
|
virtual void skip(RuntimeContext& ctx) const = 0;
|
|
virtual Time length(const RuntimeContext& ctx) const = 0;
|
|
virtual Time time(const RuntimeContext& ctx) const = 0;
|
|
};
|
|
|
|
struct ValueNode : Node {
|
|
virtual Value eval(const RuntimeContext& ctx) const = 0;
|
|
};
|
|
|
|
struct InputNode final : ValueNode {
|
|
NodeType type() const override { return anim::NodeType::INPUT; }
|
|
void serialize(OutputMemoryStream& stream) const override;
|
|
void deserialize(InputMemoryStream& stream, Controller& ctrl, u32 version) override;
|
|
Value eval(const RuntimeContext& ctx) const override;
|
|
|
|
u32 m_input_index;
|
|
};
|
|
|
|
struct ConstNode final : ValueNode {
|
|
NodeType type() const override { return anim::NodeType::CONSTANT; }
|
|
void serialize(OutputMemoryStream& stream) const override;
|
|
void deserialize(InputMemoryStream& stream, Controller& ctrl, u32 version) override;
|
|
Value eval(const RuntimeContext& ctx) const override;
|
|
|
|
Value m_value;
|
|
};
|
|
|
|
template <NodeType T>
|
|
struct MathNode final : ValueNode {
|
|
NodeType type() const override { return T; }
|
|
|
|
void serialize(OutputMemoryStream& stream) const override {
|
|
serializeNode(stream, *m_input0);
|
|
serializeNode(stream, *m_input1);
|
|
}
|
|
|
|
void deserialize(InputMemoryStream& stream, Controller& ctrl, u32 version) override {
|
|
m_input0 = (ValueNode*)deserializeNode(stream, ctrl, version);
|
|
m_input1 = (ValueNode*)deserializeNode(stream, ctrl, version);
|
|
}
|
|
|
|
Value eval(const RuntimeContext& ctx) const override {
|
|
Value v0 = m_input0->eval(ctx);
|
|
Value v1 = m_input1->eval(ctx);
|
|
// TODO other types
|
|
if constexpr (T == NodeType::CMP_GT) return v0.f > v1.f;
|
|
else if constexpr (T == NodeType::CMP_GTE) return v0.f >= v1.f;
|
|
else if constexpr (T == NodeType::CMP_LT) return v0.f < v1.f;
|
|
else if constexpr (T == NodeType::CMP_LTE) return v0.f <= v1.f;
|
|
else if constexpr (T == NodeType::CMP_NEQ) return v0.f != v1.f;
|
|
else if constexpr (T == NodeType::CMP_EQ) return v0.f == v1.f;
|
|
|
|
else if constexpr (T == NodeType::AND) return v0.b && v1.b;
|
|
else if constexpr (T == NodeType::OR) return v0.b || v1.b;
|
|
|
|
else if constexpr (T == NodeType::MUL) return v0.f * v1.f;
|
|
else if constexpr (T == NodeType::DIV) return v0.f / v1.f;
|
|
else if constexpr (T == NodeType::ADD) return v0.f + v1.f;
|
|
else if constexpr (T == NodeType::SUB) return v0.f - v1.f;
|
|
else {
|
|
ASSERT(false);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
ValueNode* m_input0 = nullptr;
|
|
ValueNode* m_input1 = nullptr;
|
|
};
|
|
|
|
struct PlayRateNode final : PoseNode {
|
|
PlayRateNode(IAllocator& allocator);
|
|
~PlayRateNode();
|
|
NodeType type() const override { return anim::NodeType::PLAYRATE; }
|
|
void serialize(OutputMemoryStream& stream) const override;
|
|
void deserialize(InputMemoryStream& stream, Controller& ctrl, u32 version) override;
|
|
void update(RuntimeContext& ctx) const override;
|
|
void enter(RuntimeContext& ctx) override;
|
|
void skip(RuntimeContext& ctx) const override;
|
|
Time length(const RuntimeContext& ctx) const override;
|
|
Time time(const RuntimeContext& ctx) const override;
|
|
|
|
IAllocator& m_allocator;
|
|
ValueNode* m_value = nullptr;
|
|
PoseNode* m_node = nullptr;
|
|
};
|
|
|
|
struct Blend1DNode final : PoseNode {
|
|
Blend1DNode(IAllocator& allocator);
|
|
~Blend1DNode();
|
|
NodeType type() const override { return anim::NodeType::BLEND1D; }
|
|
void serialize(OutputMemoryStream& stream) const override;
|
|
void deserialize(InputMemoryStream& stream, Controller& ctrl, u32 version) override;
|
|
void update(RuntimeContext& ctx) const override;
|
|
void enter(RuntimeContext& ctx) override;
|
|
void skip(RuntimeContext& ctx) const override;
|
|
Time length(const RuntimeContext& ctx) const override;
|
|
Time time(const RuntimeContext& ctx) const override;
|
|
|
|
struct Child {
|
|
float value = 0;
|
|
u32 slot = 0;
|
|
};
|
|
|
|
IAllocator& m_allocator;
|
|
Array<Child> m_children;
|
|
ValueNode* m_value = nullptr;
|
|
};
|
|
|
|
|
|
struct Blend2DNode final : PoseNode {
|
|
Blend2DNode(IAllocator& allocator);
|
|
~Blend2DNode();
|
|
NodeType type() const override { return anim::NodeType::BLEND2D; }
|
|
void serialize(OutputMemoryStream& stream) const override;
|
|
void deserialize(InputMemoryStream& stream, Controller& ctrl, u32 version) override;
|
|
void update(RuntimeContext& ctx) const override;
|
|
void enter(RuntimeContext& ctx) override;
|
|
void skip(RuntimeContext& ctx) const override;
|
|
Time length(const RuntimeContext& ctx) const override;
|
|
Time time(const RuntimeContext& ctx) const override;
|
|
|
|
struct Child {
|
|
Vec2 value = Vec2(0);
|
|
u32 slot = 0;
|
|
};
|
|
|
|
struct Triangle {
|
|
u32 a, b, c;
|
|
Vec2 circumcircle_center;
|
|
};
|
|
|
|
IAllocator& m_allocator;
|
|
Array<Triangle> m_triangles;
|
|
Array<Child> m_children;
|
|
ValueNode* m_x_value = nullptr;
|
|
ValueNode* m_y_value = nullptr;
|
|
};
|
|
|
|
struct SelectNode final : PoseNode {
|
|
struct RuntimeData {
|
|
u32 from;
|
|
u32 to;
|
|
Time t;
|
|
};
|
|
|
|
SelectNode(IAllocator& allocator);
|
|
~SelectNode();
|
|
NodeType type() const override { return anim::NodeType::SELECT; }
|
|
void serialize(OutputMemoryStream& stream) const override;
|
|
void deserialize(InputMemoryStream& stream, Controller& ctrl, u32 version) override;
|
|
void update(RuntimeContext& ctx) const override;
|
|
void enter(RuntimeContext& ctx) override;
|
|
void skip(RuntimeContext& ctx) const override;
|
|
Time length(const RuntimeContext& ctx) const override;
|
|
Time time(const RuntimeContext& ctx) const override;
|
|
|
|
IAllocator& m_allocator;
|
|
Array<PoseNode*> m_children;
|
|
ValueNode* m_value = nullptr;
|
|
Time m_blend_length;
|
|
};
|
|
|
|
struct SwitchNode final : PoseNode {
|
|
struct RuntimeData {
|
|
bool current;
|
|
bool switching;
|
|
Time t;
|
|
};
|
|
|
|
SwitchNode(IAllocator& allocator);
|
|
~SwitchNode();
|
|
NodeType type() const override { return anim::NodeType::SWITCH; }
|
|
void serialize(OutputMemoryStream& stream) const override;
|
|
void deserialize(InputMemoryStream& stream, Controller& ctrl, u32 version) override;
|
|
void update(RuntimeContext& ctx) const override;
|
|
void enter(RuntimeContext& ctx) override;
|
|
void skip(RuntimeContext& ctx) const override;
|
|
Time length(const RuntimeContext& ctx) const override;
|
|
Time time(const RuntimeContext& ctx) const override;
|
|
|
|
IAllocator& m_allocator;
|
|
PoseNode* m_true_node = nullptr;
|
|
PoseNode* m_false_node = nullptr;
|
|
ValueNode* m_value = nullptr;
|
|
Time m_blend_length;
|
|
};
|
|
|
|
struct IKNode final : PoseNode {
|
|
IKNode(IAllocator& allocator);
|
|
~IKNode();
|
|
NodeType type() const override { return anim::NodeType::IK; }
|
|
void serialize(OutputMemoryStream& stream) const override;
|
|
void deserialize(InputMemoryStream& stream, Controller& ctrl, u32 version) override;
|
|
void update(RuntimeContext& ctx) const override;
|
|
void enter(RuntimeContext& ctx) override;
|
|
void skip(RuntimeContext& ctx) const override;
|
|
Time length(const RuntimeContext& ctx) const override;
|
|
Time time(const RuntimeContext& ctx) const override;
|
|
|
|
IAllocator& m_allocator;
|
|
ValueNode* m_alpha = nullptr;
|
|
ValueNode* m_effector_position = nullptr;
|
|
PoseNode* m_input = nullptr;
|
|
u32 m_leaf_bone;
|
|
u32 m_bones_count;
|
|
};
|
|
|
|
struct AnimationNode final : PoseNode {
|
|
NodeType type() const override { return anim::NodeType::ANIMATION; }
|
|
void serialize(OutputMemoryStream& stream) const override;
|
|
void deserialize(InputMemoryStream& stream, Controller& ctrl, u32 version) override;
|
|
void update(RuntimeContext& ctx) const override;
|
|
void enter(RuntimeContext& ctx) override;
|
|
void skip(RuntimeContext& ctx) const override;
|
|
Time length(const RuntimeContext& ctx) const override;
|
|
Time time(const RuntimeContext& ctx) const override;
|
|
|
|
enum Flags : u32 {
|
|
LOOPED = 1 << 0
|
|
};
|
|
|
|
u32 m_slot = 0;
|
|
u32 m_flags = LOOPED;
|
|
};
|
|
|
|
|
|
} // namespace anim
|
|
} // namespace Lumix
|