286 lines
No EOL
8 KiB
C++
286 lines
No EOL
8 KiB
C++
#pragma once
|
|
|
|
|
|
#include "animation/animation_system.h"
|
|
#include "animation/state_machine.h"
|
|
#include "engine/array.h"
|
|
#include "imgui/imgui.h"
|
|
|
|
|
|
namespace Lumix
|
|
{
|
|
class ResourceManagerBase;
|
|
namespace Anim
|
|
{
|
|
class ControllerResource;
|
|
}
|
|
}
|
|
|
|
|
|
namespace AnimEditor
|
|
{
|
|
|
|
|
|
class IAnimationEditor;
|
|
class Container;
|
|
class ControllerResource;
|
|
class Edge;
|
|
struct EntryNode;
|
|
|
|
|
|
class Component
|
|
{
|
|
public:
|
|
Component(Lumix::Anim::Component* _engine_cmp, Container* parent, ControllerResource& controller)
|
|
: engine_cmp(_engine_cmp)
|
|
, m_parent(parent)
|
|
, m_controller(controller)
|
|
{
|
|
}
|
|
|
|
virtual ~Component();
|
|
virtual bool draw(ImDrawList* draw, const ImVec2& canvas_screen_pos, bool selected) = 0;
|
|
virtual void onGUI() {}
|
|
virtual void serialize(Lumix::OutputBlob& blob) = 0;
|
|
virtual void deserialize(Lumix::InputBlob& blob) = 0;
|
|
virtual bool hitTest(const ImVec2& on_canvas_pos) const { return false; }
|
|
virtual bool isNode() const = 0;
|
|
virtual bool isContainer() const { return false; }
|
|
virtual void drawInside(ImDrawList* draw, const ImVec2& canvas_screen_pos) {}
|
|
Container* getParent() { return m_parent; }
|
|
virtual void compile() {}
|
|
virtual void debug(ImDrawList* draw, const ImVec2& canvas_screen_pos, Lumix::Anim::ComponentInstance* runtime) {}
|
|
virtual void debugInside(ImDrawList* draw,
|
|
const ImVec2& canvas_screen_pos,
|
|
Lumix::Anim::ComponentInstance* runtime,
|
|
Container* current)
|
|
{
|
|
}
|
|
ControllerResource& getController() { return m_controller; }
|
|
|
|
Lumix::Anim::Component* engine_cmp;
|
|
|
|
protected:
|
|
Container* m_parent;
|
|
ControllerResource& m_controller;
|
|
};
|
|
|
|
|
|
class Node : public Component
|
|
{
|
|
public:
|
|
Node(Lumix::Anim::Component* engine_cmp, Container* parent, ControllerResource& controller);
|
|
~Node();
|
|
|
|
bool isNode() const override { return true; }
|
|
bool hitTest(const ImVec2& on_canvas_pos) const override;
|
|
void onGUI() override;
|
|
void serialize(Lumix::OutputBlob& blob) override;
|
|
void deserialize(Lumix::InputBlob& blob) override;
|
|
bool draw(ImDrawList* draw, const ImVec2& canvas_screen_pos, bool selected) override;
|
|
void addEdge(Edge* edge) { m_edges.push(edge); }
|
|
void addInEdge(Edge* edge) { m_in_edges.push(edge); }
|
|
void removeEdge(Edge* edge) { m_edges.eraseItemFast(edge); }
|
|
void removeInEdge(Edge* edge) { m_in_edges.eraseItemFast(edge); }
|
|
void removeEvent(int index);
|
|
|
|
public:
|
|
ImVec2 pos;
|
|
ImVec2 size;
|
|
Lumix::StaticString<64> name;
|
|
|
|
protected:
|
|
Lumix::Array<Edge*> m_edges;
|
|
Lumix::Array<Edge*> m_in_edges;
|
|
Lumix::IAllocator& m_allocator;
|
|
};
|
|
|
|
|
|
class Container : public Node
|
|
{
|
|
public:
|
|
Container(Lumix::Anim::Component* engine_cmp, Container* parent, ControllerResource& controller);
|
|
~Container();
|
|
Component* childrenHitTest(const ImVec2& pos);
|
|
Component* getChildByUID(int uid);
|
|
Component* getSelectedComponent() const { return m_selected_component; }
|
|
void deserialize(Lumix::InputBlob& blob) override;
|
|
void serialize(Lumix::OutputBlob& blob) override;
|
|
void compile() override;
|
|
|
|
virtual void dropSlot(const char* name, Lumix::u32 slot, const ImVec2& canvas_screen_pos) {}
|
|
virtual void removeChild(Component* component);
|
|
bool isContainer() const override { return true; }
|
|
|
|
protected:
|
|
Lumix::Array<Component*> m_editor_cmps;
|
|
Component* m_selected_component;
|
|
};
|
|
|
|
|
|
|
|
class Edge : public Component
|
|
{
|
|
public:
|
|
Edge(Lumix::Anim::Edge* engine_cmp, Container* parent, ControllerResource& controller);
|
|
~Edge();
|
|
|
|
bool isNode() const override { return false; }
|
|
|
|
void onGUI() override;
|
|
bool draw(ImDrawList* draw, const ImVec2& canvas_screen_pos, bool selected) override;
|
|
void serialize(Lumix::OutputBlob& blob) override;
|
|
void deserialize(Lumix::InputBlob& blob) override;
|
|
void compile() override;
|
|
bool hitTest(const ImVec2& on_canvas_pos) const override;
|
|
const char* getExpression() const { return m_expression; }
|
|
void debug(ImDrawList* draw, const ImVec2& canvas_screen_pos, Lumix::Anim::ComponentInstance* runtime) override;
|
|
|
|
private:
|
|
Node* m_from;
|
|
Node* m_to;
|
|
char m_expression[128];
|
|
};
|
|
|
|
|
|
class AnimationNode : public Node
|
|
{
|
|
public:
|
|
AnimationNode(Lumix::Anim::Component* engine_cmp, Container* parent, ControllerResource& controller);
|
|
|
|
void compile() override;
|
|
void onGUI() override;
|
|
void debug(ImDrawList* draw, const ImVec2& canvas_screen_pos, Lumix::Anim::ComponentInstance* runtime) override;
|
|
void deserialize(Lumix::InputBlob& blob) override;
|
|
|
|
int root_rotation_input = -1;
|
|
};
|
|
|
|
|
|
class Blend1DNode : public Container
|
|
{
|
|
public:
|
|
struct RootEdge;
|
|
struct RootNode : public Node
|
|
{
|
|
RootNode(Container* parent, ControllerResource& controller);
|
|
|
|
Lumix::Array<RootEdge*> edges;
|
|
};
|
|
|
|
public:
|
|
Blend1DNode(Lumix::Anim::Component* engine_cmp, Container* parent, ControllerResource& controller);
|
|
|
|
void compile() override;
|
|
void onGUI() override;
|
|
void debug(ImDrawList* draw, const ImVec2& canvas_screen_pos, Lumix::Anim::ComponentInstance* runtime) override;
|
|
void serialize(Lumix::OutputBlob& blob) override;
|
|
void deserialize(Lumix::InputBlob& blob) override;
|
|
void drawInside(ImDrawList* draw, const ImVec2& canvas_screen_pos) override;
|
|
RootNode* getRootNode() const { return m_root_node; }
|
|
void removeChild(Component* component) override;
|
|
void dropSlot(const char* name, Lumix::u32 slot, const ImVec2& canvas_screen_pos) override;
|
|
void debugInside(ImDrawList* draw,
|
|
const ImVec2& canvas_screen_pos,
|
|
Lumix::Anim::ComponentInstance* runtime,
|
|
Container* current) override;
|
|
|
|
private:
|
|
void createState(Lumix::Anim::Component::Type type, const ImVec2& pos);
|
|
RootEdge* createRootEdge(Node* node);
|
|
|
|
private:
|
|
enum MouseStatus
|
|
{
|
|
NONE,
|
|
DOWN_LEFT,
|
|
DOWN_RIGHT,
|
|
DRAG_NODE,
|
|
NEW_EDGE
|
|
} m_mouse_status;
|
|
int m_input = -1;
|
|
Node* m_drag_source = nullptr;
|
|
RootNode* m_root_node;
|
|
Component* m_context_cmp = nullptr;
|
|
};
|
|
|
|
|
|
struct EntryNode : public Node
|
|
{
|
|
EntryNode(Container* parent, ControllerResource& controller);
|
|
|
|
Lumix::Array<struct EntryEdge*> entries;
|
|
};
|
|
|
|
|
|
class StateMachine : public Container
|
|
{
|
|
public:
|
|
StateMachine(Lumix::Anim::Component* engine_cmp, Container* parent, ControllerResource& controller);
|
|
|
|
void drawInside(ImDrawList* draw, const ImVec2& canvas_screen_pos) override;
|
|
void onGUI() override;
|
|
void debugInside(ImDrawList* draw,
|
|
const ImVec2& canvas_screen_pos,
|
|
Lumix::Anim::ComponentInstance* runtime,
|
|
Container* current) override;
|
|
void debug(ImDrawList* draw, const ImVec2& canvas_screen_pos, Lumix::Anim::ComponentInstance* runtime) override;
|
|
void deserialize(Lumix::InputBlob& blob) override;
|
|
void serialize(Lumix::OutputBlob& blob) override;
|
|
EntryNode* getEntryNode() const { return m_entry_node; }
|
|
void compile() override;
|
|
void removeEntry(EntryEdge& entry);
|
|
void dropSlot(const char* name, Lumix::u32 slot, const ImVec2& canvas_screen_pos) override;
|
|
|
|
private:
|
|
void createState(Lumix::Anim::Component::Type type, const ImVec2& pos);
|
|
EntryEdge* createEntryEdge(Node* node);
|
|
|
|
private:
|
|
enum MouseStatus
|
|
{
|
|
NONE,
|
|
DOWN_LEFT,
|
|
DOWN_RIGHT,
|
|
DRAG_NODE,
|
|
NEW_EDGE
|
|
} m_mouse_status;
|
|
Node* m_drag_source;
|
|
EntryNode* m_entry_node;
|
|
Component* m_context_cmp;
|
|
};
|
|
|
|
|
|
class ControllerResource
|
|
{
|
|
public:
|
|
ControllerResource(Lumix::AnimationSystem& anim_system,
|
|
IAnimationEditor& editor,
|
|
Lumix::ResourceManagerBase& manager,
|
|
Lumix::IAllocator& allocator);
|
|
~ControllerResource();
|
|
|
|
void serialize(Lumix::OutputBlob& blob);
|
|
bool deserialize(Lumix::InputBlob& blob, Lumix::Engine& engine, Lumix::IAllocator& allocator);
|
|
Component* getRoot() { return m_root; }
|
|
Lumix::Array<Lumix::string>& getAnimationSlots() { return m_animation_slots; }
|
|
Lumix::IAllocator& getAllocator() { return m_allocator; }
|
|
Lumix::Anim::ControllerResource* getEngineResource() { return m_engine_resource; }
|
|
IAnimationEditor& getEditor() { return m_editor; }
|
|
int createUID() { ++m_last_uid; return m_last_uid; }
|
|
const char* getAnimationSlot(Lumix::u32 slot_hash) const;
|
|
void createAnimSlot(const char* name, const char* path);
|
|
Lumix::AnimationSystem& getAnimationSystem() { return m_animation_system; }
|
|
|
|
private:
|
|
int m_last_uid = 0;
|
|
IAnimationEditor& m_editor;
|
|
Lumix::IAllocator& m_allocator;
|
|
Component* m_root;
|
|
Lumix::Anim::ControllerResource* m_engine_resource;
|
|
Lumix::Array<Lumix::string> m_animation_slots;
|
|
Lumix::AnimationSystem& m_animation_system;
|
|
};
|
|
|
|
|
|
} // namespace AnimEditor
|