Browse Source

Refactored mesh serialization into the surface class. Added test-against-known-exports

Geoffrey 7 years ago
parent
commit
36dea379f7

+ 1 - 1
.gitignore

@@ -2,7 +2,7 @@
 __pycache__
 __pycache__
 
 
 *.blend[0-9]
 *.blend[0-9]
-*.escn
+tests/exports/*.escn
 
 
 .import 
 .import 
 *.import
 *.import

+ 2 - 2
.pylintrc

@@ -59,7 +59,7 @@ confidence=
 # --enable=similarities". If you want to run only the classes checker, but have
 # --enable=similarities". If you want to run only the classes checker, but have
 # no Warning level messages displayed, use"--disable=all --enable=classes
 # no Warning level messages displayed, use"--disable=all --enable=classes
 # --disable=W"
 # --disable=W"
-disable=attribute-defined-outside-init, import-error, unused-argument, too-few-public-methods
+disable=attribute-defined-outside-init, import-error, unused-argument, too-few-public-methods, no-self-use
 
 
 [REPORTS]
 [REPORTS]
 
 
@@ -212,7 +212,7 @@ generated-members=
 bad-functions=map,filter
 bad-functions=map,filter
 
 
 # Good variable names which should always be accepted, separated by a comma
 # Good variable names which should always be accepted, separated by a comma
-good-names=i,j,k,ex,Run,_
+good-names=i,j,k,ex,Run,_,uv,id
 
 
 # Bad variable names which should always be refused, separated by a comma
 # Bad variable names which should always be refused, separated by a comma
 bad-names=foo,bar,baz,toto,tutu,tata
 bad-names=foo,bar,baz,toto,tutu,tata

+ 17 - 3
Makefile

@@ -3,6 +3,8 @@ PEP8 = pep8
 BLENDER = blender
 BLENDER = blender
 GODOT = godot
 GODOT = godot
 
 
+.DEFAULT_GOAL := all
+
 pylint:
 pylint:
 	$(PYLINT) io_scene_godot
 	$(PYLINT) io_scene_godot
 	$(PYLINT) io_scene_godot
 	$(PYLINT) io_scene_godot
@@ -11,13 +13,25 @@ pep8:
 	$(PEP8) io_scene_godot
 	$(PEP8) io_scene_godot
 
 
 
 
-.PHONY = test-blends
-test-blends:
+export-blends:
 	rm -rf ./tests/.import  # Ensure we don't have any hangover data
 	rm -rf ./tests/.import  # Ensure we don't have any hangover data
 	$(BLENDER) -b --python ./tests/scenes/export_blends.py
 	$(BLENDER) -b --python ./tests/scenes/export_blends.py
 
 
 
 
-test-import: test-blends
+test-import: export-blends
 	$(GODOT) -e -q --path tests/ > log.txt 2>&1
 	$(GODOT) -e -q --path tests/ > log.txt 2>&1
 	@cat log.txt
 	@cat log.txt
 	! grep -q "ERROR" log.txt
 	! grep -q "ERROR" log.txt
+
+
+update-examples:
+	mkdir -p tests/reference-exports
+	cp tests/exports/*.escn tests/reference-exports
+	
+compare: export-blends
+	diff -x "*.escn.import" -r tests/exports/ tests/reference-exports/
+
+
+style-test: pep8 pylint
+
+all: compare style-test

+ 2 - 1
io_scene_godot/__init__.py

@@ -29,7 +29,8 @@ bl_info = {  # pylint: disable=invalid-name
     "blender": (2, 5, 8),
     "blender": (2, 5, 8),
     "api": 38691,
     "api": 38691,
     "location": "File > Import-Export",
     "location": "File > Import-Export",
-    "description": ("Export Godot Scenes to a format that can be efficiently imported. "),
+    "description": ("Export Godot Scenes to a format that can be efficiently "
+                    "imported. "),
     "warning": "",
     "warning": "",
     "wiki_url": ("https://godotengine.org"),
     "wiki_url": ("https://godotengine.org"),
     "tracker_url": "https://github.com/godotengine/blender-exporter",
     "tracker_url": "https://github.com/godotengine/blender-exporter",

+ 6 - 8
io_scene_godot/converters/material.py

@@ -37,7 +37,6 @@ def export_image(escn_file, export_settings, image):
 
 
 def export_material(escn_file, export_settings, material):
 def export_material(escn_file, export_settings, material):
     """ Exports a blender internal material as best it can"""
     """ Exports a blender internal material as best it can"""
-
     external_material = find_material(export_settings, material)
     external_material = find_material(export_settings, material)
     if external_material is not None:
     if external_material is not None:
         resource_id = escn_file.get_external_resource(material)
         resource_id = escn_file.get_external_resource(material)
@@ -53,15 +52,14 @@ def export_material(escn_file, export_settings, material):
     # Existing internal resource
     # Existing internal resource
     if resource_id is not None:
     if resource_id is not None:
         return "SubResource({})".format(resource_id)
         return "SubResource({})".format(resource_id)
-
     mat = InternalResource("SpatialMaterial")
     mat = InternalResource("SpatialMaterial")
 
 
-    mat.flags_unshaded = material.use_shadeless
-    mat.flags_vertex_lighting = material.use_vertex_color_light
-    mat.flags_transparent = material.use_transparency
-    mat.vertex_color_use_as_albedo = material.use_vertex_color_paint
-    mat.albedo_color = material.diffuse_color
-    mat.subsurf_scatter_enabled = material.subsurface_scattering.use
+    mat['flags_unshaded'] = material.use_shadeless
+    mat['flags_vertex_lighting'] = material.use_vertex_color_light
+    mat['flags_transparent'] = material.use_transparency
+    mat['vertex_color_use_as_albedo'] = material.use_vertex_color_paint
+    mat['albedo_color'] = material.diffuse_color
+    mat['subsurf_scatter_enabled'] = material.subsurface_scattering.use
 
 
     resource_id = escn_file.add_internal_resource(mat, material)
     resource_id = escn_file.add_internal_resource(mat, material)
     return "SubResource({})".format(resource_id)
     return "SubResource({})".format(resource_id)

+ 195 - 156
io_scene_godot/converters/mesh.py

@@ -1,4 +1,4 @@
-import logging
+"""Exports a normal triangle mesh"""
 import bpy
 import bpy
 import bmesh
 import bmesh
 import mathutils
 import mathutils
@@ -31,7 +31,7 @@ def export_mesh_node(escn_file, export_settings, node, parent_path):
         if node.parent is not None and node.parent.type == "ARMATURE":
         if node.parent is not None and node.parent.type == "ARMATURE":
             armature = node.parent
             armature = node.parent
 
 
-        mesh_id = export_mesh(escn_file, export_settings, node, armature)  # We need to export the mesh
+        mesh_id = export_mesh(escn_file, export_settings, node, armature)
 
 
         mesh_node = NodeTemplate(node.name, "MeshInstance", parent_path)
         mesh_node = NodeTemplate(node.name, "MeshInstance", parent_path)
         mesh_node['mesh'] = "SubResource({})".format(mesh_id)
         mesh_node['mesh'] = "SubResource({})".format(mesh_id)
@@ -55,25 +55,14 @@ def export_mesh(escn_file, export_settings, node, armature):
 
 
     mesh_resource = InternalResource('ArrayMesh')
     mesh_resource = InternalResource('ArrayMesh')
 
 
-    mesh_lines = []
-    mesh_materials = []
-    make_arrays(export_settings, node, armature, mesh_lines, mesh_materials)
+    surfaces = make_arrays(
+        escn_file,
+        export_settings,
+        node,
+        armature)
 
 
-
-    for i in range(len(mesh_lines)):
-        mesh_resource.contents += "surfaces/" + str(i) + "={\n"
-        if mesh_materials[i] is not None:
-            mat_resource = export_material(escn_file, export_settings, mesh_materials[i])
-            mesh_resource.contents += "\t" + "\"material\":" + mat_resource + ",\n"
-        mesh_resource.contents += "\t" + "\"primitive\":4,\n"
-        mesh_resource.contents += "\t" + "\"arrays\":[\n"
-
-        arrays = ",\n\t\t".join(mesh_lines[i])
-        mesh_resource.contents += "\t\t" + arrays + "\n"
-
-        mesh_resource.contents += "\t" + "],\n"
-        mesh_resource.contents += "\t" + "\"morph_arrays\":[]\n"
-        mesh_resource.contents += "}\n"
+    for surface in surfaces:
+        mesh_resource[surface.name_str] = surface
 
 
     mesh_id = escn_file.add_internal_resource(mesh_resource, mesh)
     mesh_id = escn_file.add_internal_resource(mesh_resource, mesh)
     assert mesh_id is not None
     assert mesh_id is not None
@@ -81,107 +70,112 @@ def export_mesh(escn_file, export_settings, node, armature):
     return mesh_id
     return mesh_id
 
 
 
 
-def make_arrays(export_settings, node, armature, mesh_lines, ret_materials, skeyindex=-1):
-
+def make_arrays(escn_file, export_settings, node, armature):
+    """Generates arrays of positions, normals etc"""
     mesh = node.to_mesh(bpy.context.scene,
     mesh = node.to_mesh(bpy.context.scene,
                         export_settings['use_mesh_modifiers'],
                         export_settings['use_mesh_modifiers'],
                         "RENDER")
                         "RENDER")
 
 
-    if True:  # Triangulate, always
-        bm = bmesh.new()
-        bm.from_mesh(mesh)
-        bmesh.ops.triangulate(bm, faces=bm.faces)
-        bm.to_mesh(mesh)
-        bm.free()
-
-    surfaces = []
-    material_to_surface = {}
+    # Prepare the mesh for export
+    tri_mesh = bmesh.new()
+    tri_mesh.from_mesh(mesh)
+    bmesh.ops.triangulate(tri_mesh, faces=tri_mesh.faces)
+    tri_mesh.to_mesh(mesh)
+    tri_mesh.free()
 
 
     mesh.update(calc_tessface=True)
     mesh.update(calc_tessface=True)
 
 
-    si = None
-    #if armature is not None:
-    #    si = self.skeleton_info[armature]
-
-    # TODO: Implement automatic tangent detection
-    has_tangents = True  # always use tangents, we are grown up now.
-
-    has_colors = len(mesh.vertex_colors)
-
     uv_layer_count = len(mesh.uv_textures)
     uv_layer_count = len(mesh.uv_textures)
     if uv_layer_count > 2:
     if uv_layer_count > 2:
         uv_layer_count = 2
         uv_layer_count = 2
 
 
-    if has_tangents and len(mesh.uv_textures):
-        try:
-            mesh.calc_tangents()
-        except:
-            logging.warning(
-                "CalcTangets failed for mesh %s, no tangets will be "
-                "exported.", mesh.name
-            )
-            mesh.calc_normals_split()
-            has_tangents = False
-
+    if len(mesh.uv_textures):
+        has_tangents = True
+        mesh.calc_tangents()
     else:
     else:
         mesh.calc_normals_split()
         mesh.calc_normals_split()
         has_tangents = False
         has_tangents = False
 
 
+    # Separate by materials into single-material surfaces
+    surfaces = generate_surfaces(
+        escn_file,
+        export_settings,
+        mesh,
+        has_tangents
+    )
+
+    for surface_id, surface in enumerate(surfaces):
+        surface.id = surface_id
+        surface.armature = armature
+
+    bpy.data.meshes.remove(mesh)
+
+    return surfaces
+
+
+def generate_surfaces(escn_file, export_settings, mesh, has_tangents):
+    """Splits up the mesh into surfaces with a single material each.
+    Within this, it creates the Vertex structure to contain all data about
+    a single vertex
+    """
+    material_to_surface = {}
+    surfaces = []
+
     for face_index in range(len(mesh.polygons)):
     for face_index in range(len(mesh.polygons)):
         face = mesh.polygons[face_index]
         face = mesh.polygons[face_index]
 
 
+        # Find a surface that matches the material, otherwise create a new
+        # surface for it
         if face.material_index not in material_to_surface:
         if face.material_index not in material_to_surface:
             material_to_surface[face.material_index] = len(surfaces)
             material_to_surface[face.material_index] = len(surfaces)
-            surfaces.append(Surface())
+            surface = Surface()
+            surfaces.append(surface)
             if mesh.materials:
             if mesh.materials:
                 mat = mesh.materials[face.material_index]
                 mat = mesh.materials[face.material_index]
-                ret_materials.append(mat)
-            else:
-                ret_materials.append(None)
+                if mat is not None:
+                    surface.material = export_material(
+                        escn_file,
+                        export_settings,
+                        mat
+                    )
 
 
         surface = surfaces[material_to_surface[face.material_index]]
         surface = surfaces[material_to_surface[face.material_index]]
-        vi = []
+        vertex_indices = []
 
 
-        for lt in range(face.loop_total):
-            loop_index = face.loop_start + lt
-            ml = mesh.loops[loop_index]
-            mv = mesh.vertices[ml.vertex_index]
+        for loop_id in range(face.loop_total):
+            loop_index = face.loop_start + loop_id
+            loop = mesh.loops[loop_index]
 
 
-            v = Vertex()
-            v.vertex = fix_vertex(mathutils.Vector(mv.co))
+            new_vert = Vertex()
+            new_vert.vertex = fix_vertex(mesh.vertices[loop.vertex_index].co)
 
 
-            for xt in mesh.uv_layers:
-                v.uv.append(mathutils.Vector(xt.data[loop_index].uv))
+            for uv_layer in mesh.uv_layers:
+                new_vert.uv.append(mathutils.Vector(
+                    uv_layer.data[loop_index].uv
+                ))
 
 
-            if has_colors:
-                v.color = mathutils.Vector(
+            if mesh.vertex_colors:
+                new_vert.color = mathutils.Vector(
                     mesh.vertex_colors[0].data[loop_index].color)
                     mesh.vertex_colors[0].data[loop_index].color)
 
 
-            v.normal = fix_vertex(mathutils.Vector(ml.normal))
+            new_vert.normal = fix_vertex(loop.normal)
 
 
             if has_tangents:
             if has_tangents:
-                v.tangent = fix_vertex(mathutils.Vector(ml.tangent))
-                v.bitangent = fix_vertex(mathutils.Vector(ml.bitangent))
+                new_vert.tangent = fix_vertex(loop.tangent)
+                new_vert.bitangent = fix_vertex(loop.bitangent)
 
 
-            tup = v.get_tup()
-            idx = 0
-            # Do not optmize if using shapekeys
-            if skeyindex == -1 and tup in surface.vertex_map:
-                idx = surface.vertex_map[tup]
-            else:
-                idx = len(surface.vertices)
-                surface.vertices.append(v)
-                surface.vertex_map[tup] = idx
+            # Merge similar vertices
+            tup = new_vert.get_tup()
+            if tup not in surface.vertex_map:
+                surface.vertex_map[tup] = len(surface.vertices)
+                surface.vertices.append(new_vert)
 
 
-            vi.append(idx)
+            vertex_indices.append(surface.vertex_map[tup])
 
 
-        if len(vi) > 2:  # Only triangles and above
-            surface.indices.append(vi)
+        if len(vertex_indices) > 2:  # Only triangles and above
+            surface.indices.append(vertex_indices)
 
 
-    for s in surfaces:
-        mesh_lines.append(s.generate_lines(has_tangents, has_colors, uv_layer_count, armature))
-
-    bpy.data.meshes.remove(mesh)
+    return surfaces
 
 
 
 
 class Surface:
 class Surface:
@@ -191,6 +185,9 @@ class Surface:
         self.vertices = []
         self.vertices = []
         self.vertex_map = {}
         self.vertex_map = {}
         self.indices = []
         self.indices = []
+        self.id = None
+        self.material = None
+        self.armature = None
 
 
     def calc_tangent_dp(self, vert):
     def calc_tangent_dp(self, vert):
         """Calculates the dot product of the tangent. I think this has
         """Calculates the dot product of the tangent. I think this has
@@ -199,101 +196,143 @@ class Surface:
         dot_product = cross_product.dot(vert.bitangent)
         dot_product = cross_product.dot(vert.bitangent)
         return 1.0 if dot_product > 0.0 else -1.0
         return 1.0 if dot_product > 0.0 else -1.0
 
 
-    def generate_lines(self, has_tangents, has_colors, uv_layer_count, armature):
-        surface_lines = []
-
-        position_vals = Array("Vector3Array(", values=[v.vertex for v in self.vertices])
-        normal_vals = Array("Vector3Array(", values=[v.normal for v in self.vertices])
+    def get_color_array(self):
+        """Generate a single array that contains the colors of all the vertices
+        in this surface"""
+        has_colors = self.vertices[0].color is not None
+        if has_colors:
+            color_vals = Array("ColorArray(")
+            for vert in self.vertices:
+                color_vals.extend(list(vert.color)+[1.0])
+        else:
+            color_vals = Array("null, ; no Vertex Colors", "", "")
 
 
+        return color_vals
 
 
+    def get_tangent_array(self):
+        """Generate a single array that contains the tangents of all the
+        vertices in this surface"""
+        has_tangents = self.vertices[0].tangent is not None
         if has_tangents:
         if has_tangents:
             tangent_vals = Array("FloatArray(")
             tangent_vals = Array("FloatArray(")
             for vert in self.vertices:
             for vert in self.vertices:
-                tangent_vals.extend(list(vert.tangent) + [self.calc_tangent_dp(vert)])
+                tangent_vals.extend(
+                    list(vert.tangent) + [self.calc_tangent_dp(vert)]
+                )
         else:
         else:
             tangent_vals = Array("null, ; No Tangents", "", "")
             tangent_vals = Array("null, ; No Tangents", "", "")
+        return tangent_vals
+
+    def get_uv_array(self, uv_index):
+        """Returns an array representing the specified UV index"""
+        uv_layer_count = len(self.vertices[0].uv)
+        if uv_index >= uv_layer_count:
+            # If lacking 2 UV layers, mark them as null
+            return Array("null, ; No UV"+str(uv_index+1), "", "")
+
+        uv_vals = Array("Vector2Array(")
+        for vert in self.vertices:
+            uv_vals.extend([
+                vert.uv[uv_index].x,
+                1.0-vert.uv[uv_index].y
+            ])
+
+        return uv_vals
+
+    def generate_lines(self):
+        """Generates the various arrays that are part of the surface (eg
+        normals, position etc.)"""
+        surface_lines = []
 
 
-        if has_colors:
-            color_vals = Array("ColorArray(")
-            for vert in self.vertices:
-                color_vals.extend(list(vert.color)+[1.0])
-        else:
-            color_vals = Array("null, ; no Vertex Colors", "", "")
+        position_vals = Array("Vector3Array(",
+                              values=[v.vertex for v in self.vertices])
+        normal_vals = Array("Vector3Array(",
+                            values=[v.normal for v in self.vertices])
 
 
         surface_lines.append(position_vals.to_string())
         surface_lines.append(position_vals.to_string())
         surface_lines.append(normal_vals.to_string())
         surface_lines.append(normal_vals.to_string())
-        surface_lines.append(tangent_vals.to_string())
-        surface_lines.append(color_vals.to_string())
-
-        # UV Arrays
-        for i in range(2):  # Godot always expects two arrays for UV's
-            if i >= uv_layer_count:
-                # but if there aren't enough in blender, make one of them into null
-                surface_lines.append("null, ; No UV"+str(i+1))
-                continue
-            uv_vals = Array("Vector2Array(")
-            for vert in self.vertices:
-                uv_vals.extend([vert.uv[i].x, 1.0-vert.uv[i].y])
+        surface_lines.append(self.get_tangent_array().to_string())
+        surface_lines.append(self.get_color_array().to_string())
 
 
-            surface_lines.append(uv_vals.to_string())
+        surface_lines.append(self.get_uv_array(0).to_string())
+        surface_lines.append(self.get_uv_array(1).to_string())
 
 
         # Bones and Weights
         # Bones and Weights
         # Export armature data (if armature exists)
         # Export armature data (if armature exists)
-        if armature is not None:
-            # Skin Weights!
-            float_values = "FloatArray("
-            float_valuesw = "FloatArray("
-            first = True
-            for vert in self.vertices:
-                #skin_weights_total += len(v.weights)
-                weights = []
-                for i in len(vert.bones):
-                    weights += (vert.bones[i], vert.weights[i])
-
-                weights = sorted(weights, key=lambda x: -x[1])
-                totalw = 0.0
-                for weight in weights:
-                    totalw += weight[1]
-                if totalw == 0.0:
-                    totalw = 0.000000001
-
-                for i in range(4):
-                    if i > 0:
-                        float_values += ","
-                        float_valuesw += ","
-                    if i < len(weights):
-                        float_values += " {}".format(weights[i][0])
-                        float_valuesw += " {}".format(weights[i][1]/totalw)
-                    else:
-                        float_values += " 0"
-                        float_valuesw += " 0.0"
-
-                if not first:
-                    float_values += ","
-                    float_valuesw += ","
-                else:
-                    first = False
-
-            float_values += "),"
-            surface_lines.append(float_values)
-            float_valuesw += "),"
-            surface_lines.append(float_valuesw)
+        bones, bone_weights = self._get_bone_arrays()
 
 
-        else:
-            surface_lines.append("null, ; No Bones")
-            surface_lines.append("null, ; No Weights")
+        surface_lines.append(bones.to_string())
+        surface_lines.append(bone_weights.to_string())
 
 
         # Indices- each face is made of 3 verts, and these are the indices
         # Indices- each face is made of 3 verts, and these are the indices
         # in the vertex arrays. The backface is computed from the winding
         # in the vertex arrays. The backface is computed from the winding
         # order, hence v[2] before v[1]
         # order, hence v[2] before v[1]
-        int_values = Array(
+        face_indices = Array(
             "IntArray(",
             "IntArray(",
             values=[[v[0], v[2], v[1]] for v in self.indices]
             values=[[v[0], v[2], v[1]] for v in self.indices]
         )
         )
-        surface_lines.append(int_values.to_string())
+        surface_lines.append(face_indices.to_string())
 
 
         return surface_lines
         return surface_lines
 
 
+    def _get_bone_arrays(self):
+        """Returns the most influential bones and their weights"""
+        if self.armature is None:
+            return [
+                Array("null, ; No Bones", "", ""),
+                Array("null, ; No Weights", "", "")
+            ]
+
+        # Skin Weights!
+        float_values = Array("FloatArray(")
+        float_valuesw = Array("FloatArray(")
+        for vert in self.vertices:
+            # skin_weights_total += len(v.weights)
+            weights = []
+            for i in len(vert.bones):
+                weights += (vert.bones[i], vert.weights[i])
+
+            weights = sorted(weights, key=lambda x: -x[1])
+            totalw = 0.0
+            for weight in weights:
+                totalw += weight[1]
+            if totalw == 0.0:
+                totalw = 0.000000001
+
+            for i in range(4):
+                if i < len(weights):
+                    float_values.append(weights[i][0])
+                    float_valuesw.append(weights[i][1]/totalw)
+                else:
+                    float_values.append(0)
+                    float_valuesw.append(0.0)
+
+        return float_values, float_valuesw
+
+    @property
+    def name_str(self):
+        """Used to separate surfaces that are part of the same mesh by their
+        id"""
+        return "surfaces/" + str(self.id)
+
+    def to_string(self):
+        """Serialize"""
+        out_str = "{\n"
+        if self.material is not None:
+
+            out_str += "\t\"material\":" + self.material + ",\n"
+        out_str += "\t\"primitive\":4,\n"
+        out_str += "\t\"arrays\":[\n"
+
+        arrays = ",\n\t\t".join(self.generate_lines())
+        out_str += "\t\t" + arrays + "\n"
+
+        out_str += "\t" + "],\n"
+        out_str += "\t" + "\"morph_arrays\":[]\n"
+        out_str += "}\n"
+
+        return out_str
+
 
 
 def fix_vertex(vtx):
 def fix_vertex(vtx):
     """Changes a single position vector from y-up to z-up"""
     """Changes a single position vector from y-up to z-up"""
@@ -301,6 +340,7 @@ def fix_vertex(vtx):
 
 
 
 
 class Vertex:
 class Vertex:
+    """Stores all the attributes for a single vertex"""
     def get_tup(self):
     def get_tup(self):
         """Returns a tuple form of this vertex so that it can be hashed"""
         """Returns a tuple form of this vertex so that it can be hashed"""
         tup = (self.vertex.x, self.vertex.y, self.vertex.z, self.normal.x,
         tup = (self.vertex.x, self.vertex.y, self.vertex.z, self.normal.x,
@@ -322,7 +362,7 @@ class Vertex:
         return tup
         return tup
 
 
     __slots__ = ("vertex", "normal", "tangent", "bitangent", "color", "uv",
     __slots__ = ("vertex", "normal", "tangent", "bitangent", "color", "uv",
-                 "uv2", "bones", "weights")
+                 "bones", "weights")
 
 
     def __init__(self):
     def __init__(self):
         self.vertex = mathutils.Vector((0.0, 0.0, 0.0))
         self.vertex = mathutils.Vector((0.0, 0.0, 0.0))
@@ -331,6 +371,5 @@ class Vertex:
         self.bitangent = None
         self.bitangent = None
         self.color = None
         self.color = None
         self.uv = []
         self.uv = []
-        self.uv2 = mathutils.Vector((0.0, 0.0))
         self.bones = []
         self.bones = []
         self.weights = []
         self.weights = []

+ 0 - 1
io_scene_godot/converters/physics.py

@@ -121,7 +121,6 @@ def generate_triangle_mesh_array(escn_file, export_settings, node):
 
 
     col_shape = InternalResource("ConcavePolygonShape")
     col_shape = InternalResource("ConcavePolygonShape")
 
 
-
     mesh = node.to_mesh(bpy.context.scene,
     mesh = node.to_mesh(bpy.context.scene,
                         export_settings['use_mesh_modifiers'],
                         export_settings['use_mesh_modifiers'],
                         "RENDER")
                         "RENDER")

+ 5 - 5
io_scene_godot/export_godot.py

@@ -34,7 +34,6 @@ from . import converters
 logging.basicConfig(level=logging.INFO, format="[%(levelname)s]: %(message)s")
 logging.basicConfig(level=logging.INFO, format="[%(levelname)s]: %(message)s")
 
 
 
 
-
 def find_godot_project_dir(export_path):
 def find_godot_project_dir(export_path):
     """Finds the project.godot file assuming that the export path
     """Finds the project.godot file assuming that the export path
     is inside a project (looks for a project.godot file)"""
     is inside a project (looks for a project.godot file)"""
@@ -101,10 +100,11 @@ class GodotExporter:
 
 
     def export_scene(self):
     def export_scene(self):
         """Decide what objects to export, and export them!"""
         """Decide what objects to export, and export them!"""
+        # Scene root
         self.escn_file.add_node(structures.FileEntry(
         self.escn_file.add_node(structures.FileEntry(
             "node", {
             "node", {
-                "type":"Spatial",
-                "name":self.scene.name
+                "type": "Spatial",
+                "name": self.scene.name
             }
             }
         ))
         ))
         logging.info("Exporting scene: %s", self.scene.name)
         logging.info("Exporting scene: %s", self.scene.name)
@@ -132,8 +132,8 @@ class GodotExporter:
         self.escn_file = structures.ESCNFile(structures.FileEntry(
         self.escn_file = structures.ESCNFile(structures.FileEntry(
             "gd_scene",
             "gd_scene",
             {
             {
-                "load_steps":1,
-                "format":2
+                "load_steps": 1,
+                "format": 2
             }
             }
         ))
         ))
 
 

+ 13 - 9
io_scene_godot/structures.py

@@ -81,11 +81,11 @@ class ESCNFile:
     def to_string(self):
     def to_string(self):
         """Serializes the file ready to dump out to disk"""
         """Serializes the file ready to dump out to disk"""
 
 
-        return "{}\n\n{}\n\n{}\n\n{}\n".format(
+        return "{}{}\n{}\n{}\n".format(
             self.heading.to_string(),
             self.heading.to_string(),
-            '\n'.join(i.to_string() for i in self.external_resources),
-            '\n'.join(e.to_string() for e in self.internal_resources),
-            '\n'.join(n.to_string() for n in self.nodes)
+            '\n\n'.join(i.to_string() for i in self.external_resources),
+            '\n\n'.join(e.to_string() for e in self.internal_resources),
+            '\n\n'.join(n.to_string() for n in self.nodes)
         )
         )
 
 
 
 
@@ -168,9 +168,10 @@ class ExternalResource(FileEntry):
         super().__init__(
         super().__init__(
             'ext_resource',
             'ext_resource',
             {
             {
-                'id':None,  # This is overwritten by ESCN_File.add_external_resource
-                'path':path,
-                'type':resource_type
+                # ID is overwritten by ESCN_File.add_external_resource
+                'id': None,
+                'path': path,
+                'type': resource_type
             }
             }
         )
         )
 
 
@@ -189,8 +190,9 @@ class InternalResource(FileEntry):
         super().__init__(
         super().__init__(
             'sub_resource',
             'sub_resource',
             {
             {
-                'id':None,  # This is overwritten by ESCN_File.add_external_resource
-                'type':resource_type
+                # ID is overwritten by ESCN_File.add_internal_resource
+                'id': None,
+                'type': resource_type
             }
             }
         )
         )
 
 
@@ -211,6 +213,8 @@ class Array(list):
         super().__init__()
         super().__init__()
         self.add_elements(values)
         self.add_elements(values)
 
 
+        self.__str__ = self.to_string
+
     def add_elements(self, list_of_lists):
     def add_elements(self, list_of_lists):
         """Add each element from a list of lists to the array (flatten the
         """Add each element from a list of lists to the array (flatten the
         list of lists)"""
         list of lists)"""

+ 45 - 0
tests/reference-exports/just_cameras.escn

@@ -0,0 +1,45 @@
+[gd_scene load_steps=1 format=2]
+
+
+[node type="Spatial" name="Scene"]
+
+
+[node name="Camera.004" type="Camera" parent="."]
+
+far = 10.0
+near = 5.0
+projection = 0
+fov = 90.00000250447816
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 5.0, 0.0, -0.0 )
+
+[node name="Camera.003" type="Camera" parent="."]
+
+far = 100.0
+near = 0.10000000149011612
+projection = 1
+size = 6.0
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 1.0, 0.0, -0.0 )
+
+[node name="Camera.002" type="Camera" parent="."]
+
+far = 100.0
+near = 0.10000000149011612
+projection = 1
+size = 2.0
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, -2.0, 0.0, -0.0 )
+
+[node name="Camera.001" type="Camera" parent="."]
+
+far = 100.0
+near = 0.10000000149011612
+projection = 0
+fov = 90.00000250447816
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, -5.0, 0.0, -0.0 )
+
+[node name="Camera" type="Camera" parent="."]
+
+far = 100.0
+near = 0.10000000149011612
+projection = 0
+fov = 19.99999941818584
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, -7.0, 0.0, -0.0 )

File diff suppressed because it is too large
+ 45 - 0
tests/reference-exports/just_mesh.escn


+ 123 - 0
tests/reference-exports/just_point_lights.escn

@@ -0,0 +1,123 @@
+[gd_scene load_steps=1 format=2]
+
+[sub_resource id=1 type="ArrayMesh"]
+
+surfaces/0 = {
+	"primitive":4,
+	"arrays":[
+		Vector3Array(-1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0),
+		Vector3Array(-1.0, 0.0, -0.0, -1.0, 0.0, -0.0, -1.0, 0.0, -0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, -1.0, 0.0, -0.0, 0.0, 0.0, -1.0, 1.0, 0.0, -0.0, 0.0, 0.0, 1.0, 0.0, -1.0, -0.0, 0.0, 1.0, -0.0),
+		null, ; No Tangents,
+		null, ; no Vertex Colors,
+		null, ; No UV1,
+		null, ; No UV2,
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 14, 13, 15, 17, 16, 0, 1, 18, 3, 4, 19, 6, 7, 20, 9, 10, 21, 12, 13, 22, 15, 16, 23)
+	],
+	"morph_arrays":[]
+}
+
+
+[sub_resource id=2 type="ArrayMesh"]
+
+surfaces/0 = {
+	"primitive":4,
+	"arrays":[
+		Vector3Array(-1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0),
+		Vector3Array(-1.0, 0.0, -0.0, -1.0, 0.0, -0.0, -1.0, 0.0, -0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, -1.0, 0.0, -0.0, 0.0, 0.0, -1.0, 1.0, 0.0, -0.0, 0.0, 0.0, 1.0, 0.0, -1.0, -0.0, 0.0, 1.0, -0.0),
+		null, ; No Tangents,
+		null, ; no Vertex Colors,
+		null, ; No UV1,
+		null, ; No UV2,
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 14, 13, 15, 17, 16, 0, 1, 18, 3, 4, 19, 6, 7, 20, 9, 10, 21, 12, 13, 22, 15, 16, 23)
+	],
+	"morph_arrays":[]
+}
+
+
+[sub_resource id=3 type="ArrayMesh"]
+
+surfaces/0 = {
+	"primitive":4,
+	"arrays":[
+		Vector3Array(1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0),
+		Vector3Array(0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0),
+		null, ; No Tangents,
+		null, ; no Vertex Colors,
+		null, ; No UV1,
+		null, ; No UV2,
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 0, 1, 3)
+	],
+	"morph_arrays":[]
+}
+
+[node type="Spatial" name="Scene"]
+
+
+[node name="Lamp.003" type="OmniLight" parent="."]
+
+omni_range = 5.0
+shadow_enabled = true
+light_color = Color( 0.674415111541748, 0.0003378598776180297, 1.0, 1.0 )
+transform = Transform(  1.0, 0.0, -0.0, 0.0, -4.371138828673793e-08, 1.0, -0.0, -1.0, -4.371138828673793e-08, 0.0, 0.3999999761581421, 1.0 )
+light_negative = false
+light_specular = 1.0
+light_energy = 1.0
+
+[node name="Cube.001" type="MeshInstance" parent="."]
+
+mesh = SubResource(1)
+transform = Transform(  0.30000001192092896, 0.0, -0.0, 0.0, 0.6000000238418579, -0.0, -0.0, -0.0, 0.30000001192092896, 0.0, 0.0, 0.35525739192962646 )
+
+[node name="Cube" type="MeshInstance" parent="."]
+
+mesh = SubResource(2)
+transform = Transform(  0.30000001192092896, 0.0, -0.0, 0.0, 0.6000000238418579, -0.0, -0.0, -0.0, 0.30000001192092896, -2.0, 0.0, 0.35525739192962646 )
+
+[node name="Lamp.002" type="OmniLight" parent="."]
+
+omni_range = 5.0
+shadow_enabled = false
+light_color = Color( 0.0, 1.0, 0.0024246724788099527, 1.0 )
+transform = Transform(  1.0, 0.0, -0.0, 0.0, -4.371138828673793e-08, 1.0, -0.0, -1.0, -4.371138828673793e-08, -2.0, 0.3999999761581421, 1.0 )
+light_negative = false
+light_specular = 1.0
+light_energy = 1.0
+
+[node name="Lamp.001" type="OmniLight" parent="."]
+
+omni_range = 2.0
+shadow_enabled = false
+light_color = Color( 1.0, 0.0, 0.0, 1.0 )
+transform = Transform(  1.0, 0.0, -0.0, 0.0, -4.371138828673793e-08, 1.0, -0.0, -1.0, -4.371138828673793e-08, -6.0, 1.0, 3.0 )
+light_negative = false
+light_specular = 1.0
+light_energy = 1.0
+
+[node name="Plane" type="MeshInstance" parent="."]
+
+mesh = SubResource(3)
+transform = Transform(  10.0, 0.0, -0.0, 0.0, 10.0, -0.0, -0.0, -0.0, 10.0, 0.0, 0.0, -0.0 )
+
+[node name="Lamp" type="OmniLight" parent="."]
+
+omni_range = 2.0
+shadow_enabled = false
+light_color = Color( 1.0, 1.0, 1.0, 1.0 )
+transform = Transform(  1.0, 0.0, -0.0, 0.0, -4.371138828673793e-08, 1.0, -0.0, -1.0, -4.371138828673793e-08, -6.0, 1.0, -0.0 )
+light_negative = false
+light_specular = 1.0
+light_energy = 1.0
+
+[node name="Camera" type="Camera" parent="."]
+
+far = 100.0
+near = 0.10000000149011612
+projection = 0
+fov = 49.13434207760448
+transform = Transform(  0.6859206557273865, -0.32401350140571594, 0.6515582203865051, 0.0, 0.8953956365585327, 0.44527143239974976, -0.7276763319969177, -0.3054208755493164, 0.6141703724861145, 7.481131553649902, 5.34366512298584, 6.5076398849487305 )

+ 179 - 0
tests/reference-exports/just_spot_lights.escn

@@ -0,0 +1,179 @@
+[gd_scene load_steps=1 format=2]
+
+[sub_resource id=1 type="ArrayMesh"]
+
+surfaces/0 = {
+	"primitive":4,
+	"arrays":[
+		Vector3Array(-1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0),
+		Vector3Array(-1.0, 0.0, -0.0, -1.0, 0.0, -0.0, -1.0, 0.0, -0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, -1.0, 0.0, -0.0, 0.0, 0.0, -1.0, 1.0, 0.0, -0.0, 0.0, 0.0, 1.0, 0.0, -1.0, -0.0, 0.0, 1.0, -0.0),
+		null, ; No Tangents,
+		null, ; no Vertex Colors,
+		null, ; No UV1,
+		null, ; No UV2,
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 14, 13, 15, 17, 16, 0, 1, 18, 3, 4, 19, 6, 7, 20, 9, 10, 21, 12, 13, 22, 15, 16, 23)
+	],
+	"morph_arrays":[]
+}
+
+
+[sub_resource id=2 type="ArrayMesh"]
+
+surfaces/0 = {
+	"primitive":4,
+	"arrays":[
+		Vector3Array(-1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0),
+		Vector3Array(-1.0, 0.0, -0.0, -1.0, 0.0, -0.0, -1.0, 0.0, -0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, -1.0, 0.0, -0.0, 0.0, 0.0, -1.0, 1.0, 0.0, -0.0, 0.0, 0.0, 1.0, 0.0, -1.0, -0.0, 0.0, 1.0, -0.0),
+		null, ; No Tangents,
+		null, ; no Vertex Colors,
+		null, ; No UV1,
+		null, ; No UV2,
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 14, 13, 15, 17, 16, 0, 1, 18, 3, 4, 19, 6, 7, 20, 9, 10, 21, 12, 13, 22, 15, 16, 23)
+	],
+	"morph_arrays":[]
+}
+
+
+[sub_resource id=3 type="ArrayMesh"]
+
+surfaces/0 = {
+	"primitive":4,
+	"arrays":[
+		Vector3Array(1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0),
+		Vector3Array(0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0),
+		null, ; No Tangents,
+		null, ; no Vertex Colors,
+		null, ; No UV1,
+		null, ; No UV2,
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 0, 1, 3)
+	],
+	"morph_arrays":[]
+}
+
+[node type="Spatial" name="Scene"]
+
+
+[node name="Lamp.007" type="SpotLight" parent="."]
+
+spot_range = 3.0
+spot_angle = 9.99999970909292
+spot_angle_attenuation = 20.0
+shadow_enabled = false
+light_color = Color( 0.0, 1.0, 0.7969905138015747, 1.0 )
+transform = Transform(  1.0, 0.0, -0.0, 0.0, -4.371138828673793e-08, 1.0, -0.0, -1.0, -4.371138828673793e-08, 1.0, 2.0, -3.0 )
+light_negative = false
+light_specular = 1.0
+light_energy = 5.0
+
+[node name="Lamp.006" type="SpotLight" parent="."]
+
+spot_range = 3.0
+spot_angle = 9.99999970909292
+spot_angle_attenuation = 0.19801980198019803
+shadow_enabled = false
+light_color = Color( 0.0, 1.0, 0.7969905138015747, 1.0 )
+transform = Transform(  1.0, 0.0, -0.0, 0.0, -4.371138828673793e-08, 1.0, -0.0, -1.0, -4.371138828673793e-08, 2.0, 2.0, -3.0 )
+light_negative = false
+light_specular = 1.0
+light_energy = 5.0
+
+[node name="Lamp.005" type="SpotLight" parent="."]
+
+spot_range = 3.0
+spot_angle = 9.99999970909292
+spot_angle_attenuation = 0.19801980198019803
+shadow_enabled = false
+light_color = Color( 0.0, 1.0, 0.7969905138015747, 1.0 )
+transform = Transform(  1.0, 0.0, -0.0, 0.0, -4.371138828673793e-08, 1.0, -0.0, -1.0, -4.371138828673793e-08, 2.0, 2.0, -2.0 )
+light_negative = false
+light_specular = 1.0
+light_energy = 1.0
+
+[node name="Lamp.002" type="SpotLight" parent="."]
+
+spot_range = 3.0
+spot_angle = 9.99999970909292
+spot_angle_attenuation = 20.0
+shadow_enabled = false
+light_color = Color( 0.0, 1.0, 0.7969905138015747, 1.0 )
+transform = Transform(  1.0, 0.0, -0.0, 0.0, -4.371138828673793e-08, 1.0, -0.0, -1.0, -4.371138828673793e-08, 1.0, 2.0, -2.0 )
+light_negative = false
+light_specular = 1.0
+light_energy = 1.0
+
+[node name="Lamp.001" type="SpotLight" parent="."]
+
+spot_range = 3.0
+spot_angle = 60.000001669652114
+spot_angle_attenuation = 1.249999953433873
+shadow_enabled = false
+light_color = Color( 0.0, 1.0, 0.7969905138015747, 1.0 )
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 0.9063078165054321, 0.4226182699203491, -0.0, -0.4226182699203491, 0.9063078165054321, 1.0, 1.0, 2.0 )
+light_negative = false
+light_specular = 1.0
+light_energy = 1.0
+
+[node name="Lamp.000" type="SpotLight" parent="."]
+
+spot_range = 5.0
+spot_angle = 9.99999970909292
+spot_angle_attenuation = 1.249999953433873
+shadow_enabled = false
+light_color = Color( 0.009934368543326855, 1.0, 0.0, 1.0 )
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 0.9063078165054321, 0.4226182699203491, -0.0, -0.4226182699203491, 0.9063078165054321, -1.0, 1.0, 2.0 )
+light_negative = false
+light_specular = 1.0
+light_energy = 1.0
+
+[node name="Cube.001" type="MeshInstance" parent="."]
+
+mesh = SubResource(1)
+transform = Transform(  0.30000001192092896, 0.0, -0.0, 0.0, 0.6000000238418579, -0.0, -0.0, -0.0, 0.30000001192092896, -6.0, 0.0, 0.35525739192962646 )
+
+[node name="Cube" type="MeshInstance" parent="."]
+
+mesh = SubResource(2)
+transform = Transform(  0.30000001192092896, 0.0, -0.0, 0.0, 0.6000000238418579, -0.0, -0.0, -0.0, 0.30000001192092896, -4.0, 0.0, 0.35525739192962646 )
+
+[node name="Lamp.004" type="SpotLight" parent="."]
+
+spot_range = 5.0
+spot_angle = 37.49999933598528
+spot_angle_attenuation = 1.249999953433873
+shadow_enabled = true
+light_color = Color( 0.9903545379638672, 0.0, 1.0, 1.0 )
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 0.9063078165054321, 0.4226182699203491, -0.0, -0.4226182699203491, 0.9063078165054321, -4.0, 1.0, 2.0 )
+light_negative = false
+light_specular = 1.0
+light_energy = 1.0
+
+[node name="Lamp.003" type="SpotLight" parent="."]
+
+spot_range = 5.0
+spot_angle = 37.49999933598528
+spot_angle_attenuation = 1.249999953433873
+shadow_enabled = false
+light_color = Color( 0.0, 0.3401070833206177, 1.0, 1.0 )
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 0.9063078165054321, 0.4226182699203491, -0.0, -0.4226182699203491, 0.9063078165054321, -6.0, 1.0, 2.0 )
+light_negative = false
+light_specular = 1.0
+light_energy = 1.0
+
+[node name="Plane" type="MeshInstance" parent="."]
+
+mesh = SubResource(3)
+transform = Transform(  10.0, 0.0, -0.0, 0.0, 10.0, -0.0, -0.0, -0.0, 10.0, 0.0, 0.0, -0.0 )
+
+[node name="Camera" type="Camera" parent="."]
+
+far = 100.0
+near = 0.10000000149011612
+projection = 0
+fov = 49.13434207760448
+transform = Transform(  0.6859206557273865, -0.32401350140571594, 0.6515582203865051, 0.0, 0.8953956365585327, 0.44527143239974976, -0.7276763319969177, -0.3054208755493164, 0.6141703724861145, 7.481131553649902, 5.34366512298584, 6.5076398849487305 )

+ 47 - 0
tests/reference-exports/material_search.escn

@@ -0,0 +1,47 @@
+[gd_scene load_steps=1 format=2]
+[ext_resource id=1 path="../uv_tester_material.tres" type="SpatialMaterial"]
+
+[sub_resource id=1 type="ArrayMesh"]
+
+surfaces/0 = {
+	"material":ExtResource(1),
+	"primitive":4,
+	"arrays":[
+		Vector3Array(1.0, -1.0, 1.0, -0.9999996423721313, -1.0, -1.0000003576278687, 1.0, -1.0, -0.9999999403953552, -0.9999999403953552, 1.0, -1.0, 0.9999993443489075, 1.0, 1.0000005960464478, 1.0000004768371582, 1.0, -0.999999463558197, 1.0000004768371582, 1.0, -0.999999463558197, 1.0, -1.0, 1.0, 1.0, -1.0, -0.9999999403953552, 0.9999993443489075, 1.0, 1.0000005960464478, -1.0000001192092896, -1.0, 0.9999998211860657, 1.0, -1.0, 1.0, -1.0000001192092896, -1.0, 0.9999998211860657, -0.9999999403953552, 1.0, -1.0, -0.9999996423721313, -1.0, -1.0000003576278687, 1.0, -1.0, -0.9999999403953552, -0.9999999403953552, 1.0, -1.0, 1.0000004768371582, 1.0, -0.999999463558197, 1.0, -1.0, 1.0, -1.0000001192092896, -1.0, 0.9999998211860657, -0.9999996423721313, -1.0, -1.0000003576278687, -0.9999999403953552, 1.0, -1.0, -1.0000003576278687, 1.0, 0.9999996423721313, 0.9999993443489075, 1.0, 1.0000005960464478, 1.0000004768371582, 1.0, -0.999999463558197, 0.9999993443489075, 1.0, 1.0000005960464478, 1.0, -1.0, 1.0, 0.9999993443489075, 1.0, 1.0000005960464478, -1.0000003576278687, 1.0, 0.9999996423721313, -1.0000001192092896, -1.0, 0.9999998211860657, -1.0000001192092896, -1.0, 0.9999998211860657, -1.0000003576278687, 1.0, 0.9999996423721313, -0.9999999403953552, 1.0, -1.0, 1.0, -1.0, -0.9999999403953552, -0.9999996423721313, -1.0, -1.0000003576278687, -0.9999999403953552, 1.0, -1.0),
+		Vector3Array(2.980232949312267e-08, -1.0, -0.0, 2.980232949312267e-08, -1.0, -0.0, 2.980232949312267e-08, -1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 1.0, -2.384185791015625e-07, -0.0, 1.0, -2.384185791015625e-07, -0.0, 1.0, -2.384185791015625e-07, -0.0, -8.940696716308594e-08, -4.76837158203125e-07, 1.0, -8.940696716308594e-08, -4.76837158203125e-07, 1.0, -8.940696716308594e-08, -4.76837158203125e-07, 1.0, -1.0, -1.4901156930591242e-07, -2.3841855067985307e-07, -1.0, -1.4901156930591242e-07, -2.3841855067985307e-07, -1.0, -1.4901156930591242e-07, -2.3841855067985307e-07, 2.6822084464583895e-07, 2.3841852225814364e-07, -1.0, 2.6822084464583895e-07, 2.3841852225814364e-07, -1.0, 2.6822084464583895e-07, 2.3841852225814364e-07, -1.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 5.96046660916727e-08, 1.0, -0.0, 5.96046660916727e-08, 1.0, -0.0, 5.96046660916727e-08, 1.0, -0.0, 1.0, 3.2782537573439186e-07, 5.960464477539062e-07, 1.0, 3.2782537573439186e-07, 5.960464477539062e-07, 1.0, 3.2782537573439186e-07, 5.960464477539062e-07, -4.768372150465439e-07, 1.1920927533992653e-07, 1.0, -4.768372150465439e-07, 1.1920927533992653e-07, 1.0, -4.768372150465439e-07, 1.1920927533992653e-07, 1.0, -1.0, -1.1920931797249068e-07, -2.3841863594498136e-07, -1.0, -1.1920931797249068e-07, -2.3841863594498136e-07, -1.0, -1.1920931797249068e-07, -2.3841863594498136e-07, 2.0861631355728605e-07, 8.940701690107744e-08, -1.0, 2.0861631355728605e-07, 8.940701690107744e-08, -1.0, 2.0861631355728605e-07, 8.940701690107744e-08, -1.0),
+		FloatArray(0.0, 0.0, 0.9999999403953552, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.9999999403953552, 1.0, -1.0, 0.0, -2.6822084464583895e-07, 1.0, -1.0, 0.0, -2.6822084464583895e-07, 1.0, -1.0, 0.0, -2.6822084464583895e-07, 1.0, 2.384185791015625e-07, 1.0, 2.384185791015625e-07, 1.0, 2.384185791015625e-07, 1.0, 2.384185791015625e-07, 1.0, 2.384185791015625e-07, 1.0, 2.384185791015625e-07, 1.0, -3.2782557468635787e-07, 1.0, 4.7683712978141557e-07, 1.0, -3.2782557468635787e-07, 1.0, 4.7683712978141557e-07, 1.0, -3.2782557468635787e-07, 1.0, 4.7683712978141557e-07, 1.0, -1.4901162614933128e-07, 1.0, 2.384185791015625e-07, 1.0, -1.4901162614933128e-07, 0.9999999403953552, 2.3841856489070778e-07, 1.0, -1.4901162614933128e-07, 1.0, 2.384185791015625e-07, 1.0, -2.384185791015625e-07, -1.0, -2.384185791015625e-07, 1.0, -2.384185791015625e-07, -1.0, -2.384185791015625e-07, 1.0, -2.384185791015625e-07, -1.0, -2.384185791015625e-07, 1.0, -1.7881389169360773e-07, 0.0, 0.9999999403953552, 1.0, -1.7881390590446244e-07, 0.0, 1.0, 1.0, -1.7881390590446244e-07, 0.0, 1.0, 1.0, -1.0, 5.960467319710006e-08, -4.1723259869286267e-07, 1.0, -1.0, 5.960467319710006e-08, -4.1723259869286267e-07, 1.0, -0.9999999403953552, 5.96046660916727e-08, -4.1723257027115324e-07, 1.0, -3.2782554626464844e-07, 1.0, 2.384185791015625e-07, 1.0, -3.2782554626464844e-07, 1.0, 2.384185791015625e-07, 1.0, -3.2782554626464844e-07, 1.0, 2.384185791015625e-07, 1.0, -1.1920927533992653e-07, 1.0, -1.192093321833454e-07, 1.0, -1.1920927533992653e-07, 1.0, -1.192093321833454e-07, 1.0, -1.1920926823449918e-07, 1.0, -1.192093321833454e-07, 1.0, -1.1920928955078125e-07, 1.0, -8.94069742685133e-08, 1.0, -1.1920928955078125e-07, 1.0, -8.940696716308594e-08, 1.0, -1.1920928955078125e-07, 1.0, -8.940696716308594e-08, 1.0, 1.7881390590446244e-07, -1.0, -8.94069742685133e-08, 1.0, 1.7881390590446244e-07, -0.9999999403953552, -8.94069742685133e-08, 1.0, 1.7881392011531716e-07, -1.0, -8.940698137394065e-08, 1.0),
+		null, ; no Vertex Colors,
+		Vector2Array(1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0),
+		null, ; No UV2,
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 14, 13, 15, 17, 16, 18, 20, 19, 21, 23, 22, 24, 26, 25, 27, 29, 28, 30, 32, 31, 33, 35, 34)
+	],
+	"morph_arrays":[]
+}
+
+[node type="Spatial" name="Scene"]
+
+
+[node name="Cube" type="MeshInstance" parent="."]
+
+mesh = SubResource(1)
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 0.0, 0.0, -0.0 )
+
+[node name="Lamp" type="OmniLight" parent="."]
+
+omni_range = 29.999982833862305
+shadow_enabled = true
+light_color = Color( 1.0, 1.0, 1.0, 1.0 )
+transform = Transform(  -0.29086464643478394, -0.7711008191108704, 0.5663931369781494, -0.05518905818462372, 0.6045246720314026, 0.7946722507476807, -0.9551711678504944, 0.199883371591568, -0.21839118003845215, 4.076245307922363, 5.903861999511719, -1.0054539442062378 )
+light_negative = false
+light_specular = 1.0
+light_energy = 1.0
+
+[node name="Camera" type="Camera" parent="."]
+
+far = 100.0
+near = 0.10000000149011612
+projection = 0
+fov = 49.13434207760448
+transform = Transform(  0.6859206557273865, -0.32401350140571594, 0.6515582203865051, 0.0, 0.8953956365585327, 0.44527143239974976, -0.7276763319969177, -0.3054208755493164, 0.6141703724861145, 7.481131553649902, 5.34366512298584, 6.5076398849487305 )

File diff suppressed because it is too large
+ 7 - 0
tests/reference-exports/parented_meshes.escn


File diff suppressed because it is too large
+ 4 - 0
tests/reference-exports/physics.escn


+ 81 - 0
tests/reference-exports/simple_materials.escn

@@ -0,0 +1,81 @@
+[gd_scene load_steps=1 format=2]
+
+[sub_resource id=1 type="SpatialMaterial"]
+
+flags_unshaded = false
+flags_vertex_lighting = false
+flags_transparent = false
+vertex_color_use_as_albedo = false
+albedo_color = Color( 0.013005342334508896, 0.8000000715255737, 0.0, 1.0 )
+subsurf_scatter_enabled = false
+
+[sub_resource id=2 type="SpatialMaterial"]
+
+flags_unshaded = false
+flags_vertex_lighting = false
+flags_transparent = false
+vertex_color_use_as_albedo = false
+albedo_color = Color( 0.800000011920929, 0.800000011920929, 0.800000011920929, 1.0 )
+subsurf_scatter_enabled = false
+
+[sub_resource id=3 type="ArrayMesh"]
+
+surfaces/0 = {
+	"material":SubResource(1),
+	"primitive":4,
+	"arrays":[
+		Vector3Array(1.0, -1.0, 1.0, -0.9999996423721313, -1.0, -1.0000003576278687, 1.0, -1.0, -0.9999999403953552, -0.9999999403953552, 1.0, -1.0, 0.9999993443489075, 1.0, 1.0000005960464478, 1.0000004768371582, 1.0, -0.999999463558197, 0.9999993443489075, 1.0, 1.0000005960464478, -1.0000001192092896, -1.0, 0.9999998211860657, 1.0, -1.0, 1.0, -1.0000001192092896, -1.0, 0.9999998211860657, -0.9999999403953552, 1.0, -1.0, -0.9999996423721313, -1.0, -1.0000003576278687, 1.0, -1.0, -0.9999999403953552, -0.9999999403953552, 1.0, -1.0, 1.0000004768371582, 1.0, -0.999999463558197, 1.0, -1.0, 1.0, -1.0000001192092896, -1.0, 0.9999998211860657, -0.9999996423721313, -1.0, -1.0000003576278687, -0.9999999403953552, 1.0, -1.0, -1.0000003576278687, 1.0, 0.9999996423721313, 0.9999993443489075, 1.0, 1.0000005960464478, 0.9999993443489075, 1.0, 1.0000005960464478, -1.0000003576278687, 1.0, 0.9999996423721313, -1.0000001192092896, -1.0, 0.9999998211860657, -1.0000001192092896, -1.0, 0.9999998211860657, -1.0000003576278687, 1.0, 0.9999996423721313, -0.9999999403953552, 1.0, -1.0, 1.0, -1.0, -0.9999999403953552, -0.9999996423721313, -1.0, -1.0000003576278687, -0.9999999403953552, 1.0, -1.0),
+		Vector3Array(2.980232949312267e-08, -1.0, -0.0, 2.980232949312267e-08, -1.0, -0.0, 2.980232949312267e-08, -1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, -8.940696716308594e-08, -4.76837158203125e-07, 1.0, -8.940696716308594e-08, -4.76837158203125e-07, 1.0, -8.940696716308594e-08, -4.76837158203125e-07, 1.0, -1.0, -1.4901156930591242e-07, -2.3841855067985307e-07, -1.0, -1.4901156930591242e-07, -2.3841855067985307e-07, -1.0, -1.4901156930591242e-07, -2.3841855067985307e-07, 2.6822084464583895e-07, 2.3841852225814364e-07, -1.0, 2.6822084464583895e-07, 2.3841852225814364e-07, -1.0, 2.6822084464583895e-07, 2.3841852225814364e-07, -1.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 5.96046660916727e-08, 1.0, -0.0, 5.96046660916727e-08, 1.0, -0.0, 5.96046660916727e-08, 1.0, -0.0, -4.768372150465439e-07, 1.1920927533992653e-07, 1.0, -4.768372150465439e-07, 1.1920927533992653e-07, 1.0, -4.768372150465439e-07, 1.1920927533992653e-07, 1.0, -1.0, -1.1920931797249068e-07, -2.3841863594498136e-07, -1.0, -1.1920931797249068e-07, -2.3841863594498136e-07, -1.0, -1.1920931797249068e-07, -2.3841863594498136e-07, 2.0861631355728605e-07, 8.940701690107744e-08, -1.0, 2.0861631355728605e-07, 8.940701690107744e-08, -1.0, 2.0861631355728605e-07, 8.940701690107744e-08, -1.0),
+		null, ; No Tangents,
+		null, ; no Vertex Colors,
+		null, ; No UV1,
+		null, ; No UV2,
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 14, 13, 15, 17, 16, 18, 20, 19, 21, 23, 22, 24, 26, 25, 27, 29, 28)
+	],
+	"morph_arrays":[]
+}
+
+surfaces/1 = {
+	"material":SubResource(2),
+	"primitive":4,
+	"arrays":[
+		Vector3Array(1.0000004768371582, 1.0, -0.999999463558197, 1.0, -1.0, 1.0, 1.0, -1.0, -0.9999999403953552, 1.0000004768371582, 1.0, -0.999999463558197, 0.9999993443489075, 1.0, 1.0000005960464478, 1.0, -1.0, 1.0),
+		Vector3Array(1.0, -2.384185791015625e-07, -0.0, 1.0, -2.384185791015625e-07, -0.0, 1.0, -2.384185791015625e-07, -0.0, 1.0, 3.2782537573439186e-07, 5.960464477539062e-07, 1.0, 3.2782537573439186e-07, 5.960464477539062e-07, 1.0, 3.2782537573439186e-07, 5.960464477539062e-07),
+		null, ; No Tangents,
+		null, ; no Vertex Colors,
+		null, ; No UV1,
+		null, ; No UV2,
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 3, 5, 4)
+	],
+	"morph_arrays":[]
+}
+
+[node type="Spatial" name="Scene"]
+
+
+[node name="Cube" type="MeshInstance" parent="."]
+
+mesh = SubResource(3)
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 0.0, 0.0, -0.0 )
+
+[node name="Lamp" type="OmniLight" parent="."]
+
+omni_range = 29.999982833862305
+shadow_enabled = true
+light_color = Color( 1.0, 1.0, 1.0, 1.0 )
+transform = Transform(  -0.29086464643478394, -0.7711008191108704, 0.5663931369781494, -0.05518905818462372, 0.6045246720314026, 0.7946722507476807, -0.9551711678504944, 0.199883371591568, -0.21839118003845215, 4.076245307922363, 5.903861999511719, -1.0054539442062378 )
+light_negative = false
+light_specular = 1.0
+light_energy = 1.0
+
+[node name="Camera" type="Camera" parent="."]
+
+far = 100.0
+near = 0.10000000149011612
+projection = 0
+fov = 49.13434207760448
+transform = Transform(  0.6859206557273865, -0.32401350140571594, 0.6515582203865051, 0.0, 0.8953956365585327, 0.44527143239974976, -0.7276763319969177, -0.3054208755493164, 0.6141703724861145, 7.481131553649902, 5.34366512298584, 6.5076398849487305 )

+ 27 - 0
tests/reference-exports/tangent_test.escn

@@ -0,0 +1,27 @@
+[gd_scene load_steps=1 format=2]
+
+[sub_resource id=1 type="ArrayMesh"]
+
+surfaces/0 = {
+	"primitive":4,
+	"arrays":[
+		Vector3Array(1.0, 0.8924096822738647, -1.75, -1.0, 1.0, -2.0, -1.0, 0.8924096822738647, -1.75, -1.0, 0.8924096822738647, 1.75, 1.0, 1.0, 2.0, 1.0, 0.8924096822738647, 1.75, -1.0, 0.0, -0.0, 1.0, 0.14240968227386475, 0.25, 1.0, 0.0, -0.0, -1.0, 0.14240968227386475, 0.25, 1.0, 0.37984538078308105, 0.5, -1.0, 0.37984538078308105, 0.5, 1.0, 0.7216095328330994, 0.75, -1.0, 0.7216095328330994, 0.75, 1.0, 1.167702078819275, 1.0, -1.0, 1.167702078819275, 1.0, 1.0, 0.9716095328330994, 1.25, 1.0, 1.167702078819275, 1.0, -1.0, 0.9716095328330994, 1.25, 1.0, 0.879845380783081, 1.5, -1.0, 0.879845380783081, 1.5, 1.0, 0.0, -0.0, -1.0, 0.14240968227386475, -0.25, -1.0, 0.0, -0.0, 1.0, 0.14240968227386475, -0.25, -1.0, 0.37984538078308105, -0.5, 1.0, 0.37984538078308105, -0.5, -1.0, 0.7216095328330994, -0.75, 1.0, 0.7216095328330994, -0.75, -1.0, 1.167702078819275, -1.0, 1.0, 1.167702078819275, -1.0, -1.0, 0.9716095328330994, -1.25, -1.0, 1.167702078819275, -1.0, 1.0, 0.9716095328330994, -1.25, -1.0, 0.879845380783081, -1.5, 1.0, 0.879845380783081, -1.5, 1.0, 1.0, -2.0, -1.0, 1.0, 2.0, -1.0, 1.167702078819275, 1.0, 1.0, 1.167702078819275, -1.0),
+		Vector3Array(0.0, 0.9740505218505859, 0.2263306975364685, 0.0, 0.9185487627983093, 0.39530783891677856, 0.0, 0.9740505218505859, 0.22633066773414612, 0.0, 0.9740505218505859, -0.2263306975364685, 0.0, 0.9185487627983093, -0.39530783891677856, 0.0, 0.9740505218505859, -0.22633066773414612, 0.0, 0.8689122796058655, -0.4949660897254944, 0.0, 0.8028644919395447, -0.5961616039276123, 0.0, 0.8689122796058655, -0.4949660897254944, 0.0, 0.8028644323348999, -0.5961614847183228, 0.0, 0.6604078412055969, -0.7509071826934814, 0.0, 0.6604078412055969, -0.7509071230888367, 0.0, 0.5406267642974854, -0.8412624597549438, 0.0, 0.5406267642974854, -0.8412624597549438, 0.0, 0.48888346552848816, -0.8723491430282593, 0.0, 0.7868317365646362, 0.6171674132347107, 0.0, 0.8734937906265259, 0.4868352711200714, 0.0, 0.7868318557739258, 0.6171674728393555, 0.0, 0.8734937906265259, 0.48683539032936096, 0.0, 0.9886532425880432, 0.1502160131931305, 0.0, 0.9886532425880432, 0.1502160280942917, 0.0, 0.8689122796058655, 0.4949660897254944, 0.0, 0.8028644919395447, 0.5961616039276123, 0.0, 0.8689122796058655, 0.4949660897254944, 0.0, 0.8028644323348999, 0.5961614847183228, 0.0, 0.6604078412055969, 0.7509071826934814, 0.0, 0.6604078412055969, 0.7509071230888367, 0.0, 0.5406267642974854, 0.8412624597549438, 0.0, 0.5406267642974854, 0.8412624597549438, 0.0, 0.48888346552848816, 0.8723491430282593, 0.0, 0.7868317365646362, -0.6171674132347107, 0.0, 0.8734937906265259, -0.4868352711200714, 0.0, 0.7868318557739258, -0.6171674728393555, 0.0, 0.8734937906265259, -0.48683539032936096, 0.0, 0.9886532425880432, -0.1502160131931305, 0.0, 0.9886532425880432, -0.1502160280942917, 0.0, 0.9185487627983093, 0.3953078091144562, 0.0, 0.9185487627983093, -0.3953078091144562, 0.0, 0.48888349533081055, -0.8723491430282593, 0.0, 0.48888349533081055, 0.8723491430282593),
+		FloatArray(1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 0.9999999403953552, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 0.9999999403953552, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0),
+		null, ; no Vertex Colors,
+		Vector2Array(1.0, 0.12500011920928955, 0.0, 0.0, 0.0, 0.12500011920928955, 0.0, 0.8750001788139343, 1.0, 1.0, 1.0, 0.8750001788139343, 0.0, 0.0, 1.0, 0.12500011920928955, 1.0, 0.0, 0.0, 0.12500011920928955, 1.0, 0.25000011920928955, 0.0, 0.25000011920928955, 1.0, 0.3749999403953552, 0.0, 0.3749999403953552, 1.0, 0.5000000596046448, 0.0, 0.5000000596046448, 1.0, 0.6250000596046448, 1.0, 0.5000000596046448, 0.0, 0.6250000596046448, 1.0, 0.7500000298023224, 0.0, 0.7500000298023224, 1.0, 1.0, 0.0, 0.8749998807907104, 0.0, 1.0, 1.0, 0.8749998807907104, 0.0, 0.750000074505806, 1.0, 0.750000074505806, 0.0, 0.6249999701976776, 1.0, 0.6249999701976776, 0.0, 0.4999998211860657, 1.0, 0.4999998211860657, 0.0, 0.3750000596046448, 0.0, 0.4999998211860657, 1.0, 0.3750000596046448, 0.0, 0.2500002384185791, 1.0, 0.2500002384185791, 1.0, 0.0, 0.0, 1.0, 0.0, 0.5000000596046448, 1.0, 0.4999998211860657),
+		null, ; No UV2,
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 7, 10, 11, 10, 12, 13, 12, 14, 15, 17, 16, 18, 16, 19, 20, 19, 5, 21, 23, 22, 24, 22, 25, 26, 25, 27, 28, 27, 29, 30, 32, 31, 33, 31, 34, 35, 34, 2, 0, 1, 36, 3, 4, 37, 6, 7, 9, 9, 10, 11, 11, 12, 13, 13, 14, 38, 15, 16, 18, 18, 19, 20, 20, 5, 3, 21, 22, 24, 24, 25, 26, 26, 27, 28, 28, 29, 39, 30, 31, 33, 33, 34, 35, 35, 2, 0)
+	],
+	"morph_arrays":[]
+}
+
+[node type="Spatial" name="Scene"]
+
+
+[node name="Plane" type="MeshInstance" parent="."]
+
+mesh = SubResource(1)
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 0.0, 0.0, -0.0 )

+ 99 - 0
tests/reference-exports/uv_testing.escn

@@ -0,0 +1,99 @@
+[gd_scene load_steps=1 format=2]
+
+[sub_resource id=1 type="ArrayMesh"]
+
+surfaces/0 = {
+	"primitive":4,
+	"arrays":[
+		Vector3Array(-1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0),
+		Vector3Array(-1.0, 0.0, -0.0, -1.0, 0.0, -0.0, -1.0, 0.0, -0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, -1.0, 0.0, -0.0, 0.0, 0.0, -1.0, 1.0, 0.0, -0.0, 0.0, 0.0, 1.0, 0.0, -1.0, -0.0, 0.0, 1.0, -0.0),
+		FloatArray(0.0, -1.0, 4.4703494239684005e-08, 1.0, 0.0, -1.0, 4.4703494239684005e-08, 1.0, 0.0, -1.0, -0.0, 1.0, -1.788139627478813e-07, -1.0, -0.0, 1.0, -1.788139627478813e-07, -1.0, -0.0, 1.0, -1.788139627478813e-07, -1.0, -0.0, 1.0, 0.0, -1.0, -2.6822095833267667e-07, 1.0, 0.0, -1.0, -2.6822095833267667e-07, 1.0, 0.0, -1.0, -2.6822095833267667e-07, 1.0, -1.0, -1.4901161193847656e-07, -0.0, 1.0, -1.0, -1.4901161193847656e-07, -0.0, 1.0, -1.0, -1.788139627478813e-07, -0.0, 1.0, -1.0, 0.0, -4.470350134511136e-08, 1.0, -1.0, 0.0, -4.470350134511136e-08, 1.0, -1.0, 0.0, -0.0, 1.0, -8.940698847936801e-08, 0.0, -1.0, 1.0, -8.940698847936801e-08, 0.0, -1.0, 1.0, -1.7881397695873602e-07, 0.0, -1.0, 1.0, 0.0, -1.0, 8.940698847936801e-08, 1.0, -1.788139627478813e-07, -1.0, -0.0, 1.0, 0.0, -1.0, -2.6822095833267667e-07, 1.0, -1.0, -1.1920926823449918e-07, -0.0, 1.0, -1.0, 0.0, -8.940700269022273e-08, 1.0, 0.0, 0.0, -1.0, 1.0),
+		null, ; no Vertex Colors,
+		Vector2Array(1.0, 0.0, 2.9802322387695312e-08, 1.0, 1.0, 0.9999999701976776, 1.0, 0.0, 2.9802322387695312e-08, 1.0, 1.0, 0.9999999701976776, 1.0, 0.0, 2.9802322387695312e-08, 1.0, 1.0, 0.9999999701976776, 1.0, 0.0, 2.9802322387695312e-08, 1.0, 1.0, 0.9999999701976776, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0000000596046448, 1.0, 0.0, -5.960464477539063e-08, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0),
+		Vector2Array(0.33333346247673035, 0.3333333730697632, 0.6666666865348816, 0.6666666567325592, 0.6666667461395264, 0.3333333730697632, 3.973642037635727e-08, 0.3333333134651184, 0.333333283662796, 0.6666666567325592, 0.3333333432674408, 0.3333333730697632, 1.291433733285885e-07, 0.6666666567325592, 0.3333333134651184, 1.0, 0.33333340287208557, 0.6666667461395264, 0.33333340287208557, 0.9999999602635832, 0.6666667461395264, 0.6666667461395264, 0.33333346247673035, 0.6666666865348816, 0.6666667461395264, 0.6666667759418488, 1.0, 1.0, 1.0, 0.6666667759418488, 0.333333283662796, 5.960464477539063e-08, 0.0, 0.33333325386047363, 0.33333325386047363, 0.3333333134651184, 0.33333340287208557, 0.6666666269302368, 0.0, 0.6666665971279144, 0.0, 0.9999999105930613, 0.6666666865348816, 1.0, 0.6666667461395264, 0.9999999701976865, 4.967052547044659e-08, 5.960464477539063e-08),
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 14, 13, 15, 17, 16, 0, 1, 18, 3, 4, 19, 6, 7, 20, 9, 10, 21, 12, 13, 22, 15, 16, 23)
+	],
+	"morph_arrays":[]
+}
+
+
+[sub_resource id=2 type="ArrayMesh"]
+
+surfaces/0 = {
+	"primitive":4,
+	"arrays":[
+		Vector3Array(1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0),
+		Vector3Array(0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0),
+		FloatArray(1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0),
+		null, ; no Vertex Colors,
+		Vector2Array(0.27497005462646484, 0.27496999502182007, -0.02496999502182007, -0.024970054626464844, -0.02496999502182007, 0.27496999502182007, 0.27497005462646484, -0.024970054626464844),
+		Vector2Array(1.0249700546264648, 0.27496999502182007, 0.7250300049781799, -0.024970054626464844, 0.7250300049781799, 0.27496999502182007, 1.0249700546264648, -0.024970054626464844),
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 0, 1, 3)
+	],
+	"morph_arrays":[]
+}
+
+
+[sub_resource id=3 type="ArrayMesh"]
+
+surfaces/0 = {
+	"primitive":4,
+	"arrays":[
+		Vector3Array(-1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0),
+		Vector3Array(-1.0, 0.0, -0.0, -1.0, 0.0, -0.0, -1.0, 0.0, -0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 1.0, 0.0, -0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, -1.0, 0.0, -0.0, 0.0, 0.0, -1.0, 1.0, 0.0, -0.0, 0.0, 0.0, 1.0, 0.0, -1.0, -0.0, 0.0, 1.0, -0.0),
+		FloatArray(0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, -1.0, 0.0, -0.0, 1.0, -1.0, 0.0, -0.0, 1.0, -1.0, 0.0, -0.0, 1.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0, -1.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, -2.980232594040899e-08, 0.0, 1.0, 1.0, -2.980232594040899e-08, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, -1.0, 0.0, -0.0, 1.0, 0.0, 0.0, -1.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, -5.960465188081798e-08, 0.0, 1.0, 1.0),
+		null, ; no Vertex Colors,
+		Vector2Array(1.0, 0.0, 2.9802322387695312e-08, 1.0, 1.0, 0.9999999701976776, 1.0, 0.0, 2.9802322387695312e-08, 1.0, 1.0, 0.9999999701976776, 1.0, 0.0, 2.9802322387695312e-08, 1.0, 1.0, 0.9999999701976776, 1.0, 0.0, 2.9802322387695312e-08, 1.0, 1.0, 0.9999999701976776, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0000000596046448, 1.0, 0.0, -5.960464477539063e-08, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0),
+		null, ; No UV2,
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 14, 13, 15, 17, 16, 0, 1, 18, 3, 4, 19, 6, 7, 20, 9, 10, 21, 12, 13, 22, 15, 16, 23)
+	],
+	"morph_arrays":[]
+}
+
+
+[sub_resource id=4 type="ArrayMesh"]
+
+surfaces/0 = {
+	"primitive":4,
+	"arrays":[
+		Vector3Array(2.0, 0.0, 1.0, -2.0, 0.0, -2.0, -2.0, 0.0, 1.0, 1.0, 0.0, 2.0, 2.0, 0.0, 2.0, 2.0, 0.0, -2.0, -1.0, 0.0, 2.0),
+		Vector3Array(0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0, 0.0, 1.0, -0.0),
+		FloatArray(1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0, 1.0, 0.0, -0.0, 1.0),
+		null, ; no Vertex Colors,
+		Vector2Array(1.0, 0.7500000596046448, 0.0, 0.0, 0.0, 0.7500000596046448, 0.7500000596046448, 1.0, 1.0, 1.0, 1.0, 0.0, 0.25, 1.0),
+		null, ; No UV2,
+		null, ; No Bones,
+		null, ; No Weights,
+		IntArray(0, 2, 1, 2, 0, 3, 0, 4, 3, 0, 1, 5, 2, 3, 6)
+	],
+	"morph_arrays":[]
+}
+
+[node type="Spatial" name="Scene"]
+
+
+[node name="Cube.001" type="MeshInstance" parent="."]
+
+mesh = SubResource(1)
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 4.0, 0.0, 4.0 )
+
+[node name="MultiUV" type="MeshInstance" parent="."]
+
+mesh = SubResource(2)
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 0.0, 0.0, 4.0 )
+
+[node name="Cube" type="MeshInstance" parent="."]
+
+mesh = SubResource(3)
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 4.0, 0.0, -0.0 )
+
+[node name="Plane" type="MeshInstance" parent="."]
+
+mesh = SubResource(4)
+transform = Transform(  1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 0.0, 0.0, -0.0 )

File diff suppressed because it is too large
+ 7 - 0
tests/reference-exports/vertex_color.escn


+ 29 - 21
tests/scenes/export_blends.py

@@ -8,31 +8,39 @@ from io_scene_godot import export_godot
 
 
 
 
 def export_escn(out_file):
 def export_escn(out_file):
-	"""Fake the export operator call"""
-	class op:
-		def __init__(self):
-			self.report = print
-			
-	res = export_godot.save(op(), bpy.context, out_file, 
-		object_types={"EMPTY", "CAMERA", "LAMP", "ARMATURE", "MESH", "CURVE"},
-		use_active_layers=False,
-		use_export_selected=False,
-		use_mesh_modifiers=True,
-		material_search_paths = 'PROJECT_DIR'
-	)
+    """Fake the export operator call"""
+    class op:
+        def __init__(self):
+            self.report = print
+            
+    res = export_godot.save(op(), bpy.context, out_file, 
+        object_types={"EMPTY", "CAMERA", "LAMP", "ARMATURE", "MESH", "CURVE"},
+        use_active_layers=False,
+        use_export_selected=False,
+        use_mesh_modifiers=True,
+        material_search_paths = 'PROJECT_DIR'
+    )
 
 
 
 
 
 
 def main():
 def main():
-	target_dir = os.path.join(os.getcwd(), "tests/scenes")
-	for file_name in os.listdir(target_dir):
-		full_path = os.path.join(target_dir, file_name)
-		if full_path.endswith(".blend"):
-			print("Exporting {}".format(full_path))
-			bpy.ops.wm.open_mainfile(filepath=full_path)
-			export_escn(full_path.replace('.blend', '.escn'))
-			print("Exported")
+    target_dir = os.path.join(os.getcwd(), "tests/scenes")
+    for file_name in os.listdir(target_dir):
+        full_path = os.path.join(target_dir, file_name)
+        if full_path.endswith(".blend"):
+            print("Exporting {}".format(full_path))
+            bpy.ops.wm.open_mainfile(filepath=full_path)
+            
+            out_path, blend_name = os.path.split(full_path)
+            out_path = os.path.normpath(os.path.join(out_path, '../exports/'))
+            out_path = os.path.join(
+                out_path, 
+                blend_name.replace('.blend', '.escn')
+                )
+            print(out_path)
+            export_escn(out_path)
+            print("Exported")
 
 
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":
-	main()
+    main()

BIN
tests/scenes/simple_materials.blend


+ 1 - 1
tests/scenes/just_mesh.tscn → tests/viewers/just_mesh.tscn

@@ -1,6 +1,6 @@
 [gd_scene load_steps=2 format=2]
 [gd_scene load_steps=2 format=2]
 
 
-[ext_resource path="res://scenes/just_mesh.escn" type="PackedScene" id=1]
+[ext_resource path="res://exports/just_mesh.escn" type="PackedScene" id=1]
 
 
 [node name="Scene Root" index="0" instance=ExtResource( 1 )]
 [node name="Scene Root" index="0" instance=ExtResource( 1 )]
 
 

+ 3 - 1
tests/scenes/tangent_test.tscn → tests/viewers/tangent_test.tscn

@@ -1,6 +1,8 @@
 [gd_scene load_steps=4 format=2]
 [gd_scene load_steps=4 format=2]
 
 
-[ext_resource path="res://scenes/tangent_test.escn" type="PackedScene" id=1]
+
+
+[ext_resource path="res://exports/tangent_test.escn" type="PackedScene" id=1]
 [ext_resource path="res://uvtester_normals.jpg" type="Texture" id=2]
 [ext_resource path="res://uvtester_normals.jpg" type="Texture" id=2]
 
 
 [sub_resource type="SpatialMaterial" id=1]
 [sub_resource type="SpatialMaterial" id=1]

+ 1 - 1
tests/scenes/uv_testing.tscn → tests/viewers/uv_testing.tscn

@@ -1,6 +1,6 @@
 [gd_scene load_steps=4 format=2]
 [gd_scene load_steps=4 format=2]
 
 
-[ext_resource path="res://scenes/uv_testing.escn" type="PackedScene" id=1]
+[ext_resource path="res://exports/uv_testing.escn" type="PackedScene" id=1]
 [ext_resource path="res://multi_uv_tester.tres" type="Material" id=2]
 [ext_resource path="res://multi_uv_tester.tres" type="Material" id=2]
 [ext_resource path="res://uv_tester_material.tres" type="Material" id=3]
 [ext_resource path="res://uv_tester_material.tres" type="Material" id=3]
 
 

+ 1 - 1
tests/scenes/vertex_color.tscn → tests/viewers/vertex_color.tscn

@@ -1,6 +1,6 @@
 [gd_scene load_steps=3 format=2]
 [gd_scene load_steps=3 format=2]
 
 
-[ext_resource path="res://scenes/vertex_color.escn" type="PackedScene" id=1]
+[ext_resource path="res://exports/vertex_color.escn" type="PackedScene" id=1]
 
 
 [sub_resource type="SpatialMaterial" id=1]
 [sub_resource type="SpatialMaterial" id=1]
 
 

Some files were not shown because too many files changed in this diff