コード例 #1
0
    def determine_texture_types(self, b_mat):
        """Checks all texture nodes of a material and checks their labels for relevant texture cues.
        Stores all slots as class properties."""
        self.b_mat = b_mat
        self._reset_fields()

        for b_texture_node in self.get_used_textslots(b_mat):
            shown_label = b_texture_node.label
            if shown_label == '':
                shown_label = b_texture_node.image.name
            NifLog.debug(
                f"Found node {b_texture_node.name} of type {shown_label}")

            # go over all slots
            for slot_name in self.slots.keys():
                if slot_name in shown_label:
                    # slot has already been populated
                    if self.slots[slot_name]:
                        raise NifError(
                            f"Multiple {slot_name} textures in material '{b_mat.name}''.\n"
                            f"Make sure there is only one texture node labeled as '{slot_name}'"
                        )
                    # it's a new slot so store it
                    self.slots[slot_name] = b_texture_node
                    break
            # unsupported texture type
            else:
                raise NifError(
                    f"Do not know how to export texture node '{b_texture_node.name}' in material '{b_mat.name}' with label '{shown_label}'."
                    f"Delete it or change its label.")
コード例 #2
0
def register():
    # addon updater code and configurations in case of broken version, try to register the updater first
    # so that users can revert back to a working version
    NifLog.debug("Starting registration")
    configure_autoupdater()

    register_modules(MODS, __name__)
コード例 #3
0
    def import_bhkcapsule_shape(self, bhk_shape):
        """Import a BhkCapsule block as a simple cylinder collision object"""
        NifLog.debug(f"Importing {bhk_shape.__class__.__name__}")

        radius = bhk_shape.radius * self.HAVOK_SCALE
        p_1 = bhk_shape.first_point
        p_2 = bhk_shape.second_point
        length = (p_1 - p_2).norm() * self.HAVOK_SCALE
        first_point = p_1 * self.HAVOK_SCALE
        second_point = p_2 * self.HAVOK_SCALE
        minx = miny = -radius
        maxx = maxy = +radius
        minz = -radius - length / 2
        maxz = length / 2 + radius

        # create blender object
        b_obj = Object.box_from_extents("capsule", minx, maxx, miny, maxy,
                                        minz, maxz)
        # here, these are not encoded as a direction so we must first calculate the direction
        b_obj.matrix_local = self.center_origin_to_matrix(
            (first_point + second_point) / 2, first_point - second_point)
        self.set_b_collider(b_obj,
                            bounds_type="CAPSULE",
                            display_type="CAPSULE",
                            radius=radius,
                            n_obj=bhk_shape)
        return [b_obj]
コード例 #4
0
    def import_bhk_ridgidbody_t(self, bhk_shape):
        """Imports a BhkRigidBody block and applies the transform to the collision objects"""
        NifLog.debug(f"Importing {bhk_shape.__class__.__name__}")

        # import shapes
        collision_objs = self.import_bhk_shape(bhk_shape.shape)

        # find transformation matrix in case of the T version
        # set rotation
        b_rot = bhk_shape.rotation
        transform = mathutils.Quaternion([b_rot.w, b_rot.x, b_rot.y,
                                          b_rot.z]).to_matrix().to_4x4()

        # set translation
        b_trans = bhk_shape.translation
        transform.translation = mathutils.Vector(
            (b_trans.x, b_trans.y, b_trans.z)) * self.HAVOK_SCALE

        # apply transform
        for b_col_obj in collision_objs:
            b_col_obj.matrix_local = b_col_obj.matrix_local @ transform

        self._import_bhk_rigid_body(bhk_shape, collision_objs)

        # and return a list of transformed collision shapes
        return collision_objs
コード例 #5
0
    def process_nispecular_property(self, prop):
        """SpecularProperty based specular"""

        # TODO [material][property]
        if NifData.data.version == 0x14000004:
            self.b_mat.specular_intensity = 0.0  # no specular prop
        NifLog.debug("NiSpecularProperty property processed")
コード例 #6
0
    def fix_pose(self, n_armature, n_node, armature_space_bind_store,
                 armature_space_pose_store):
        """reposition non-skeletal bones to maintain their local orientation to their skeletal parents"""
        for n_child_node in n_node.children:
            # only process nodes
            if not isinstance(n_child_node, NifFormat.NiNode):
                continue
            if n_child_node not in armature_space_bind_store and n_child_node in armature_space_pose_store:
                NifLog.debug(
                    f"Calculating bind pose for non-skeletal bone {n_child_node.name}"
                )
                # get matrices for n_node (the parent) - fallback to getter if it is not in the store
                n_armature_pose = armature_space_pose_store.get(
                    n_node, n_node.get_transform(n_armature))
                # get bind of parent node or pose if it has no bind pose
                n_armature_bind = armature_space_bind_store.get(
                    n_node, n_armature_pose)

                # the child must have a pose, no need for a fallback
                n_child_armature_pose = armature_space_pose_store[n_child_node]
                # get the relative transform of n_child_node from pose * inverted parent pose
                n_child_local_pose = n_child_armature_pose * n_armature_pose.get_inverse(
                    fast=False)
                # get object space transform by multiplying with bind of parent bone
                armature_space_bind_store[
                    n_child_node] = n_child_local_pose * n_armature_bind

            self.fix_pose(n_armature, n_child_node, armature_space_bind_store,
                          armature_space_pose_store)
コード例 #7
0
    def import_sequence_stream_helper(self, kf_root, b_armature_obj,
                                      bind_data):
        NifLog.debug('Importing NiSequenceStreamHelper...')
        b_action = self.create_action(b_armature_obj,
                                      kf_root.name.decode(),
                                      retrieve=False)
        # import parallel trees of extra datas and keyframe controllers
        extra = kf_root.extra_data
        controller = kf_root.controller
        while extra and controller:
            # textkeys in the stack do not specify node names, import as markers
            while isinstance(extra, NifFormat.NiTextKeyExtraData):
                self.import_text_key_extra_data(extra, b_action)
                extra = extra.next_extra_data

            # grabe the node name from string data
            bone_name = None
            if isinstance(extra, NifFormat.NiStringExtraData):
                node_name = extra.string_data.decode()
                bone_name = block_registry.get_bone_name_for_blender(node_name)
            # import keyframe controller
            if bone_name in bind_data:
                niBone_bind_scale, niBone_bind_rot_inv, niBone_bind_trans = bind_data[
                    bone_name]
                self.import_keyframe_controller(controller, b_armature_obj,
                                                bone_name, niBone_bind_scale,
                                                niBone_bind_rot_inv,
                                                niBone_bind_trans)
            # grab next pair of extra and controller
            extra = extra.next_extra_data
            controller = controller.next_controller
コード例 #8
0
 def process_nimaterial_property(self, prop):
     """Import a NiMaterialProperty based material"""
     NiMaterial().import_material(self.n_block, self.b_mat, prop)
     # TODO [animation][material] merge this call into import_material
     MaterialAnimation().import_material_controllers(
         self.n_block, self.b_mat)
     NifLog.debug("NiMaterialProperty property processed")
コード例 #9
0
 def import_controller_manager(self, n_block, b_obj, b_armature):
     ctrlm = n_block.controller
     if ctrlm and isinstance(ctrlm, NifFormat.NiControllerManager):
         NifLog.debug(f'Importing NiControllerManager')
         if b_armature:
             self.get_bind_data(b_armature)
         for ctrl in ctrlm.controller_sequences:
             self.import_kf_root(ctrl, b_armature)
コード例 #10
0
    def import_bhksphere_shape(self, bhk_shape):
        """Import a BhkSphere block as a simple sphere collision object"""
        NifLog.debug(f"Importing {bhk_shape.__class__.__name__}")

        r = bhk_shape.radius * self.HAVOK_SCALE
        b_obj = Object.box_from_extents("sphere", -r, r, -r, r, -r, r)
        self.set_b_collider(b_obj, display_type="SPHERE", bounds_type='SPHERE', radius=r, n_obj=bhk_shape)
        return [b_obj]
コード例 #11
0
    def import_bhk_ridgid_body(self, bhk_shape):
        """Imports a BhkRigidBody block and applies the transform to the collision objects"""
        NifLog.debug(f"Importing {bhk_shape.__class__.__name__}")

        # import shapes
        collision_objs = self.import_bhk_shape(bhk_shape.shape)
        self._import_bhk_rigid_body(bhk_shape, collision_objs)

        # and return a list of transformed collision shapes
        return collision_objs
コード例 #12
0
 def create_and_link(self, slot_name, n_tex_info):
     """"""
     slot_lower = slot_name.lower().replace(' ', '_')
     import_func_name = f"link_{slot_lower}_node"
     import_func = getattr(self, import_func_name, None)
     if not import_func:
         NifLog.debug(f"Could not find texture linking function {import_func_name}")
         return
     b_texture = self.create_texture_slot(n_tex_info)
     import_func(b_texture)
コード例 #13
0
    def import_morph_controller(self, n_node, b_obj):
        """Import NiGeomMorpherController as shape keys for blender object."""

        n_morphCtrl = math.find_controller(n_node, NifFormat.NiGeomMorpherController)
        if n_morphCtrl:
            NifLog.debug("NiGeomMorpherController processed")
            b_mesh = b_obj.data
            morphData = n_morphCtrl.data
            if morphData.num_morphs:
                # get name for base key
                keyname = morphData.morphs[0].frame_name.decode()
                if not keyname:
                    keyname = 'Base'

                # insert base key at frame 1, using relative keys
                sk_basis = b_obj.shape_key_add(name=keyname)

                # get base vectors and import all morphs
                baseverts = morphData.morphs[0].vectors

                shape_action = self.create_action(b_obj.data.shape_keys, b_obj.name + "-Morphs")
                
                for idxMorph in range(1, morphData.num_morphs):
                    # get name for key
                    keyname = morphData.morphs[idxMorph].frame_name.decode()
                    if not keyname:
                        keyname = f'Key {idxMorph}'
                    NifLog.info(f"Inserting key '{keyname}'")
                    # get vectors
                    morph_verts = morphData.morphs[idxMorph].vectors
                    self.morph_mesh(b_mesh, baseverts, morph_verts)
                    shape_key = b_obj.shape_key_add(name=keyname, from_mix=False)

                    # first find the keys
                    # older versions store keys in the morphData
                    morph_data = morphData.morphs[idxMorph]
                    # newer versions store keys in the controller
                    if not morph_data.keys:
                        try:
                            if n_morphCtrl.interpolators:
                                morph_data = n_morphCtrl.interpolators[idxMorph].data.data
                            elif n_morphCtrl.interpolator_weights:
                                morph_data = n_morphCtrl.interpolator_weights[idxMorph].interpolator.data.data
                        except KeyError:
                            NifLog.info(f"Unsupported interpolator \"{type(n_morphCtrl.interpolator_weights['idxMorph'].interpolator)}\"")
                            continue
                        
                    # get the interpolation mode
                    interp = self.get_b_interp_from_n_interp( morph_data.interpolation)
                    fcu = self.create_fcurves(shape_action, "value", (0,), flags=n_morphCtrl.flags, keyname=shape_key.name)
                    
                    # set keyframes
                    for key in morph_data.keys:
                        self.add_key(fcu, key.time, (key.value,), interp)
コード例 #14
0
 def store_pose_matrices(self, n_node, n_root):
     """Stores the nif armature space matrix of a node tree"""
     # check that n_block is indeed a bone
     if not self.is_bone(n_node):
         return None
     NifLog.debug(f"Storing pose matrix for {n_node.name}")
     # calculate the transform relative to root, ie. turn nif local into nif armature space
     self.pose_store[n_node] = n_node.get_transform(n_root)
     # move down the hierarchy
     for n_child in n_node.children:
         self.store_pose_matrices(n_child, n_root)
コード例 #15
0
def configure_autoupdater():
    NifLog.debug("Configuring auto-updater")
    addon_updater_ops.register(bl_info)
    addon_updater_ops.updater.select_link = select_zip_file
    addon_updater_ops.updater.use_releases = True
    addon_updater_ops.updater.remove_pre_update_patterns = [
        "*.py", "*.pyc", "*.xml", "*.exe", "*.rst", "VERSION", "*.xsd"
    ]
    addon_updater_ops.updater.user = "******"
    addon_updater_ops.updater.repo = "blender_niftools_addon"
    addon_updater_ops.updater.website = "https://github.com/niftools/blender_niftools_addon/"
    addon_updater_ops.updater.version_min_update = (0, 0, 4)
コード例 #16
0
 def import_nitextureprop_textures(self, n_texture_desc, nodes_wrapper):
     # NifLog.debug(f"Importing {n_texture_desc}")
     # go over all valid texture slots
     for slot_name, _ in self.slots.items():
         # get the field name used by nif xml for this texture
         slot_lower = slot_name.lower().replace(' ', '_')
         field_name = f"{slot_lower}_texture"
         # get the tex desc link
         has_tex = getattr(n_texture_desc, "has_" + field_name, None)
         if has_tex:
             NifLog.debug(f"Texdesc has active {slot_name}")
             n_tex = getattr(n_texture_desc, field_name)
             nodes_wrapper.create_and_link(slot_name, n_tex)
コード例 #17
0
 def populate_bone_tree(self, skelroot):
     """Add all of skelroot's bones to its dict_armatures list."""
     for bone in skelroot.tree():
         if bone is skelroot:
             continue
         if not isinstance(bone, NifFormat.NiNode):
             continue
         if isinstance(bone, NifFormat.NiLODNode):
             # LOD nodes are never bones
             continue
         if bone not in self.dict_armatures[skelroot]:
             self.dict_armatures[skelroot].append(bone)
             NifLog.debug(f"'{bone.name}' marked as extra bone of armature '{skelroot.name}'")
コード例 #18
0
    def import_bhkconvex_vertices_shape(self, bhk_shape):
        """Import a BhkConvexVertex block as a convex hull collision object"""
        NifLog.debug(f"Importing {bhk_shape.__class__.__name__}")

        # find vertices (and fix scale)
        scaled_verts = [(self.HAVOK_SCALE * n_vert.x, self.HAVOK_SCALE * n_vert.y, self.HAVOK_SCALE * n_vert.z)
                        for n_vert in bhk_shape.vertices]
        verts, faces = qhull3d(scaled_verts)

        b_obj = Object.mesh_from_data("convexpoly", verts, faces)
        radius = bhk_shape.radius * self.HAVOK_SCALE
        self.set_b_collider(b_obj, bounds_type="CONVEX_HULL", radius=radius, n_obj=bhk_shape)
        return [b_obj]
コード例 #19
0
 def check_for_skin(self, n_root):
     """Checks all tri geometry for skinning, sets self.skinned accordingly"""
     # set these here once per run
     self.n_armature = None
     self.skinned = False
     for n_block in self.get_skinned_geometries(n_root):
         self.skinned = True
         NifLog.debug(f"{n_block.name} has skinning.")
         # one is enough to require an armature, so stop
         return
     # force import of nodes as bones, even if no geometries are present
     if NifOp.props.process == "SKELETON_ONLY":
         self.skinned = True
     NifLog.debug(f"Found no skinned geometries.")
コード例 #20
0
 def export_nitextureprop_tex_descs(self, texprop):
     # go over all valid texture slots
     for slot_name, b_texture_node in self.slots.items():
         if b_texture_node:
             # get the field name used by nif xml for this texture
             field_name = f"{slot_name.lower().replace(' ', '_')}_texture"
             NifLog.debug(f"Activating {field_name} for {b_texture_node.name}")
             setattr(texprop, "has_"+field_name, True)
             # get the tex desc link
             texdesc = getattr(texprop, field_name)
             uv_index = self.get_uv_node(b_texture_node)
             # set uv index and source texture to the texdesc
             texdesc.uv_set = uv_index
             texdesc.source = TextureWriter.export_source_texture(b_texture_node)
コード例 #21
0
    def get_matching_block(self, block_type, **kwargs):
        """Try to find a block matching block_type. Keyword arguments are a dict of parameters and required attributes of the block"""
        # go over all blocks of block_type

        NifLog.debug(f"Looking for {block_type} block. Kwargs: {kwargs}")
        for block in block_store.block_to_obj:
            # if isinstance(block, block_type):
            if block_type in str(type(block)):
                # skip blocks that don't match additional conditions
                for param, attribute in kwargs.items():
                    # now skip this block if any of the conditions does not match
                    if attribute is not None:
                        ret_attr = getattr(block, param, None)
                        if ret_attr != attribute:
                            NifLog.debug(
                                f"break, {param} != {attribute}, returns {ret_attr}"
                            )
                            break
                else:
                    # we did not break out of the loop, so all checks went through, so we can use this block
                    NifLog.debug(
                        f"Found existing {block_type} block matching all criteria!"
                    )
                    return block
        # we are still here, so we must create a block of this type and set all attributes accordingly
        NifLog.debug(
            f"Created new {block_type} block because none matched the required criteria!"
        )
        block = block_store.create_block(block_type)
        for param, attribute in kwargs.items():
            if attribute is not None:
                setattr(block, param, attribute)
        return block
コード例 #22
0
    def export_uv_controller(self, b_material, n_geom):
        """Export the material UV controller data."""

        # get fcurves - a bit more elaborate here so we can zip with the NiUVData later
        # nb. these are actually specific to the texture slot in blender
        # here we don't care and just take the first fcurve that matches
        fcurves = []
        for dp, ind in (("offset", 0), ("offset", 1), ("scale", 0), ("scale",
                                                                     1)):
            for fcu in b_material.animation_data.action.fcurves:
                if dp in fcu.data_path and fcu.array_index == ind:
                    fcurves.append(fcu)
                    break
            else:
                fcurves.append(None)

        # continue if at least one fcurve exists
        if not any(fcurves):
            return

        # get the uv curves and translate them into nif data
        n_uv_data = NifFormat.NiUVData()
        for fcu, n_uv_group in zip(fcurves, n_uv_data.uv_groups):
            if fcu:
                NifLog.debug(f"Exporting {fcu} as NiUVData")
                n_uv_group.num_keys = len(fcu.keyframe_points)
                n_uv_group.interpolation = NifFormat.KeyType.LINEAR_KEY
                n_uv_group.keys.update_size()
                for b_point, n_key in zip(fcu.keyframe_points,
                                          n_uv_group.keys):
                    # add each point of the curve
                    b_frame, b_value = b_point.co
                    if "offset" in fcu.data_path:
                        # offsets are negated in blender
                        b_value = -b_value
                    n_key.arg = n_uv_group.interpolation
                    n_key.time = b_frame / self.fps
                    n_key.value = b_value

        # if uv data is present then add the controller so it is exported
        if fcurves[0].keyframe_points:
            n_uv_ctrl = NifFormat.NiUVController()
            self.set_flags_and_timing(n_uv_ctrl, fcurves)
            n_uv_ctrl.data = n_uv_data
            # attach block to geometry
            n_geom.add_controller(n_uv_ctrl)
コード例 #23
0
    def import_bhkpackednitristrips_shape(self, bhk_shape):
        """Import a BhkPackedNiTriStrips block as a Triangle-Mesh collision object"""
        NifLog.debug(f"Importing {bhk_shape.__class__.__name__}")

        # create mesh for each sub shape
        hk_objects = []
        vertex_offset = 0
        subshapes = bhk_shape.sub_shapes

        if not subshapes:
            # fallout 3 stores them in the data
            subshapes = bhk_shape.data.sub_shapes

        for subshape_num, subshape in enumerate(subshapes):
            verts = []
            faces = []
            for vert_index in range(vertex_offset,
                                    vertex_offset + subshape.num_vertices):
                n_vert = bhk_shape.data.vertices[vert_index]
                verts.append(
                    (n_vert.x * self.HAVOK_SCALE, n_vert.y * self.HAVOK_SCALE,
                     n_vert.z * self.HAVOK_SCALE))

            for bhk_triangle in bhk_shape.data.triangles:
                bhk_tri = bhk_triangle.triangle
                if (vertex_offset <= bhk_tri.v_1) and (
                        bhk_tri.v_1 < vertex_offset + subshape.num_vertices):
                    faces.append((bhk_tri.v_1 - vertex_offset,
                                  bhk_tri.v_2 - vertex_offset,
                                  bhk_tri.v_3 - vertex_offset))
                else:
                    continue

            b_obj = Object.mesh_from_data(f'poly{subshape_num:d}', verts,
                                          faces)
            radius = min(vert.co.length for vert in b_obj.data.vertices)
            self.set_b_collider(b_obj,
                                bounds_type="MESH",
                                radius=radius,
                                n_obj=subshape)

            vertex_offset += subshape.num_vertices
            hk_objects.append(b_obj)

        return hk_objects
コード例 #24
0
 def complete_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
     assert skelroot in self.dict_armatures  # debug
     assert bone in self.dict_armatures[skelroot]  # debug
     # get the node parent, this should be marked as an armature or as a bone
     boneparent = bone._parent
     if boneparent != skelroot:
         # parent is not the skeleton root
         if boneparent not in self.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)
コード例 #25
0
    def import_bhkbox_shape(self, bhk_shape):
        """Import a BhkBox block as a simple Box collision object"""
        NifLog.debug(f"Importing {bhk_shape.__class__.__name__}")

        # create box
        r = bhk_shape.radius * self.HAVOK_SCALE
        dims = bhk_shape.dimensions
        minx = -dims.x * self.HAVOK_SCALE
        maxx = +dims.x * self.HAVOK_SCALE
        miny = -dims.y * self.HAVOK_SCALE
        maxy = +dims.y * self.HAVOK_SCALE
        minz = -dims.z * self.HAVOK_SCALE
        maxz = +dims.z * self.HAVOK_SCALE

        # create blender object
        b_obj = Object.box_from_extents("box", minx, maxx, miny, maxy, minz, maxz)
        self.set_b_collider(b_obj, radius=r, n_obj=bhk_shape)
        return [b_obj]
コード例 #26
0
    def process_property_list(self, n_block, b_obj):
        b_mesh = b_obj.data

        # get all valid properties that are attached to n_block
        props = list(prop for prop in itertools.chain(
            n_block.properties, n_block.bs_properties) if prop is not None)

        # we need no material if we have no properties
        if not props:
            return

        # just to avoid duped materials, a first pass, make sure a named material is created or retrieved
        for prop in props:
            if prop.name:
                name = prop.name.decode()
                if name and name in bpy.data.materials:
                    b_mat = bpy.data.materials[name]
                    NifLog.debug(
                        f"Retrieved already imported material {b_mat.name} from name {name}"
                    )
                else:
                    b_mat = bpy.data.materials.new(name)
                    NifLog.debug(
                        f"Created material {name} to store properties in {b_mat.name}"
                    )
                break
        else:
            # bs shaders often have no name, so generate one from mesh name
            name = n_block.name.decode() + "_nt_mat"
            b_mat = bpy.data.materials.new(name)
            NifLog.debug(
                f"Created material {name} to store properties in {b_mat.name}")

        # do initial settings for the material here
        self.nodes_wrapper.b_mat = b_mat
        self.nodes_wrapper.clear_default_nodes()

        # link the material to the mesh
        b_mesh.materials.append(b_mat)

        # set the vars on every processor
        for processor in self.processors:
            processor.n_block = n_block
            processor.b_obj = b_obj
            processor.b_mesh = b_mesh
            processor.b_mat = b_mat
            processor.nodes_wrapper = self.nodes_wrapper

        # run all processors
        for prop in props:
            NifLog.debug(f"{type(prop)} property found")
            self.process_property(prop)

        self.nodes_wrapper.connect_to_output(b_mesh.vertex_colors)
コード例 #27
0
 def get_body_part_groups(self, b_obj, b_mesh):
     """Returns a set of vertices (no dupes) for each body part"""
     bodypartgroups = []
     for bodypartgroupname in NifFormat.BSDismemberBodyPartType(
     ).get_editor_keys():
         vertex_group = b_obj.vertex_groups.get(bodypartgroupname)
         vertices_list = set()
         if vertex_group:
             for b_vert in b_mesh.vertices:
                 for b_groupname in b_vert.groups:
                     if b_groupname.group == vertex_group.index:
                         vertices_list.add(b_vert.index)
             NifLog.debug(f"Found body part {bodypartgroupname}")
             bodypartgroups.append([
                 bodypartgroupname,
                 getattr(NifFormat.BSDismemberBodyPartType,
                         bodypartgroupname), vertices_list
             ])
     return bodypartgroups
コード例 #28
0
    def import_name(n_block):
        """Get name of n_block, ready for blender but not necessarily unique.

        :param n_block: A named nif block.
        :type n_block: :class:`~pyffi.formats.nif.NifFormat.NiObjectNET`
        """
        if n_block is None:
            return ""

        NifLog.debug(f"Importing name for {n_block.__class__.__name__} block from {n_block.name}")

        n_name = n_block.name.decode()

        # if name is empty, create something non-empty
        if not n_name:
            n_name = "noname"
        n_name = get_bone_name_for_blender(n_name)

        return n_name
コード例 #29
0
    def import_controller_sequence(self, kf_root, b_armature_obj, bind_data):
        NifLog.debug('Importing NiControllerSequence...')
        b_action = self.create_action(b_armature_obj, kf_root.name.decode())

        # import text keys
        self.import_text_keys(kf_root, b_action)

        # go over all controlled blocks (NiKeyframeController)
        for controlledblock in kf_root.controlled_blocks:
            # get bone name
            # todo [pyffi] fixed get_node_name() is up, make release and clean up here
            # ZT2 - old way is not supported by pyffi's get_node_name()
            n_name = controlledblock.target_name
            # fallout (node_name) & Loki (StringPalette)
            if not n_name:
                n_name = controlledblock.get_node_name()
            bone_name = block_registry.get_bone_name_for_blender(n_name)
            if bone_name not in b_armature_obj.data.bones:
                continue
            b_bone = b_armature_obj.data.bones[bone_name]
            # import bone priority
            b_bone.niftools.priority = controlledblock.priority
            # import animation
            if bone_name in bind_data:
                niBone_bind_scale, niBone_bind_rot_inv, niBone_bind_trans = bind_data[
                    bone_name]
                # ZT2
                kfc = controlledblock.controller
                # fallout, Loki
                if not kfc:
                    kfc = controlledblock.interpolator
                if kfc:
                    self.import_keyframe_controller(kfc, b_armature_obj,
                                                    bone_name,
                                                    niBone_bind_scale,
                                                    niBone_bind_rot_inv,
                                                    niBone_bind_trans)
        # fallout: set global extrapolation mode here (older versions have extrapolation per controller)
        if kf_root.cycle_type:
            extend = self.get_extend_from_cycle_type(kf_root.cycle_type)
            self.set_extrapolation(extend, b_action.fcurves)
コード例 #30
0
    def set_alpha(b_mat, n_alpha_prop):
        NifLog.debug("Alpha prop detected")
        # flags is a bitfield
        blend_enable = 1 & n_alpha_prop.flags
        test_enable = (1 << 9) & n_alpha_prop.flags
        if blend_enable and test_enable:
            b_mat.blend_method = "HASHED"
            b_mat.shadow_method = "HASHED"
        elif blend_enable:
            b_mat.blend_method = "BLEND"
            b_mat.shadow_method = "HASHED"
        elif test_enable:
            b_mat.blend_method = "CLIP"
            b_mat.shadow_method = "CLIP"
        else:
            b_mat.blend_method = "OPAQUE"
            b_mat.shadow_method = "OPAQUE"

        b_mat.alpha_threshold = n_alpha_prop.threshold / 255  # transparency threshold
        b_mat.niftools_alpha.alphaflag = n_alpha_prop.flags

        return b_mat