[Bf-extensions-cvs] [e0e0fe92] master: io_export_paper_model: update to github rev 6c28ce48b0

Adam Dominec noreply at git.blender.org
Tue Feb 21 22:47:22 CET 2017


Commit: e0e0fe92738e345746ef566b6ecfb79d28a28d6d
Author: Adam Dominec
Date:   Tue Feb 21 22:46:22 2017 +0100
Branches: master
https://developer.blender.org/rBACe0e0fe92738e345746ef566b6ecfb79d28a28d6d

io_export_paper_model: update to github rev 6c28ce48b0

===================================================================

M	io_export_paper_model.py

===================================================================

diff --git a/io_export_paper_model.py b/io_export_paper_model.py
index 225b17e9..9842305d 100644
--- a/io_export_paper_model.py
+++ b/io_export_paper_model.py
@@ -58,7 +58,7 @@ import bgl
 import mathutils as M
 from re import compile as re_compile
 from itertools import chain, repeat
-from math import pi
+from math import pi, ceil
 
 try:
     import os.path as os_path
@@ -153,6 +153,57 @@ def create_blank_image(image_name, dimensions, alpha=1):
     return image
 
 
+def bake(face_indices, uvmap, image):
+    import bpy
+    is_cycles = (bpy.context.scene.render.engine == 'CYCLES')
+    if is_cycles:
+        # please excuse the following mess. Cycles baking API does not seem to allow better.
+        ob = bpy.context.active_object
+        me = ob.data
+        mat = bpy.data.materials.new("unfolder dummy")
+        mat.use_nodes = True
+        img = mat.node_tree.nodes.new('ShaderNodeTexImage')
+        img.image = image
+        mat.node_tree.nodes.active = img
+        uv = mat.node_tree.nodes.new('ShaderNodeUVMap')
+        uv.uv_map = uvmap.name
+        mat.node_tree.links.new(uv.outputs['UV'], img.inputs['Vector'])
+        uvmap.active = True
+        recall_object_slots, recall_mesh_slots = [slot.material for slot in ob.material_slots], me.materials[:]
+        for i, slot in enumerate(ob.material_slots):
+            slot.material = me.materials[i] = mat
+        me.materials.append(mat)
+        loop = me.uv_layers[me.uv_layers.active_index].data
+        face_indices = set(face_indices)
+        ignored_uvs = [face.loop_start + i for face in me.polygons if face.index not in face_indices for i, v in enumerate(face.vertices)]
+        for vid in ignored_uvs:
+            loop[vid].uv[0] *= -1
+            loop[vid].uv[1] *= -1
+        bake_type = bpy.context.scene.cycles.bake_type
+        sta = bpy.context.scene.render.bake.use_selected_to_active
+        try:
+            bpy.ops.object.bake(type=bake_type, margin=0, use_selected_to_active=sta, cage_extrusion=100, use_clear=False)
+        except RuntimeError as e:
+            raise UnfoldError(*e.args)
+        finally:
+            me.materials.pop()
+            for slot, recall in zip(ob.material_slots, recall_object_slots):
+                slot.material = recall
+            for i, recall in enumerate(recall_mesh_slots):
+                me.materials[i] = recall
+            bpy.data.materials.remove(mat)
+        for vid in ignored_uvs:
+            loop[vid].uv[0] *= -1
+            loop[vid].uv[1] *= -1
+    else:
+        texfaces = uvmap.data
+        for fid in face_indices:
+            texfaces[fid].image = image
+        bpy.ops.object.bake_image()
+        for fid in face_indices:
+            texfaces[fid].image = None
+
+
 class UnfoldError(ValueError):
     pass
 
@@ -166,7 +217,8 @@ class Unfolder:
     def prepare(self, cage_size=None, create_uvmap=False, mark_seams=False, priority_effect=default_priority_effect, scale=1):
         """Create the islands of the net"""
         self.mesh.generate_cuts(cage_size / scale if cage_size else None, priority_effect)
-        self.mesh.finalize_islands()
+        is_landscape = cage_size and cage_size.x > cage_size.y
+        self.mesh.finalize_islands(is_landscape)
         self.mesh.enumerate_islands()
         if create_uvmap:
             self.tex = self.mesh.save_uv()
@@ -215,7 +267,7 @@ class Unfolder:
         text_height = properties.sticker_width if (properties.do_create_numbers and len(self.mesh.islands) > 1) else 0
         aspect_ratio = printable_size.x / printable_size.y
         # title height must be somewhat larger that text size, glyphs go below the baseline
-        self.mesh.finalize_islands(title_height=text_height * 1.2)
+        self.mesh.finalize_islands(is_landscape=(printable_size.x > printable_size.y), title_height=text_height * 1.2)
         self.mesh.fit_islands(cage_size=printable_size)
 
         if properties.output_type != 'NONE':
@@ -225,13 +277,24 @@ class Unfolder:
             tex = self.mesh.save_uv(cage_size=printable_size, separate_image=use_separate_images, tex=self.tex)
             if not tex:
                 raise UnfoldError("The mesh has no UV Map slots left. Either delete a UV Map or export the net without textures.")
-            rd = bpy.context.scene.render
-            recall = rd.bake_type, rd.use_bake_to_vertex_color, rd.use_bake_selected_to_active, rd.bake_distance, rd.bake_bias, rd.bake_margin, rd.use_bake_clear
-
-            rd.bake_type = 'TEXTURE' if properties.output_type == 'TEXTURE' else 'FULL'
-            rd.use_bake_selected_to_active = (properties.output_type == 'SELECTED_TO_ACTIVE')
 
-            rd.bake_margin, rd.bake_distance, rd.bake_bias, rd.use_bake_to_vertex_color, rd.use_bake_clear = 0, 0, 0.001, False, False
+            sce = bpy.context.scene
+            rd = sce.render
+            bk = rd.bake
+            if rd.engine == 'CYCLES':
+                recall = sce.cycles.bake_type, bk.use_selected_to_active, bk.margin, bk.cage_extrusion, bk.use_cage, bk.use_clear
+                lookup = {'TEXTURE': 'DIFFUSE_COLOR', 'AMBIENT_OCCLUSION': 'AO', 'RENDER': 'COMBINED', 'SELECTED_TO_ACTIVE': 'COMBINED'}
+                sce.cycles.bake_type = lookup[properties.output_type]
+                bk.use_selected_to_active = (properties.output_type == 'SELECTED_TO_ACTIVE')
+                bk.margin, bk.cage_extrusion, bk.use_cage, bk.use_clear = 0, 10, False, False
+            else:
+                recall = rd.engine, rd.bake_type, rd.use_bake_to_vertex_color, rd.use_bake_selected_to_active, rd.bake_distance, rd.bake_bias, rd.bake_margin, rd.use_bake_clear
+                rd.engine = 'BLENDER_RENDER'
+                lookup = {'TEXTURE': 'TEXTURE', 'AMBIENT_OCCLUSION': 'AO', 'RENDER': 'FULL', 'SELECTED_TO_ACTIVE': 'FULL'}
+                rd.bake_type = lookup[properties.output_type]
+                rd.use_bake_selected_to_active = (properties.output_type == 'SELECTED_TO_ACTIVE')
+                rd.bake_margin, rd.bake_distance, rd.bake_bias, rd.use_bake_to_vertex_color, rd.use_bake_clear = 0, 0, 0.001, False, False
+            
             if image_packing == 'PAGE_LINK':
                 self.mesh.save_image(tex, printable_size * ppm, filepath)
             elif image_packing == 'ISLAND_LINK':
@@ -240,7 +303,10 @@ class Unfolder:
                 self.mesh.save_separate_images(tex, ppm, filepath, embed=Exporter.encode_image)
 
             # revoke settings
-            rd.bake_type, rd.use_bake_to_vertex_color, rd.use_bake_selected_to_active, rd.bake_distance, rd.bake_bias, rd.bake_margin, rd.use_bake_clear = recall
+            if rd.engine == 'CYCLES':
+                sce.cycles.bake_type, bk.use_selected_to_active, bk.margin, bk.cage_extrusion, bk.use_cage, bk.use_clear = recall
+            else:
+                rd.engine, rd.bake_type, rd.use_bake_to_vertex_color, rd.use_bake_selected_to_active, rd.bake_distance, rd.bake_bias, rd.bake_margin, rd.use_bake_clear = recall
             if not properties.do_create_uvmap:
                 tex.active = True
                 bpy.ops.mesh.uv_texture_remove()
@@ -436,13 +502,17 @@ class Mesh:
             for point in chain((vertex.co for vertex in island.verts), island.fake_verts):
                 point *= scale
 
-    def finalize_islands(self, title_height=0):
+    def finalize_islands(self, is_landscape=False, title_height=0):
         for island in self.islands:
             if title_height:
                 island.title = "[{}] {}".format(island.abbreviation, island.label)
             points = list(vertex.co for vertex in island.verts) + island.fake_verts
             angle = M.geometry.box_fit_2d(points)
             rot = M.Matrix.Rotation(angle, 2)
+            # ensure that the island matches page orientation (portrait/landscape)
+            dimensions = M.Vector(max(r * v for v in points) - min(r * v for v in points) for r in rot)
+            if dimensions.x > dimensions.y != is_landscape:
+                rot = M.Matrix.Rotation(angle + pi / 2, 2)
             for point in points:
                 # note: we need an in-place operation, and Vector.rotate() seems to work for 3d vectors only
                 point[:] = rot * point
@@ -454,7 +524,7 @@ class Mesh:
             island.bounding_box = M.Vector((max(v.x for v in points), max(v.y for v in points)))
 
     def largest_island_ratio(self, page_size):
-        return max(max(island.bounding_box.x / page_size.x, island.bounding_box.y / page_size.y) for island in self.islands)
+        return max(i / p for island in self.islands for (i, p) in zip(island.bounding_box, page_size))
 
     def fit_islands(self, cage_size):
         """Move islands so that they fit onto pages, based on their bounding boxes"""
@@ -543,42 +613,20 @@ class Mesh:
         return tex
 
     def save_image(self, tex, page_size_pixels: M.Vector, filename):
-        texfaces = tex.data
-        # omitting this causes a "Circular reference in texture stack" error
-        for island in self.islands:
-            for uvface in island.faces:
-                texfaces[uvface.face.index].image = None
-
         for page in self.pages:
             image = create_blank_image("{} {} Unfolded".format(self.data.name[:14], page.name), page_size_pixels, alpha=1)
             image.filepath_raw = page.image_path = "{}_{}.png".format(filename, page.name)
-            for island in page.islands:
-                for uvface in island.faces:
-                    texfaces[uvface.face.index].image = image
-            try:
-                bpy.ops.object.bake_image()
-                image.save()
-            finally:
-                for island in page.islands:
-                    for uvface in island.faces:
-                        texfaces[uvface.face.index].image = None
-                image.user_clear()
-                bpy.data.images.remove(image)
+            faces = [uvface.face.index for island in page.islands for uvface in island.faces]
+            bake(faces, tex, image)
+            image.save()
+            image.user_clear()
+            bpy.data.images.remove(image)
 
     def save_separate_images(self, tex, scale, filepath, embed=None):
-        texface

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list