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())
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