[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