def import_skin(ni_block, b_obj):
        """Import a NiSkinInstance and its contents as vertex groups"""
        skininst = ni_block.skin_instance
        if skininst:
            skindata = skininst.data
            bones = skininst.bones
            # the usual case
            if skindata.has_vertex_weights:
                bone_weights = skindata.bone_list
                for idx, n_bone in enumerate(bones):
                    # skip empty bones (see pyffi issue #3114079)
                    if not n_bone:
                        continue

                    vertex_weights = bone_weights[idx].vertex_weights
                    group_name = block_store.import_name(n_bone)
                    if group_name not in b_obj.vertex_groups:
                        v_group = b_obj.vertex_groups.new(name=group_name)

                    for skinWeight in vertex_weights:
                        vert = skinWeight.index
                        weight = skinWeight.weight
                        v_group.add([vert], weight, 'REPLACE')

            # WLP2 - hides the weights in the partition
            else:
                skin_partition = skininst.skin_partition
                for block in skin_partition.skin_partition_blocks:
                    # create all vgroups for this block's bones
                    block_bone_names = [block_store.import_name(bones[i]) for i in block.bones]
                    for group_name in block_bone_names:
                        b_obj.vertex_groups.new(name=group_name)

                    # go over each vert in this block
                    for vert, vertex_weights, bone_indices in zip(block.vertex_map, block.vertex_weights, block.bone_indices):

                        # assign this vert's 4 weights to its 4 vgroups (at max)
                        for w, b_i in zip(vertex_weights, bone_indices):
                            if w > 0:
                                group_name = block_bone_names[b_i]
                                v_group = b_obj.vertex_groups[group_name]
                                v_group.add([vert], w, 'REPLACE')

        # import body parts as face maps
        # get faces (triangles) as map of tuples to index
        tri_map = {frozenset(polygon.vertices): polygon.index for polygon in b_obj.data.polygons}
        if isinstance(skininst, NifFormat.BSDismemberSkinInstance):
            skinpart = ni_block.get_skin_partition()
            for bodypart, skinpartblock in zip(skininst.partitions, skinpart.skin_partition_blocks):
                bodypart_wrap = NifFormat.BSDismemberBodyPartType()
                bodypart_wrap.set_value(bodypart.body_part)
                group_name = bodypart_wrap.get_detail_display()

                # create face map if it did not exist yet
                if group_name not in b_obj.face_maps:
                    f_group = b_obj.face_maps.new(name=group_name)

                # add the triangles to the face map
                f_group.add([tri_map[frozenset(vertices)] for vertices in skinpartblock.get_mapped_triangles()])
Esempio n. 2
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
Esempio n. 3
0
 def get_polygon_parts(self, b_obj, b_mesh):
     """Returns the body part indices of the mesh polygons. -1 is either not assigned to a face map or not a valid
     body part"""
     index_group_map = {-1: -1}
     for bodypartgroupname in NifFormat.BSDismemberBodyPartType(
     ).get_editor_keys():
         face_map = b_obj.face_maps.get(bodypartgroupname)
         if face_map:
             index_group_map[face_map.index] = getattr(
                 NifFormat.BSDismemberBodyPartType, bodypartgroupname)
     if len(index_group_map) <= 1:
         # there were no valid face maps
         return []
     bm = bmesh.new()
     bm.from_mesh(b_mesh)
     bm.faces.ensure_lookup_table()
     fm = bm.faces.layers.face_map.verify()
     polygon_parts = [
         index_group_map.get(face[fm], -1) for face in bm.faces
     ]
     bm.free()
     return polygon_parts
Esempio n. 4
0
    def import_skin(ni_block, b_obj):
        """Import a NiSkinInstance and its contents as vertex groups"""
        skininst = ni_block.skin_instance
        if skininst:
            skindata = skininst.data
            bones = skininst.bones
            # the usual case
            if skindata.has_vertex_weights:
                bone_weights = skindata.bone_list
                for idx, n_bone in enumerate(bones):
                    # skip empty bones (see pyffi issue #3114079)
                    if not n_bone:
                        continue

                    vertex_weights = bone_weights[idx].vertex_weights
                    group_name = block_store.import_name(n_bone)
                    if group_name not in b_obj.vertex_groups:
                        v_group = b_obj.vertex_groups.new(name=group_name)

                    for skinWeight in vertex_weights:
                        vert = skinWeight.index
                        weight = skinWeight.weight
                        v_group.add([vert], weight, 'REPLACE')

            # WLP2 - hides the weights in the partition
            else:
                skin_partition = skininst.skin_partition
                for block in skin_partition.skin_partition_blocks:
                    # create all vgroups for this block's bones
                    block_bone_names = [
                        block_store.import_name(bones[i]) for i in block.bones
                    ]
                    for group_name in block_bone_names:
                        b_obj.vertex_groups.new(name=group_name)

                    # go over each vert in this block
                    for vert, vertex_weights, bone_indices in zip(
                            block.vertex_map, block.vertex_weights,
                            block.bone_indices):

                        # assign this vert's 4 weights to its 4 vgroups (at max)
                        for w, b_i in zip(vertex_weights, bone_indices):
                            if w > 0:
                                group_name = block_bone_names[b_i]
                                v_group = b_obj.vertex_groups[group_name]
                                v_group.add([vert], w, 'REPLACE')

        # import body parts as vertex groups
        if isinstance(skininst, NifFormat.BSDismemberSkinInstance):
            skinpart_list = []
            bodypart_flag = []
            skinpart = ni_block.get_skin_partition()
            for bodypart, skinpartblock in zip(skininst.partitions,
                                               skinpart.skin_partition_blocks):
                bodypart_wrap = NifFormat.BSDismemberBodyPartType()
                bodypart_wrap.set_value(bodypart.body_part)
                group_name = bodypart_wrap.get_detail_display()

                # create vertex group if it did not exist yet
                if group_name not in b_obj.vertex_groups:
                    v_group = b_obj.vertex_groups.new(name=group_name)
                    skinpart_index = len(skinpart_list)
                    skinpart_list.append((skinpart_index, group_name))
                    bodypart_flag.append(bodypart.part_flag)

                # find vertex indices of this group
                groupverts = [v_index for v_index in skinpartblock.vertex_map]

                # create the group
                v_group.add(groupverts, 1, 'ADD')
            b_obj.niftools_part_flags_panel.pf_partcount = len(skinpart_list)
            for i, pl_name in skinpart_list:
                b_obj_partflag = b_obj.niftools_part_flags.add()
                # b_obj.niftools_part_flags.pf_partint = (i)
                b_obj_partflag.name = pl_name
                b_obj_partflag.pf_editorflag = bodypart_flag[
                    i].pf_editor_visible
                b_obj_partflag.pf_startflag = bodypart_flag[
                    i].pf_start_net_boneset