Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDalai Felinto <dfelinto@gmail.com>2018-09-06 15:40:20 +0300
committerDalai Felinto <dfelinto@gmail.com>2018-09-06 16:19:19 +0300
commit25d49a3436164c3cf95c47ab77ffa3e0bc80ce67 (patch)
tree53b4466fdd995607d8864baba88dca2f45f3fe42 /io_mesh_uv_layout
parent9ff1e5eca76413b0f178ead688e9cde1c1385e36 (diff)
Multi-Objects: UV_OT_export_layout (80%)
""" Apart from the 'export as PNG' all seems to be working ok. 'Export to PNG' also seems to work but doesn't look acceptable because the mesh wireframe modifier is used to draw UV wireframes (I was going to see if a curve object would be usable to draw wireframes). Something in setting the renderer up could also be wrong or missing. """ D3507 by @Al Note from reviewer: I can't get this addon to show in the menus. But the syntax seems correct, and it's pep8 friendly, so no harm in committing it so I can ask other devs to see why the addon is never registering here. Also, some changes I made include making it pep8 friendly and replace: ['foo', 'bar'] with {'foo', 'bar'}.
Diffstat (limited to 'io_mesh_uv_layout')
-rw-r--r--io_mesh_uv_layout/__init__.py109
-rw-r--r--io_mesh_uv_layout/export_uv_eps.py117
-rw-r--r--io_mesh_uv_layout/export_uv_png.py287
-rw-r--r--io_mesh_uv_layout/export_uv_svg.py105
4 files changed, 370 insertions, 248 deletions
diff --git a/io_mesh_uv_layout/__init__.py b/io_mesh_uv_layout/__init__.py
index 30dff949..e33dcb41 100644
--- a/io_mesh_uv_layout/__init__.py
+++ b/io_mesh_uv_layout/__init__.py
@@ -22,7 +22,7 @@ bl_info = {
"name": "UV Layout",
"author": "Campbell Barton, Matt Ebb",
"version": (1, 1, 1),
- "blender": (2, 75, 0),
+ "blender": (2, 80, 0),
"location": "Image-Window > UVs > Export UV Layout",
"description": "Export the UV layout as a 2D graphic",
"warning": "",
@@ -114,7 +114,7 @@ class ExportUVLayout(bpy.types.Operator):
@classmethod
def poll(cls, context):
obj = context.active_object
- return (obj and obj.type == 'MESH' and obj.data.uv_textures)
+ return (obj and obj.type == 'MESH' and obj.data.uv_layers)
def _space_image(self, context):
space_data = context.space_data
@@ -138,27 +138,82 @@ class ExportUVLayout(bpy.types.Operator):
return image_width, image_height
- def _face_uv_iter(self, context, mesh, tessellated):
+ # Trying to be consistent with ED_object_get_active_image
+ # from uvedit_ops.c so that what is exported are the uvs
+ # that are seen in the UV Editor
+ #
+ # returns Image or None
+ def _get_active_texture(self, mat):
+ if mat is None or not mat.use_nodes:
+ return None
+
+ node = self._get_active_texture_nodetree(mat.node_tree)
+
+ if node is not None and node.bl_rna.identifier in {'ShaderNodeTexImage', 'ShaderNodeTexEnvironment'}:
+ return node.image
+
+ return None
+
+ # returns image node or None
+ def _get_active_texture_nodetree(self, node_tree):
+ active_tex_node = None
+ active_group = None
+ has_group = False
+ inactive_node = None
+
+ for node in node_tree.nodes:
+ if node.show_texture:
+ active_tex_node = node
+ if node.select:
+ return node
+ elif inactive_node is None and node.bl_rna.identifier in {'ShaderNodeTexImage', 'ShaderNodeTexEnvironment'}:
+ inactive_node = node
+ elif node.bl_rna.identifier == 'ShaderNodeGroup':
+ if node.select:
+ active_group = node
+ else:
+ has_group = True
+
+ # Not found a selected show_texture node
+ # Try to find a selected show_texture node in the selected group
+ if active_group is not None:
+ node = self._get_active_texture_nodetree(active_group.node_tree)
+ if node is not None:
+ return node
+
+ if active_tex_node is not None:
+ return active_tex_node
+
+ if has_group:
+ for node in node_tree.nodes:
+ if node.bl_rna.identifier == 'ShaderNodeGroup':
+ n = self._get_active_texture_nodetree(node.node_tree)
+ if n is not None and (n.show_texture or inactive_node is None):
+ return n
+
+ return None
+
+ def _face_uv_iter(self, context, material_slots, mesh):
uv_layer = mesh.uv_layers.active.data
polys = mesh.polygons
if not self.export_all:
- uv_tex = mesh.uv_textures.active.data
- local_image = Ellipsis
+ local_image = None
if context.tool_settings.show_uv_local_view:
space_data = self._space_image(context)
if space_data:
local_image = space_data.image
+ has_active_texture = [
+ self._get_active_texture(slot.material)
+ is local_image for slot in material_slots]
for i, p in enumerate(polys):
# context checks
- if polys[i].select and local_image in {Ellipsis,
- uv_tex[i].image}:
+ if (polys[i].select and (local_image is None or has_active_texture[polys[i].material_index])):
start = p.loop_start
end = start + p.loop_total
- uvs = tuple((uv.uv[0], uv.uv[1])
- for uv in uv_layer[start:end])
+ uvs = tuple((uv.uv[0], uv.uv[1]) for uv in uv_layer[start:end])
# just write what we see.
yield (i, uvs)
@@ -171,7 +226,6 @@ class ExportUVLayout(bpy.types.Operator):
yield (i, uvs)
def execute(self, context):
-
obj = context.active_object
is_editmode = (obj.mode == 'EDIT')
if is_editmode:
@@ -186,24 +240,36 @@ class ExportUVLayout(bpy.types.Operator):
if mode == 'EPS':
from . import export_uv_eps
- func = export_uv_eps.write
+ exportUV = export_uv_eps.Export_UV_EPS()
elif mode == 'PNG':
from . import export_uv_png
- func = export_uv_png.write
+ exportUV = export_uv_png.Export_UV_PNG()
elif mode == 'SVG':
from . import export_uv_svg
- func = export_uv_svg.write
+ exportUV = export_uv_svg.Export_UV_SVG()
- if self.modified:
- mesh = obj.to_mesh(context.scene, True, 'PREVIEW')
- else:
- mesh = obj.data
+ obList = [ob for ob in context.selected_objects if ob.type == 'MESH']
+
+ for obj in obList:
+ obj.data.tag = False
- func(fw, mesh, self.size[0], self.size[1], self.opacity,
- lambda: self._face_uv_iter(context, mesh, self.tessellated))
+ exportUV.begin(fw, self.size, self.opacity)
- if self.modified:
- bpy.data.meshes.remove(mesh)
+ for obj in obList:
+ if (obj.data.tag):
+ continue
+
+ obj.data.tag = True
+
+ if self.modified:
+ mesh = obj.to_mesh(context.scene, True, 'PREVIEW')
+ else:
+ mesh = obj.data
+
+ exportUV.build(mesh, lambda: self._face_uv_iter(
+ context, obj.material_slots, mesh))
+
+ exportUV.end()
if is_editmode:
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
@@ -242,5 +308,6 @@ def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.IMAGE_MT_uvs.remove(menu_func)
+
if __name__ == "__main__":
register()
diff --git a/io_mesh_uv_layout/export_uv_eps.py b/io_mesh_uv_layout/export_uv_eps.py
index a15dc266..d00e998a 100644
--- a/io_mesh_uv_layout/export_uv_eps.py
+++ b/io_mesh_uv_layout/export_uv_eps.py
@@ -21,66 +21,75 @@
import bpy
-def write(fw, mesh, image_width, image_height, opacity, face_iter_func):
- fw("%!PS-Adobe-3.0 EPSF-3.0\n")
- fw("%%%%Creator: Blender %s\n" % bpy.app.version_string)
- fw("%%Pages: 1\n")
- fw("%%Orientation: Portrait\n")
- fw("%%%%BoundingBox: 0 0 %d %d\n" % (image_width, image_height))
- fw("%%%%HiResBoundingBox: 0.0 0.0 %.4f %.4f\n" %
- (image_width, image_height))
- fw("%%EndComments\n")
- fw("%%Page: 1 1\n")
- fw("0 0 translate\n")
- fw("1.0 1.0 scale\n")
- fw("0 0 0 setrgbcolor\n")
- fw("[] 0 setdash\n")
- fw("1 setlinewidth\n")
- fw("1 setlinejoin\n")
- fw("1 setlinecap\n")
+class Export_UV_EPS:
+ def begin(self, fw, image_size, opacity):
- polys = mesh.polygons
+ self.fw = fw
+ self.image_width = image_size[0]
+ self.image_height = image_size[1]
+ self.opacity = opacity
- if opacity > 0.0:
- for i, mat in enumerate(mesh.materials if mesh.materials else [None]):
- fw("/DRAW_%d {" % i)
- fw("gsave\n")
- if mat:
- color = tuple((1.0 - ((1.0 - c) * opacity))
- for c in mat.diffuse_color)
- else:
- color = 1.0, 1.0, 1.0
- fw("%.3g %.3g %.3g setrgbcolor\n" % color)
- fw("fill\n")
- fw("grestore\n")
- fw("0 setgray\n")
- fw("} def\n")
+ fw("%!PS-Adobe-3.0 EPSF-3.0\n")
+ fw("%%%%Creator: Blender %s\n" % bpy.app.version_string)
+ fw("%%Pages: 1\n")
+ fw("%%Orientation: Portrait\n")
+ fw("%%%%BoundingBox: 0 0 %d %d\n" % (self.image_width, self.image_height))
+ fw("%%%%HiResBoundingBox: 0.0 0.0 %.4f %.4f\n" %
+ (self.image_width, self.image_height))
+ fw("%%EndComments\n")
+ fw("%%Page: 1 1\n")
+ fw("0 0 translate\n")
+ fw("1.0 1.0 scale\n")
+ fw("0 0 0 setrgbcolor\n")
+ fw("[] 0 setdash\n")
+ fw("1 setlinewidth\n")
+ fw("1 setlinejoin\n")
+ fw("1 setlinecap\n")
- # fill
+ def build(self, mesh, face_iter_func):
+ polys = mesh.polygons
+
+ if self.opacity > 0.0:
+ for i, mat in enumerate(mesh.materials if mesh.materials else [None]):
+ self.fw("/DRAW_%d {" % i)
+ self.fw("gsave\n")
+ if mat:
+ color = tuple((1.0 - ((1.0 - c) * self.opacity))
+ for c in mat.diffuse_color)
+ else:
+ color = 1.0, 1.0, 1.0
+ self.fw("%.3g %.3g %.3g setrgbcolor\n" % color)
+ self.fw("fill\n")
+ self.fw("grestore\n")
+ self.fw("0 setgray\n")
+ self.fw("} def\n")
+
+ # fill
+ for i, uvs in face_iter_func():
+ self.fw("newpath\n")
+ for j, uv in enumerate(uvs):
+ uv_scale = (uv[0] * self.image_width, uv[1] * self.image_height)
+ if j == 0:
+ self.fw("%.5f %.5f moveto\n" % uv_scale)
+ else:
+ self.fw("%.5f %.5f lineto\n" % uv_scale)
+
+ self.fw("closepath\n")
+ self.fw("DRAW_%d\n" % polys[i].material_index)
+
+ # stroke only
for i, uvs in face_iter_func():
- fw("newpath\n")
+ self.fw("newpath\n")
for j, uv in enumerate(uvs):
- uv_scale = (uv[0] * image_width, uv[1] * image_height)
+ uv_scale = (uv[0] * self.image_width, uv[1] * self.image_height)
if j == 0:
- fw("%.5f %.5f moveto\n" % uv_scale)
+ self.fw("%.5f %.5f moveto\n" % uv_scale)
else:
- fw("%.5f %.5f lineto\n" % uv_scale)
-
- fw("closepath\n")
- fw("DRAW_%d\n" % polys[i].material_index)
-
- # stroke only
- for i, uvs in face_iter_func():
- fw("newpath\n")
- for j, uv in enumerate(uvs):
- uv_scale = (uv[0] * image_width, uv[1] * image_height)
- if j == 0:
- fw("%.5f %.5f moveto\n" % uv_scale)
- else:
- fw("%.5f %.5f lineto\n" % uv_scale)
+ self.fw("%.5f %.5f lineto\n" % uv_scale)
- fw("closepath\n")
- fw("stroke\n")
+ self.fw("closepath\n")
+ self.fw("stroke\n")
- fw("showpage\n")
- fw("%%EOF\n")
+ def end(self):
+ self.fw("showpage\n")
+ self.fw("%%EOF\n")
diff --git a/io_mesh_uv_layout/export_uv_png.py b/io_mesh_uv_layout/export_uv_png.py
index b556c982..be03ed0b 100644
--- a/io_mesh_uv_layout/export_uv_png.py
+++ b/io_mesh_uv_layout/export_uv_png.py
@@ -21,131 +21,162 @@
import bpy
-def write(fw, mesh_source, image_width, image_height, opacity, face_iter_func):
- filepath = fw.__self__.name
- fw.__self__.close()
-
- material_solids = [bpy.data.materials.new("uv_temp_solid")
- for i in range(max(1, len(mesh_source.materials)))]
-
- material_wire = bpy.data.materials.new("uv_temp_wire")
-
- scene = bpy.data.scenes.new("uv_temp")
- mesh = bpy.data.meshes.new("uv_temp")
- for mat_solid in material_solids:
- mesh.materials.append(mat_solid)
-
- polys_source = mesh_source.polygons
-
- # get unique UV's in case there are many overlapping
- # which slow down filling.
- face_hash = {(uvs, polys_source[i].material_index)
- for i, uvs in face_iter_func()}
-
- # now set the faces coords and locations
- # build mesh data
- mesh_new_vertices = []
- mesh_new_materials = []
- mesh_new_polys_startloop = []
- mesh_new_polys_totloop = []
- mesh_new_loops_vertices = []
-
- current_vert = 0
-
- for uvs, mat_idx in face_hash:
- num_verts = len(uvs)
- dummy = (0.0,) * num_verts
- for uv in uvs:
- mesh_new_vertices += (uv[0], uv[1], 0.0)
- mesh_new_polys_startloop.append(current_vert)
- mesh_new_polys_totloop.append(num_verts)
- mesh_new_loops_vertices += range(current_vert,
- current_vert + num_verts)
- mesh_new_materials.append(mat_idx)
- current_vert += num_verts
-
- mesh.vertices.add(current_vert)
- mesh.loops.add(current_vert)
- mesh.polygons.add(len(mesh_new_polys_startloop))
-
- mesh.vertices.foreach_set("co", mesh_new_vertices)
- mesh.loops.foreach_set("vertex_index", mesh_new_loops_vertices)
- mesh.polygons.foreach_set("loop_start", mesh_new_polys_startloop)
- mesh.polygons.foreach_set("loop_total", mesh_new_polys_totloop)
- mesh.polygons.foreach_set("material_index", mesh_new_materials)
-
- mesh.update(calc_edges=True)
-
- obj_solid = bpy.data.objects.new("uv_temp_solid", mesh)
- obj_wire = bpy.data.objects.new("uv_temp_wire", mesh)
- base_solid = scene.objects.link(obj_solid)
- base_wire = scene.objects.link(obj_wire)
- base_solid.layers[0] = True
- base_wire.layers[0] = True
-
- # place behind the wire
- obj_solid.location = 0, 0, -1
-
- obj_wire.material_slots[0].link = 'OBJECT'
- obj_wire.material_slots[0].material = material_wire
-
- # setup the camera
- cam = bpy.data.cameras.new("uv_temp")
- cam.type = 'ORTHO'
- cam.ortho_scale = 1.0
- obj_cam = bpy.data.objects.new("uv_temp_cam", cam)
- obj_cam.location = 0.5, 0.5, 1.0
- scene.objects.link(obj_cam)
- scene.camera = obj_cam
-
- # setup materials
- for i, mat_solid in enumerate(material_solids):
- if mesh_source.materials and mesh_source.materials[i]:
- mat_solid.diffuse_color = mesh_source.materials[i].diffuse_color
-
- mat_solid.use_shadeless = True
- mat_solid.use_transparency = True
- mat_solid.alpha = opacity
-
- material_wire.type = 'WIRE'
- material_wire.use_shadeless = True
- material_wire.diffuse_color = 0, 0, 0
- material_wire.use_transparency = True
-
- # scene render settings
- scene.render.use_raytrace = False
- scene.render.alpha_mode = 'TRANSPARENT'
- scene.render.image_settings.color_mode = 'RGBA'
-
- scene.render.resolution_x = image_width
- scene.render.resolution_y = image_height
- scene.render.resolution_percentage = 100
-
- if image_width > image_height:
- scene.render.pixel_aspect_y = image_width / image_height
- elif image_width < image_height:
- scene.render.pixel_aspect_x = image_height / image_width
-
- scene.frame_start = 1
- scene.frame_end = 1
-
- scene.render.image_settings.file_format = 'PNG'
- scene.render.filepath = filepath
-
- scene.update()
-
- data_context = {"blend_data": bpy.context.blend_data, "scene": scene}
- bpy.ops.render.render(data_context, write_still=True)
-
- # cleanup
- bpy.data.scenes.remove(scene, do_unlink=True)
- bpy.data.objects.remove(obj_cam, do_unlink=True)
- bpy.data.objects.remove(obj_solid, do_unlink=True)
- bpy.data.objects.remove(obj_wire, do_unlink=True)
-
- bpy.data.cameras.remove(cam, do_unlink=True)
- bpy.data.meshes.remove(mesh, do_unlink=True)
-
- bpy.data.materials.remove(material_wire, do_unlink=True)
- for mat_solid in material_solids:
- bpy.data.materials.remove(mat_solid, do_unlink=True)
+class Export_UV_PNG:
+ def begin(self, fw, image_size, opacity):
+ self.filepath = fw.__self__.name
+ fw.__self__.close()
+
+ self.scene = bpy.data.scenes.new("uv_temp")
+
+ image_width = image_size[0]
+ image_height = image_size[1]
+
+ self.scene.render.resolution_x = image_width
+ self.scene.render.resolution_y = image_height
+ self.scene.render.resolution_percentage = 100
+
+ self.scene.render.alpha_mode = 'TRANSPARENT'
+
+ if image_width > image_height:
+ self.scene.render.pixel_aspect_y = image_width / image_height
+ elif image_width < image_height:
+ self.scene.render.pixel_aspect_x = image_height / image_width
+
+ self.base_material = bpy.data.materials.new("uv_temp_base")
+ self.base_material.use_nodes = True
+ self.base_material.node_tree.nodes.clear()
+ output_node = self.base_material.node_tree.nodes.new(type="ShaderNodeOutputMaterial")
+ emission_node = self.base_material.node_tree.nodes.new(type="ShaderNodeEmission")
+ emission_node.inputs["Color"].default_value = (1.0, 1.0, 1.0, opacity)
+ self.base_material.node_tree.links.new(
+ output_node.inputs["Surface"],
+ emission_node.outputs["Emission"])
+
+ self.material_wire = self.base_material.copy()
+ self.material_wire.name = "Wire"
+ self.material_wire.node_tree.nodes['Emission'].inputs["Color"].default_value = (0.0, 0.0, 0.0, 1.0)
+
+ self.base_material.blend_method = "BLEND"
+
+ self.material_solids_list = [] # list of lists
+ self.material_solids_list.append([self.base_material,
+ self.material_wire])
+
+ self.mesh_list = []
+ self.obj_list = []
+
+ def build(self, mesh_source, face_iter_func):
+ material_solids = [self.base_material.copy() for i in range(max(1, len(mesh_source.materials)))]
+
+ self.material_solids_list.append(material_solids)
+
+ mesh = bpy.data.meshes.new("uv_temp")
+ self.mesh_list.append(mesh)
+
+ for mat_solid in material_solids:
+ mesh.materials.append(mat_solid)
+
+ # setup materials
+ for i, mat_solid in enumerate(material_solids):
+ if mesh_source.materials and mesh_source.materials[i]:
+ mat_solid.node_tree.nodes['Emission'].\
+ inputs["Color"].default_value[0:3]\
+ = mesh_source.materials[i].diffuse_color
+
+ # Add materials for wireframe modifier.
+ for mat_solid in material_solids:
+ mesh.materials.append(self.material_wire)
+
+ polys_source = mesh_source.polygons
+
+ # get unique UV's in case there are many overlapping
+ # which slow down filling.
+ face_hash = {(uvs, polys_source[i].material_index)
+ for i, uvs in face_iter_func()}
+
+ # now set the faces coords and locations
+ # build mesh data
+ mesh_new_vertices = []
+ mesh_new_materials = []
+ mesh_new_polys_startloop = []
+ mesh_new_polys_totloop = []
+ mesh_new_loops_vertices = []
+
+ current_vert = 0
+
+ for uvs, mat_idx in face_hash:
+ num_verts = len(uvs)
+ # dummy = (0.0,) * num_verts
+ for uv in uvs:
+ mesh_new_vertices += (uv[0], uv[1], 0.0)
+ mesh_new_polys_startloop.append(current_vert)
+ mesh_new_polys_totloop.append(num_verts)
+ mesh_new_loops_vertices += range(current_vert,
+ current_vert + num_verts)
+ mesh_new_materials.append(mat_idx)
+ current_vert += num_verts
+
+ mesh.vertices.add(current_vert)
+ mesh.loops.add(current_vert)
+ mesh.polygons.add(len(mesh_new_polys_startloop))
+
+ mesh.vertices.foreach_set("co", mesh_new_vertices)
+ mesh.loops.foreach_set("vertex_index", mesh_new_loops_vertices)
+ mesh.polygons.foreach_set("loop_start", mesh_new_polys_startloop)
+ mesh.polygons.foreach_set("loop_total", mesh_new_polys_totloop)
+ mesh.polygons.foreach_set("material_index", mesh_new_materials)
+
+ mesh.update(calc_edges=True)
+
+ obj_solid = bpy.data.objects.new("uv_temp_solid", mesh)
+
+ wire_mod = obj_solid.modifiers.new("wire_mod", 'WIREFRAME')
+ wire_mod.use_replace = False
+ wire_mod.use_relative_offset = True
+
+ wire_mod.material_offset = len(material_solids)
+
+ self.obj_list.append(obj_solid)
+ self.scene.collection.objects.link(obj_solid)
+
+ def end(self):
+ # setup the camera
+ cam = bpy.data.cameras.new("uv_temp")
+ cam.type = 'ORTHO'
+ cam.ortho_scale = 1.0
+ obj_cam = bpy.data.objects.new("uv_temp_cam", cam)
+ obj_cam.location = 0.5, 0.5, 1.0
+ self.scene.collection.objects.link(obj_cam)
+ self.obj_list.append(obj_cam)
+ self.scene.camera = obj_cam
+
+ # scene render settings
+ self.scene.render.alpha_mode = 'TRANSPARENT'
+ self.scene.render.image_settings.color_mode = 'RGBA'
+
+ self.scene.frame_start = 1
+ self.scene.frame_end = 1
+
+ self.scene.render.image_settings.file_format = 'PNG'
+ self.scene.render.filepath = self.filepath
+
+ self.scene.update()
+
+ data_context = {"blend_data": bpy.context.blend_data,
+ "scene": self.scene}
+ bpy.ops.render.render(data_context, write_still=True)
+
+ # cleanup
+ bpy.data.scenes.remove(self.scene, do_unlink=True)
+
+ for obj in self.obj_list:
+ bpy.data.objects.remove(obj, do_unlink=True)
+
+ bpy.data.cameras.remove(cam, do_unlink=True)
+
+ for mesh in self.mesh_list:
+ bpy.data.meshes.remove(mesh, do_unlink=True)
+
+ for material_solids in self.material_solids_list:
+ for mat_solid in material_solids:
+ bpy.data.materials.remove(mat_solid, do_unlink=True)
diff --git a/io_mesh_uv_layout/export_uv_svg.py b/io_mesh_uv_layout/export_uv_svg.py
index 764f0d34..fe727d09 100644
--- a/io_mesh_uv_layout/export_uv_svg.py
+++ b/io_mesh_uv_layout/export_uv_svg.py
@@ -21,48 +21,63 @@
import bpy
-def write(fw, mesh, image_width, image_height, opacity, face_iter_func):
- # for making an XML compatible string
- from xml.sax.saxutils import escape
- from os.path import basename
-
- fw('<?xml version="1.0" standalone="no"?>\n')
- fw('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" \n')
- fw(' "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n')
- fw('<svg width="%d" height="%d" viewBox="0 0 %d %d"\n' %
- (image_width, image_height, image_width, image_height))
- fw(' xmlns="http://www.w3.org/2000/svg" version="1.1">\n')
- desc = ("%r, %s, (Blender %s)" %
- (basename(bpy.data.filepath), mesh.name, bpy.app.version_string))
- fw('<desc>%s</desc>\n' % escape(desc))
-
- # svg colors
- fill_settings = []
- fill_default = 'fill="grey"'
- for mat in mesh.materials if mesh.materials else [None]:
- if mat:
- fill_settings.append('fill="rgb(%d, %d, %d)"' %
- tuple(int(c * 255)
- for c in mat.diffuse_color))
- else:
- fill_settings.append(fill_default)
-
- polys = mesh.polygons
- for i, uvs in face_iter_func():
- try: # rare cases material index is invalid.
- fill = fill_settings[polys[i].material_index]
- except IndexError:
- fill = fill_default
-
- fw('<polygon stroke="black" stroke-width="1"')
- if opacity > 0.0:
- fw(' %s fill-opacity="%.2g"' % (fill, opacity))
-
- fw(' points="')
-
- for j, uv in enumerate(uvs):
- x, y = uv[0], 1.0 - uv[1]
- fw('%.3f,%.3f ' % (x * image_width, y * image_height))
- fw('" />\n')
- fw('\n')
- fw('</svg>\n')
+from xml.sax.saxutils import escape
+from os.path import basename
+
+
+class Export_UV_SVG:
+ def begin(self, fw, image_size, opacity):
+
+ self.fw = fw
+ self.image_width = image_size[0]
+ self.image_height = image_size[1]
+ self.opacity = opacity
+
+ fw('<?xml version="1.0" standalone="no"?>\n')
+ fw('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" \n')
+ fw(' "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n')
+ fw('<svg width="%d" height="%d" viewBox="0 0 %d %d"\n' %
+ (self.image_width, self.image_height, self.image_width, self.image_height))
+ fw(' xmlns="http://www.w3.org/2000/svg" version="1.1">\n')
+ desc = ("%r, (Blender %s)" %
+ (basename(bpy.data.filepath), bpy.app.version_string))
+ fw('<desc>%s</desc>\n' % escape(desc))
+
+ def build(self, mesh, face_iter_func):
+ self.fw('<g>\n')
+ desc = ("Mesh: %s" % (mesh.name))
+ self.fw('<desc>%s</desc>\n' % escape(desc))
+
+ # svg colors
+ fill_settings = []
+ fill_default = 'fill="grey"'
+ for mat in mesh.materials if mesh.materials else [None]:
+ if mat:
+ fill_settings.append('fill="rgb(%d, %d, %d)"' %
+ tuple(int(c * 255) for c in mat.diffuse_color))
+ else:
+ fill_settings.append(fill_default)
+
+ polys = mesh.polygons
+ for i, uvs in face_iter_func():
+ try: # rare cases material index is invalid.
+ fill = fill_settings[polys[i].material_index]
+ except IndexError:
+ fill = fill_default
+
+ self.fw('<polygon stroke="black" stroke-width="1"')
+ if self.opacity > 0.0:
+ self.fw(' %s fill-opacity="%.2g"' % (fill, self.opacity))
+
+ self.fw(' points="')
+
+ for j, uv in enumerate(uvs):
+ x, y = uv[0], 1.0 - uv[1]
+ self.fw('%.3f,%.3f ' % (x * self.image_width, y * self.image_height))
+ self.fw('" />\n')
+
+ self.fw('</g>\n')
+
+ def end(self):
+ self.fw('\n')
+ self.fw('</svg>\n')