# add it to the name list if there is a bone with that name
ifbone_block:
NifLog.info(f"Identified nif block '{nif_bone_name}' with bone '{bone_name}' in selected armature")
self.dict_armatures[skelroot].append(bone_block)
self.complete_bone_tree(bone_block,skelroot)
# search for all NiTriShape or NiTriStrips blocks...
ifisinstance(ni_block,NifFormat.NiTriBasedGeom):
# yes, we found one, get its skin instance
ifni_block.is_skin():
NifLog.debug(f"Skin found on block '{ni_block.name}'")
# it has a skin instance, so get the skeleton root
# which is an armature only if it's not a skinning influence
# so mark the node to be imported as an armature
skininst=ni_block.skin_instance
skelroot=skininst.skeleton_root
ifNifOp.props.process=="EVERYTHING":
ifskelrootnotinself.dict_armatures:
self.dict_armatures[skelroot]=[]
NifLog.debug(f"'{skelroot.name}' is an armature")
elifNifOp.props.process=="GEOMETRY_ONLY":
ifskelrootnotinself.dict_armatures:
raiseio_scene_niftools.utils.logging.NifError(f"Nif structure incompatible with '{b_armature_obj.name}' as armature: node '{ni_block.name}' has '{skelroot.name}' as armature")
forboneBlockinskininst.bones:
# boneBlock can be None; see pyffi issue #3114079
ifnotboneBlock:
continue
ifboneBlocknotinself.dict_armatures[skelroot]:
self.dict_armatures[skelroot].append(boneBlock)
NifLog.debug(f"'{boneBlock.name}' is a bone of armature '{skelroot.name}'")
# now we "attach" the bone to the armature:
# we make sure all NiNodes from this bone all the way
# down to the armature NiNode are marked as bones
self.complete_bone_tree(boneBlock,skelroot)
# mark all nodes as bones
self.populate_bone_tree(skelroot)
# continue down the tree
forchildinni_block.get_refs():
ifnotisinstance(child,NifFormat.NiAVObject):
continue# skip blocks that don't have transforms
self.mark_armatures_bones(child)
defpopulate_bone_tree(self,skelroot):
"""Add all of skelroot's bones to its dict_armatures list."""
forboneinskelroot.tree():
ifboneisskelroot:
continue
ifnotisinstance(bone,NifFormat.NiNode):
continue
ifisinstance(bone,NifFormat.NiLODNode):
# LOD nodes are never bones
continue
ifbonenotinself.dict_armatures[skelroot]:
self.dict_armatures[skelroot].append(bone)
NifLog.debug(f"'{bone.name}' marked as extra bone of armature '{skelroot.name}'")
defcomplete_bone_tree(self,bone,skelroot):
"""Make sure that the complete hierarchy from bone up to skelroot is marked in dict_armatures."""
# we must already have marked both as a bone
assertskelrootinself.dict_armatures# debug
assertboneinself.dict_armatures[skelroot]# debug
# get the node parent, this should be marked as an armature or as a bone
boneparent=bone._parent
ifboneparent!=skelroot:
# parent is not the skeleton root
ifboneparentnotinself.dict_armatures[skelroot]:
# neither is it marked as a bone: so mark the parent as a bone
self.dict_armatures[skelroot].append(boneparent)
# store the coordinates for realignement autodetection
NifLog.debug(f"'{boneparent.name}' is a bone of armature '{skelroot.name}'")
# now the parent is marked as a bone
# recursion: complete the bone tree,
# this time starting from the parent bone
self.complete_bone_tree(boneparent,skelroot)
defis_bone(self,ni_block):
"""Tests a NiNode to see if it has been marked as a bone."""
ifni_block:
forbonesinself.dict_armatures.values():
ifni_blockinbones:
returnTrue
ifisinstance(ni_block,NifFormat.NiNode):
returnself.skinned
defis_armature_root(self,ni_block):
defis_armature_root(self,n_block):
"""Tests a block to see if it's an armature."""
ifisinstance(ni_block,NifFormat.NiNode):
returnni_blockinself.dict_armatures
ifisinstance(n_block,NifFormat.NiNode):
# we have skinning and are waiting for a suitable start node of the tree