LumixEngine/src/animation/animation_system.cpp

344 lines
7.5 KiB
C++
Raw Normal View History

2014-06-16 21:18:15 +02:00
#include "animation_system.h"
#include "animation/animation.h"
#include "core/crc32.h"
#include "core/json_serializer.h"
#include "core/profiler.h"
2014-06-29 15:20:21 +02:00
#include "core/resource_manager.h"
2014-08-01 21:22:03 +02:00
#include "editor/world_editor.h"
2014-06-16 21:18:15 +02:00
#include "engine/engine.h"
2015-06-18 01:33:49 +02:00
#include "graphics/render_scene.h"
2014-06-16 21:18:15 +02:00
#include "universe/universe.h"
2014-08-22 22:02:53 +02:00
2014-06-16 21:18:15 +02:00
namespace Lumix
{
2015-07-23 23:17:51 +02:00
static const uint32_t RENDERABLE_HASH = crc32("renderable");
static const uint32_t ANIMABLE_HASH = crc32("animable");
2014-06-16 21:18:15 +02:00
2015-07-23 23:17:51 +02:00
namespace FS
{
class FileSystem;
};
2015-07-23 23:17:51 +02:00
class Animation;
class Engine;
class JsonSerializer;
class Universe;
2014-06-16 21:18:15 +02:00
2015-07-25 00:09:11 +02:00
class AnimationSceneImpl : public IScene
2015-07-23 23:17:51 +02:00
{
private:
struct Animable
2014-06-16 21:18:15 +02:00
{
2015-07-23 23:17:51 +02:00
bool m_is_free;
2015-07-24 22:38:11 +02:00
ComponentIndex m_renderable;
2015-07-23 23:17:51 +02:00
float m_time;
class Animation* m_animation;
Entity m_entity;
};
2014-06-16 21:18:15 +02:00
2015-07-23 23:17:51 +02:00
public:
AnimationSceneImpl(IPlugin& anim_system,
Engine& engine,
Universe& universe,
IAllocator& allocator)
: m_universe(universe)
, m_engine(engine)
, m_anim_system(anim_system)
, m_animables(allocator)
{
2015-07-24 22:38:11 +02:00
IScene* scene = engine.getScene(crc32("renderer"));
ASSERT(scene);
m_render_scene = static_cast<RenderScene*>(scene);
m_render_scene->renderableCreated()
.bind<AnimationSceneImpl, &AnimationSceneImpl::onRenderableCreated>(
2015-07-23 23:17:51 +02:00
this);
2015-07-24 22:38:11 +02:00
m_render_scene->renderableDestroyed()
.bind<AnimationSceneImpl,
&AnimationSceneImpl::onRenderableDestroyed>(this);
2015-07-23 23:17:51 +02:00
}
2014-06-16 21:18:15 +02:00
2015-07-25 00:09:11 +02:00
~AnimationSceneImpl()
2015-07-23 23:17:51 +02:00
{
2015-07-24 22:38:11 +02:00
m_render_scene->renderableCreated()
2015-07-23 23:17:51 +02:00
.unbind<AnimationSceneImpl,
2015-07-24 22:38:11 +02:00
&AnimationSceneImpl::onRenderableCreated>(this);
m_render_scene->renderableDestroyed()
.unbind<AnimationSceneImpl,
&AnimationSceneImpl::onRenderableDestroyed>(this);
2015-07-23 23:17:51 +02:00
}
2014-06-16 21:18:15 +02:00
2015-07-19 18:37:31 +02:00
2015-07-23 23:17:51 +02:00
virtual Universe& getUniverse() override { return m_universe; }
2015-07-19 18:37:31 +02:00
2015-01-04 15:05:20 +01:00
2015-07-23 23:17:51 +02:00
virtual bool ownComponentType(uint32_t type) const override
{
return type == ANIMABLE_HASH;
}
2015-01-04 15:05:20 +01:00
2015-07-23 23:17:51 +02:00
2015-07-24 08:42:35 +02:00
virtual ComponentIndex createComponent(uint32_t type,
Entity entity) override
2015-07-23 23:17:51 +02:00
{
if (type == ANIMABLE_HASH)
{
2015-07-25 00:09:11 +02:00
return createAnimable(entity);
2015-07-23 23:17:51 +02:00
}
2015-07-24 22:38:11 +02:00
return INVALID_COMPONENT;
2015-07-23 23:17:51 +02:00
}
2014-06-16 21:18:15 +02:00
2015-07-24 08:42:35 +02:00
virtual void destroyComponent(ComponentIndex component, uint32_t type)
2015-07-23 23:17:51 +02:00
{
if (type == ANIMABLE_HASH)
{
m_animables[component].m_is_free = true;
2015-07-24 22:38:11 +02:00
m_universe.destroyComponent(
m_animables[component].m_entity, type, this, component);
2015-07-23 23:17:51 +02:00
}
}
2014-06-16 21:18:15 +02:00
2015-07-23 23:17:51 +02:00
virtual void serialize(OutputBlob& serializer) override
{
serializer.write((int32_t)m_animables.size());
for (int i = 0; i < m_animables.size(); ++i)
{
2015-07-24 22:38:11 +02:00
serializer.write(m_animables[i].m_entity);
2015-07-23 23:17:51 +02:00
serializer.write(m_animables[i].m_time);
serializer.write(m_animables[i].m_is_free);
serializer.writeString(
m_animables[i].m_animation
? m_animables[i].m_animation->getPath().c_str()
: "");
}
}
2014-06-16 21:18:15 +02:00
2015-07-23 23:17:51 +02:00
virtual void deserialize(InputBlob& serializer) override
{
int32_t count;
serializer.read(count);
m_animables.resize(count);
for (int i = 0; i < count; ++i)
{
serializer.read(m_animables[i].m_entity);
2015-07-24 22:38:11 +02:00
ComponentIndex renderable =
2015-07-23 23:17:51 +02:00
m_render_scene->getRenderableComponent(m_animables[i].m_entity);
2015-07-24 22:38:11 +02:00
if (renderable >= 0)
2014-06-16 21:18:15 +02:00
{
2015-07-23 23:17:51 +02:00
m_animables[i].m_renderable = renderable;
2014-06-16 21:18:15 +02:00
}
2015-07-23 23:17:51 +02:00
serializer.read(m_animables[i].m_time);
serializer.read(m_animables[i].m_is_free);
char path[LUMIX_MAX_PATH];
serializer.readString(path, sizeof(path));
m_animables[i].m_animation =
2015-07-25 19:33:19 +02:00
path[0] == '\0' ? nullptr : loadAnimation(path);
2015-07-23 23:17:51 +02:00
m_universe.addComponent(
m_animables[i].m_entity, ANIMABLE_HASH, this, i);
}
}
2014-06-16 21:18:15 +02:00
2015-07-24 08:42:35 +02:00
void getPreview(ComponentIndex cmp, string& path)
2015-07-23 23:17:51 +02:00
{
2015-07-24 08:42:35 +02:00
path = m_animables[cmp].m_animation
? m_animables[cmp].m_animation->getPath().c_str()
2015-07-23 23:17:51 +02:00
: "";
}
2015-07-24 08:42:35 +02:00
void setPreview(ComponentIndex cmp, const string& path)
2015-07-23 23:17:51 +02:00
{
playAnimation(cmp, path.c_str());
}
2015-07-25 00:09:11 +02:00
void playAnimation(ComponentIndex cmp, const char* path)
2015-07-23 23:17:51 +02:00
{
2015-07-24 08:42:35 +02:00
m_animables[cmp].m_animation = loadAnimation(path);
m_animables[cmp].m_time = 0;
2015-07-23 23:17:51 +02:00
}
2014-07-31 23:45:57 +02:00
2014-08-21 01:22:57 +02:00
2015-07-23 23:17:51 +02:00
virtual void update(float time_delta) override
{
PROFILE_FUNCTION();
if (m_animables.empty())
return;
for (int i = 0, c = m_animables.size(); i < c; ++i)
{
Animable& animable = m_animables[i];
if (!animable.m_is_free && animable.m_animation &&
animable.m_animation->isReady())
2014-06-16 21:18:15 +02:00
{
2015-07-23 23:17:51 +02:00
animable.m_animation->getPose(
animable.m_time,
2015-07-24 22:38:11 +02:00
m_render_scene->getPose(animable.m_renderable),
*m_render_scene->getRenderableModel(animable.m_renderable));
2015-07-25 00:09:11 +02:00
float t = animable.m_time + time_delta;
float l = animable.m_animation->getLength();
while (t > l)
2014-06-16 21:18:15 +02:00
{
2015-07-25 00:09:11 +02:00
t -= l;
2014-06-16 21:18:15 +02:00
}
2015-07-25 00:09:11 +02:00
animable.m_time = t;
2014-06-16 21:18:15 +02:00
}
2015-07-23 23:17:51 +02:00
}
}
2014-08-17 17:55:34 +02:00
2015-07-23 23:17:51 +02:00
private:
Animation* loadAnimation(const char* path)
{
ResourceManager& rm = m_engine.getResourceManager();
return static_cast<Animation*>(
rm.get(ResourceManager::ANIMATION)->load(Path(path)));
}
2014-08-21 01:22:57 +02:00
2015-07-24 22:38:11 +02:00
void onRenderableCreated(ComponentIndex cmp)
2015-07-23 23:17:51 +02:00
{
2015-07-24 22:38:11 +02:00
Entity entity = m_render_scene->getRenderableEntity(cmp);
for (int i = 0; i < m_animables.size(); ++i)
2015-07-23 23:17:51 +02:00
{
2015-07-24 22:38:11 +02:00
if (m_animables[i].m_entity == entity)
2014-08-21 01:22:57 +02:00
{
2015-07-24 22:38:11 +02:00
m_animables[i].m_renderable = cmp;
break;
}
}
}
void onRenderableDestroyed(ComponentIndex cmp)
{
Entity entity = m_render_scene->getRenderableEntity(cmp);
for (int i = 0; i < m_animables.size(); ++i)
{
if (m_animables[i].m_entity == entity)
{
m_animables[i].m_renderable = INVALID_COMPONENT;
break;
2014-08-21 01:22:57 +02:00
}
2015-07-23 23:17:51 +02:00
}
}
2014-08-21 01:22:57 +02:00
2015-07-25 00:09:11 +02:00
ComponentIndex createAnimable(Entity entity)
2015-07-23 23:17:51 +02:00
{
2015-07-25 19:33:19 +02:00
Animable* src = nullptr;
2015-07-23 23:17:51 +02:00
for (int i = 0, c = m_animables.size(); i < c; ++i)
{
if (m_animables[i].m_is_free)
2014-08-21 01:22:57 +02:00
{
2015-07-23 23:17:51 +02:00
src = &m_animables[i];
break;
2014-08-21 01:22:57 +02:00
}
2015-07-23 23:17:51 +02:00
}
Animable& animable = src ? *src : m_animables.pushEmpty();
animable.m_time = 0;
animable.m_is_free = false;
2015-07-24 22:38:11 +02:00
animable.m_renderable = INVALID_COMPONENT;
2015-07-25 19:33:19 +02:00
animable.m_animation = nullptr;
2015-07-23 23:17:51 +02:00
animable.m_entity = entity;
2015-07-24 22:38:11 +02:00
ComponentIndex renderable =
m_render_scene->getRenderableComponent(entity);
if (renderable >= 0)
2015-07-23 23:17:51 +02:00
{
animable.m_renderable = renderable;
}
2015-07-25 00:09:11 +02:00
m_universe.addComponent(
2015-07-23 23:17:51 +02:00
entity, ANIMABLE_HASH, this, m_animables.size() - 1);
2015-07-25 00:09:11 +02:00
return m_animables.size() - 1;
2015-07-23 23:17:51 +02:00
}
2014-08-21 01:22:57 +02:00
2015-07-23 23:17:51 +02:00
virtual IPlugin& getPlugin() const override { return m_anim_system; }
2014-08-21 01:22:57 +02:00
2015-07-23 23:17:51 +02:00
private:
Universe& m_universe;
IPlugin& m_anim_system;
Engine& m_engine;
Array<Animable> m_animables;
RenderScene* m_render_scene;
};
2014-08-21 01:22:57 +02:00
2015-07-23 23:17:51 +02:00
struct AnimationSystemImpl : public IPlugin
{
public:
AnimationSystemImpl(Engine& engine)
: m_allocator(engine.getAllocator())
, m_engine(engine)
, m_animation_manager(m_allocator)
2014-08-21 01:22:57 +02:00
{
2015-07-23 23:17:51 +02:00
}
2014-08-21 01:22:57 +02:00
2015-07-23 23:17:51 +02:00
virtual IScene* createScene(Universe& universe) override
{
return m_allocator.newObject<AnimationSceneImpl>(
*this, m_engine, universe, m_allocator);
}
2014-11-07 22:18:47 +01:00
2015-07-23 23:17:51 +02:00
virtual void destroyScene(IScene* scene) override
{
m_allocator.deleteObject(scene);
}
2014-08-21 01:22:57 +02:00
2014-08-17 17:55:34 +02:00
2015-07-23 23:17:51 +02:00
virtual const char* getName() const override { return "animation"; }
2014-08-17 17:55:34 +02:00
2015-07-23 23:17:51 +02:00
virtual void setWorldEditor(WorldEditor& editor) override
{
IAllocator& allocator = editor.getAllocator();
editor.registerComponentType("animable", "Animable");
editor.registerProperty(
"animable",
allocator.newObject<FilePropertyDescriptor<AnimationSceneImpl>>(
"preview",
&AnimationSceneImpl::getPreview,
&AnimationSceneImpl::setPreview,
"Animation (*.ani)",
allocator));
}
2015-07-23 23:17:51 +02:00
virtual bool create() override
{
m_animation_manager.create(ResourceManager::ANIMATION,
m_engine.getResourceManager());
return true;
}
2014-08-17 17:55:34 +02:00
2015-07-23 23:17:51 +02:00
virtual void destroy() override {}
2014-08-17 17:55:34 +02:00
2015-07-23 23:17:51 +02:00
BaseProxyAllocator m_allocator;
Engine& m_engine;
AnimationManager m_animation_manager;
2015-07-23 23:17:51 +02:00
private:
void operator=(const AnimationSystemImpl&);
AnimationSystemImpl(const AnimationSystemImpl&);
};
2014-08-17 17:55:34 +02:00
2015-07-23 23:17:51 +02:00
extern "C" IPlugin* createPlugin(Engine& engine)
{
return engine.getAllocator().newObject<AnimationSystemImpl>(engine);
}
2014-06-16 21:18:15 +02:00
} // ~namespace Lumix