LumixEngine/src/animation/state_machine.h
2016-11-19 00:07:07 +01:00

194 lines
3.6 KiB
C++

#pragma once
#include "condition.h"
#include "engine/array.h"
#include "engine/blob.h"
#include "engine/lumix.h"
#include "renderer/pose.h"
namespace Lumix
{
class Animation;
class Engine;
class Model;
struct Pose;
struct Vec3;
class Path;
struct Quat;
namespace Anim
{
struct Container;
struct ComponentInstance;
struct StateMachine;
struct ComponentInstance
{
virtual ~ComponentInstance() {}
virtual ComponentInstance* update(RunningContext& rc) = 0;
virtual void fillPose(Engine& engine, Pose& pose, Model& model, float weight) = 0;
virtual void enter(RunningContext& rc, ComponentInstance* from) = 0;
virtual float getTime() const = 0;
virtual float getLength() const = 0;
};
struct Component
{
enum Type : int
{
SIMPLE_ANIMATION,
EDGE,
STATE_MACHINE
};
Component(Type _type) : type(_type), uid(-1) {}
virtual ~Component() {}
virtual ComponentInstance* createInstance(IAllocator& allocator) = 0;
virtual void serialize(OutputBlob& blob) { blob.write(uid); }
virtual void deserialize(InputBlob& blob, Container* parent) { blob.read(uid); }
int uid;
const Type type;
};
struct Edge;
struct Node : public Component
{
Node(Component::Type type, IAllocator& allocator)
: Component(type)
, out_edges(allocator)
{
}
void serializeEdges(OutputBlob& blob);
void deserializeEdges(InputBlob& blob, Container& parent);
Array<Edge*> out_edges;
};
struct Container : public Node
{
Container(Component::Type type, IAllocator& _allocator)
: Node(type, _allocator)
, children(_allocator)
, allocator(_allocator)
{
}
void serialize(OutputBlob& blob) override;
void deserialize(InputBlob& blob, Container* parent) override;
Component* getChildByUID(int uid)
{
for (auto* child : children)
{
if (child->uid == uid) return child;
}
return nullptr;
}
IAllocator& allocator;
Array<Component*> children;
};
struct Edge : public Component
{
Edge(IAllocator& allocator);
ComponentInstance* createInstance(IAllocator& allocator) override;
void serialize(OutputBlob& blob) override;
void deserialize(InputBlob& blob, Container* parent) override;
Condition condition;
Node* from;
Node* to;
float length;
};
struct NodeInstance : public ComponentInstance
{
ComponentInstance* checkOutEdges(Node& node, RunningContext& rc)
{
rc.current = this;
for (auto* edge : node.out_edges)
{
if (edge->condition(rc))
{
ComponentInstance* new_item = edge->createInstance(*rc.allocator);
new_item->enter(rc, this);
return new_item;
}
}
return this;
}
};
struct SimpleAnimationNode : public Node
{
SimpleAnimationNode(IAllocator& allocator);
ComponentInstance* createInstance(IAllocator& allocator) override;
void serialize(OutputBlob& blob) override;
void deserialize(InputBlob& blob, Container* parent) override;
uint32 animation_hash;
bool looped = true;
};
struct StateMachineInstance : public NodeInstance
{
StateMachineInstance(StateMachine& _source, IAllocator& _allocator);
ComponentInstance* update(RunningContext& rc) override;
void fillPose(Engine& engine, Pose& pose, Model& model, float weight) override;
void enter(RunningContext& rc, ComponentInstance* from) override;
float getTime() const override { return 0; }
float getLength() const override { return 0; }
StateMachine& source;
ComponentInstance* current;
IAllocator& allocator;
};
struct StateMachine : public Container
{
StateMachine(IAllocator& _allocator)
: Container(Component::STATE_MACHINE, _allocator)
{
}
ComponentInstance* createInstance(IAllocator& allocator) override;
Node* default_state;
};
Component* createComponent(Component::Type type, IAllocator& allocator);
} // namespace Anim
} // namespace Lumix