static bool HasUserPropBuffer(NiNodeRef node) { if (node) { if (NiStringExtraDataRef data = SelectFirstObjectOfType<NiStringExtraData>(node->GetExtraData())){ if (strmatch(data->GetName(), "UserPropBuffer")) return true; } } return false; }
/*---------------------------------------------------------------------------*/ NiNodeRef NifPrepareUtility::parse4Blender(NiNodeRef pNode) { vector<NiAVObjectRef> childList(pNode->GetChildren()); list<NiExtraDataRef> extraList(pNode->GetExtraData()); // parse extra data for BSInvMarker for (auto pIter(extraList.begin()), pEnd(extraList.end()); pIter != pEnd; pIter++) { if (_remBSInvMarker && (DynamicCast<BSInvMarker>(*pIter) != NULL)) { pNode->RemoveExtraData(*pIter); } } // unlink children pNode->ClearChildren(); // iterate over children for (auto pIter(childList.begin()), pEnd(childList.end()); pIter != pEnd; pIter++) { // NiTriShape => remove BSLightingShaderProperty if (DynamicCast<NiTriShape>(*pIter) != NULL) { if (_remBSProperties) { NiTriShapeRef pShape (DynamicCast<NiTriShape>(*pIter)); // remove properties (Bethesda uses max. 2) pShape->SetBSProperty(0, NULL); pShape->SetBSProperty(1, NULL); } // add shape to node pNode->AddChild(*pIter); } // BSInvMarker => remove whole object else if (_remBSInvMarker && (DynamicCast<BSInvMarker>(*pIter) != NULL)) { // skip entry => do not add to final list } // NiNode (and derived classes?) => iterate subnodes else if (DynamicCast<NiNode>(*pIter) != NULL) { pNode->AddChild(&(*parse4Blender(DynamicCast<NiNode>(*pIter)))); } } // for (auto pIter(childList.begin()), pEnd(childList.end()); pIter != pEnd; pIter++) return pNode; }
bool NifImporter::IsBiped() { if (HasSkeleton()){ NiNodeRef rootNode = root; if (rootNode){ list<NiExtraDataRef> extraData = rootNode->GetExtraData(); if (!extraData.empty()) { if ( BSXFlagsRef flags = SelectFirstObjectOfType<BSXFlags>(extraData) ) { return (flags->GetData() & 0x4); } } } } return false; }
void NifImporter::ImportBones(NiNodeRef node, bool recurse) { try { if (uncontrolledDummies) BuildControllerRefList(node, ctrlCount); string name = node->GetName(); vector<NiAVObjectRef> children = node->GetChildren(); vector<NiNodeRef> childNodes = DynamicCast<NiNode>(children); NiAVObject::CollisionType cType = node->GetCollisionMode(); if (children.empty() && name == "Bounding Box") return; // Do all node manipulations here NiNodeRef parent = node->GetParent(); string parentname = (parent ? parent->GetName() : ""); Matrix44 m4 = node->GetWorldTransform(); // Check for Prn strings and change parent if necessary if (supportPrnStrings) { list<NiStringExtraDataRef> strings = DynamicCast<NiStringExtraData>(node->GetExtraData()); for (list<NiStringExtraDataRef>::iterator itr = strings.begin(); itr != strings.end(); ++itr){ if (strmatch((*itr)->GetName(), "Prn")) { parentname = (*itr)->GetData(); if (INode *pn = gi->GetINodeByName(parentname.c_str())){ // Apparently Heads tend to need to be rotated 90 degrees on import for if (!rotate90Degrees.empty() && wildmatch(rotate90Degrees, parentname)) { m4 *= TOMATRIX4(RotateYMatrix(TORAD(90))); } m4 *= TOMATRIX4(pn->GetObjTMAfterWSM(0, NULL)); } } } } float len = node->GetLocalTranslation().Magnitude(); // Remove NonAccum nodes and merge into primary bone if (mergeNonAccum && wildmatch("* NonAccum", name) && parent) { string realname = name.substr(0, name.length() - 9); if (strmatch(realname, parent->GetName())) { Matrix44 tm = parent->GetLocalTransform() * node->GetLocalTransform(); name = realname; len += tm.GetTranslation().Magnitude(); parent = parent->GetParent(); } } PosRotScale prs = prsDefault; Vector3 pos; Matrix33 rot; float scale; m4.Decompose(pos, rot, scale); Matrix3 im = TOMATRIX3(m4); Point3 p = im.GetTrans(); Quat q(im); //q.Normalize(); Vector3 ppos; Point3 zAxis(0,0,0); bool hasChildren = !children.empty(); if (hasChildren) { float len = 0.0f; for (vector<NiAVObjectRef>::iterator itr=children.begin(), end = children.end(); itr != end; ++itr) { len += GetObjectLength(*itr); } len /= float(children.size()); ppos = pos + Vector3(len, 0.0f, 0.0f); // just really need magnitude as rotation will take care of positioning } else if (parent) { ppos = pos + Vector3(len/3.0f, 0.0f, 0.0f); } Point3 pp(ppos.x, ppos.y, ppos.z); Point3 qp = TORAD(TOEULER(im)); INode *bone = NULL; if (!doNotReuseExistingBones) // Games like BC3 reuse the same bone names { bone = FindNode(node); if (bone == NULL) bone = gi->GetINodeByName(name.c_str()); } if (bone) { // Is there a better way of "Affect Pivot Only" behaviors? INode *pinode = bone->GetParentNode(); if (pinode) bone->Detach(0,1); PosRotScaleNode(bone, p, q, scale, prs); if (pinode) pinode->AttachChild(bone, 1); } else { bool isDummy = ( (uncontrolledDummies && !HasControllerRef(ctrlCount, name)) || (!dummyNodeMatches.empty() && wildmatch(dummyNodeMatches, name)) || (convertBillboardsToDummyNodes && node->IsDerivedType(NiBillboardNode::TYPE)) ); if (wildmatch("Camera*", name)) { if (enableCameras) { if (bone = CreateCamera(name)) { PosRotScaleNode(bone, p, q, scale, prs); bone->Hide(node->GetVisibility() ? FALSE : TRUE); } } }else if (isDummy && createNubsForBones) bone = CreateHelper(name, p); else if (bone = CreateBone(name, p, pp, zAxis)) { PosRotScaleNode(bone, p, q, scale, prs); bone->Hide(node->GetVisibility() ? FALSE : TRUE); } if (bone) { if (!parentname.empty()) { if (mergeNonAccum && wildmatch("* NonAccum", parentname)) { parentname = parentname.substr(0, parentname.length() - 9); } if (INode *pn = gi->GetINodeByName(parentname.c_str())) pn->AttachChild(bone, 1); } RegisterNode(node, bone); } } // Import UPB if (bone) ImportUPB(bone, node); // Import Havok Collision Data surrounding node, // unfortunately this causes double import of collision so I'm disabling it for now. if (enableCollision && node->GetParent()) { ImportCollision(node); } if (bone && recurse) { ImportBones(childNodes); } } catch( exception & e ) { e=e; } catch( ... ) { } }