|
|
|
@ -275,21 +275,28 @@ namespace NifOsg
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Nif::ExtraPtr extra = seq->extra;
|
|
|
|
|
if (extra.empty() || extra->recType != Nif::RC_NiTextKeyExtraData)
|
|
|
|
|
Nif::ExtraList extraList = seq->getExtraList();
|
|
|
|
|
if (extraList.empty())
|
|
|
|
|
{
|
|
|
|
|
Log(Debug::Warning) << "NIFFile Warning: NiSequenceStreamHelper has no text keys. File: "
|
|
|
|
|
<< nif.getFilename();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (extraList[0]->recType != Nif::RC_NiTextKeyExtraData)
|
|
|
|
|
{
|
|
|
|
|
Log(Debug::Warning) << "NIFFile Warning: First extra data was not a NiTextKeyExtraData, but a "
|
|
|
|
|
<< (extra.empty() ? std::string_view("nil") : std::string_view(extra->recName))
|
|
|
|
|
<< ". File: " << nif.getFilename();
|
|
|
|
|
<< std::string_view(extraList[0]->recName) << ". File: " << nif.getFilename();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extractTextKeys(static_cast<const Nif::NiTextKeyExtraData*>(extra.getPtr()), target.mTextKeys);
|
|
|
|
|
auto textKeyExtraData = static_cast<const Nif::NiTextKeyExtraData*>(extraList[0].getPtr());
|
|
|
|
|
extractTextKeys(textKeyExtraData, target.mTextKeys);
|
|
|
|
|
|
|
|
|
|
extra = extra->mNext;
|
|
|
|
|
Nif::ControllerPtr ctrl = seq->controller;
|
|
|
|
|
for (; !extra.empty() && !ctrl.empty(); (extra = extra->mNext), (ctrl = ctrl->next))
|
|
|
|
|
Nif::ControllerPtr ctrl = seq->mController;
|
|
|
|
|
for (size_t i = 1; i < extraList.size() && !ctrl.empty(); i++, (ctrl = ctrl->next))
|
|
|
|
|
{
|
|
|
|
|
Nif::ExtraPtr extra = extraList[i];
|
|
|
|
|
if (extra->recType != Nif::RC_NiStringExtraData || ctrl->recType != Nif::RC_NiKeyframeController)
|
|
|
|
|
{
|
|
|
|
|
Log(Debug::Warning) << "NIFFile Warning: Unexpected extra data " << extra->recName
|
|
|
|
@ -454,7 +461,7 @@ namespace NifOsg
|
|
|
|
|
static osg::ref_ptr<osg::LOD> handleLodNode(const Nif::NiLODNode* niLodNode)
|
|
|
|
|
{
|
|
|
|
|
osg::ref_ptr<osg::LOD> lod(new osg::LOD);
|
|
|
|
|
lod->setName(niLodNode->name);
|
|
|
|
|
lod->setName(niLodNode->mName);
|
|
|
|
|
lod->setCenterMode(osg::LOD::USER_DEFINED_CENTER);
|
|
|
|
|
lod->setCenter(niLodNode->lodCenter);
|
|
|
|
|
for (unsigned int i = 0; i < niLodNode->lodLevels.size(); ++i)
|
|
|
|
@ -469,7 +476,7 @@ namespace NifOsg
|
|
|
|
|
static osg::ref_ptr<osg::Switch> handleSwitchNode(const Nif::NiSwitchNode* niSwitchNode)
|
|
|
|
|
{
|
|
|
|
|
osg::ref_ptr<osg::Switch> switchNode(new osg::Switch);
|
|
|
|
|
switchNode->setName(niSwitchNode->name);
|
|
|
|
|
switchNode->setName(niSwitchNode->mName);
|
|
|
|
|
switchNode->setNewChildDefaultValue(false);
|
|
|
|
|
switchNode->setSingleChildOn(niSwitchNode->initialIndex);
|
|
|
|
|
return switchNode;
|
|
|
|
@ -479,7 +486,7 @@ namespace NifOsg
|
|
|
|
|
{
|
|
|
|
|
const Nif::NiFltAnimationNode* niFltAnimationNode = static_cast<const Nif::NiFltAnimationNode*>(nifNode);
|
|
|
|
|
osg::ref_ptr<osg::Sequence> sequenceNode(new osg::Sequence);
|
|
|
|
|
sequenceNode->setName(niFltAnimationNode->name);
|
|
|
|
|
sequenceNode->setName(niFltAnimationNode->mName);
|
|
|
|
|
if (!niFltAnimationNode->children.empty())
|
|
|
|
|
{
|
|
|
|
|
if (niFltAnimationNode->swing())
|
|
|
|
@ -604,7 +611,7 @@ namespace NifOsg
|
|
|
|
|
// This takes advantage of the fact root nodes can't have additional controllers
|
|
|
|
|
// loaded from an external .kf file (original engine just throws "can't find node" errors if you
|
|
|
|
|
// try).
|
|
|
|
|
if (nifNode->parents.empty() && nifNode->controller.empty() && nifNode->trafo.isIdentity())
|
|
|
|
|
if (nifNode->parents.empty() && nifNode->mController.empty() && nifNode->trafo.isIdentity())
|
|
|
|
|
node = new osg::Group;
|
|
|
|
|
|
|
|
|
|
dataVariance = nifNode->isBone ? osg::Object::DYNAMIC : osg::Object::STATIC;
|
|
|
|
@ -622,7 +629,7 @@ namespace NifOsg
|
|
|
|
|
osg::ref_ptr<osg::Node> handleNode(
|
|
|
|
|
const Nif::Node* nifNode, const Nif::Parent* parent, osg::Group* parentNode, HandleNodeArgs args)
|
|
|
|
|
{
|
|
|
|
|
if (args.mRootNode && Misc::StringUtils::ciEqual(nifNode->name, "Bounding Box"))
|
|
|
|
|
if (args.mRootNode && Misc::StringUtils::ciEqual(nifNode->mName, "Bounding Box"))
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
osg::ref_ptr<osg::Group> node = createNode(nifNode);
|
|
|
|
@ -632,7 +639,7 @@ namespace NifOsg
|
|
|
|
|
node->addCullCallback(new BillboardCallback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
node->setName(nifNode->name);
|
|
|
|
|
node->setName(nifNode->mName);
|
|
|
|
|
|
|
|
|
|
if (parentNode)
|
|
|
|
|
parentNode->addChild(node);
|
|
|
|
@ -646,16 +653,7 @@ namespace NifOsg
|
|
|
|
|
// - finding a random child NiNode in NiBspArrayController
|
|
|
|
|
node->setUserValue("recIndex", nifNode->recIndex);
|
|
|
|
|
|
|
|
|
|
std::vector<Nif::ExtraPtr> extraCollection;
|
|
|
|
|
|
|
|
|
|
for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->mNext)
|
|
|
|
|
extraCollection.emplace_back(e);
|
|
|
|
|
|
|
|
|
|
for (const auto& extraNode : nifNode->extralist)
|
|
|
|
|
if (!extraNode.empty())
|
|
|
|
|
extraCollection.emplace_back(extraNode);
|
|
|
|
|
|
|
|
|
|
for (const auto& e : extraCollection)
|
|
|
|
|
for (const auto& e : nifNode->getExtraList())
|
|
|
|
|
{
|
|
|
|
|
if (e->recType == Nif::RC_NiTextKeyExtraData && args.mTextKeys)
|
|
|
|
|
{
|
|
|
|
@ -727,7 +725,7 @@ namespace NifOsg
|
|
|
|
|
if (nifNode->isHidden())
|
|
|
|
|
{
|
|
|
|
|
bool hasVisController = false;
|
|
|
|
|
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
{
|
|
|
|
|
hasVisController |= (ctrl->recType == Nif::RC_NiVisController);
|
|
|
|
|
if (hasVisController)
|
|
|
|
@ -755,12 +753,12 @@ namespace NifOsg
|
|
|
|
|
bool skip;
|
|
|
|
|
if (args.mNifVersion <= Nif::NIFFile::NIFVersion::VER_MW)
|
|
|
|
|
{
|
|
|
|
|
skip = (args.mHasMarkers && Misc::StringUtils::ciStartsWith(nifNode->name, "tri editormarker"))
|
|
|
|
|
|| Misc::StringUtils::ciStartsWith(nifNode->name, "shadow")
|
|
|
|
|
|| Misc::StringUtils::ciStartsWith(nifNode->name, "tri shadow");
|
|
|
|
|
skip = (args.mHasMarkers && Misc::StringUtils::ciStartsWith(nifNode->mName, "tri editormarker"))
|
|
|
|
|
|| Misc::StringUtils::ciStartsWith(nifNode->mName, "shadow")
|
|
|
|
|
|| Misc::StringUtils::ciStartsWith(nifNode->mName, "tri shadow");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
skip = args.mHasMarkers && Misc::StringUtils::ciStartsWith(nifNode->name, "EditorMarker");
|
|
|
|
|
skip = args.mHasMarkers && Misc::StringUtils::ciStartsWith(nifNode->mName, "EditorMarker");
|
|
|
|
|
if (!skip)
|
|
|
|
|
{
|
|
|
|
|
Nif::NiSkinInstancePtr skin = static_cast<const Nif::NiGeometry*>(nifNode)->skin;
|
|
|
|
@ -770,7 +768,7 @@ namespace NifOsg
|
|
|
|
|
else
|
|
|
|
|
handleSkinnedGeometry(nifNode, parent, node, composite, args.mBoundTextures, args.mAnimFlags);
|
|
|
|
|
|
|
|
|
|
if (!nifNode->controller.empty())
|
|
|
|
|
if (!nifNode->mController.empty())
|
|
|
|
|
handleMeshControllers(nifNode, node, composite, args.mBoundTextures, args.mAnimFlags);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -807,9 +805,9 @@ namespace NifOsg
|
|
|
|
|
const Nif::NiSwitchNode* niSwitchNode = static_cast<const Nif::NiSwitchNode*>(nifNode);
|
|
|
|
|
osg::ref_ptr<osg::Switch> switchNode = handleSwitchNode(niSwitchNode);
|
|
|
|
|
node->addChild(switchNode);
|
|
|
|
|
if (niSwitchNode->name == Constants::NightDayLabel)
|
|
|
|
|
if (niSwitchNode->mName == Constants::NightDayLabel)
|
|
|
|
|
mHasNightDayLabel = true;
|
|
|
|
|
else if (niSwitchNode->name == Constants::HerbalismLabel)
|
|
|
|
|
else if (niSwitchNode->mName == Constants::HerbalismLabel)
|
|
|
|
|
mHasHerbalismLabel = true;
|
|
|
|
|
|
|
|
|
|
currentNode = switchNode;
|
|
|
|
@ -860,7 +858,7 @@ namespace NifOsg
|
|
|
|
|
SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures,
|
|
|
|
|
int animflags)
|
|
|
|
|
{
|
|
|
|
|
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
{
|
|
|
|
|
if (!ctrl->isActive())
|
|
|
|
|
continue;
|
|
|
|
@ -887,7 +885,7 @@ namespace NifOsg
|
|
|
|
|
|
|
|
|
|
void handleNodeControllers(const Nif::Node* nifNode, osg::Node* node, int animflags, bool& isAnimated)
|
|
|
|
|
{
|
|
|
|
|
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
{
|
|
|
|
|
if (!ctrl->isActive())
|
|
|
|
|
continue;
|
|
|
|
@ -965,7 +963,7 @@ namespace NifOsg
|
|
|
|
|
void handleMaterialControllers(const Nif::Property* materialProperty,
|
|
|
|
|
SceneUtil::CompositeStateSetUpdater* composite, int animflags, const osg::Material* baseMaterial)
|
|
|
|
|
{
|
|
|
|
|
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
for (Nif::ControllerPtr ctrl = materialProperty->mController; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
{
|
|
|
|
|
if (!ctrl->isActive())
|
|
|
|
|
continue;
|
|
|
|
@ -1016,7 +1014,7 @@ namespace NifOsg
|
|
|
|
|
void handleTextureControllers(const Nif::Property* texProperty, SceneUtil::CompositeStateSetUpdater* composite,
|
|
|
|
|
Resource::ImageManager* imageManager, osg::StateSet* stateset, int animflags)
|
|
|
|
|
{
|
|
|
|
|
for (Nif::ControllerPtr ctrl = texProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
for (Nif::ControllerPtr ctrl = texProperty->mController; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
{
|
|
|
|
|
if (!ctrl->isActive())
|
|
|
|
|
continue;
|
|
|
|
@ -1256,7 +1254,7 @@ namespace NifOsg
|
|
|
|
|
partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
|
|
|
|
|
|
|
|
|
|
const Nif::NiParticleSystemController* partctrl = nullptr;
|
|
|
|
|
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
{
|
|
|
|
|
if (!ctrl->isActive())
|
|
|
|
|
continue;
|
|
|
|
@ -1465,7 +1463,7 @@ namespace NifOsg
|
|
|
|
|
new osg::DrawElementsUShort(osg::PrimitiveSet::LINES, line.size(), line.data()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
handleNiGeometryData(geometry, niGeometryData, boundTextures, nifNode->name);
|
|
|
|
|
handleNiGeometryData(geometry, niGeometryData, boundTextures, nifNode->mName);
|
|
|
|
|
|
|
|
|
|
// osg::Material properties are handled here for two reasons:
|
|
|
|
|
// - if there are no vertex colors, we need to disable colorMode.
|
|
|
|
@ -1487,7 +1485,7 @@ namespace NifOsg
|
|
|
|
|
if (geom->empty())
|
|
|
|
|
return;
|
|
|
|
|
osg::ref_ptr<osg::Drawable> drawable;
|
|
|
|
|
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next)
|
|
|
|
|
{
|
|
|
|
|
if (!ctrl->isActive())
|
|
|
|
|
continue;
|
|
|
|
@ -1507,7 +1505,7 @@ namespace NifOsg
|
|
|
|
|
}
|
|
|
|
|
if (!drawable.get())
|
|
|
|
|
drawable = geom;
|
|
|
|
|
drawable->setName(nifNode->name);
|
|
|
|
|
drawable->setName(nifNode->mName);
|
|
|
|
|
parentNode->addChild(drawable);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1543,7 +1541,7 @@ namespace NifOsg
|
|
|
|
|
return;
|
|
|
|
|
osg::ref_ptr<SceneUtil::RigGeometry> rig(new SceneUtil::RigGeometry);
|
|
|
|
|
rig->setSourceGeometry(geometry);
|
|
|
|
|
rig->setName(nifNode->name);
|
|
|
|
|
rig->setName(nifNode->mName);
|
|
|
|
|
|
|
|
|
|
// Assign bone weights
|
|
|
|
|
osg::ref_ptr<SceneUtil::RigGeometry::InfluenceMap> map(new SceneUtil::RigGeometry::InfluenceMap);
|
|
|
|
@ -1553,7 +1551,7 @@ namespace NifOsg
|
|
|
|
|
const Nif::NodeList& bones = skin->mBones;
|
|
|
|
|
for (std::size_t i = 0; i < bones.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->name);
|
|
|
|
|
std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName);
|
|
|
|
|
|
|
|
|
|
SceneUtil::RigGeometry::BoneInfluence influence;
|
|
|
|
|
influence.mWeights = data->mBones[i].mWeights;
|
|
|
|
@ -1839,7 +1837,7 @@ namespace NifOsg
|
|
|
|
|
for (size_t i = 0; i < texprop->textures.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
if (texprop->textures[i].inUse
|
|
|
|
|
|| (i == Nif::NiTexturingProperty::BaseTexture && !texprop->controller.empty()))
|
|
|
|
|
|| (i == Nif::NiTexturingProperty::BaseTexture && !texprop->mController.empty()))
|
|
|
|
|
{
|
|
|
|
|
switch (i)
|
|
|
|
|
{
|
|
|
|
@ -1866,7 +1864,7 @@ namespace NifOsg
|
|
|
|
|
if (texprop->textures[i].inUse)
|
|
|
|
|
{
|
|
|
|
|
const Nif::NiTexturingProperty::Texture& tex = texprop->textures[i];
|
|
|
|
|
if (tex.texture.empty() && texprop->controller.empty())
|
|
|
|
|
if (tex.texture.empty() && texprop->mController.empty())
|
|
|
|
|
{
|
|
|
|
|
if (i == 0)
|
|
|
|
|
Log(Debug::Warning) << "Base texture is in use but empty on shape \"" << nodeName
|
|
|
|
@ -2424,7 +2422,7 @@ namespace NifOsg
|
|
|
|
|
mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(matprop->data.specular, 1.f));
|
|
|
|
|
mat->setShininess(osg::Material::FRONT_AND_BACK, matprop->data.glossiness);
|
|
|
|
|
|
|
|
|
|
if (!matprop->controller.empty())
|
|
|
|
|
if (!matprop->mController.empty())
|
|
|
|
|
{
|
|
|
|
|
hasMatCtrl = true;
|
|
|
|
|
handleMaterialControllers(matprop, composite, animflags, mat);
|
|
|
|
|