示例#1
0
    def __init__(self, context, report, version, game_version, apply_modifiers,
                 triangulate_faces, edge_split, use_edge_angle, use_edge_sharp,
                 split_angle, clean_normalize_weights, hidden_geo,
                 custom_scale):

        global_functions.unhide_all_collections()
        view_layer = bpy.context.view_layer
        object_list = list(bpy.context.scene.objects)
        self.materials = []
        self.objects = []
        self.instances = []
        material_list = []
        armature = []
        geometry_list = []
        original_geometry_list = []
        unique_instance_geometry_list = []
        unique_instance_geometry_list_2 = []
        object_properties = []
        object_count = 0
        for obj in object_list:
            object_properties.append([obj.hide_get(), obj.hide_viewport])
            if hidden_geo:
                global_functions.unhide_object(obj)

            if obj.type == 'MESH':
                if global_functions.set_ignore(obj) == False or hidden_geo:
                    if clean_normalize_weights:
                        if len(obj.vertex_groups) > 0:
                            view_layer.objects.active = obj
                            bpy.ops.object.mode_set(mode='EDIT')
                            bpy.ops.mesh.select_all(action='SELECT')
                            bpy.ops.object.vertex_group_clean(
                                group_select_mode='ALL', limit=0.0)
                            bpy.ops.object.vertex_group_normalize_all()
                            bpy.ops.object.mode_set(mode='OBJECT')

                modifier_list = []
                if apply_modifiers:
                    for modifier in obj.modifiers:
                        modifier.show_render = True
                        modifier.show_viewport = True
                        modifier.show_in_editmode = True
                        modifier_list.append(modifier.type)

                if triangulate_faces:
                    if not 'TRIANGULATE' in modifier_list:
                        obj.modifiers.new("Triangulate", type='TRIANGULATE')

                if edge_split:
                    if not 'EDGE_SPLIT' in modifier_list:
                        edge_split = obj.modifiers.new("EdgeSplit",
                                                       type='EDGE_SPLIT')
                        edge_split.use_edge_angle = use_edge_angle
                        edge_split.split_angle = split_angle
                        edge_split.use_edge_sharp = use_edge_sharp
                    else:
                        modifier_idx = modifier_list.index('EDGE_SPLIT')
                        obj.modifiers[
                            modifier_idx].use_edge_angle = use_edge_angle
                        obj.modifiers[modifier_idx].split_angle = split_angle
                        obj.modifiers[
                            modifier_idx].use_edge_sharp = use_edge_sharp

        depsgraph = context.evaluated_depsgraph_get()

        for obj in object_list:
            if obj.type == 'ARMATURE':
                if global_functions.set_ignore(obj) == False or hidden_geo:
                    for bone in obj.data.bones:
                        if not bone.name in unique_instance_geometry_list:
                            unique_instance_geometry_list.append(bone.name)

                        geometry_list.append(
                            (bone, 'BONE', bone.name, bone.name))
                        original_geometry_list.append(bone)
                        object_count += 1

            elif obj.type == 'MESH' and len(obj.data.polygons) > 0:
                if global_functions.set_ignore(obj) == False or hidden_geo:
                    if not obj.data.name in unique_instance_geometry_list:
                        unique_instance_geometry_list.append(obj.data.name)
                        object_count += 1

                    if obj.data.ass_jms.Object_Type == 'SPHERE':
                        me = obj.to_mesh(preserve_all_data_layers=True)
                        geometry_list.append(
                            (me, 'SPHERE', obj.name, obj.data.name))
                        original_geometry_list.append(obj)

                    elif obj.data.ass_jms.Object_Type == 'BOX':
                        me = obj.to_mesh(preserve_all_data_layers=True)
                        geometry_list.append(
                            (me, 'BOX', obj.name, obj.data.name))
                        original_geometry_list.append(obj)

                    elif obj.data.ass_jms.Object_Type == 'CAPSULES':
                        me = obj.to_mesh(preserve_all_data_layers=True)
                        geometry_list.append(
                            (me, 'PILL', obj.name, obj.data.name))
                        original_geometry_list.append(obj)

                    elif obj.data.ass_jms.Object_Type == 'CONVEX SHAPES':
                        if apply_modifiers:
                            obj_for_convert = obj.evaluated_get(depsgraph)
                            me = obj_for_convert.to_mesh(
                                preserve_all_data_layers=True,
                                depsgraph=depsgraph)
                            geometry_list.append(
                                (me, 'MESH', obj.name, obj.data.name))
                            original_geometry_list.append(obj)

                        else:
                            me = obj.to_mesh(preserve_all_data_layers=True)
                            geometry_list.append(
                                (me, 'MESH', obj.name, obj.data.name))
                            original_geometry_list.append(obj)

            else:
                if global_functions.set_ignore(obj) == False or hidden_geo:
                    geometry_list.append(
                        (None, 'EMPTY', obj.name, obj.data.name))
                    original_geometry_list.append(obj)

        self.instances.append(
            ASSScene.Instance(name='Scene Root',
                              local_transform=ASSScene.Transform(),
                              pivot_transform=ASSScene.Transform()))
        for idx, geometry in enumerate(geometry_list):
            verts = []
            triangles = []
            node_index_list = []
            original_geo = original_geometry_list[idx]
            mesh = geometry[0]
            geo_class = geometry[1]
            geo_name = geometry[2]
            mesh_name = geometry[3]
            object_index = -1
            if not geo_class == 'EMPTY':
                object_index = unique_instance_geometry_list.index(mesh_name)
            material_index = -1
            radius = 2
            extents = [1.0, 1.0, 1.0]
            height = 1
            parent_id = 0
            inheritance_flag = 0
            xref_name = ""
            is_bone = False
            if geo_class == 'BONE':
                armature_name = original_geo.id_data.name
                armature = bpy.data.objects[armature_name]
                parent = original_geo.parent
                is_bone = True
            else:
                if armature:
                    parent = original_geo.parent_bone
                else:
                    parent = original_geo.parent

            if not parent == None:
                if not geo_class == 'BONE':
                    if not original_geo.parent.type == 'ARMATURE':
                        parent_id = original_geometry_list.index(parent) + 1
                else:
                    parent_id = original_geometry_list.index(parent) + 1

            geo_matrix = global_functions.get_matrix(
                original_geo, original_geo, True, armature,
                original_geometry_list, is_bone, version, 'ASS', 0)
            geo_dimensions = global_functions.get_dimensions(
                geo_matrix, original_geo, None, None, custom_scale, version,
                None, False, is_bone, armature, 'ASS')
            rotation = (geo_dimensions.quat_i_a, geo_dimensions.quat_j_a,
                        geo_dimensions.quat_k_a, geo_dimensions.quat_w_a)
            translation = (geo_dimensions.pos_x_a, geo_dimensions.pos_y_a,
                           geo_dimensions.pos_z_a)
            if geo_class == 'BONE':
                scale = armature.pose.bones[original_geo.name].scale
            else:
                scale = original_geo.scale
            local_transform = ASSScene.Transform(rotation, translation, scale)
            self.instances.append(
                ASSScene.Instance(geo_name,
                                  object_index,
                                  idx,
                                  parent_id,
                                  inheritance_flag,
                                  local_transform,
                                  pivot_transform=ASSScene.Transform()))
            if not mesh_name in unique_instance_geometry_list_2 and not object_index == -1:
                unique_instance_geometry_list_2.append(mesh_name)
                if geo_class == 'BONE':
                    armature_name = mesh.id_data.name
                    armature = bpy.data.objects[armature_name]
                    xref_path = bpy.path.abspath(
                        armature.data.ass_jms.XREF_path)
                    if xref_path != "":
                        xref_name = armature.name

                elif geo_class == 'SPHERE':
                    xref_path = bpy.path.abspath(
                        original_geo.data.ass_jms.XREF_path)
                    if xref_path != "":
                        xref_name = original_geo.name

                    radius = geo_dimensions.radius_a
                    face = original_geo.data.polygons[0]
                    material = global_functions.get_material(
                        game_version,
                        original_geo,
                        face,
                        mesh,
                        material_list,
                        'ASS',
                        None,
                        None,
                    )
                    if not material == -1:
                        material_list = global_functions.gather_materials(
                            game_version, material, material_list, 'ASS', None,
                            None, None)
                        material_index = material_list.index(material)

                elif geo_class == 'BOX':
                    xref_path = bpy.path.abspath(
                        original_geo.data.ass_jms.XREF_path)
                    if xref_path != "":
                        xref_name = original_geo.name

                    face = original_geo.data.polygons[0]
                    extents = [
                        geo_dimensions.dimension_x_a,
                        geo_dimensions.dimension_y_a,
                        geo_dimensions.dimension_z_a
                    ]
                    material = global_functions.get_material(
                        game_version,
                        original_geo,
                        face,
                        mesh,
                        material_list,
                        'ASS',
                        None,
                        None,
                    )
                    if not material == -1:
                        material_list = global_functions.gather_materials(
                            game_version, material, material_list, 'ASS', None,
                            None, None)
                        material_index = material_list.index(material)

                elif geo_class == 'PILL':
                    xref_path = bpy.path.abspath(
                        original_geo.data.ass_jms.XREF_path)
                    if xref_path != "":
                        xref_name = original_geo.name

                    face = original_geo.data.polygons[0]
                    height = (geo_dimensions.pill_z_a)
                    radius = (geo_dimensions.radius_a)
                    material = global_functions.get_material(
                        game_version,
                        original_geo,
                        face,
                        mesh,
                        material_list,
                        'ASS',
                        None,
                        None,
                    )
                    if not material == -1:
                        material_list = global_functions.gather_materials(
                            game_version, material, material_list, 'ASS', None,
                            None, None)
                        material_index = material_list.index(material)

                elif geo_class == 'MESH':
                    xref_path = bpy.path.abspath(
                        original_geo.data.ass_jms.XREF_path)
                    if xref_path != "":
                        xref_name = original_geo.name

                    vertex_groups = original_geo.vertex_groups.keys()
                    for face in mesh.polygons:
                        v0 = len(verts)
                        v1 = len(verts) + 1
                        v2 = len(verts) + 2
                        material = global_functions.get_material(
                            game_version,
                            original_geo,
                            face,
                            mesh,
                            material_list,
                            'ASS',
                            None,
                            None,
                        )
                        material_index = -1
                        if not material == -1:
                            material_list = global_functions.gather_materials(
                                game_version, material, material_list, 'ASS',
                                None, None, None)
                            material_index = material_list.index(material)

                        triangles.append(
                            ASSScene.Triangle(material_index, v0, v1, v2))
                        for loop_index in face.loop_indices:
                            vert = mesh.vertices[
                                mesh.loops[loop_index].vertex_index]

                            original_geo_matrix = global_functions.get_matrix(
                                original_geo, original_geo, False, armature,
                                original_geometry_list, False, version, 'ASS',
                                0)

                            translation = vert.co
                            world_translation = original_geo_matrix @ vert.co

                            mesh_dimensions = global_functions.get_dimensions(
                                None, None, None, None, custom_scale, version,
                                translation, True, False, armature, 'ASS')
                            scaled_translation = (mesh_dimensions.pos_x_a,
                                                  mesh_dimensions.pos_y_a,
                                                  mesh_dimensions.pos_z_a)

                            normal = (vert.normal).normalized()
                            uv_set = []
                            for uv_index in range(len(mesh.uv_layers)):
                                mesh.uv_layers.active = mesh.uv_layers[
                                    uv_index]
                                uv = mesh.uv_layers.active.data[
                                    mesh.loops[loop_index].index].uv
                                uv_set.append(uv)

                            uv = uv_set
                            node_influence_count = 0
                            node_set = []
                            if len(vert.groups) != 0:
                                object_vert_group_list = []
                                vertex_vert_group_list = []
                                for group_index in range(len(vert.groups)):
                                    vert_group = vert.groups[group_index].group
                                    object_vertex_group = vertex_groups[
                                        vert_group]
                                    if armature:
                                        if object_vertex_group in armature.data.bones:
                                            vertex_vert_group_list.append(
                                                group_index)
                                            if armature.data.bones[
                                                    object_vertex_group] in original_geometry_list:
                                                object_vert_group_list.append(
                                                    vert_group)

                                    else:
                                        if object_vertex_group in bpy.data.objects:
                                            vertex_vert_group_list.append(
                                                group_index)
                                            if bpy.data.objects[
                                                    object_vertex_group] in original_geometry_list:
                                                object_vert_group_list.append(
                                                    vert_group)

                                value = len(object_vert_group_list)
                                if value > 4:
                                    value = 4

                                node_influence_count = int(value)
                                if len(object_vert_group_list) != 0:
                                    for idx, group_index in enumerate(
                                            object_vert_group_list):
                                        vert_index = int(
                                            vertex_vert_group_list[idx])
                                        vert_group = vert.groups[
                                            vert_index].group
                                        object_vertex_group = vertex_groups[
                                            vert_group]
                                        if armature:
                                            node_obj = armature.data.bones[
                                                object_vertex_group]

                                        else:
                                            node_obj = bpy.data.objects[
                                                object_vertex_group]

                                        node_index = int(
                                            original_geometry_list.index(
                                                node_obj))
                                        if not node_index in node_index_list:
                                            node_index_list.append(node_index)
                                        node_weight = float(
                                            vert.groups[vert_index].weight)
                                        node_set.append(
                                            [node_index, node_weight])

                            verts.append(
                                ASSScene.Vertex(
                                    node_influence_count,
                                    node_set,
                                    scaled_translation,
                                    normal,
                                    uv_set,
                                ))

                original_geo.to_mesh_clear()

                self.objects.append(
                    ASSScene.Object(
                        geo_class,
                        xref_path,
                        xref_name,
                        material_index,
                        radius,
                        extents,
                        height,
                        verts,
                        triangles,
                        node_index_list,
                    ))

        for material in material_list:
            self.materials.append(
                ASSScene.Material(
                    material.name,
                    material.ass_jms.material_effect,
                ))

        for idx, obj in enumerate(object_list):
            property_value = object_properties[idx]
            obj.hide_set(property_value[0])
            obj.hide_viewport = property_value[1]
    def __init__(self, context, report, version, game_version, extension,
                 custom_scale, biped_controller):
        global_functions.unhide_all_collections()
        scene = bpy.context.scene
        view_layer = bpy.context.view_layer
        object_properties = []
        object_list = list(scene.objects)
        object_count = len(object_list)
        node_list = []
        armature = []
        armature_count = 0
        first_frame = scene.frame_start
        last_frame = scene.frame_end + 1
        total_frame_count = scene.frame_end - first_frame + 1
        for obj in object_list:
            object_properties.append([obj.hide_get(), obj.hide_viewport])
            if obj.type == 'ARMATURE':
                global_functions.unhide_object(obj)
                armature_count += 1
                armature = obj
                view_layer.objects.active = obj
                obj.select_set(True)
                node_list = list(obj.data.bones)

        self.transform_count = total_frame_count
        #actor related items are hardcoded due to them being an unused feature in tool. Do not attempt to do anything to write this out as it is a waste of time and will get you nothing.
        self.actor_names = ['unnamedActor']
        self.node_count = len(node_list)
        self.transforms = []
        self.biped_controller_transforms = []
        self.nodes = []
        root_node_count = global_functions.count_root_nodes(node_list)
        h2_extension_list = ['JRMX', 'JMH']
        sorted_list = global_functions.sort_list(node_list, armature,
                                                 game_version, version, False)
        joined_list = sorted_list[0]
        reversed_joined_list = sorted_list[1]

        if self.node_count == 0:  #JMSv2 files can have JMS files without a node for physics.
            raise global_functions.SceneParseError(
                "No nodes in scene. Add an armature or object mesh named frame."
            )
            return {'CANCELLED'}

        elif armature_count >= 2:
            raise global_functions.SceneParseError(
                "More than one armature object. Please delete all but one.")
            return {'CANCELLED'}

        elif root_node_count >= 2:
            raise global_functions.SceneParseError(
                "More than one root node. Please remove or rename objects until you only have one root frame object."
            )
            return {'CANCELLED'}

        elif len(object_list) == 0:
            raise global_functions.SceneParseError("No objects in scene.")
            return {'CANCELLED'}

        elif extension in h2_extension_list and game_version == 'haloce':
            raise global_functions.SceneParseError(
                "This extension is not used in Halo CE.")
            return {'CANCELLED'}

        elif version >= 16393 and game_version == 'haloce':
            raise global_functions.SceneParseError(
                "This version is not supported for Halo CE. Choose from 16390-16392 if you wish to export for Halo CE."
            )
            return {'CANCELLED'}

        elif game_version == 'haloce' and self.node_count > 64:
            raise global_functions.SceneParseError(
                "This model has more nodes than Halo CE supports. Please limit your node count to 64 nodes"
            )
            return {'CANCELLED'}

        elif game_version == 'halo2' and self.node_count > 255:
            raise global_functions.SceneParseError(
                "This model has more nodes than Halo 2 supports. Please limit your node count to 255 nodes"
            )
            return {'CANCELLED'}

        self.node_checksum = 0
        for node in joined_list:
            name = node.name
            find_child_node = global_functions.get_child(
                node, reversed_joined_list)
            find_sibling_node = global_functions.get_sibling(
                armature, node, reversed_joined_list)
            first_child_node = -1
            first_sibling_node = -1
            parent_node = -1
            if not find_child_node == None:
                first_child_node = joined_list.index(find_child_node)

            if not find_sibling_node == None:
                first_sibling_node = joined_list.index(find_sibling_node)

            if not node.parent == None:
                parent_node = joined_list.index(node.parent)

            self.nodes.append(
                JMAScene.Node(name, parent_node, first_child_node,
                              first_sibling_node))

        self.node_checksum = global_functions.node_hierarchy_checksum(
            self.nodes, self.nodes[0], self.node_checksum)

        for frame in range(first_frame, last_frame):
            transforms_for_frame = []
            for node in joined_list:
                bpy.context.scene.frame_set(frame)
                is_bone = False
                if armature:
                    is_bone = True

                bone_matrix = global_functions.get_matrix(
                    node, node, True, armature, joined_list, True, version,
                    'JMA', 0)
                mesh_dimensions = global_functions.get_dimensions(
                    bone_matrix, node, None, None, custom_scale, version, None,
                    False, is_bone, armature, 'JMA')
                vector = (mesh_dimensions.pos_x_a, mesh_dimensions.pos_y_a,
                          mesh_dimensions.pos_z_a)
                rotation = (mesh_dimensions.quat_i_a, mesh_dimensions.quat_j_a,
                            mesh_dimensions.quat_k_a, mesh_dimensions.quat_w_a)
                scale = (mesh_dimensions.scale_x_a)

                transforms_for_frame.append(
                    JMAScene.Transform(vector, rotation, scale))

            self.transforms.append(transforms_for_frame)

        #H2 specific biped controller data bool value.
        if version > 16394 and biped_controller:
            for frame in range(self.transform_count):
                bpy.context.scene.frame_set(frame)
                armature_matrix = global_functions.get_matrix(
                    armature, armature, True, None, joined_list, False,
                    version, 'JMA', 0)
                mesh_dimensions = global_functions.get_dimensions(
                    armature_matrix, armature, None, None, custom_scale,
                    version, None, False, False, armature, 'JMA')

                vector = (mesh_dimensions.pos_x_a, mesh_dimensions.pos_y_a,
                          mesh_dimensions.pos_z_a)
                rotation = (mesh_dimensions.quat_i_a, mesh_dimensions.quat_j_a,
                            mesh_dimensions.quat_k_a, mesh_dimensions.quat_w_a)
                scale = (mesh_dimensions.scale_x_a)

                self.biped_controller_transforms.append(
                    JMAScene.Transform(vector, rotation, scale))

        scene.frame_set(1)
        for idx, obj in enumerate(object_list):
            property_value = object_properties[idx]
            obj.hide_set(property_value[0])
            obj.hide_viewport = property_value[1]