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 'uv_magic_uv/op/copy_paste_uv_object.py')
-rw-r--r--uv_magic_uv/op/copy_paste_uv_object.py312
1 files changed, 185 insertions, 127 deletions
diff --git a/uv_magic_uv/op/copy_paste_uv_object.py b/uv_magic_uv/op/copy_paste_uv_object.py
index d80ee415..eb6d87c9 100644
--- a/uv_magic_uv/op/copy_paste_uv_object.py
+++ b/uv_magic_uv/op/copy_paste_uv_object.py
@@ -20,8 +20,8 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "5.1"
-__date__ = "24 Feb 2018"
+__version__ = "5.2"
+__date__ = "17 Nov 2018"
import bpy
import bmesh
@@ -31,6 +31,41 @@ from bpy.props import (
)
from .. import common
+from .copy_paste_uv import (
+ get_copy_uv_layers,
+ get_paste_uv_layers,
+ paste_uv
+)
+
+
+__all__ = [
+ 'Properties',
+ 'OperatorCopyUV',
+ 'MenuCopyUV',
+ 'OperatorPasteUV',
+ 'MenuPasteUV',
+]
+
+
+def is_valid_context(context):
+ obj = context.object
+
+ # only object mode is allowed to execute
+ if obj is None:
+ return False
+ if obj.type != 'MESH':
+ return False
+ if context.object.mode != 'OBJECT':
+ return False
+
+ # only 'VIEW_3D' space is allowed to execute
+ for space in context.area.spaces:
+ if space.type == 'VIEW_3D':
+ break
+ else:
+ return False
+
+ return True
def memorize_view_3d_mode(fn):
@@ -42,101 +77,138 @@ def memorize_view_3d_mode(fn):
return __memorize_view_3d_mode
-class MUV_CPUVObjCopyUV(bpy.types.Operator):
+class Properties:
+ @classmethod
+ def init_props(cls, scene):
+ class Props():
+ src_info = None
+
+ scene.muv_props.copy_paste_uv_object = Props()
+
+ scene.muv_copy_paste_uv_object_copy_seams = BoolProperty(
+ name="Seams",
+ description="Copy Seams",
+ default=True
+ )
+
+ @classmethod
+ def del_props(cls, scene):
+ del scene.muv_props.copy_paste_uv_object
+ del scene.muv_copy_paste_uv_object_copy_seams
+
+
+class OperatorCopyUV(bpy.types.Operator):
"""
- Operation class: Copy UV coordinate per object
+ Operation class: Copy UV coordinate among objects
"""
- bl_idname = "object.muv_cpuv_obj_copy_uv"
- bl_label = "Copy UV"
- bl_description = "Copy UV coordinate"
+ bl_idname = "object.muv_copy_paste_uv_object_operator_copy_uv"
+ bl_label = "Copy UV (Among Objects)"
+ bl_description = "Copy UV coordinate (Among Objects)"
bl_options = {'REGISTER', 'UNDO'}
- uv_map = StringProperty(options={'HIDDEN'})
+ uv_map = StringProperty(default="__default", options={'HIDDEN'})
+
+ @classmethod
+ def poll(cls, context):
+ # we can not get area/space/region from console
+ if common.is_console_mode():
+ return True
+ return is_valid_context(context)
@memorize_view_3d_mode
def execute(self, context):
- props = context.scene.muv_props.cpuv_obj
- if self.uv_map == "":
- self.report({'INFO'}, "Copy UV coordinate per object")
- else:
- self.report(
- {'INFO'},
- "Copy UV coordinate per object (UV map:%s)" % (self.uv_map))
+ props = context.scene.muv_props.copy_paste_uv_object
bpy.ops.object.mode_set(mode='EDIT')
-
obj = context.active_object
- bm = bmesh.from_edit_mesh(obj.data)
- if common.check_version(2, 73, 0) >= 0:
- bm.faces.ensure_lookup_table()
+ bm = common.create_bmesh(obj)
# get UV layer
- if self.uv_map == "":
- if not bm.loops.layers.uv:
- self.report(
- {'WARNING'}, "Object must have more than one UV map")
- return {'CANCELLED'}
- uv_layer = bm.loops.layers.uv.verify()
- else:
- uv_layer = bm.loops.layers.uv[self.uv_map]
+ uv_layers = get_copy_uv_layers(self, bm)
+ if not uv_layers:
+ return {'CANCELLED'}
# get selected face
- props.src_uvs = []
- props.src_pin_uvs = []
- props.src_seams = []
- for face in bm.faces:
- uvs = [l[uv_layer].uv.copy() for l in face.loops]
- pin_uvs = [l[uv_layer].pin_uv for l in face.loops]
- seams = [l.edge.seam for l in face.loops]
- props.src_uvs.append(uvs)
- props.src_pin_uvs.append(pin_uvs)
- props.src_seams.append(seams)
-
- self.report({'INFO'}, "%s's UV coordinates are copied" % (obj.name))
+ props.src_info = {}
+ for layer in uv_layers:
+ face_info = []
+ for face in bm.faces:
+ if face.select:
+ info = {
+ "uvs": [l[layer].uv.copy() for l in face.loops],
+ "pin_uvs": [l[layer].pin_uv for l in face.loops],
+ "seams": [l.edge.seam for l in face.loops],
+ }
+ face_info.append(info)
+ props.src_info[layer.name] = face_info
+
+ self.report({'INFO'},
+ "{}'s UV coordinates are copied".format(obj.name))
return {'FINISHED'}
-class MUV_CPUVObjCopyUVMenu(bpy.types.Menu):
+class MenuCopyUV(bpy.types.Menu):
"""
- Menu class: Copy UV coordinate per object
+ Menu class: Copy UV coordinate among objects
"""
- bl_idname = "object.muv_cpuv_obj_copy_uv_menu"
- bl_label = "Copy UV"
- bl_description = "Copy UV coordinate per object"
+ bl_idname = "object.muv_copy_paste_uv_object_menu_copy_uv"
+ bl_label = "Copy UV (Among Objects) (Menu)"
+ bl_description = "Menu of Copy UV coordinate (Among Objects)"
+
+ @classmethod
+ def poll(cls, context):
+ return is_valid_context(context)
def draw(self, _):
layout = self.layout
# create sub menu
uv_maps = bpy.context.active_object.data.uv_textures.keys()
- layout.operator(MUV_CPUVObjCopyUV.bl_idname, text="[Default]")\
- .uv_map = ""
+
+ ops = layout.operator(OperatorCopyUV.bl_idname, text="[Default]")
+ ops.uv_map = "__default"
+
+ ops = layout.operator(OperatorCopyUV.bl_idname, text="[All]")
+ ops.uv_map = "__all"
+
for m in uv_maps:
- layout.operator(MUV_CPUVObjCopyUV.bl_idname, text=m).uv_map = m
+ ops = layout.operator(OperatorCopyUV.bl_idname, text=m)
+ ops.uv_map = m
-class MUV_CPUVObjPasteUV(bpy.types.Operator):
+class OperatorPasteUV(bpy.types.Operator):
"""
- Operation class: Paste UV coordinate per object
+ Operation class: Paste UV coordinate among objects
"""
- bl_idname = "object.muv_cpuv_obj_paste_uv"
- bl_label = "Paste UV"
- bl_description = "Paste UV coordinate"
+ bl_idname = "object.muv_copy_paste_uv_object_operator_paste_uv"
+ bl_label = "Paste UV (Among Objects)"
+ bl_description = "Paste UV coordinate (Among Objects)"
bl_options = {'REGISTER', 'UNDO'}
- uv_map = StringProperty(options={'HIDDEN'})
+ uv_map = StringProperty(default="__default", options={'HIDDEN'})
copy_seams = BoolProperty(
- name="Copy Seams",
+ name="Seams",
description="Copy Seams",
default=True
)
+ @classmethod
+ def poll(cls, context):
+ # we can not get area/space/region from console
+ if common.is_console_mode():
+ return True
+ sc = context.scene
+ props = sc.muv_props.copy_paste_uv_object
+ if not props.src_info:
+ return False
+ return is_valid_context(context)
+
@memorize_view_3d_mode
def execute(self, context):
- props = context.scene.muv_props.cpuv_obj
- if not props.src_uvs or not props.src_pin_uvs:
+ props = context.scene.muv_props.copy_paste_uv_object
+ if not props.src_info:
self.report({'WARNING'}, "Need copy UV at first")
return {'CANCELLED'}
@@ -149,90 +221,67 @@ class MUV_CPUVObjPasteUV(bpy.types.Operator):
bpy.ops.object.mode_set(mode='EDIT')
obj = context.active_object
- bm = bmesh.from_edit_mesh(obj.data)
- if common.check_version(2, 73, 0) >= 0:
- bm.faces.ensure_lookup_table()
-
- if (self.uv_map == "" or
- self.uv_map not in bm.loops.layers.uv.keys()):
- self.report({'INFO'}, "Paste UV coordinate per object")
- else:
- self.report(
- {'INFO'},
- "Paste UV coordinate per object (UV map: %s)"
- % (self.uv_map))
+ bm = common.create_bmesh(obj)
# get UV layer
- if (self.uv_map == "" or
- self.uv_map not in bm.loops.layers.uv.keys()):
- if not bm.loops.layers.uv:
- self.report(
- {'WARNING'}, "Object must have more than one UV map")
- return {'CANCELLED'}
- uv_layer = bm.loops.layers.uv.verify()
- else:
- uv_layer = bm.loops.layers.uv[self.uv_map]
+ uv_layers = get_paste_uv_layers(self, obj, bm, props.src_info)
+ if not uv_layers:
+ return {'CANCELLED'}
# get selected face
- dest_uvs = []
- dest_pin_uvs = []
- dest_seams = []
- dest_face_indices = []
- for face in bm.faces:
- dest_face_indices.append(face.index)
- uvs = [l[uv_layer].uv.copy() for l in face.loops]
- pin_uvs = [l[uv_layer].pin_uv for l in face.loops]
- seams = [l.edge.seam for l in face.loops]
- dest_uvs.append(uvs)
- dest_pin_uvs.append(pin_uvs)
- dest_seams.append(seams)
- if len(props.src_uvs) != len(dest_uvs):
- self.report(
- {'WARNING'},
- "Number of faces is different from copied " +
- "(src:%d, dest:%d)"
- % (len(props.src_uvs), len(dest_uvs))
- )
- return {'CANCELLED'}
+ dest_info = {}
+ for layer in uv_layers:
+ face_info = []
+ for face in bm.faces:
+ if face.select:
+ info = {
+ "uvs": [l[layer].uv.copy() for l in face.loops],
+ }
+ face_info.append(info)
+ key = list(props.src_info.keys())[0]
+ src_face_count = len(props.src_info[key])
+ dest_face_count = len(face_info)
+ if src_face_count != dest_face_count:
+ self.report(
+ {'WARNING'},
+ "Number of selected faces is different from copied" +
+ "(src:{}, dest:{})"
+ .format(src_face_count, dest_face_count))
+ return {'CANCELLED'}
+ dest_info[layer.name] = face_info
# paste
- for i, idx in enumerate(dest_face_indices):
- suv = props.src_uvs[i]
- spuv = props.src_pin_uvs[i]
- ss = props.src_seams[i]
- duv = dest_uvs[i]
- if len(suv) != len(duv):
- self.report({'WARNING'}, "Some faces are different size")
- return {'CANCELLED'}
- suvs_fr = [uv for uv in suv]
- spuvs_fr = [pin_uv for pin_uv in spuv]
- ss_fr = [s for s in ss]
- # paste UVs
- for l, suv, spuv, ss in zip(
- bm.faces[idx].loops, suvs_fr, spuvs_fr, ss_fr):
- l[uv_layer].uv = suv
- l[uv_layer].pin_uv = spuv
- if self.copy_seams is True:
- l.edge.seam = ss
+ ret = paste_uv(self, bm, props.src_info, dest_info, uv_layers,
+ 'N_N', 0, 0, self.copy_seams)
+ if ret:
+ return {'CANCELLED'}
bmesh.update_edit_mesh(obj.data)
if self.copy_seams is True:
obj.data.show_edge_seams = True
self.report(
- {'INFO'}, "%s's UV coordinates are pasted" % (obj.name))
+ {'INFO'}, "{}'s UV coordinates are pasted".format(obj.name))
return {'FINISHED'}
-class MUV_CPUVObjPasteUVMenu(bpy.types.Menu):
+class MenuPasteUV(bpy.types.Menu):
"""
- Menu class: Paste UV coordinate per object
+ Menu class: Paste UV coordinate among objects
"""
- bl_idname = "object.muv_cpuv_obj_paste_uv_menu"
- bl_label = "Paste UV"
- bl_description = "Paste UV coordinate per object"
+ bl_idname = "object.muv_copy_paste_uv_object_menu_paste_uv"
+ bl_label = "Paste UV (Among Objects) (Menu)"
+ bl_description = "Menu of Paste UV coordinate (Among Objects)"
+
+ @classmethod
+ def poll(cls, context):
+ sc = context.scene
+ props = sc.muv_props.copy_paste_uv_object
+ if not props.src_info:
+ return False
+ return is_valid_context(context)
def draw(self, context):
sc = context.scene
@@ -242,11 +291,20 @@ class MUV_CPUVObjPasteUVMenu(bpy.types.Menu):
for obj in bpy.data.objects:
if hasattr(obj.data, "uv_textures") and obj.select:
uv_maps.extend(obj.data.uv_textures.keys())
- uv_maps = list(set(uv_maps))
- ops = layout.operator(MUV_CPUVObjPasteUV.bl_idname, text="[Default]")
- ops.uv_map = ""
- ops.copy_seams = sc.muv_cpuv_copy_seams
+
+ ops = layout.operator(OperatorPasteUV.bl_idname, text="[Default]")
+ ops.uv_map = "__default"
+ ops.copy_seams = sc.muv_copy_paste_uv_object_copy_seams
+
+ ops = layout.operator(OperatorPasteUV.bl_idname, text="[New]")
+ ops.uv_map = "__new"
+ ops.copy_seams = sc.muv_copy_paste_uv_object_copy_seams
+
+ ops = layout.operator(OperatorPasteUV.bl_idname, text="[All]")
+ ops.uv_map = "__all"
+ ops.copy_seams = sc.muv_copy_paste_uv_object_copy_seams
+
for m in uv_maps:
- ops = layout.operator(MUV_CPUVObjPasteUV.bl_idname, text=m)
+ ops = layout.operator(OperatorPasteUV.bl_idname, text=m)
ops.uv_map = m
- ops.copy_seams = sc.muv_cpuv_copy_seams
+ ops.copy_seams = sc.muv_copy_paste_uv_object_copy_seams