Separate keyframes logic to provide basis for osgAnimation integration.

pull/593/head
Nelsson Huotari 4 years ago
parent 37661bffea
commit f78a5d795c

@ -936,7 +936,7 @@ void split(const std::string &s, char delim, std::vector<std::string> &elems) {
} }
} }
void CharacterController::handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, const NifOsg::TextKeyMap& map) void CharacterController::handleTextKey(const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key, const SceneUtil::TextKeyMap& map)
{ {
const std::string &evt = key->second; const std::string &evt = key->second;

@ -241,7 +241,7 @@ public:
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim); CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
virtual ~CharacterController(); virtual ~CharacterController();
void handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, const NifOsg::TextKeyMap& map) override; void handleTextKey(const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key, const SceneUtil::TextKeyMap& map) override;
// Be careful when to call this, see comment in Actors // Be careful when to call this, see comment in Actors
void updateContinuousVfx(); void updateContinuousVfx();

@ -20,8 +20,7 @@
#include <components/misc/constants.hpp> #include <components/misc/constants.hpp>
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>
#include <components/nifosg/nifloader.hpp> // KeyframeHolder #include <components/sceneutil/keyframe.hpp>
#include <components/nifosg/controller.hpp>
#include <components/vfs/manager.hpp> #include <components/vfs/manager.hpp>
@ -148,7 +147,7 @@ namespace
} }
}; };
float calcAnimVelocity(const NifOsg::TextKeyMap& keys, NifOsg::KeyframeController *nonaccumctrl, float calcAnimVelocity(const SceneUtil::TextKeyMap& keys, SceneUtil::KeyframeController *nonaccumctrl,
const osg::Vec3f& accum, const std::string &groupname) const osg::Vec3f& accum, const std::string &groupname)
{ {
const std::string start = groupname+": start"; const std::string start = groupname+": start";
@ -530,13 +529,13 @@ namespace MWRender
struct Animation::AnimSource struct Animation::AnimSource
{ {
osg::ref_ptr<const NifOsg::KeyframeHolder> mKeyframes; osg::ref_ptr<const SceneUtil::KeyframeHolder> mKeyframes;
typedef std::map<std::string, osg::ref_ptr<NifOsg::KeyframeController> > ControllerMap; typedef std::map<std::string, osg::ref_ptr<SceneUtil::KeyframeController> > ControllerMap;
ControllerMap mControllerMap[Animation::sNumBlendMasks]; ControllerMap mControllerMap[Animation::sNumBlendMasks];
const NifOsg::TextKeyMap& getTextKeys() const; const SceneUtil::TextKeyMap& getTextKeys() const;
}; };
void UpdateVfxCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) void UpdateVfxCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
@ -688,7 +687,7 @@ namespace MWRender
return 0; return 0;
} }
const NifOsg::TextKeyMap &Animation::AnimSource::getTextKeys() const const SceneUtil::TextKeyMap &Animation::AnimSource::getTextKeys() const
{ {
return mKeyframes->mTextKeys; return mKeyframes->mTextKeys;
} }
@ -729,8 +728,6 @@ namespace MWRender
if(kfname.size() > 4 && kfname.compare(kfname.size()-4, 4, ".nif") == 0) if(kfname.size() > 4 && kfname.compare(kfname.size()-4, 4, ".nif") == 0)
kfname.replace(kfname.size()-4, 4, ".kf"); kfname.replace(kfname.size()-4, 4, ".kf");
else
return;
addSingleAnimSource(kfname, baseModel); addSingleAnimSource(kfname, baseModel);
@ -753,7 +750,7 @@ namespace MWRender
const NodeMap& nodeMap = getNodeMap(); const NodeMap& nodeMap = getNodeMap();
for (NifOsg::KeyframeHolder::KeyframeControllerMap::const_iterator it = animsrc->mKeyframes->mKeyframeControllers.begin(); for (SceneUtil::KeyframeHolder::KeyframeControllerMap::const_iterator it = animsrc->mKeyframes->mKeyframeControllers.begin();
it != animsrc->mKeyframes->mKeyframeControllers.end(); ++it) it != animsrc->mKeyframes->mKeyframeControllers.end(); ++it)
{ {
std::string bonename = Misc::StringUtils::lowerCase(it->first); std::string bonename = Misc::StringUtils::lowerCase(it->first);
@ -769,7 +766,7 @@ namespace MWRender
size_t blendMask = detectBlendMask(node); size_t blendMask = detectBlendMask(node);
// clone the controller, because each Animation needs its own ControllerSource // clone the controller, because each Animation needs its own ControllerSource
osg::ref_ptr<NifOsg::KeyframeController> cloned = new NifOsg::KeyframeController(*it->second, osg::CopyOp::SHALLOW_COPY); osg::ref_ptr<SceneUtil::KeyframeController> cloned = osg::clone(it->second.get(), osg::CopyOp::SHALLOW_COPY);
cloned->setSource(mAnimationTimePtr[blendMask]); cloned->setSource(mAnimationTimePtr[blendMask]);
animsrc->mControllerMap[blendMask].insert(std::make_pair(bonename, cloned)); animsrc->mControllerMap[blendMask].insert(std::make_pair(bonename, cloned));
@ -810,7 +807,7 @@ namespace MWRender
AnimSourceList::const_iterator iter(mAnimSources.begin()); AnimSourceList::const_iterator iter(mAnimSources.begin());
for(;iter != mAnimSources.end();++iter) for(;iter != mAnimSources.end();++iter)
{ {
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys(); const SceneUtil::TextKeyMap &keys = (*iter)->getTextKeys();
if (keys.hasGroupStart(anim)) if (keys.hasGroupStart(anim))
return true; return true;
} }
@ -822,7 +819,7 @@ namespace MWRender
{ {
for(AnimSourceList::const_reverse_iterator iter(mAnimSources.rbegin()); iter != mAnimSources.rend(); ++iter) for(AnimSourceList::const_reverse_iterator iter(mAnimSources.rbegin()); iter != mAnimSources.rend(); ++iter)
{ {
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys(); const SceneUtil::TextKeyMap &keys = (*iter)->getTextKeys();
const auto found = keys.findGroupStart(groupname); const auto found = keys.findGroupStart(groupname);
if(found != keys.end()) if(found != keys.end())
@ -835,7 +832,7 @@ namespace MWRender
{ {
for(AnimSourceList::const_reverse_iterator iter(mAnimSources.rbegin()); iter != mAnimSources.rend(); ++iter) for(AnimSourceList::const_reverse_iterator iter(mAnimSources.rbegin()); iter != mAnimSources.rend(); ++iter)
{ {
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys(); const SceneUtil::TextKeyMap &keys = (*iter)->getTextKeys();
for(auto iterKey = keys.begin(); iterKey != keys.end(); ++iterKey) for(auto iterKey = keys.begin(); iterKey != keys.end(); ++iterKey)
{ {
@ -847,8 +844,8 @@ namespace MWRender
return -1.f; return -1.f;
} }
void Animation::handleTextKey(AnimState &state, const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, void Animation::handleTextKey(AnimState &state, const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key,
const NifOsg::TextKeyMap& map) const SceneUtil::TextKeyMap& map)
{ {
const std::string &evt = key->second; const std::string &evt = key->second;
@ -911,7 +908,7 @@ namespace MWRender
AnimSourceList::reverse_iterator iter(mAnimSources.rbegin()); AnimSourceList::reverse_iterator iter(mAnimSources.rbegin());
for(;iter != mAnimSources.rend();++iter) for(;iter != mAnimSources.rend();++iter)
{ {
const NifOsg::TextKeyMap &textkeys = (*iter)->getTextKeys(); const SceneUtil::TextKeyMap &textkeys = (*iter)->getTextKeys();
if(reset(state, textkeys, groupname, start, stop, startpoint, loopfallback)) if(reset(state, textkeys, groupname, start, stop, startpoint, loopfallback))
{ {
state.mSource = *iter; state.mSource = *iter;
@ -956,7 +953,7 @@ namespace MWRender
resetActiveGroups(); resetActiveGroups();
} }
bool Animation::reset(AnimState &state, const NifOsg::TextKeyMap &keys, const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, bool loopfallback) bool Animation::reset(AnimState &state, const SceneUtil::TextKeyMap &keys, const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, bool loopfallback)
{ {
// Look for text keys in reverse. This normally wouldn't matter, but for some reason undeadwolf_2.nif has two // Look for text keys in reverse. This normally wouldn't matter, but for some reason undeadwolf_2.nif has two
// separate walkforward keys, and the last one is supposed to be used. // separate walkforward keys, and the last one is supposed to be used.
@ -1186,7 +1183,7 @@ namespace MWRender
AnimSourceList::const_reverse_iterator animsrc(mAnimSources.rbegin()); AnimSourceList::const_reverse_iterator animsrc(mAnimSources.rbegin());
for(;animsrc != mAnimSources.rend();++animsrc) for(;animsrc != mAnimSources.rend();++animsrc)
{ {
const NifOsg::TextKeyMap &keys = (*animsrc)->getTextKeys(); const SceneUtil::TextKeyMap &keys = (*animsrc)->getTextKeys();
if (keys.hasGroupStart(groupname)) if (keys.hasGroupStart(groupname))
break; break;
} }
@ -1194,7 +1191,7 @@ namespace MWRender
return 0.0f; return 0.0f;
float velocity = 0.0f; float velocity = 0.0f;
const NifOsg::TextKeyMap &keys = (*animsrc)->getTextKeys(); const SceneUtil::TextKeyMap &keys = (*animsrc)->getTextKeys();
const AnimSource::ControllerMap& ctrls = (*animsrc)->mControllerMap[0]; const AnimSource::ControllerMap& ctrls = (*animsrc)->mControllerMap[0];
for (AnimSource::ControllerMap::const_iterator it = ctrls.begin(); it != ctrls.end(); ++it) for (AnimSource::ControllerMap::const_iterator it = ctrls.begin(); it != ctrls.end(); ++it)
@ -1215,7 +1212,7 @@ namespace MWRender
while(!(velocity > 1.0f) && ++animiter != mAnimSources.rend()) while(!(velocity > 1.0f) && ++animiter != mAnimSources.rend())
{ {
const NifOsg::TextKeyMap &keys2 = (*animiter)->getTextKeys(); const SceneUtil::TextKeyMap &keys2 = (*animiter)->getTextKeys();
const AnimSource::ControllerMap& ctrls2 = (*animiter)->mControllerMap[0]; const AnimSource::ControllerMap& ctrls2 = (*animiter)->mControllerMap[0];
for (AnimSource::ControllerMap::const_iterator it = ctrls2.begin(); it != ctrls2.end(); ++it) for (AnimSource::ControllerMap::const_iterator it = ctrls2.begin(); it != ctrls2.end(); ++it)
@ -1265,7 +1262,7 @@ namespace MWRender
continue; continue;
} }
const NifOsg::TextKeyMap &textkeys = state.mSource->getTextKeys(); const SceneUtil::TextKeyMap &textkeys = state.mSource->getTextKeys();
auto textkey = textkeys.upperBound(state.getTime()); auto textkey = textkeys.upperBound(state.getTime());
float timepassed = duration * state.mSpeedMult; float timepassed = duration * state.mSpeedMult;
@ -1839,7 +1836,7 @@ namespace MWRender
osg::Callback* cb = node->getUpdateCallback(); osg::Callback* cb = node->getUpdateCallback();
while (cb) while (cb)
{ {
if (dynamic_cast<NifOsg::KeyframeController*>(cb)) if (dynamic_cast<SceneUtil::KeyframeController*>(cb))
{ {
foundKeyframeCtrl = true; foundKeyframeCtrl = true;
break; break;

@ -4,8 +4,8 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include <components/sceneutil/controller.hpp> #include <components/sceneutil/controller.hpp>
#include <components/sceneutil/textkeymap.hpp>
#include <components/sceneutil/util.hpp> #include <components/sceneutil/util.hpp>
#include <components/nifosg/textkeymap.hpp>
#include <vector> #include <vector>
@ -20,14 +20,10 @@ namespace Resource
class ResourceSystem; class ResourceSystem;
} }
namespace NifOsg namespace SceneUtil
{ {
class KeyframeHolder; class KeyframeHolder;
class KeyframeController; class KeyframeController;
}
namespace SceneUtil
{
class LightSource; class LightSource;
class LightListCallback; class LightListCallback;
class Skeleton; class Skeleton;
@ -150,8 +146,8 @@ public:
class TextKeyListener class TextKeyListener
{ {
public: public:
virtual void handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, virtual void handleTextKey(const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key,
const NifOsg::TextKeyMap& map) = 0; const SceneUtil::TextKeyMap& map) = 0;
virtual ~TextKeyListener() = default; virtual ~TextKeyListener() = default;
}; };
@ -242,7 +238,7 @@ protected:
osg::ref_ptr<osg::Node> mAccumRoot; osg::ref_ptr<osg::Node> mAccumRoot;
// The controller animating that node. // The controller animating that node.
osg::ref_ptr<NifOsg::KeyframeController> mAccumCtrl; osg::ref_ptr<SceneUtil::KeyframeController> mAccumCtrl;
// Used to reset the position of the accumulation root every frame - the movement should be applied to the physics system // Used to reset the position of the accumulation root every frame - the movement should be applied to the physics system
osg::ref_ptr<ResetAccumRootCallback> mResetAccumRootCallback; osg::ref_ptr<ResetAccumRootCallback> mResetAccumRootCallback;
@ -306,12 +302,12 @@ protected:
* the marker is not found, or if the markers are the same, it returns * the marker is not found, or if the markers are the same, it returns
* false. * false.
*/ */
bool reset(AnimState &state, const NifOsg::TextKeyMap &keys, bool reset(AnimState &state, const SceneUtil::TextKeyMap &keys,
const std::string &groupname, const std::string &start, const std::string &stop, const std::string &groupname, const std::string &start, const std::string &stop,
float startpoint, bool loopfallback); float startpoint, bool loopfallback);
void handleTextKey(AnimState &state, const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, void handleTextKey(AnimState &state, const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key,
const NifOsg::TextKeyMap& map); const SceneUtil::TextKeyMap& map);
/** Sets the root model of the object. /** Sets the root model of the object.
* *

@ -19,11 +19,10 @@
#include <components/sceneutil/attach.hpp> #include <components/sceneutil/attach.hpp>
#include <components/sceneutil/visitor.hpp> #include <components/sceneutil/visitor.hpp>
#include <components/sceneutil/skeleton.hpp> #include <components/sceneutil/skeleton.hpp>
#include <components/sceneutil/keyframe.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/nifosg/nifloader.hpp> // TextKeyMapHolder
#include <components/vfs/manager.hpp> #include <components/vfs/manager.hpp>
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
@ -864,7 +863,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
for (unsigned int i=0; i<node->getUserDataContainer()->getNumUserObjects(); ++i) for (unsigned int i=0; i<node->getUserDataContainer()->getNumUserObjects(); ++i)
{ {
osg::Object* obj = node->getUserDataContainer()->getUserObject(i); osg::Object* obj = node->getUserDataContainer()->getUserObject(i);
if (NifOsg::TextKeyMapHolder* keys = dynamic_cast<NifOsg::TextKeyMapHolder*>(obj)) if (SceneUtil::TextKeyMapHolder* keys = dynamic_cast<SceneUtil::TextKeyMapHolder*>(obj))
{ {
for (const auto &key : keys->mTextKeys) for (const auto &key : keys->mTextKeys)
{ {

@ -71,8 +71,7 @@ KeyframeController::KeyframeController()
} }
KeyframeController::KeyframeController(const KeyframeController &copy, const osg::CopyOp &copyop) KeyframeController::KeyframeController(const KeyframeController &copy, const osg::CopyOp &copyop)
: osg::NodeCallback(copy, copyop) : SceneUtil::KeyframeController(copy, copyop)
, Controller(copy)
, mRotations(copy.mRotations) , mRotations(copy.mRotations)
, mXRotations(copy.mXRotations) , mXRotations(copy.mXRotations)
, mYRotations(copy.mYRotations) , mYRotations(copy.mYRotations)

@ -6,7 +6,7 @@
#include <components/nif/controller.hpp> #include <components/nif/controller.hpp>
#include <components/nif/data.hpp> #include <components/nif/data.hpp>
#include <components/sceneutil/controller.hpp> #include <components/sceneutil/keyframe.hpp>
#include <components/sceneutil/statesetupdater.hpp> #include <components/sceneutil/statesetupdater.hpp>
#include <set> #include <set>
@ -226,7 +226,7 @@ namespace NifOsg
std::vector<FloatInterpolator> mKeyFrames; std::vector<FloatInterpolator> mKeyFrames;
}; };
class KeyframeController : public osg::NodeCallback, public SceneUtil::Controller class KeyframeController : public SceneUtil::KeyframeController
{ {
public: public:
// This is used if there's no interpolator but there is data (Morrowind meshes). // This is used if there's no interpolator but there is data (Morrowind meshes).
@ -242,7 +242,7 @@ namespace NifOsg
META_Object(NifOsg, KeyframeController) META_Object(NifOsg, KeyframeController)
virtual osg::Vec3f getTranslation(float time) const; osg::Vec3f getTranslation(float time) const override;
void operator() (osg::Node*, osg::NodeVisitor*) override; void operator() (osg::Node*, osg::NodeVisitor*) override;

@ -139,7 +139,7 @@ namespace
} }
}; };
void extractTextKeys(const Nif::NiTextKeyExtraData *tk, NifOsg::TextKeyMap &textkeys) void extractTextKeys(const Nif::NiTextKeyExtraData *tk, SceneUtil::TextKeyMap &textkeys)
{ {
for(size_t i = 0;i < tk->list.size();i++) for(size_t i = 0;i < tk->list.size();i++)
{ {
@ -234,7 +234,7 @@ namespace NifOsg
// This is used to queue emitters that weren't attached to their node yet. // This is used to queue emitters that weren't attached to their node yet.
std::vector<std::pair<size_t, osg::ref_ptr<Emitter>>> mEmitterQueue; std::vector<std::pair<size_t, osg::ref_ptr<Emitter>>> mEmitterQueue;
static void loadKf(Nif::NIFFilePtr nif, KeyframeHolder& target) static void loadKf(Nif::NIFFilePtr nif, SceneUtil::KeyframeHolder& target)
{ {
const Nif::NiSequenceStreamHelper *seq = nullptr; const Nif::NiSequenceStreamHelper *seq = nullptr;
const size_t numRoots = nif->numRoots(); const size_t numRoots = nif->numRoots();
@ -284,7 +284,7 @@ namespace NifOsg
if (key->data.empty() && key->interpolator.empty()) if (key->data.empty() && key->interpolator.empty())
continue; continue;
osg::ref_ptr<NifOsg::KeyframeController> callback(handleKeyframeController(key)); osg::ref_ptr<SceneUtil::KeyframeController> callback(handleKeyframeController(key));
callback->setFunction(std::shared_ptr<NifOsg::ControllerFunction>(new NifOsg::ControllerFunction(key))); callback->setFunction(std::shared_ptr<NifOsg::ControllerFunction>(new NifOsg::ControllerFunction(key)));
if (!target.mKeyframeControllers.emplace(strdata->string, callback).second) if (!target.mKeyframeControllers.emplace(strdata->string, callback).second)
@ -305,7 +305,7 @@ namespace NifOsg
if (!nifNode) if (!nifNode)
nif->fail("Found no root nodes"); nif->fail("Found no root nodes");
osg::ref_ptr<TextKeyMapHolder> textkeys (new TextKeyMapHolder); osg::ref_ptr<SceneUtil::TextKeyMapHolder> textkeys (new SceneUtil::TextKeyMapHolder);
osg::ref_ptr<osg::Node> created = handleNode(nifNode, nullptr, imageManager, std::vector<unsigned int>(), 0, false, false, false, &textkeys->mTextKeys); osg::ref_ptr<osg::Node> created = handleNode(nifNode, nullptr, imageManager, std::vector<unsigned int>(), 0, false, false, false, &textkeys->mTextKeys);
@ -353,10 +353,10 @@ namespace NifOsg
else if (props[i].getPtr()->recType == Nif::RC_NiTexturingProperty) else if (props[i].getPtr()->recType == Nif::RC_NiTexturingProperty)
{ {
if (props[i].getPtr()->recIndex == mFirstRootTextureIndex) if (props[i].getPtr()->recIndex == mFirstRootTextureIndex)
applyTo->setUserValue("overrideFx", 1); applyTo->setUserValue("overrideFx", 1);
} }
handleProperty(props[i].getPtr(), applyTo, composite, imageManager, boundTextures, animflags); handleProperty(props[i].getPtr(), applyTo, composite, imageManager, boundTextures, animflags);
} }
} }
} }
@ -514,7 +514,7 @@ namespace NifOsg
} }
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager, osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager,
std::vector<unsigned int> boundTextures, int animflags, bool skipMeshes, bool hasMarkers, bool hasAnimatedParents, TextKeyMap* textKeys, osg::Node* rootNode=nullptr) std::vector<unsigned int> boundTextures, int animflags, bool skipMeshes, bool hasMarkers, bool hasAnimatedParents, SceneUtil::TextKeyMap* textKeys, osg::Node* rootNode=nullptr)
{ {
if (rootNode != nullptr && Misc::StringUtils::ciEqual(nifNode->name, "Bounding Box")) if (rootNode != nullptr && Misc::StringUtils::ciEqual(nifNode->name, "Bounding Box"))
return nullptr; return nullptr;
@ -1197,7 +1197,7 @@ namespace NifOsg
for (const auto& strip : data->strips) for (const auto& strip : data->strips)
{ {
if (strip.size() >= 3) if (strip.size() >= 3)
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(), geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(),
(unsigned short*)strip.data())); (unsigned short*)strip.data()));
} }
} }
@ -1929,7 +1929,7 @@ namespace NifOsg
return impl.load(file, imageManager); return impl.load(file, imageManager);
} }
void Loader::loadKf(Nif::NIFFilePtr kf, KeyframeHolder& target) void Loader::loadKf(Nif::NIFFilePtr kf, SceneUtil::KeyframeHolder& target)
{ {
LoaderImpl impl(kf->getFilename(), kf->getVersion(), kf->getUserVersion(), kf->getBethVersion()); LoaderImpl impl(kf->getFilename(), kf->getVersion(), kf->getUserVersion(), kf->getBethVersion());
impl.loadKf(kf, target); impl.loadKf(kf, target);

@ -2,12 +2,13 @@
#define OPENMW_COMPONENTS_NIFOSG_LOADER #define OPENMW_COMPONENTS_NIFOSG_LOADER
#include <components/nif/niffile.hpp> #include <components/nif/niffile.hpp>
#include <components/sceneutil/keyframe.hpp>
#include <components/sceneutil/textkeymap.hpp>
#include <osg/ref_ptr> #include <osg/ref_ptr>
#include <osg/Referenced> #include <osg/Referenced>
#include "controller.hpp" #include "controller.hpp"
#include "textkeymap.hpp"
namespace osg namespace osg
{ {
@ -21,39 +22,6 @@ namespace Resource
namespace NifOsg namespace NifOsg
{ {
struct TextKeyMapHolder : public osg::Object
{
public:
TextKeyMapHolder() {}
TextKeyMapHolder(const TextKeyMapHolder& copy, const osg::CopyOp& copyop)
: osg::Object(copy, copyop)
, mTextKeys(copy.mTextKeys)
{}
TextKeyMap mTextKeys;
META_Object(NifOsg, TextKeyMapHolder)
};
class KeyframeHolder : public osg::Object
{
public:
KeyframeHolder() {}
KeyframeHolder(const KeyframeHolder& copy, const osg::CopyOp& copyop)
: mTextKeys(copy.mTextKeys)
, mKeyframeControllers(copy.mKeyframeControllers)
{
}
TextKeyMap mTextKeys;
META_Object(OpenMW, KeyframeHolder)
typedef std::map<std::string, osg::ref_ptr<const KeyframeController> > KeyframeControllerMap;
KeyframeControllerMap mKeyframeControllers;
};
/// The main class responsible for loading NIF files into an OSG-Scenegraph. /// The main class responsible for loading NIF files into an OSG-Scenegraph.
/// @par This scene graph is self-contained and can be cloned using osg::clone if desired. Particle emitters /// @par This scene graph is self-contained and can be cloned using osg::clone if desired. Particle emitters
/// and programs hold a pointer to their ParticleSystem, which would need to be manually updated when cloning. /// and programs hold a pointer to their ParticleSystem, which would need to be manually updated when cloning.
@ -64,7 +32,7 @@ namespace NifOsg
static osg::ref_ptr<osg::Node> load(Nif::NIFFilePtr file, Resource::ImageManager* imageManager); static osg::ref_ptr<osg::Node> load(Nif::NIFFilePtr file, Resource::ImageManager* imageManager);
/// Load keyframe controllers from the given kf file. /// Load keyframe controllers from the given kf file.
static void loadKf(Nif::NIFFilePtr kf, KeyframeHolder& target); static void loadKf(Nif::NIFFilePtr kf, SceneUtil::KeyframeHolder& target);
/// Set whether or not nodes marked as "MRK" should be shown. /// Set whether or not nodes marked as "MRK" should be shown.
/// These should be hidden ingame, but visible in the editor. /// These should be hidden ingame, but visible in the editor.

@ -2,13 +2,45 @@
#include <components/vfs/manager.hpp> #include <components/vfs/manager.hpp>
#include <components/nifosg/nifloader.hpp>
#include "objectcache.hpp" #include "objectcache.hpp"
#include "scenemanager.hpp"
namespace
{
class RetrieveAnimationsVisitor : public osg::NodeVisitor
{
public:
RetrieveAnimationsVisitor(SceneUtil::KeyframeHolder& target) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), mTarget(target) {}
virtual void apply(osg::Node& node)
{
if (node.libraryName() == std::string("osgAnimation"))
std::cout << "found an " << node.className() << std::endl;
traverse(node);
}
private:
SceneUtil::KeyframeHolder& mTarget;
};
std::string getFileExtension(const std::string& file)
{
size_t extPos = file.find_last_of('.');
if (extPos != std::string::npos && extPos+1 < file.size())
return file.substr(extPos+1);
return std::string();
}
}
namespace Resource namespace Resource
{ {
KeyframeManager::KeyframeManager(const VFS::Manager* vfs) KeyframeManager::KeyframeManager(const VFS::Manager* vfs, SceneManager* sceneManager)
: ResourceManager(vfs) : ResourceManager(vfs)
, mSceneManager(sceneManager)
{ {
} }
@ -16,19 +48,28 @@ namespace Resource
{ {
} }
osg::ref_ptr<const NifOsg::KeyframeHolder> KeyframeManager::get(const std::string &name) osg::ref_ptr<const SceneUtil::KeyframeHolder> KeyframeManager::get(const std::string &name)
{ {
std::string normalized = name; std::string normalized = name;
mVFS->normalizeFilename(normalized); mVFS->normalizeFilename(normalized);
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized); osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized);
if (obj) if (obj)
return osg::ref_ptr<const NifOsg::KeyframeHolder>(static_cast<NifOsg::KeyframeHolder*>(obj.get())); return osg::ref_ptr<const SceneUtil::KeyframeHolder>(static_cast<SceneUtil::KeyframeHolder*>(obj.get()));
else else
{ {
osg::ref_ptr<NifOsg::KeyframeHolder> loaded (new NifOsg::KeyframeHolder); osg::ref_ptr<SceneUtil::KeyframeHolder> loaded (new SceneUtil::KeyframeHolder);
NifOsg::Loader::loadKf(Nif::NIFFilePtr(new Nif::NIFFile(mVFS->getNormalized(normalized), normalized)), *loaded.get()); std::string ext = getFileExtension(normalized);
if (ext == "kf")
{
NifOsg::Loader::loadKf(Nif::NIFFilePtr(new Nif::NIFFile(mVFS->getNormalized(normalized), normalized)), *loaded.get());
}
else
{
osg::ref_ptr<const osg::Node> scene = mSceneManager->getTemplate(normalized);
RetrieveAnimationsVisitor rav(*loaded.get());
const_cast<osg::Node*>(scene.get())->accept(rav); // const_cast required because there is no const version of osg::NodeVisitor
}
mCache->addEntryToObjectCache(normalized, loaded); mCache->addEntryToObjectCache(normalized, loaded);
return loaded; return loaded;
} }

@ -4,26 +4,30 @@
#include <osg/ref_ptr> #include <osg/ref_ptr>
#include <string> #include <string>
#include <components/nifosg/nifloader.hpp> #include <components/sceneutil/keyframe.hpp>
#include "resourcemanager.hpp" #include "resourcemanager.hpp"
namespace Resource namespace Resource
{ {
class SceneManager;
/// @brief Managing of keyframe resources /// @brief Managing of keyframe resources
/// @note May be used from any thread. /// @note May be used from any thread.
class KeyframeManager : public ResourceManager class KeyframeManager : public ResourceManager
{ {
public: public:
KeyframeManager(const VFS::Manager* vfs); KeyframeManager(const VFS::Manager* vfs, SceneManager* sceneManager);
~KeyframeManager(); ~KeyframeManager();
/// Retrieve a read-only keyframe resource by name (case-insensitive). /// Retrieve a read-only keyframe resource by name (case-insensitive).
/// @note Throws an exception if the resource is not found. /// @note Throws an exception if the resource is not found.
osg::ref_ptr<const NifOsg::KeyframeHolder> get(const std::string& name); osg::ref_ptr<const SceneUtil::KeyframeHolder> get(const std::string& name);
void reportStats(unsigned int frameNumber, osg::Stats* stats) const override; void reportStats(unsigned int frameNumber, osg::Stats* stats) const override;
private:
SceneManager* mSceneManager;
}; };
} }

@ -14,9 +14,9 @@ namespace Resource
: mVFS(vfs) : mVFS(vfs)
{ {
mNifFileManager.reset(new NifFileManager(vfs)); mNifFileManager.reset(new NifFileManager(vfs));
mKeyframeManager.reset(new KeyframeManager(vfs));
mImageManager.reset(new ImageManager(vfs)); mImageManager.reset(new ImageManager(vfs));
mSceneManager.reset(new SceneManager(vfs, mImageManager.get(), mNifFileManager.get())); mSceneManager.reset(new SceneManager(vfs, mImageManager.get(), mNifFileManager.get()));
mKeyframeManager.reset(new KeyframeManager(vfs, mSceneManager.get()));
addResourceManager(mNifFileManager.get()); addResourceManager(mNifFileManager.get());
addResourceManager(mKeyframeManager.get()); addResourceManager(mKeyframeManager.get());

@ -0,0 +1,68 @@
#ifndef OPENMW_COMPONENTS_SCENEUTIL_KEYFRAME_HPP
#define OPENMW_COMPONENTS_SCENEUTIL_KEYFRAME_HPP
#include <map>
#include <osg/Node>
#include <components/sceneutil/controller.hpp>
#include <components/sceneutil/textkeymap.hpp>
namespace SceneUtil
{
class KeyframeController : public osg::NodeCallback, public SceneUtil::Controller
{
public:
KeyframeController() {}
KeyframeController(const KeyframeController& copy, const osg::CopyOp& copyop)
: osg::NodeCallback(copy, copyop)
, SceneUtil::Controller(copy)
{}
META_Object(SceneUtil, KeyframeController)
virtual osg::Vec3f getTranslation(float time) const { return osg::Vec3f(); }
virtual void operator() (osg::Node* node, osg::NodeVisitor* nodeVisitor) { traverse(node, nodeVisitor); }
};
/// Wrapper object containing an animation track as a ref-countable osg::Object.
struct TextKeyMapHolder : public osg::Object
{
public:
TextKeyMapHolder() {}
TextKeyMapHolder(const TextKeyMapHolder& copy, const osg::CopyOp& copyop)
: osg::Object(copy, copyop)
, mTextKeys(copy.mTextKeys)
{}
TextKeyMap mTextKeys;
META_Object(SceneUtil, TextKeyMapHolder)
};
/// Wrapper object containing the animation track and its KeyframeControllers.
class KeyframeHolder : public osg::Object
{
public:
KeyframeHolder() {}
KeyframeHolder(const KeyframeHolder& copy, const osg::CopyOp& copyop)
: mTextKeys(copy.mTextKeys)
, mKeyframeControllers(copy.mKeyframeControllers)
{
}
TextKeyMap mTextKeys;
META_Object(SceneUtil, KeyframeHolder)
/// Controllers mapped to node name.
typedef std::map<std::string, osg::ref_ptr<const KeyframeController> > KeyframeControllerMap;
KeyframeControllerMap mKeyframeControllers;
};
}
#endif

@ -1,12 +1,12 @@
#ifndef OPENMW_COMPONENTS_NIFOSG_TEXTKEYMAP #ifndef OPENMW_COMPONENTS_SCENEUTIL_TEXTKEYMAP
#define OPENMW_COMPONENTS_NIFOSG_TEXTKEYMAP #define OPENMW_COMPONENTS_SCENEUTIL_TEXTKEYMAP
#include <algorithm> #include <algorithm>
#include <map> #include <map>
#include <set> #include <set>
#include <string> #include <string>
namespace NifOsg namespace SceneUtil
{ {
class TextKeyMap class TextKeyMap
{ {
Loading…
Cancel
Save