Пример #1
0
    def __init__(self, filepath):
        super().__init__(filepath)
        self.version = int(self.next())
        version_list = [1, 2, 3, 4, 5, 6, 7]
        if not self.version in version_list:
            raise global_functions.AssetParseError("Importer does not support this ASS version")

        self.skip(4) # skip header
        self.materials = []
        self.objects = []
        self.instances = []
        material_count = int(self.next())
        for material in range(material_count):
            name = self.next().strip('\"')
            material_effect = self.next().strip('\"')
            self.materials.append(ASSAsset.Material(name, material_effect))

        object_count = int(self.next())
        for object in range(object_count):
            vertices = []
            node_index_list = []
            triangles = []
            geo_class = self.next().strip('\"')
            xref_path = self.next().strip('\"')
            xref_name = self.next().strip('\"')
            material_index = -1
            radius = 2
            extents = [1.0, 1.0, 1.0]
            height = 1
            if geo_class == 'SPHERE':
                material_index = int(self.next())
                radius = float(self.next())

            elif geo_class == 'BOX':
                material_index = int(self.next())
                extents = self.next_vector()

            elif geo_class == 'PILL':
                material_index = int(self.next())
                height = float(self.next())
                radius = float(self.next())

            elif geo_class == 'MESH':
                vert_count = int(self.next())
                for vert in range(vert_count):
                    node_set = []
                    uv_set = []
                    translation = self.next_vector()
                    normal = self.next_vector()
                    node_influence_count = int(self.next())
                    for node in range(node_influence_count):
                        node_index = int(self.next())
                        if not node_index in node_index_list:
                            node_index_list.append(node_index)

                        node_weight = float(self.next())
                        node_set.append([node_index, node_weight])

                    uv_count = int(self.next())
                    for uv in range(uv_count):
                        tex_u = float(self.next())
                        tex_v = float(self.next())
                        uv_set.append([tex_u, tex_v])

                    vertices.append(ASSAsset.Vertex(node_influence_count, node_set, translation, normal, uv_set))

                triangle_count = int(self.next())
                for triangle in range(triangle_count):
                    material_index = int(self.next())
                    v0 = int(self.next())
                    v1 = int(self.next())
                    v2 = int(self.next())

                    triangles.append(ASSAsset.Triangle(material_index, v0, v1, v2))

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

        name_list = []
        instance_count = int(self.next())
        for instance in range(instance_count):
            object_index = int(self.next())
            object_element = self.objects[object_index]
            bone_influence_count = 0
            if not object_index == -1:
                bone_influence_count = len(object_element.node_index_list)

            name = self.next().strip('\"')
            if name in name_list:
                true_name = '%s_%s' % (name, instance)
            else:
                true_name = name
            name_list.append(name)
            unique_id = int(self.next())
            parent_id = int(self.next())
            inheritance_flag = int(self.next())
            local_transform = self.next_transform(self.version)
            pivot_transform = self.next_transform(self.version)
            if bone_influence_count > 0:
                self.skip(bone_influence_count)

            if not object_index == -1 or not unique_id == -1 or not parent_id == -1:
                self.instances.append(ASSAsset.Instance(true_name, object_index, unique_id, parent_id, inheritance_flag, local_transform, pivot_transform))

        if self.left() != 0: # is something wrong with the parser?
            raise RuntimeError("%s elements left after parse end" % self.left())
Пример #2
0
    def __init__(self, filepath, game_version):
        super().__init__(filepath)
        extension = global_functions.get_true_extension(filepath, None, True)
        self.node_checksum = -1
        self.version = int(self.next())
        version_list = (16390, 16391, 16392, 16393, 16394, 16395)
        if not self.version in version_list:
            raise global_functions.AssetParseError(
                "Importer does not support this " + extension + " version")
        self.game_version = game_version
        if game_version == 'auto':
            self.game_version = global_functions.get_game_version(
                self.version, 'JMA')
        if self.version >= 16394:
            self.node_checksum = int(self.next())
        transform_count = int(self.next())
        self.frame_rate = float(self.next())
        actor_count = int(self.next())
        self.actor_name = self.next()
        self.frame_count = transform_count

        if actor_count != 1:
            raise global_functions.AssetParseError(extension +
                                                   " actor count must be 1!")

        node_count = int(self.next())
        if self.version < 16394:
            self.node_checksum = int(self.next())
        self.nodes = []
        self.transforms = []
        if self.version >= 16394:
            for _ in range(node_count):
                name = self.next()
                parent = int(self.next())
                self.nodes.append(JMAAsset.Node(name, parent=parent))
        elif self.version >= 16392:
            for _ in range(node_count):
                name = self.next()
                child = int(self.next())
                sibling = int(self.next())
                self.nodes.append(
                    JMAAsset.Node(name, child=child, sibling=sibling))
        elif self.version == 16391:
            for _ in range(node_count):
                self.nodes.append(JMAAsset.Node(self.next()))
        else:
            self.node_count = node_count

        for _ in range(transform_count):
            transforms_for_frame = []

            for node_idx in range(node_count):
                transforms_for_frame.append(self.next_transform())

            self.transforms.append(transforms_for_frame)

        self.biped_controller_frame_type = JMAAsset.BipedControllerFrameType.DISABLE
        if self.version == 16395:
            self.biped_controller_transforms = []
            biped_controller_enabled = int(self.next())
            if biped_controller_enabled > 0:
                # different animation file types use the data differently
                if extension == 'jma':
                    self.biped_controller_frame_type = JMAAsset.BipedControllerFrameType.JMA
                elif extension == 'jmt':
                    self.biped_controller_frame_type = JMAAsset.BipedControllerFrameType.JMT
                elif extension == 'jmrx':
                    self.biped_controller_frame_type = JMAAsset.BipedControllerFrameType.JMRX

                for _ in range(transform_count):
                    self.biped_controller_transforms.append(
                        self.next_transform())

        if self.left() != 0:  # is something wrong with the parser?
            raise RuntimeError("%s elements left after parse end" %
                               self.left())

        # update node graph
        if self.version >= 16394:
            # loop over nodes and
            for node_idx in range(node_count):
                node = self.nodes[node_idx]
                if node.parent == -1:
                    continue  # this is a root node, nothing to update
                if node.parent >= len(self.nodes) or node.parent == node_idx:
                    raise global_functions.AssetParseError(
                        "Malformed node graph (bad parent index)")
                parent_node = self.nodes[node.parent]
                if parent_node.child:
                    node.sibling = parent_node.child
                else:
                    node.sibling = -1
                if node.sibling >= len(self.nodes):
                    raise global_functions.AssetParseError(
                        "Malformed node graph (sibling index out of range)")
                parent_node.child = node_idx
        elif self.version >= 16392:
            for node_idx in range(node_count):
                node = self.nodes[node_idx]
                if node.child == -1:
                    continue  # no child nodes, nothing to update
                if node.child >= len(self.nodes) or node.child == node_idx:
                    raise global_functions.AssetParseError(
                        "Malformed node graph (bad child index)")
                child_node = self.nodes[node.child]
                while child_node != None:
                    child_node.parent = node_idx
                    if child_node.visited:
                        raise global_functions.AssetParseError(
                            "Malformed node graph (circular reference)")
                    child_node.visited = True
                    if child_node.sibling >= len(self.nodes):
                        raise global_functions.AssetParseError(
                            "Malformed node graph (sibling index out of range)"
                        )
                    if child_node.sibling != -1:
                        child_node = self.nodes[child_node.sibling]
                    else:
                        child_node = None