addons-contrib: objects.link/unlink syntax update
[blender-addons-contrib.git] / io_scene_map / export_map.py
index 5c868d8..cce1f26 100644 (file)
@@ -25,6 +25,10 @@ import os
 import mathutils
 from mathutils import Vector
 
+from contextlib import redirect_stdout
+import io
+stdout = io.StringIO()
+
 # TODO, make options
 PREF_SCALE = 1
 PREF_FACE_THICK = 0.1
@@ -272,7 +276,7 @@ def write_quake_brush_face(fw, ob, face):
 
     # reuse face vertices
     f_vertices = [me.vertices[vi] for vi in face.vertices]
-  
+
     # original verts as tuples for writing
     orig_vco = tuple(round_vec(v.co) for v in f_vertices)
 
@@ -338,7 +342,7 @@ def write_doom_brush(fw, ob, me):
                 image_text = material.name
 
         # reuse face vertices
-        plane = poly_to_doom(me, p, radius)    
+        plane = poly_to_doom(me, p, radius)
         if plane is None:
             print("    ERROR: Could not create the plane from polygon!");
         elif doom_check_plane(done_planes, plane):
@@ -380,6 +384,71 @@ def write_node_map(fw, ob):
     return True
 
 
+def split_objects(context, objects):
+    scene = context.scene
+    view_layer = context.view_layer
+    final_objects = []
+
+    bpy.ops.object.select_all(action='DESELECT')
+    for ob in objects:
+        ob.select_set(True)
+
+    bpy.ops.object.duplicate()
+    objects = bpy.context.selected_objects
+
+    bpy.ops.object.select_all(action='DESELECT')
+
+    tot_ob = len(objects)
+    for i, ob in enumerate(objects):
+        print("Splitting object: %d/%d" % (i, tot_ob))
+        ob.select_set(True)
+
+        if ob.type == "MESH":
+            view_layer.objects.active = ob
+            bpy.ops.object.mode_set(mode='EDIT')
+            bpy.ops.mesh.select_all(action='DESELECT')
+            bpy.ops.mesh.select_mode(type='EDGE')
+            bpy.ops.object.mode_set(mode='OBJECT')
+            for edge in ob.data.edges:
+                if edge.use_seam:
+                    edge.select = True
+            bpy.ops.object.mode_set(mode='EDIT')
+            bpy.ops.mesh.edge_split()
+            bpy.ops.mesh.separate(type='LOOSE')
+            bpy.ops.object.mode_set(mode='OBJECT')
+
+            split_objects = context.selected_objects
+            for split_ob in split_objects:
+                assert(split_ob.type == "MESH")
+
+                view_layer.objects.active = split_ob
+                bpy.ops.object.mode_set(mode='EDIT')
+                bpy.ops.mesh.select_mode(type='EDGE')
+                bpy.ops.mesh.select_all(action="SELECT")
+                bpy.ops.mesh.region_to_loop()
+                bpy.ops.mesh.fill_holes(sides=8)
+                slot_idx = 0
+                for slot_idx, m in enumerate(split_ob.material_slots):
+                   if m.name == "textures/common/caulk":
+                      break
+                   #if m.name != "textures/common/caulk":
+                   #   mat = bpy.data.materials.new("textures/common/caulk")
+                   #   bpy.context.object.data.materials.append(mat)
+                split_ob.active_material_index = slot_idx  # we need to use either actual material name or custom property instead of index
+                bpy.ops.object.material_slot_assign()
+                with redirect_stdout(stdout):
+                   bpy.ops.mesh.remove_doubles()
+                bpy.ops.mesh.quads_convert_to_tris()
+                bpy.ops.mesh.tris_convert_to_quads()
+                bpy.ops.object.mode_set(mode='OBJECT')
+            final_objects += split_objects
+
+        ob.select_set(False)
+
+    print(final_objects)
+    return final_objects
+
+
 def export_map(context, filepath):
     """
     pup_block = [\
@@ -408,6 +477,7 @@ def export_map(context, filepath):
     print("Map Exporter 0.0")
 
     scene = context.scene
+    collection = context.collection
     objects = context.selected_objects
 
     obs_mesh = []
@@ -431,20 +501,26 @@ def export_map(context, filepath):
         elif type == 'EMPTY':
             obs_empty.append(ob)
 
+    obs_mesh = split_objects(context, obs_mesh)
+
     with open(filepath, 'w') as fl:
         fw = fl.write
 
         if obs_mesh or obs_surf:
             if PREF_DOOM3_FORMAT:
                 fw('Version 2')
-            
+
             # brushes and surf's must be under worldspan
             fw('\n// entity 0\n')
             fw('{\n')
             fw('"classname" "worldspawn"\n')
 
         print("\twriting cubes from meshes")
-        for ob in obs_mesh:
+
+        tot_ob = len(obs_mesh)
+        for i, ob in enumerate(obs_mesh):
+            print("Exporting object: %d/%d" % (i, tot_ob))
+
             dummy_mesh = ob.to_mesh(scene, True, 'PREVIEW')
 
             #print len(mesh_split2connected(dummy_mesh))
@@ -581,6 +657,10 @@ def export_map(context, filepath):
             else:
                 print("\t\tignoring %s" % ob.name)
 
+    for ob in obs_mesh:
+        collection.objects.unlink(ob)
+        bpy.data.objects.remove(ob)
+
     print("Exported Map in %.4fsec" % (time.time() - t))
     print("Brushes: %d  Nodes: %d  Lamps %d\n" % (TOTBRUSH, TOTNODE, TOTLAMP))
 
@@ -588,7 +668,7 @@ def export_map(context, filepath):
 def save(operator,
          context,
          filepath=None,
-         global_scale=100.0,
+         global_scale=1.0,
          face_thickness=0.1,
          texture_null="NULL",
          texture_opts='0 0 0 1 1 0 0 0',
@@ -609,7 +689,7 @@ def save(operator,
     PREF_DEF_TEX_OPTS = texture_opts
     PREF_GRID_SNAP = grid_snap
     PREF_DOOM3_FORMAT = doom3_format
-    
+
     if (PREF_DOOM3_FORMAT):
         PREF_DEF_TEX_OPTS = '0 0 0'
     else:
@@ -617,4 +697,4 @@ def save(operator,
 
     export_map(context, filepath)
 
-    return {'FINISHED'}
\ No newline at end of file
+    return {'FINISHED'}