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:
Diffstat (limited to 'io_mesh_uv_layout/__init__.py')
-rw-r--r--io_mesh_uv_layout/__init__.py299
1 files changed, 150 insertions, 149 deletions
diff --git a/io_mesh_uv_layout/__init__.py b/io_mesh_uv_layout/__init__.py
index 30dff949..bd2c97bd 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": "",
@@ -43,15 +43,16 @@ if "bpy" in locals():
if "export_uv_svg" in locals():
importlib.reload(export_uv_svg)
+import os
import bpy
from bpy.props import (
- StringProperty,
- BoolProperty,
- EnumProperty,
- IntVectorProperty,
- FloatProperty,
- )
+ StringProperty,
+ BoolProperty,
+ EnumProperty,
+ IntVectorProperty,
+ FloatProperty,
+)
class ExportUVLayout(bpy.types.Operator):
@@ -61,172 +62,171 @@ class ExportUVLayout(bpy.types.Operator):
bl_label = "Export UV Layout"
bl_options = {'REGISTER', 'UNDO'}
- filepath = StringProperty(
- subtype='FILE_PATH',
- )
- check_existing = BoolProperty(
- name="Check Existing",
- description="Check and warn on overwriting existing files",
- default=True,
- options={'HIDDEN'},
- )
- export_all = BoolProperty(
- name="All UVs",
- description="Export all UVs in this mesh (not just visible ones)",
- default=False,
- )
- modified = BoolProperty(
- name="Modified",
- description="Exports UVs from the modified mesh",
- default=False,
- )
- mode = EnumProperty(
- items=(('SVG', "Scalable Vector Graphic (.svg)",
- "Export the UV layout to a vector SVG file"),
- ('EPS', "Encapsulate PostScript (.eps)",
- "Export the UV layout to a vector EPS file"),
- ('PNG', "PNG Image (.png)",
- "Export the UV layout to a bitmap image"),
- ),
- name="Format",
- description="File format to export the UV layout to",
- default='PNG',
- )
- size = IntVectorProperty(
- size=2,
- default=(1024, 1024),
- min=8, max=32768,
- description="Dimensions of the exported file",
- )
- opacity = FloatProperty(
- name="Fill Opacity",
- min=0.0, max=1.0,
- default=0.25,
- description="Set amount of opacity for exported UV layout"
- )
- tessellated = BoolProperty(
- name="Tessellated UVs",
- description="Export tessellated UVs instead of polygons ones",
- default=False,
- options={'HIDDEN'}, # As not working currently :/
- )
+ filepath: StringProperty(
+ subtype='FILE_PATH',
+ )
+ export_all: BoolProperty(
+ name="All UVs",
+ description="Export all UVs in this mesh (not just visible ones)",
+ default=False,
+ )
+ modified: BoolProperty(
+ name="Modified",
+ description="Exports UVs from the modified mesh",
+ default=False,
+ )
+ mode: EnumProperty(
+ items=(
+ ('SVG', "Scalable Vector Graphic (.svg)",
+ "Export the UV layout to a vector SVG file"),
+ ('EPS', "Encapsulate PostScript (.eps)",
+ "Export the UV layout to a vector EPS file"),
+ ('PNG', "PNG Image (.png)",
+ "Export the UV layout to a bitmap image"),
+ ),
+ name="Format",
+ description="File format to export the UV layout to",
+ default='PNG',
+ )
+ size: IntVectorProperty(
+ size=2,
+ default=(1024, 1024),
+ min=8, max=32768,
+ description="Dimensions of the exported file",
+ )
+ opacity: FloatProperty(
+ name="Fill Opacity",
+ min=0.0, max=1.0,
+ default=0.25,
+ description="Set amount of opacity for exported UV layout",
+ )
@classmethod
def poll(cls, context):
obj = context.active_object
- return (obj and obj.type == 'MESH' and obj.data.uv_textures)
+ return obj is not None and obj.type == 'MESH' and obj.data.uv_layers
- def _space_image(self, context):
- space_data = context.space_data
- if isinstance(space_data, bpy.types.SpaceImageEditor):
- return space_data
- else:
- return None
-
- def _image_size(self, context, default_width=1024, default_height=1024):
- # fallback if not in image context.
- image_width, image_height = default_width, default_height
+ def invoke(self, context, event):
+ self.size = self.get_image_size(context)
+ self.filepath = self.get_default_file_name(context) + "." + self.mode.lower()
+ context.window_manager.fileselect_add(self)
+ return {'RUNNING_MODAL'}
- space_data = self._space_image(context)
- if space_data:
- image = space_data.image
- if image:
- width, height = tuple(context.space_data.image.size)
- # in case no data is found.
- if width and height:
- image_width, image_height = width, height
+ def get_default_file_name(self, context):
+ AMOUNT = 3
+ objects = list(self.iter_objects_to_export(context))
+ name = " ".join(sorted([obj.name for obj in objects[:AMOUNT]]))
+ if len(objects) > AMOUNT:
+ name += " and more"
+ return name
- return image_width, image_height
+ def check(self, context):
+ if any(self.filepath.endswith(ext) for ext in (".png", ".eps", ".svg")):
+ self.filepath = self.filepath[:-4]
- def _face_uv_iter(self, context, mesh, tessellated):
- 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
-
- if context.tool_settings.show_uv_local_view:
- space_data = self._space_image(context)
- if space_data:
- local_image = space_data.image
-
- for i, p in enumerate(polys):
- # context checks
- if polys[i].select and local_image in {Ellipsis,
- uv_tex[i].image}:
- start = p.loop_start
- end = start + p.loop_total
- uvs = tuple((uv.uv[0], uv.uv[1])
- for uv in uv_layer[start:end])
-
- # just write what we see.
- yield (i, uvs)
- else:
- # all, simple
- for i, p in enumerate(polys):
- start = p.loop_start
- end = start + p.loop_total
- uvs = tuple((uv.uv[0], uv.uv[1]) for uv in uv_layer[start:end])
- yield (i, uvs)
+ ext = "." + self.mode.lower()
+ self.filepath = bpy.path.ensure_ext(self.filepath, ext)
+ return True
def execute(self, context):
-
obj = context.active_object
is_editmode = (obj.mode == 'EDIT')
if is_editmode:
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
- mode = self.mode
-
filepath = self.filepath
- filepath = bpy.path.ensure_ext(filepath, "." + mode.lower())
- file = open(filepath, "w")
- fw = file.write
-
- if mode == 'EPS':
- from . import export_uv_eps
- func = export_uv_eps.write
- elif mode == 'PNG':
- from . import export_uv_png
- func = export_uv_png.write
- elif mode == 'SVG':
- from . import export_uv_svg
- func = export_uv_svg.write
+ filepath = bpy.path.ensure_ext(filepath, "." + self.mode.lower())
+ meshes = list(self.iter_meshes_to_export(context))
+ polygon_data = list(self.iter_polygon_data_to_draw(context, meshes))
+ different_colors = set(color for _, color in polygon_data)
if self.modified:
- mesh = obj.to_mesh(context.scene, True, 'PREVIEW')
- else:
- mesh = obj.data
+ self.free_meshes(meshes)
- func(fw, mesh, self.size[0], self.size[1], self.opacity,
- lambda: self._face_uv_iter(context, mesh, self.tessellated))
-
- if self.modified:
- bpy.data.meshes.remove(mesh)
+ export = self.get_exporter()
+ export(filepath, polygon_data, different_colors, self.size[0], self.size[1], self.opacity)
if is_editmode:
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
- file.close()
-
return {'FINISHED'}
- def check(self, context):
- filepath = bpy.path.ensure_ext(self.filepath, "." + self.mode.lower())
- if filepath != self.filepath:
- self.filepath = filepath
- return True
- else:
- return False
+ def iter_meshes_to_export(self, context):
+ for obj in self.iter_objects_to_export(context):
+ if self.modified:
+ yield obj.to_mesh(context.depsgraph, apply_modifiers=True)
+ else:
+ yield obj.data
+
+ @staticmethod
+ def iter_objects_to_export(context):
+ for obj in context.selected_objects:
+ if obj.type != 'MESH':
+ continue
+ mesh = obj.data
+ if mesh.uv_layers.active is None:
+ continue
+ yield obj
- def invoke(self, context, event):
- import os
- self.size = self._image_size(context)
- self.filepath = os.path.splitext(bpy.data.filepath)[0]
- wm = context.window_manager
- wm.fileselect_add(self)
- return {'RUNNING_MODAL'}
+ @staticmethod
+ def free_meshes(meshes):
+ for mesh in meshes:
+ bpy.data.meshes.remove(mesh)
+
+ @staticmethod
+ def currently_image_image_editor(context):
+ return isinstance(context.space_data, bpy.types.SpaceImageEditor)
+
+ def get_currently_opened_image(self, context):
+ if not self.currently_image_image_editor(context):
+ return None
+ return context.space_data.image
+
+ def get_image_size(self, context):
+ # fallback if not in image context
+ image_width = self.size[0]
+ image_height = self.size[1]
+
+ # get size of "active" image if some exist
+ image = self.get_currently_opened_image(context)
+ if image is not None:
+ width, height = image.size
+ if width and height:
+ image_width = width
+ image_height = height
+
+ return image_width, image_height
+
+ def iter_polygon_data_to_draw(self, context, meshes):
+ for mesh in meshes:
+ uv_layer = mesh.uv_layers.active.data
+ for polygon in mesh.polygons:
+ if self.export_all or polygon.select:
+ start = polygon.loop_start
+ end = start + polygon.loop_total
+ uvs = tuple(tuple(uv.uv) for uv in uv_layer[start:end])
+ yield (uvs, self.get_polygon_color(mesh, polygon))
+
+ @staticmethod
+ def get_polygon_color(mesh, polygon, default=(0.8, 0.8, 0.8)):
+ if polygon.material_index < len(mesh.materials):
+ material = mesh.materials[polygon.material_index]
+ if material is not None:
+ return tuple(material.diffuse_color)
+ return default
+
+ def get_exporter(self):
+ if self.mode == 'PNG':
+ from . import export_uv_png
+ return export_uv_png.export
+ elif self.mode == 'EPS':
+ from . import export_uv_eps
+ return export_uv_eps.export
+ elif self.mode == 'SVG':
+ from . import export_uv_svg
+ return export_uv_svg.export
+ else:
+ assert False
def menu_func(self, context):
@@ -234,13 +234,14 @@ def menu_func(self, context):
def register():
- bpy.utils.register_module(__name__)
+ bpy.utils.register_class(ExportUVLayout)
bpy.types.IMAGE_MT_uvs.append(menu_func)
def unregister():
- bpy.utils.unregister_module(__name__)
+ bpy.utils.unregister_class(ExportUVLayout)
bpy.types.IMAGE_MT_uvs.remove(menu_func)
+
if __name__ == "__main__":
register()