From 8aa1b14c4485a3058bf332d2389bdef289256dee Mon Sep 17 00:00:00 2001
From: Campbell Barton <ideasman42@gmail.com>
Date: Mon, 3 Oct 2011 18:10:39 +0000
Subject: [PATCH] fix [#28297] problem exporting large .3ds files

objects with too large arrays will be skipped.
---
 io_scene_3ds/export_3ds.py | 64 ++++++++++++++++++++++++--------------
 1 file changed, 41 insertions(+), 23 deletions(-)

diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py
index 125e9a8b5..151fe0df6 100644
--- a/io_scene_3ds/export_3ds.py
+++ b/io_scene_3ds/export_3ds.py
@@ -273,6 +273,9 @@ class _3ds_face(object):
     def get_size(self):
         return 4 * SZ_SHORT
 
+    # no need to validate every face vert. the oversized array will
+    # catch this problem
+
     def write(self, file):
         # The last zero is only used by 3d studio
         file.write(struct.pack("<4H", self.vindex[0], self.vindex[1], self.vindex[2], 0))
@@ -300,9 +303,11 @@ class _3ds_array(object):
     def get_size(self):
         return self.size
 
+    def validate(self):
+        return len(self.values) <= 65535
+
     def write(self, file):
         _3ds_ushort(len(self.values)).write(file)
-        #_3ds_uint(len(self.values)).write(file)
         for value in self.values:
             value.write(file)
 
@@ -333,13 +338,10 @@ class _3ds_named_variable(object):
 
     def dump(self, indent):
         if self.value is not None:
-            spaces = ""
-            for i in range(indent):
-                spaces += "  "
-            if (self.name != ""):
-                print(spaces, self.name, " = ", self.value)
-            else:
-                print(spaces, "[unnamed]", " = ", self.value)
+            print(indent * " ",
+                  self.name if self.name else "[unnamed]",
+                  " = ",
+                  self.value)
 
 
 #the chunk class
@@ -378,6 +380,19 @@ class _3ds_chunk(object):
         self.size.value = tmpsize
         return self.size.value
 
+    def validate(self):
+        for var in self.variables:
+            func = getattr(var.value, "validate", None)
+            if (func is not None) and not func():
+                return False
+
+        for chunk in self.subchunks:
+            func = getattr(chunk, "validate", None)
+            if (func is not None) and not func():
+                return False
+
+        return True
+
     def write(self, file):
         '''Write the chunk to a file.
 
@@ -395,10 +410,9 @@ class _3ds_chunk(object):
 
         Dump is used for debugging purposes, to dump the contents of a chunk to the standard output.
         Uses the dump function of the named variables and the subchunks to do the actual work.'''
-        spaces = ""
-        for i in range(indent):
-            spaces += "  "
-        print(spaces, "ID=", hex(self.ID.value), "size=", self.get_size())
+        print(indent * " ",
+              "ID=%r" % hex(self.ID.value),
+              "size=%r" % self.get_size())
         for variable in self.variables:
             variable.dump(indent + 1)
         for subchunk in self.subchunks:
@@ -472,14 +486,14 @@ def make_material_chunk(material, image):
     material_chunk.add_subchunk(name)
 
     if not material:
-        material_chunk.add_subchunk(make_material_subchunk(MATAMBIENT, (0, 0, 0)))
-        material_chunk.add_subchunk(make_material_subchunk(MATDIFFUSE, (.8, .8, .8)))
-        material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, (1, 1, 1)))
+        material_chunk.add_subchunk(make_material_subchunk(MATAMBIENT, (0.0, 0.0, 0.0)))
+        material_chunk.add_subchunk(make_material_subchunk(MATDIFFUSE, (0.8, 0.8, 0.8)))
+        material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, (1.0, 1.0, 1.0))
 
     else:
-        material_chunk.add_subchunk(make_material_subchunk(MATAMBIENT, [a * material.ambient for a in material.diffuse_color]))
-        material_chunk.add_subchunk(make_material_subchunk(MATDIFFUSE, material.diffuse_color))
-        material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, material.specular_color))
+        material_chunk.add_subchunk(make_material_subchunk(MATAMBIENT, (material.ambient * material.diffuse_color)[:]))
+        material_chunk.add_subchunk(make_material_subchunk(MATDIFFUSE, material.diffuse_color[:]))
+        material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, material.specular_color[:]))
 
         images = get_material_images(material)  # can be None
         if image:
@@ -949,8 +963,7 @@ def save(operator,
                 mat_ls_len = len(mat_ls)
 
                 # get material/image tuples.
-                if len(data.uv_textures):
-# 				if data.faceUV:
+                if data.uv_textures:
                     if not mat_ls:
                         mat = mat_name = None
 
@@ -976,9 +989,7 @@ def save(operator,
                     # Why 0 Why!
                     for f in data.faces:
                         if f.material_index >= mat_ls_len:
-# 						if f.mat >= mat_ls_len:
                             f.material_index = 0
-                            # f.mat = 0
 
         if free:
             free_derived_objects(ob)
@@ -1007,7 +1018,14 @@ def save(operator,
 
         # make a mesh chunk out of the mesh:
         object_chunk.add_subchunk(make_mesh_chunk(blender_mesh, matrix, materialDict))
-        object_info.add_subchunk(object_chunk)
+
+        # ensure the mesh has no over sized arrays
+        # skip ones that do!, otherwise we cant write since the array size wont
+        # fit into USHORT.
+        if object_chunk.validate():
+            object_info.add_subchunk(object_chunk)
+        else:
+            operator.report({'WARNING'}, "Object %r can't be written into a 3DS file")
 
         ''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX
         # make a kf object node for the object:
-- 
GitLab