#ifndef OPENMW_MWRENDER_ANIMBLENDCONTROLLER_H #define OPENMW_MWRENDER_ANIMBLENDCONTROLLER_H #include #include #include #include #include #include #include #include #include #include #include namespace MWRender { namespace Easings { typedef float (*EasingFn)(float); } struct AnimBlendStateData { std::string mGroupname; std::string mStartKey; }; template class AnimBlendControllerBase : public SceneUtil::NodeCallback, NodeClass*>, public SceneUtil::Controller { public: AnimBlendControllerBase(osg::ref_ptr keyframeTrack, AnimBlendStateData animState, osg::ref_ptr blendRules); AnimBlendControllerBase() {} AnimBlendControllerBase(const AnimBlendControllerBase& copy, const osg::CopyOp&) : mTimeFactor(0.0f) , mInterpFactor(0.0f) { setKeyframeTrack(copy.getKeyframeTrack(), copy.getAnimState(), copy.getBlendRules()); } META_Object(MWRender, AnimBlendControllerBase) void operator()(NifOsg::MatrixTransform* node, osg::NodeVisitor* nv); void operator()(osgAnimation::Bone* node, osg::NodeVisitor* nv); void setKeyframeTrack(osg::ref_ptr kft, AnimBlendStateData animState, osg::ref_ptr blendRules); osg::Callback* getAsCallback() { return this; } bool getBlendTrigger() const { return mBlendTrigger; } void gatherRecursiveBoneTransforms(osgAnimation::Bone* parent, bool isRoot = true); void applyBoneBlend(osgAnimation::Bone* parent); osg::ref_ptr getKeyframeTrack() const { return mKeyframeTrack; } osg::ref_ptr getBlendRules() const { return mAnimBlendRules; } AnimBlendStateData getAnimState() const { return mAnimState; } private: Easings::EasingFn mEasingFn; float mBlendDuration; bool mBlendTrigger = false; float mBlendStartTime; osg::Quat mBlendStartRot; osg::Vec3f mBlendStartTrans; float mBlendStartScale; float mTimeFactor; float mInterpFactor; bool mInterpActive; AnimBlendStateData mAnimState; osg::ref_ptr mAnimBlendRules; osg::ref_ptr mKeyframeTrack; std::unordered_map mBlendBoneTransforms; inline void calculateInterpFactor(float time); }; using AnimBlendController = AnimBlendControllerBase; using BoneAnimBlendController = AnimBlendControllerBase; // Assigned to child bones with an instance of AnimBlendControllerBase class BoneAnimBlendControllerWrapper : public osg::Callback { public: BoneAnimBlendControllerWrapper(osg::ref_ptr rootCallback, osg::Node* node) { mRootCallback = rootCallback; mNode = dynamic_cast(node); } bool run(osg::Object* object, osg::Object* data) override { mRootCallback->applyBoneBlend(mNode); traverse(object, data); return true; } const char* libraryName() const override { return "openmw"; } const char* className() const override { return "AnimBlendController"; } private: osg::ref_ptr mRootCallback; osgAnimation::Bone* mNode; }; } #endif