#ifndef OPENMW_MWRENDER_ANIMBLENDCONTROLLER_H #define OPENMW_MWRENDER_ANIMBLENDCONTROLLER_H #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 AnimBlendController : public SceneUtil::NodeCallback, NodeClass*>, public SceneUtil::Controller { public: AnimBlendController(osg::ref_ptr keyframeTrack, const AnimBlendStateData& animState, osg::ref_ptr blendRules); AnimBlendController() {} AnimBlendController(const AnimBlendController& other, const osg::CopyOp&) : AnimBlendController(other.mKeyframeTrack, other.mAnimState, other.mAnimBlendRules) { } META_Object(MWRender, AnimBlendController) void operator()(NifOsg::MatrixTransform* node, osg::NodeVisitor* nv); void operator()(osgAnimation::Bone* node, osg::NodeVisitor* nv); void setKeyframeTrack(osg::ref_ptr kft, const 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); 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 NifAnimBlendController = AnimBlendController; using BoneAnimBlendController = AnimBlendController; // Assigned to child bones with an instance of AnimBlendController class BoneAnimBlendControllerWrapper : public osg::Callback { public: BoneAnimBlendControllerWrapper(osg::ref_ptr rootCallback, osgAnimation::Bone* node) : mRootCallback(rootCallback) , mNode(node) { } BoneAnimBlendControllerWrapper() {} BoneAnimBlendControllerWrapper(const BoneAnimBlendControllerWrapper& copy, const osg::CopyOp&) : mRootCallback(copy.mRootCallback) , mNode(copy.mNode) { } META_Object(MWRender, BoneAnimBlendControllerWrapper) bool run(osg::Object* object, osg::Object* data) override { mRootCallback->applyBoneBlend(mNode); traverse(object, data); return true; } private: osg::ref_ptr mRootCallback; osgAnimation::Bone* mNode; }; } #endif