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.py314
1 files changed, 179 insertions, 135 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..d9f42447 100644
--- a/uv_magic_uv/op/copy_paste_uv_object.py
+++ b/uv_magic_uv/op/copy_paste_uv_object.py
@@ -20,17 +20,72 @@
__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
+import bpy
from bpy.props import (
StringProperty,
BoolProperty,
)
+from ..impl import copy_paste_uv_impl as impl
from .. import common
+from ..utils.bl_class_registry import BlClassRegistry
+from ..utils.property_class_registry import PropertyClassRegistry
+
+__all__ = [
+ 'Properties',
+ 'MUV_OT_CopyPasteUVObject_CopyUV',
+ 'MUV_MT_CopyPasteUVObject_CopyUV',
+ 'MUV_OT_CopyPasteUVObject_PasteUV',
+ 'MUV_MT_CopyPasteUVObject_PasteUV',
+]
+
+
+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
+
+
+@PropertyClassRegistry()
+class Properties:
+ idname = "copy_paste_uv_object"
+
+ @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
def memorize_view_3d_mode(fn):
@@ -42,197 +97,173 @@ def memorize_view_3d_mode(fn):
return __memorize_view_3d_mode
-class MUV_CPUVObjCopyUV(bpy.types.Operator):
+@BlClassRegistry()
+class MUV_OT_CopyPasteUVObject_CopyUV(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 = impl.get_copy_uv_layers(self, bm, self.uv_map)
+ 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))
+ src_info = impl.get_src_face_info(self, bm, uv_layers)
+ if src_info is None:
+ return {'CANCELLED'}
+ props.src_info = src_info
+
+ self.report({'INFO'},
+ "{}'s UV coordinates are copied".format(obj.name))
return {'FINISHED'}
-class MUV_CPUVObjCopyUVMenu(bpy.types.Menu):
+@BlClassRegistry()
+class MUV_MT_CopyPasteUVObject_CopyUV(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 = ""
+ uv_maps = bpy.context.active_object.data.uv_layers.keys()
+
+ ops = layout.operator(MUV_OT_CopyPasteUVObject_CopyUV.bl_idname,
+ text="[Default]")
+ ops.uv_map = "__default"
+
+ ops = layout.operator(MUV_OT_CopyPasteUVObject_CopyUV.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(MUV_OT_CopyPasteUVObject_CopyUV.bl_idname,
+ text=m)
+ ops.uv_map = m
-class MUV_CPUVObjPasteUV(bpy.types.Operator):
+@BlClassRegistry()
+class MUV_OT_CopyPasteUVObject_PasteUV(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'})
- copy_seams = BoolProperty(
- name="Copy Seams",
+ uv_map: StringProperty(default="__default", options={'HIDDEN'})
+ copy_seams: BoolProperty(
+ 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'}
for o in bpy.data.objects:
- if not hasattr(o.data, "uv_textures") or not o.select:
+ if not hasattr(o.data, "uv_layers") or not o.select_get():
continue
bpy.ops.object.mode_set(mode='OBJECT')
- bpy.context.scene.objects.active = o
+ bpy.context.view_layer.objects.active = o
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 = impl.get_paste_uv_layers(self, obj, bm, props.src_info,
+ self.uv_map)
+ 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))
- )
+ dest_info = impl.get_dest_face_info(self, bm, uv_layers,
+ props.src_info, 'N_N')
+ if dest_info is None:
return {'CANCELLED'}
# 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 = impl.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):
+@BlClassRegistry()
+class MUV_MT_CopyPasteUVObject_PasteUV(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
@@ -240,13 +271,26 @@ class MUV_CPUVObjPasteUVMenu(bpy.types.Menu):
# create sub menu
uv_maps = []
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
+ if hasattr(obj.data, "uv_layers") and obj.select_get():
+ uv_maps.extend(obj.data.uv_layers.keys())
+
+ ops = layout.operator(MUV_OT_CopyPasteUVObject_PasteUV.bl_idname,
+ text="[Default]")
+ ops.uv_map = "__default"
+ ops.copy_seams = sc.muv_copy_paste_uv_object_copy_seams
+
+ ops = layout.operator(MUV_OT_CopyPasteUVObject_PasteUV.bl_idname,
+ text="[New]")
+ ops.uv_map = "__new"
+ ops.copy_seams = sc.muv_copy_paste_uv_object_copy_seams
+
+ ops = layout.operator(MUV_OT_CopyPasteUVObject_PasteUV.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(MUV_OT_CopyPasteUVObject_PasteUV.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