diff --git a/README.md b/README.md index 4eb52c2..b594cb1 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,6 @@ This is a Blender addon allowing you to export static meshes to the now-defunct ASE (ASCII Scene Export) format still in use in legacy programs like Unreal Tournament 2004. Check out [this video](https://www.youtube.com/watch?v=gpmBxCGHQjU) on how to install and use the addon. + +Resources: +* https://wiki.beyondunreal.com/Legacy:ASE_File_Format \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py index 3ca7257..b45bb32 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -2,7 +2,7 @@ 'name': 'ASCII Scene Export', 'description': 'Export ASE (ASCII Scene Export) files', 'author': 'Colin Basnett (Darklight Games)', - 'version': (1, 0, 3), + 'version': (1, 1, 0), 'blender': (2, 90, 0), 'location': 'File > Import-Export', 'warning': 'This add-on is under development.', diff --git a/src/ase.py b/src/ase.py index 96329f3..82c9936 100644 --- a/src/ase.py +++ b/src/ase.py @@ -26,11 +26,16 @@ def is_collision_name(name): return name.startswith('MCDCX_') +class ASEUVLayer(object): + def __init__(self): + self.texture_vertices = [] + + class ASEGeometryObject(object): def __init__(self): self.name = '' self.vertices = [] - self.texture_vertices = [] + self.uv_layers = [] self.faces = [] self.texture_vertex_faces = [] self.face_normals = [] diff --git a/src/builder.py b/src/builder.py index c0814cc..40ced71 100644 --- a/src/builder.py +++ b/src/builder.py @@ -89,13 +89,15 @@ def build(self, context, options: ASEBuilderOptions): face_normal.vertex_normals.append(vertex_normal) geometry_object.face_normals.append(face_normal) - uv_layer = mesh_data.uv_layers.active.data - - # Texture Coordinates if not geometry_object.is_collision: - for loop_index, loop in enumerate(mesh_data.loops): - u, v = uv_layer[loop_index].uv - geometry_object.texture_vertices.append((u, v, 0.0)) + # Texture Coordinates + for i, uv_layer_data in enumerate([x.data for x in mesh_data.uv_layers]): + if i >= len(geometry_object.uv_layers): + geometry_object.uv_layers.append(ASEUVLayer()) + uv_layer = geometry_object.uv_layers[i] + for loop_index, loop in enumerate(mesh_data.loops): + u, v = uv_layer_data[loop_index].uv + uv_layer.texture_vertices.append((u, v, 0.0)) # Texture Faces if not geometry_object.is_collision: @@ -107,7 +109,7 @@ def build(self, context, options: ASEBuilderOptions): )) # Update data offsets for next iteration - geometry_object.texture_vertex_offset = len(geometry_object.texture_vertices) + geometry_object.texture_vertex_offset = len(mesh_data.loops) geometry_object.vertex_offset = len(geometry_object.vertices) if len(ase.geometry_objects) == 0: diff --git a/src/writer.py b/src/writer.py index 0ff3c41..09b136b 100644 --- a/src/writer.py +++ b/src/writer.py @@ -146,21 +146,23 @@ def build_ase_tree(ase) -> ASEFile: face_node.push_sub_command('MESH_MTLID').push_datum(face.material_index) # Texture Coordinates - if len(geometry_object.texture_vertices) > 0: - mesh_node.push_child('MESH_NUMTVERTEX').push_datum(len(geometry_object.texture_vertices)) - tvertlist_node = mesh_node.push_child('MESH_TVERTLIST') - for tvert_index, tvert in enumerate(geometry_object.texture_vertices): + for i, uv_layer in enumerate(geometry_object.uv_layers): + parent_node = mesh_node if i == 0 else mesh_node.push_child('MESH_MAPPINGCHANNEL') + if i > 0: + parent_node.push_datum(i + 1) + parent_node.push_child('MESH_NUMTVERTEX').push_datum(len(uv_layer.texture_vertices)) + tvertlist_node = parent_node.push_child('MESH_TVERTLIST') + for tvert_index, tvert in enumerate(uv_layer.texture_vertices): tvert_node = tvertlist_node.push_child('MESH_TVERT') tvert_node.push_datum(tvert_index) tvert_node.push_data(list(tvert)) - - # Texture Faces - if len(geometry_object.texture_vertex_faces) > 0: - mesh_node.push_child('MESH_NUMTVFACES').push_datum(len(geometry_object.texture_vertex_faces)) - texture_faces_node = mesh_node.push_child('MESH_TFACELIST') - for texture_face_index, texture_face in enumerate(geometry_object.texture_vertex_faces): - texture_face_node = texture_faces_node.push_child('MESH_TFACE') - texture_face_node.push_data([texture_face_index] + list(texture_face)) + # Texture Faces + if len(geometry_object.texture_vertex_faces) > 0: + parent_node.push_child('MESH_NUMTVFACES').push_datum(len(geometry_object.texture_vertex_faces)) + texture_faces_node = parent_node.push_child('MESH_TFACELIST') + for texture_face_index, texture_face in enumerate(geometry_object.texture_vertex_faces): + texture_face_node = texture_faces_node.push_child('MESH_TFACE') + texture_face_node.push_data([texture_face_index] + list(texture_face)) # Normals if len(geometry_object.face_normals) > 0: