shared animation controllers

This commit is contained in:
Mikulas Florek 2017-02-15 16:49:12 +01:00
parent f5068f55b7
commit abb46860cc
6 changed files with 136 additions and 6 deletions

View file

@ -25,8 +25,17 @@ namespace Lumix
{
enum class AnimationSceneVersion
{
SHARED_CONTROLLER,
LATEST
};
static const ComponentType ANIMABLE_TYPE = PropertyRegister::getComponentType("animable");
static const ComponentType CONTROLLER_TYPE = PropertyRegister::getComponentType("anim_controller");
static const ComponentType SHARED_CONTROLLER_TYPE = PropertyRegister::getComponentType("shared_anim_controller");
static const ResourceType ANIMATION_TYPE("animation");
static const ResourceType CONTROLLER_RESOURCE_TYPE("anim_controller");
@ -70,6 +79,12 @@ struct AnimationSceneImpl LUMIX_FINAL : public AnimationScene
{
friend struct AnimationSystemImpl;
struct SharedController
{
Entity entity;
Entity parent;
};
struct Controller
{
Controller(IAllocator& allocator) : input(allocator) {}
@ -97,16 +112,34 @@ struct AnimationSceneImpl LUMIX_FINAL : public AnimationScene
, m_anim_system(anim_system)
, m_animables(allocator)
, m_controllers(allocator)
, m_shared_controllers(allocator)
, m_event_stream(allocator)
{
m_is_game_running = false;
m_render_scene = static_cast<RenderScene*>(universe.getScene(crc32("renderer")));
universe.registerComponentType(ANIMABLE_TYPE, this, &AnimationSceneImpl::serializeAnimable, &AnimationSceneImpl::deserializeAnimable);
universe.registerComponentType(CONTROLLER_TYPE, this, &AnimationSceneImpl::serializeController, &AnimationSceneImpl::deserializeController);
universe.registerComponentType(SHARED_CONTROLLER_TYPE, this, &AnimationSceneImpl::serializeSharedController, &AnimationSceneImpl::deserializeSharedController);
ASSERT(m_render_scene);
}
void serializeSharedController(ISerializer& serializer, ComponentHandle cmp)
{
SharedController& ctrl = m_shared_controllers[{cmp.index}];
serializer.write("parent", ctrl.parent);
}
void deserializeSharedController(IDeserializer& serializer, Entity entity, int /*scene_version*/)
{
Entity parent;
serializer.read(&parent);
m_shared_controllers.insert(entity, {entity, parent});
m_universe.addComponent(entity, SHARED_CONTROLLER_TYPE, this, {entity.index});
}
void serializeAnimable(ISerializer& serializer, ComponentHandle cmp)
{
Animable& animable = m_animables[{cmp.index}];
@ -115,6 +148,7 @@ struct AnimationSceneImpl LUMIX_FINAL : public AnimationScene
serializer.write("animation", animable.animation ? animable.animation->getPath().c_str() : "");
}
void deserializeAnimable(IDeserializer& serializer, Entity entity, int /*scene_version*/)
{
Animable& animable = m_animables.insert(entity);
@ -291,6 +325,11 @@ struct AnimationSceneImpl LUMIX_FINAL : public AnimationScene
if (m_controllers.find(entity) < 0) return INVALID_COMPONENT;
return {entity.index};
}
else if (type == SHARED_CONTROLLER_TYPE)
{
if (m_shared_controllers.find(entity) < 0) return INVALID_COMPONENT;
return {entity.index};
}
return INVALID_COMPONENT;
}
@ -299,6 +338,7 @@ struct AnimationSceneImpl LUMIX_FINAL : public AnimationScene
{
if (type == ANIMABLE_TYPE) return createAnimable(entity);
if (type == CONTROLLER_TYPE) return createController(entity);
if (type == SHARED_CONTROLLER_TYPE) return createSharedController(entity);
return INVALID_COMPONENT;
}
@ -338,6 +378,12 @@ struct AnimationSceneImpl LUMIX_FINAL : public AnimationScene
m_controllers.erase(entity);
m_universe.destroyComponent(entity, type, this, component);
}
else if (type == SHARED_CONTROLLER_TYPE)
{
Entity entity = {component.index};
m_shared_controllers.erase(entity);
m_universe.destroyComponent(entity, type, this, component);
}
}
@ -358,6 +404,13 @@ struct AnimationSceneImpl LUMIX_FINAL : public AnimationScene
serializer.write(controller.entity);
serializer.writeString(controller.resource ? controller.resource->getPath().c_str() : "");
}
serializer.write(m_shared_controllers.size());
for (const SharedController& controller : m_shared_controllers)
{
serializer.write(controller.entity);
serializer.write(controller.parent);
}
}
@ -395,9 +448,30 @@ struct AnimationSceneImpl LUMIX_FINAL : public AnimationScene
ComponentHandle cmp = { controller.entity.index };
m_universe.addComponent(controller.entity, CONTROLLER_TYPE, this, cmp);
}
serializer.read(count);
m_shared_controllers.reserve(count);
for (int i = 0; i < count; ++i)
{
SharedController controller;
serializer.read(controller.entity);
serializer.read(controller.parent);
m_shared_controllers.insert(controller.entity, controller);
ComponentHandle cmp = {controller.entity.index};
m_universe.addComponent(controller.entity, SHARED_CONTROLLER_TYPE, this, cmp);
}
}
void setSharedControllerParent(ComponentHandle cmp, Entity parent) override
{
m_shared_controllers[{cmp.index}].parent = parent;
}
Entity getSharedControllerParent(ComponentHandle cmp) override { return m_shared_controllers[{cmp.index}].parent; }
float getTimeScale(ComponentHandle cmp) { return m_animables[{cmp.index}].time_scale; }
void setTimeScale(ComponentHandle cmp, float time_scale) { m_animables[{cmp.index}].time_scale = time_scale; }
float getStartTime(ComponentHandle cmp) { return m_animables[{cmp.index}].start_time; }
@ -538,6 +612,33 @@ struct AnimationSceneImpl LUMIX_FINAL : public AnimationScene
}
void updateSharedController(SharedController& controller, float time_delta)
{
if (!isValid(controller.parent)) return;
int parent_controller_idx = m_controllers.find(controller.parent);
if (parent_controller_idx < 0) return;
Controller& parent_controller = m_controllers.at(parent_controller_idx);
ComponentHandle model_instance = m_render_scene->getModelInstanceComponent(controller.entity);
if (model_instance == INVALID_COMPONENT) return;
Pose* pose = m_render_scene->getPose(model_instance);
if (!pose) return;
Model* model = m_render_scene->getModelInstanceModel(model_instance);
model->getPose(*pose);
pose->computeRelative(*model);
parent_controller.root->fillPose(m_anim_system.m_engine, *pose, *model, 1);
pose->computeAbsolute(*model);
}
void updateController(Controller& controller, float time_delta)
{
if (!controller.resource->isReady())
@ -593,6 +694,11 @@ struct AnimationSceneImpl LUMIX_FINAL : public AnimationScene
AnimationSceneImpl::updateController(controller, time_delta);
}
for (SharedController& controller : m_shared_controllers)
{
AnimationSceneImpl::updateSharedController(controller, time_delta);
}
processEventStream();
}
@ -673,6 +779,16 @@ struct AnimationSceneImpl LUMIX_FINAL : public AnimationScene
return cmp;
}
ComponentHandle createSharedController(Entity entity)
{
m_shared_controllers.insert(entity, {entity, INVALID_ENTITY});
ComponentHandle cmp = {entity.index};
m_universe.addComponent(entity, SHARED_CONTROLLER_TYPE, this, cmp);
return cmp;
}
IPlugin& getPlugin() const override { return m_anim_system; }
@ -681,6 +797,7 @@ struct AnimationSceneImpl LUMIX_FINAL : public AnimationScene
Engine& m_engine;
AssociativeArray<Entity, Animable> m_animables;
AssociativeArray<Entity, Controller> m_controllers;
AssociativeArray<Entity, SharedController> m_shared_controllers;
RenderScene* m_render_scene;
bool m_is_game_running;
OutputBlob m_event_stream;
@ -716,6 +833,11 @@ AnimationSystemImpl::AnimationSystemImpl(Engine& engine)
LUMIX_NEW(m_allocator, DecimalPropertyDescriptor<AnimationSceneImpl>)(
"Time scale", &AnimationSceneImpl::getTimeScale, &AnimationSceneImpl::setTimeScale, 0, FLT_MAX, 0.1f));
PropertyRegister::add("shared_anim_controller",
LUMIX_NEW(m_allocator, EntityPropertyDescriptor<AnimationSceneImpl>)(
"Parent", &AnimationSceneImpl::getSharedControllerParent, &AnimationSceneImpl::setSharedControllerParent));
registerLuaAPI();
}

View file

@ -31,6 +31,9 @@ struct AnimationScene : public IScene
virtual class Path getControllerSource(ComponentHandle cmp) = 0;
virtual Anim::ComponentInstance* getControllerRoot(ComponentHandle cmp) = 0;
virtual int getControllerInputIndex(ComponentHandle cmp, const char* name) const = 0;
virtual Entity getSharedControllerParent(ComponentHandle cmp) = 0;
virtual void setSharedControllerParent(ComponentHandle cmp, Entity parent) = 0;
};

View file

@ -206,6 +206,7 @@ LUMIX_STUDIO_ENTRY(animation)
{
app.registerComponentWithResource("animable", "Animation/Animable", ANIMATION_TYPE, "Animation");
app.registerComponentWithResource("anim_controller", "Animation/Controller", CONTROLLER_RESOURCE_TYPE, "Source");
app.registerComponent("shared_anim_controller", "Animation/Shared controller");
auto& allocator = app.getWorldEditor()->getAllocator();
auto* ab_plugin = LUMIX_NEW(allocator, AssetBrowserPlugin)(app);

View file

@ -3,6 +3,7 @@
#include "engine/engine.h"
#include "engine/hash_map.h"
#include "engine/json_serializer.h"
#include "engine/log.h"
#include "engine/property_register.h"
#include "engine/serializer.h"
#include "universe.h"
@ -265,6 +266,11 @@ public:
void setParent(ComponentHandle child, Entity parent) override
{
Entity child_entity = {child.index};
if (child_entity == parent)
{
g_log_warning.log("Hierarchy") << "Can not set entity " << parent.index << " as its own parent.";
return;
}
Parents::iterator old_parent_iter = m_parents.find(child_entity);
if (old_parent_iter.isValid())
{

View file

@ -311,6 +311,7 @@ struct PropertyGridPlugin LUMIX_FINAL : public PropertyGrid::IPlugin
auto& cmd = static_cast<SetPropertyCommand&>(command);
if (cmd.script_index == script_index && cmd.property_name == property_name)
{
//cmd.scene = scene;
cmd.value = value;
return true;
}

View file

@ -927,12 +927,10 @@ namespace Lumix
if (prop.type == Property::STRING) tmp << "\"" << value << "\"";
else tmp << value;
bool errors =
luaL_loadbuffer(state, tmp, stringLength(tmp), nullptr) != LUA_OK;
bool errors = luaL_loadbuffer(state, tmp, stringLength(tmp), nullptr) != LUA_OK;
if (errors)
{
g_log_error.log("Lua Script") << script.m_script->getPath() << ": "
<< lua_tostring(state, -1);
g_log_error.log("Lua Script") << script.m_script->getPath() << ": " << lua_tostring(state, -1);
lua_pop(state, 1);
return;
}
@ -945,8 +943,7 @@ namespace Lumix
if (errors)
{
g_log_error.log("Lua Script") << script.m_script->getPath() << ": "
<< lua_tostring(state, -1);
g_log_error.log("Lua Script") << script.m_script->getPath() << ": " << lua_tostring(state, -1);
lua_pop(state, 1);
}
}