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:
authorNutti <nutti.metro@gmail.com>2017-11-19 09:35:57 +0300
committerNutti <nutti.metro@gmail.com>2017-11-19 09:35:57 +0300
commit85a2b50e0e3d505f702a172efc0befa46e87d853 (patch)
tree3e93434e0f9e18a53f2384f0f9da96952614179d
parentc21b887882e6dd51abdab678e4ebadf9ed483077 (diff)
Magic UV: release v4.5
-rw-r--r--uv_magic_uv/__init__.py14
-rw-r--r--uv_magic_uv/muv_common.py12
-rw-r--r--uv_magic_uv/muv_cpuv_ops.py29
-rw-r--r--uv_magic_uv/muv_cpuv_selseq_ops.py25
-rw-r--r--uv_magic_uv/muv_fliprot_ops.py15
-rw-r--r--uv_magic_uv/muv_menu.py21
-rw-r--r--uv_magic_uv/muv_mirroruv_ops.py10
-rw-r--r--uv_magic_uv/muv_mvuv_ops.py4
-rw-r--r--uv_magic_uv/muv_packuv_ops.py14
-rw-r--r--uv_magic_uv/muv_preferences.py12
-rw-r--r--uv_magic_uv/muv_preserve_uv_aspect.py117
-rw-r--r--uv_magic_uv/muv_props.py12
-rw-r--r--uv_magic_uv/muv_texlock_ops.py10
-rw-r--r--uv_magic_uv/muv_texproj_ops.py4
-rw-r--r--uv_magic_uv/muv_transuv_ops.py76
-rw-r--r--uv_magic_uv/muv_unwrapconst_ops.py12
-rw-r--r--uv_magic_uv/muv_uvbb_ops.py45
-rw-r--r--uv_magic_uv/muv_uvw_ops.py222
-rw-r--r--uv_magic_uv/muv_wsuv_ops.py165
19 files changed, 640 insertions, 179 deletions
diff --git a/uv_magic_uv/__init__.py b/uv_magic_uv/__init__.py
index 6b9b6d2b..171a5ac4 100644
--- a/uv_magic_uv/__init__.py
+++ b/uv_magic_uv/__init__.py
@@ -20,15 +20,15 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
bl_info = {
"name": "Magic UV",
"author": "Nutti, Mifth, Jace Priester, kgeogeo, mem, "
- "Keith (Wahooney) Boshoff, McBuff, MaxRobinot",
- "version": (4, 4, 0),
+ "Keith (Wahooney) Boshoff, McBuff, MaxRobinot, Alexander Milovsky",
+ "version": (4, 5, 0),
"blender": (2, 79, 0),
"location": "See Add-ons Preferences",
"description": "UV Manipulator Tools. See Add-ons Preferences for details",
@@ -59,6 +59,7 @@ if "bpy" in locals():
importlib.reload(muv_wsuv_ops)
importlib.reload(muv_unwrapconst_ops)
importlib.reload(muv_preserve_uv_aspect)
+ importlib.reload(muv_uvw_ops)
else:
from . import muv_preferences
from . import muv_menu
@@ -77,6 +78,7 @@ else:
from . import muv_wsuv_ops
from . import muv_unwrapconst_ops
from . import muv_preserve_uv_aspect
+ from . import muv_uvw_ops
import bpy
@@ -84,7 +86,8 @@ import bpy
def view3d_uvmap_menu_fn(self, context):
self.layout.separator()
self.layout.menu(muv_menu.MUV_CPUVMenu.bl_idname, icon="IMAGE_COL")
- self.layout.operator(muv_fliprot_ops.MUV_FlipRot.bl_idname, icon="IMAGE_COL")
+ self.layout.operator(
+ muv_fliprot_ops.MUV_FlipRot.bl_idname, icon="IMAGE_COL")
self.layout.menu(muv_menu.MUV_TransUVMenu.bl_idname, icon="IMAGE_COL")
self.layout.operator(muv_mvuv_ops.MUV_MVUV.bl_idname, icon="IMAGE_COL")
self.layout.menu(muv_menu.MUV_TexLockMenu.bl_idname, icon="IMAGE_COL")
@@ -96,6 +99,7 @@ def view3d_uvmap_menu_fn(self, context):
self.layout.menu(
muv_preserve_uv_aspect.MUV_PreserveUVAspectMenu.bl_idname,
icon='IMAGE_COL')
+ self.layout.menu(muv_menu.MUV_UVWMenu.bl_idname, icon="IMAGE_COL")
def image_uvs_menu_fn(self, context):
diff --git a/uv_magic_uv/muv_common.py b/uv_magic_uv/muv_common.py
index ff2fe3f0..b52971ec 100644
--- a/uv_magic_uv/muv_common.py
+++ b/uv_magic_uv/muv_common.py
@@ -20,8 +20,8 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
import bpy
from . import muv_props
@@ -45,11 +45,9 @@ def check_version(major, minor, _):
return 0
if bpy.app.version[0] > major:
return 1
- else:
- if bpy.app.version[1] > minor:
- return 1
- else:
- return -1
+ if bpy.app.version[1] > minor:
+ return 1
+ return -1
def redraw_all_areas():
diff --git a/uv_magic_uv/muv_cpuv_ops.py b/uv_magic_uv/muv_cpuv_ops.py
index c3e0e6a3..82f043c6 100644
--- a/uv_magic_uv/muv_cpuv_ops.py
+++ b/uv_magic_uv/muv_cpuv_ops.py
@@ -20,17 +20,17 @@
__author__ = "Nutti <nutti.metro@gmail.com>, Jace Priester"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
import bpy
import bmesh
from bpy.props import (
- StringProperty,
- BoolProperty,
- IntProperty,
- EnumProperty,
- )
+ StringProperty,
+ BoolProperty,
+ IntProperty,
+ EnumProperty,
+)
from . import muv_common
@@ -85,11 +85,11 @@ class MUV_CPUVCopyUV(bpy.types.Operator):
if face.select:
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]
+ 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)
- if len(props.src_uvs) == 0 or len(props.src_pin_uvs) == 0:
+ if not props.src_uvs or not props.src_pin_uvs:
self.report({'WARNING'}, "No faces are selected")
return {'CANCELLED'}
self.report({'INFO'}, "%d face(s) are selected" % len(props.src_uvs))
@@ -164,7 +164,7 @@ class MUV_CPUVPasteUV(bpy.types.Operator):
def execute(self, context):
props = context.scene.muv_props.cpuv
- if len(props.src_uvs) == 0 or len(props.src_pin_uvs) == 0:
+ if not props.src_uvs or not props.src_pin_uvs:
self.report({'WARNING'}, "Need copy UV at first")
return {'CANCELLED'}
if self.uv_map == "":
@@ -201,7 +201,7 @@ class MUV_CPUVPasteUV(bpy.types.Operator):
dest_uvs.append(uvs)
dest_pin_uvs.append(pin_uvs)
dest_seams.append(seams)
- if len(dest_uvs) == 0 or len(dest_pin_uvs) == 0:
+ if not dest_uvs or not dest_pin_uvs:
self.report({'WARNING'}, "No faces are selected")
return {'CANCELLED'}
if self.strategy == 'N_N' and len(props.src_uvs) != len(dest_uvs):
@@ -248,7 +248,8 @@ class MUV_CPUVPasteUV(bpy.types.Operator):
spuvs_fr.insert(0, pin_uv)
ss_fr.insert(0, s)
# paste UVs
- for l, suv, spuv, ss in zip(bm.faces[idx].loops, suvs_fr, spuvs_fr, ss_fr):
+ 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:
@@ -331,7 +332,7 @@ class MUV_CPUVObjCopyUV(bpy.types.Operator):
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]
+ 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)
@@ -383,7 +384,7 @@ class MUV_CPUVObjPasteUV(bpy.types.Operator):
@memorize_view_3d_mode
def execute(self, context):
props = context.scene.muv_props.cpuv_obj
- if len(props.src_uvs) == 0 or len(props.src_pin_uvs) == 0:
+ if not props.src_uvs or not props.src_pin_uvs:
self.report({'WARNING'}, "Need copy UV at first")
return {'CANCELLED'}
diff --git a/uv_magic_uv/muv_cpuv_selseq_ops.py b/uv_magic_uv/muv_cpuv_selseq_ops.py
index 5a1154a9..3cf69ff7 100644
--- a/uv_magic_uv/muv_cpuv_selseq_ops.py
+++ b/uv_magic_uv/muv_cpuv_selseq_ops.py
@@ -20,17 +20,17 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
import bpy
import bmesh
from bpy.props import (
- StringProperty,
- BoolProperty,
- IntProperty,
- EnumProperty,
- )
+ StringProperty,
+ BoolProperty,
+ IntProperty,
+ EnumProperty,
+)
from . import muv_common
@@ -78,11 +78,11 @@ class MUV_CPUVSelSeqCopyUV(bpy.types.Operator):
if isinstance(hist, bmesh.types.BMFace) and hist.select:
uvs = [l[uv_layer].uv.copy() for l in hist.loops]
pin_uvs = [l[uv_layer].pin_uv for l in hist.loops]
- seams = [l.edge.seam for l in hist.loops]
+ seams = [l.edge.seam for l in hist.loops]
props.src_uvs.append(uvs)
props.src_pin_uvs.append(pin_uvs)
props.src_seams.append(seams)
- if len(props.src_uvs) == 0 or len(props.src_pin_uvs) == 0:
+ if not props.src_uvs or not props.src_pin_uvs:
self.report({'WARNING'}, "No faces are selected")
return {'CANCELLED'}
self.report({'INFO'}, "%d face(s) are selected" % len(props.src_uvs))
@@ -152,7 +152,7 @@ class MUV_CPUVSelSeqPasteUV(bpy.types.Operator):
def execute(self, context):
props = context.scene.muv_props.cpuv_selseq
- if len(props.src_uvs) == 0 or len(props.src_pin_uvs) == 0:
+ if not props.src_uvs or not props.src_pin_uvs:
self.report({'WARNING'}, "Need copy UV at first")
return {'CANCELLED'}
if self.uv_map == "":
@@ -192,7 +192,7 @@ class MUV_CPUVSelSeqPasteUV(bpy.types.Operator):
dest_uvs.append(uvs)
dest_pin_uvs.append(pin_uvs)
dest_seams.append(seams)
- if len(dest_uvs) == 0 or len(dest_pin_uvs) == 0:
+ if not dest_uvs or not dest_pin_uvs:
self.report({'WARNING'}, "No faces are selected")
return {'CANCELLED'}
if self.strategy == 'N_N' and len(props.src_uvs) != len(dest_uvs):
@@ -239,7 +239,8 @@ class MUV_CPUVSelSeqPasteUV(bpy.types.Operator):
spuvs_fr.insert(0, pin_uv)
ss_fr.insert(0, s)
# paste UVs
- for l, suv, spuv, ss in zip(bm.faces[idx].loops, suvs_fr, spuvs_fr, ss_fr):
+ 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:
diff --git a/uv_magic_uv/muv_fliprot_ops.py b/uv_magic_uv/muv_fliprot_ops.py
index 7b8b6a7f..334eb14c 100644
--- a/uv_magic_uv/muv_fliprot_ops.py
+++ b/uv_magic_uv/muv_fliprot_ops.py
@@ -20,15 +20,15 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
import bpy
import bmesh
from bpy.props import (
- BoolProperty,
- IntProperty,
- )
+ BoolProperty,
+ IntProperty,
+)
from . import muv_common
@@ -86,13 +86,14 @@ class MUV_FlipRot(bpy.types.Operator):
dest_uvs.append(uvs)
dest_pin_uvs.append(pin_uvs)
dest_seams.append(seams)
- if len(dest_uvs) == 0 or len(dest_pin_uvs) == 0:
+ if not dest_uvs or not dest_pin_uvs:
self.report({'WARNING'}, "No faces are selected")
return {'CANCELLED'}
self.report({'INFO'}, "%d face(s) are selected" % len(dest_uvs))
# paste
- for idx, duvs, dpuvs, dss in zip(dest_face_indices, dest_uvs, dest_pin_uvs, dest_seams):
+ for idx, duvs, dpuvs, dss in zip(dest_face_indices, dest_uvs,
+ dest_pin_uvs, dest_seams):
duvs_fr = [uv for uv in duvs]
dpuvs_fr = [pin_uv for pin_uv in dpuvs]
dss_fr = [s for s in dss]
diff --git a/uv_magic_uv/muv_menu.py b/uv_magic_uv/muv_menu.py
index f53a8d7f..47c79bbd 100644
--- a/uv_magic_uv/muv_menu.py
+++ b/uv_magic_uv/muv_menu.py
@@ -20,8 +20,8 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
import bpy
from . import muv_cpuv_ops
@@ -29,6 +29,7 @@ from . import muv_cpuv_selseq_ops
from . import muv_transuv_ops
from . import muv_texlock_ops
from . import muv_wsuv_ops
+from . import muv_uvw_ops
class MUV_CPUVMenu(bpy.types.Menu):
@@ -119,3 +120,19 @@ class MUV_WSUVMenu(bpy.types.Menu):
muv_wsuv_ops.MUV_WSUVMeasure.bl_idname, icon="IMAGE_COL")
self.layout.operator(
muv_wsuv_ops.MUV_WSUVApply.bl_idname, icon="IMAGE_COL")
+
+
+class MUV_UVWMenu(bpy.types.Menu):
+ """
+ Menu class: Master menu of UVW
+ """
+
+ bl_idname = "uv.muv_uvw_menu"
+ bl_label = "UVW"
+ bl_description = ""
+
+ def draw(self, _):
+ self.layout.operator(
+ muv_uvw_ops.MUV_UVWBoxMap.bl_idname, icon="IMAGE_COL")
+ self.layout.operator(
+ muv_uvw_ops.MUV_UVWBestPlanerMap.bl_idname, icon="IMAGE_COL")
diff --git a/uv_magic_uv/muv_mirroruv_ops.py b/uv_magic_uv/muv_mirroruv_ops.py
index e1955360..63eb9bd5 100644
--- a/uv_magic_uv/muv_mirroruv_ops.py
+++ b/uv_magic_uv/muv_mirroruv_ops.py
@@ -20,14 +20,14 @@
__author__ = "Keith (Wahooney) Boshoff, Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
import bpy
from bpy.props import (
- EnumProperty,
- FloatProperty,
- )
+ EnumProperty,
+ FloatProperty,
+)
import bmesh
from mathutils import Vector
from . import muv_common
diff --git a/uv_magic_uv/muv_mvuv_ops.py b/uv_magic_uv/muv_mvuv_ops.py
index 847b34fe..28346270 100644
--- a/uv_magic_uv/muv_mvuv_ops.py
+++ b/uv_magic_uv/muv_mvuv_ops.py
@@ -20,8 +20,8 @@
__author__ = "kgeogeo, mem, Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
import bpy
import bmesh
diff --git a/uv_magic_uv/muv_packuv_ops.py b/uv_magic_uv/muv_packuv_ops.py
index 66d32766..f663e662 100644
--- a/uv_magic_uv/muv_packuv_ops.py
+++ b/uv_magic_uv/muv_packuv_ops.py
@@ -20,8 +20,8 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
from math import fabs
from collections import defaultdict
@@ -30,10 +30,10 @@ import bpy
import bmesh
import mathutils
from bpy.props import (
- FloatProperty,
- FloatVectorProperty,
- BoolProperty,
- )
+ FloatProperty,
+ FloatVectorProperty,
+ BoolProperty,
+)
from mathutils import Vector
from . import muv_common
@@ -279,7 +279,7 @@ class MUV_PackUV(bpy.types.Operator):
uv_island_lists = []
faces_left = set(self.__face_to_verts.keys())
- while len(faces_left) > 0:
+ while faces_left:
current_island = []
face_idx = list(faces_left)[0]
self.__parse_island(bm, face_idx, faces_left, current_island)
diff --git a/uv_magic_uv/muv_preferences.py b/uv_magic_uv/muv_preferences.py
index fe807d67..e14ce99b 100644
--- a/uv_magic_uv/muv_preferences.py
+++ b/uv_magic_uv/muv_preferences.py
@@ -20,14 +20,14 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
from bpy.props import (
- BoolProperty,
- FloatProperty,
- FloatVectorProperty,
- )
+ BoolProperty,
+ FloatProperty,
+ FloatVectorProperty,
+)
from bpy.types import AddonPreferences
diff --git a/uv_magic_uv/muv_preserve_uv_aspect.py b/uv_magic_uv/muv_preserve_uv_aspect.py
index 93f53307..68e75f74 100644
--- a/uv_magic_uv/muv_preserve_uv_aspect.py
+++ b/uv_magic_uv/muv_preserve_uv_aspect.py
@@ -20,12 +20,12 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
import bpy
import bmesh
-from bpy.props import StringProperty
+from bpy.props import StringProperty, EnumProperty
from mathutils import Vector
from . import muv_common
@@ -41,6 +41,23 @@ class MUV_PreserveUVAspect(bpy.types.Operator):
bl_options = {'REGISTER', 'UNDO'}
dest_img_name = StringProperty(options={'HIDDEN'})
+ origin = EnumProperty(
+ name="Origin",
+ description="Aspect Origin",
+ items=[
+ ('CENTER', 'Center', 'Center'),
+ ('LEFT_TOP', 'Left Top', 'Left Bottom'),
+ ('LEFT_CENTER', 'Left Center', 'Left Center'),
+ ('LEFT_BOTTOM', 'Left Bottom', 'Left Bottom'),
+ ('CENTER_TOP', 'Center Top', 'Center Top'),
+ ('CENTER_BOTTOM', 'Center Bottom', 'Center Bottom'),
+ ('RIGHT_TOP', 'Right Top', 'Right Top'),
+ ('RIGHT_CENTER', 'Right Center', 'Right Center'),
+ ('RIGHT_BOTTOM', 'Right Bottom', 'Right Bottom')
+
+ ],
+ default="CENTER"
+ )
@classmethod
def poll(cls, context):
@@ -83,12 +100,85 @@ class MUV_PreserveUVAspect(bpy.types.Operator):
ratio = Vector((
dest_img.size[0] / src_img.size[0],
dest_img.size[1] / src_img.size[1]))
- origin = Vector((100000.0, 100000.0))
- for f in info[img]['faces']:
- for l in f.loops:
- uv = l[uv_layer].uv
- origin.x = min(uv.x, origin.x)
- origin.y = min(uv.y, origin.y)
+
+ if self.origin == 'CENTER':
+ origin = Vector((0.0, 0.0))
+ num = 0
+ for f in info[img]['faces']:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin = origin + uv
+ num = num + 1
+ origin = origin / num
+ elif self.origin == 'LEFT_TOP':
+ origin = Vector((100000.0, -100000.0))
+ for f in info[img]['faces']:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = min(origin.x, uv.x)
+ origin.y = max(origin.y, uv.y)
+ elif self.origin == 'LEFT_CENTER':
+ origin = Vector((100000.0, 0.0))
+ num = 0
+ for f in info[img]['faces']:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = min(origin.x, uv.x)
+ origin.y = origin.y + uv.y
+ num = num + 1
+ origin.y = origin.y / num
+ elif self.origin == 'LEFT_BOTTOM':
+ origin = Vector((100000.0, 100000.0))
+ for f in info[img]['faces']:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = min(origin.x, uv.x)
+ origin.y = min(origin.y, uv.y)
+ elif self.origin == 'CENTER_TOP':
+ origin = Vector((0.0, -100000.0))
+ num = 0
+ for f in info[img]['faces']:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = origin.x + uv.x
+ origin.y = max(origin.y, uv.y)
+ num = num + 1
+ origin.x = origin.x / num
+ elif self.origin == 'CENTER_BOTTOM':
+ origin = Vector((0.0, 100000.0))
+ num = 0
+ for f in info[img]['faces']:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = origin.x + uv.x
+ origin.y = min(origin.y, uv.y)
+ num = num + 1
+ origin.x = origin.x / num
+ elif self.origin == 'RIGHT_TOP':
+ origin = Vector((-100000.0, -100000.0))
+ for f in info[img]['faces']:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = max(origin.x, uv.x)
+ origin.y = max(origin.y, uv.y)
+ elif self.origin == 'RIGHT_CENTER':
+ origin = Vector((-100000.0, 0.0))
+ num = 0
+ for f in info[img]['faces']:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = max(origin.x, uv.x)
+ origin.y = origin.y + uv.y
+ num = num + 1
+ origin.y = origin.y / num
+ elif self.origin == 'RIGHT_BOTTOM':
+ origin = Vector((-100000.0, 100000.0))
+ for f in info[img]['faces']:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = max(origin.x, uv.x)
+ origin.y = min(origin.y, uv.y)
+
info[img]['ratio'] = ratio
info[img]['origin'] = origin
@@ -100,11 +190,14 @@ class MUV_PreserveUVAspect(bpy.types.Operator):
f[tex_layer].image = dest_img
for l in f.loops:
uv = l[uv_layer].uv
- diff = uv - info[img]['origin']
- diff.x = diff.x / info[img]['ratio'].x
- diff.y = diff.y / info[img]['ratio'].y
+ origin = info[img]['origin']
+ ratio = info[img]['ratio']
+ diff = uv - origin
+ diff.x = diff.x / ratio.x
+ diff.y = diff.y / ratio.y
uv.x = origin.x + diff.x
uv.y = origin.y + diff.y
+ l[uv_layer].uv = uv
bmesh.update_edit_mesh(obj.data)
diff --git a/uv_magic_uv/muv_props.py b/uv_magic_uv/muv_props.py
index 24f552d5..c0a7d961 100644
--- a/uv_magic_uv/muv_props.py
+++ b/uv_magic_uv/muv_props.py
@@ -20,15 +20,15 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
import bpy
from bpy.props import (
- FloatProperty,
- EnumProperty,
- BoolProperty,
- )
+ FloatProperty,
+ EnumProperty,
+ BoolProperty,
+)
DEBUG = False
diff --git a/uv_magic_uv/muv_texlock_ops.py b/uv_magic_uv/muv_texlock_ops.py
index 08b42309..bfc95129 100644
--- a/uv_magic_uv/muv_texlock_ops.py
+++ b/uv_magic_uv/muv_texlock_ops.py
@@ -20,14 +20,14 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
import math
from math import (
- atan2, cos,
- sqrt, sin, fabs,
- )
+ atan2, cos,
+ sqrt, sin, fabs,
+)
import bpy
import bmesh
diff --git a/uv_magic_uv/muv_texproj_ops.py b/uv_magic_uv/muv_texproj_ops.py
index 1cf749ab..ffa4e789 100644
--- a/uv_magic_uv/muv_texproj_ops.py
+++ b/uv_magic_uv/muv_texproj_ops.py
@@ -20,8 +20,8 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
from collections import namedtuple
diff --git a/uv_magic_uv/muv_transuv_ops.py b/uv_magic_uv/muv_transuv_ops.py
index faf1304d..ed0a3c46 100644
--- a/uv_magic_uv/muv_transuv_ops.py
+++ b/uv_magic_uv/muv_transuv_ops.py
@@ -20,8 +20,8 @@
__author__ = "Nutti <nutti.metro@gmail.com>, Mifth, MaxRobinot"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
from collections import OrderedDict
@@ -134,46 +134,48 @@ class MUV_TransUVPaste(bpy.types.Operator):
# parse selection history
for i, _ in enumerate(all_sel_faces):
- if i > 0 and i % 2 != 0:
- sel_faces = [all_sel_faces[i - 1], all_sel_faces[i]]
- active_face = all_sel_faces[i]
-
- # parse all faces according to selection history
- active_face_nor = active_face.normal.copy()
- if self.invert_normals:
- active_face_nor.negate()
- all_sorted_faces = main_parse(
- self, uv_layer, sel_faces, active_face,
- active_face_nor)
-
- if all_sorted_faces:
- # check amount of copied/pasted faces
- if len(all_sorted_faces) != len(props.topology_copied):
+ if (i == 0) or (i % 2 == 0):
+ continue
+ sel_faces = [all_sel_faces[i - 1], all_sel_faces[i]]
+ active_face = all_sel_faces[i]
+
+ # parse all faces according to selection history
+ active_face_nor = active_face.normal.copy()
+ if self.invert_normals:
+ active_face_nor.negate()
+ all_sorted_faces = main_parse(
+ self, uv_layer, sel_faces, active_face,
+ active_face_nor)
+
+ if all_sorted_faces:
+ # check amount of copied/pasted faces
+ if len(all_sorted_faces) != len(props.topology_copied):
+ self.report(
+ {'WARNING'},
+ "Mesh has different amount of faces"
+ )
+ return {'FINISHED'}
+
+ for j, face_data in enumerate(all_sorted_faces.values()):
+ copied_data = props.topology_copied[j]
+
+ # check amount of copied/pasted verts
+ if len(copied_data[0]) != len(face_data[2]):
+ bpy.ops.mesh.select_all(action='DESELECT')
+ # select problematic face
+ list(all_sorted_faces.keys())[j].select = True
self.report(
{'WARNING'},
- "Mesh has different amount of faces"
+ "Face have different amount of vertices"
)
return {'FINISHED'}
- for i, face_data in enumerate(all_sorted_faces.values()):
- copied_data = props.topology_copied[i]
-
- # check amount of copied/pasted verts
- if len(copied_data[0]) != len(face_data[2]):
- bpy.ops.mesh.select_all(action='DESELECT')
- # select problematic face
- list(all_sorted_faces.keys())[i].select = True
- self.report(
- {'WARNING'},
- "Face have different amount of vertices"
- )
- return {'FINISHED'}
-
- for j, (edge, uvloop) in enumerate(zip(face_data[1], face_data[2])):
- uvloop.uv = copied_data[0][j]
- uvloop.pin_uv = copied_data[1][j]
- if self.copy_seams:
- edge.seam = copied_data[2][j]
+ for k, (edge, uvloop) in enumerate(zip(face_data[1],
+ face_data[2])):
+ uvloop.uv = copied_data[0][k]
+ uvloop.pin_uv = copied_data[1][k]
+ if self.copy_seams:
+ edge.seam = copied_data[2][k]
bmesh.update_edit_mesh(active_obj.data)
if self.copy_seams:
diff --git a/uv_magic_uv/muv_unwrapconst_ops.py b/uv_magic_uv/muv_unwrapconst_ops.py
index 28800c42..1a691119 100644
--- a/uv_magic_uv/muv_unwrapconst_ops.py
+++ b/uv_magic_uv/muv_unwrapconst_ops.py
@@ -18,16 +18,16 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
import bpy
import bmesh
from bpy.props import (
- BoolProperty,
- EnumProperty,
- FloatProperty,
- )
+ BoolProperty,
+ EnumProperty,
+ FloatProperty,
+)
from . import muv_common
diff --git a/uv_magic_uv/muv_uvbb_ops.py b/uv_magic_uv/muv_uvbb_ops.py
index c3fedf8e..4f7b0631 100644
--- a/uv_magic_uv/muv_uvbb_ops.py
+++ b/uv_magic_uv/muv_uvbb_ops.py
@@ -20,8 +20,8 @@
__author__ = "Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
from enum import IntEnum
import math
@@ -399,26 +399,25 @@ class MUV_UVBBStateNone(MUV_UVBBStateBase):
prefs = context.user_preferences.addons["uv_magic_uv"].preferences
cp_react_size = prefs.uvbb_cp_react_size
is_uscaling = context.scene.muv_uvbb_uniform_scaling
- if event.type == 'LEFTMOUSE':
- if event.value == 'PRESS':
- x, y = context.region.view2d.view_to_region(
- mouse_view.x, mouse_view.y)
- for i, p in enumerate(ctrl_points):
- px, py = context.region.view2d.view_to_region(p.x, p.y)
- in_cp_x = (px + cp_react_size > x and
- px - cp_react_size < x)
- in_cp_y = (py + cp_react_size > y and
- py - cp_react_size < y)
- if in_cp_x and in_cp_y:
- if is_uscaling:
- arr = [1, 3, 6, 8]
- if i in arr:
- return (
- MUV_UVBBState.UNIFORM_SCALING_1 +
- arr.index(i)
- )
- else:
- return MUV_UVBBState.TRANSLATING + i
+ if (event.type == 'LEFTMOUSE') and (event.value == 'PRESS'):
+ x, y = context.region.view2d.view_to_region(
+ mouse_view.x, mouse_view.y)
+ for i, p in enumerate(ctrl_points):
+ px, py = context.region.view2d.view_to_region(p.x, p.y)
+ in_cp_x = (px + cp_react_size > x and
+ px - cp_react_size < x)
+ in_cp_y = (py + cp_react_size > y and
+ py - cp_react_size < y)
+ if in_cp_x and in_cp_y:
+ if is_uscaling:
+ arr = [1, 3, 6, 8]
+ if i in arr:
+ return (
+ MUV_UVBBState.UNIFORM_SCALING_1 +
+ arr.index(i)
+ )
+ else:
+ return MUV_UVBBState.TRANSLATING + i
return MUV_UVBBState.NONE
@@ -615,7 +614,7 @@ class MUV_UVBBUpdater(bpy.types.Operator):
if f.select:
for i, l in enumerate(f.loops):
uv_info.append((f.index, i, l[uv_layer].uv.copy()))
- if len(uv_info) == 0:
+ if not uv_info:
return None
return uv_info
diff --git a/uv_magic_uv/muv_uvw_ops.py b/uv_magic_uv/muv_uvw_ops.py
new file mode 100644
index 00000000..eb366e97
--- /dev/null
+++ b/uv_magic_uv/muv_uvw_ops.py
@@ -0,0 +1,222 @@
+# <pep8-80 compliant>
+
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+__author__ = "Alexander Milovsky, Nutti <nutti.metro@gmail.com>"
+__status__ = "production"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
+
+
+from math import sin, cos, pi
+
+import bpy
+import bmesh
+from bpy.props import (
+ FloatProperty,
+ FloatVectorProperty
+)
+from mathutils import Vector
+
+from . import muv_common
+
+
+class MUV_UVWBoxMap(bpy.types.Operator):
+ bl_idname = "uv.muv_uvw_box_map"
+ bl_label = "Box Map"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ size = FloatProperty(
+ name="Size",
+ default=1.0,
+ precision=4
+ )
+ rotation = FloatVectorProperty(
+ name="XYZ Rotation",
+ size=3,
+ default=(0.0, 0.0, 0.0)
+ )
+ offset = FloatVectorProperty(
+ name="XYZ Offset",
+ size=3,
+ default=(0.0, 0.0, 0.0)
+ )
+ tex_aspect = FloatProperty(
+ name="Texture Aspect",
+ default=1.0,
+ precision=4
+ )
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.active_object
+ return obj and obj.type == 'MESH'
+
+ def execute(self, context):
+ obj = context.active_object
+ bm = bmesh.from_edit_mesh(obj.data)
+ if muv_common.check_version(2, 73, 0) >= 0:
+ bm.faces.ensure_lookup_table()
+
+ # get UV layer
+ 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()
+
+ scale = 1.0 / self.size
+
+ sx = 1.0 * scale
+ sy = 1.0 * scale
+ sz = 1.0 * scale
+ ofx = self.offset[0]
+ ofy = self.offset[1]
+ ofz = self.offset[2]
+ rx = self.rotation[0] * pi / 180.0
+ ry = self.rotation[1] * pi / 180.0
+ rz = self.rotation[2] * pi / 180.0
+ aspect = self.tex_aspect
+
+ sel_faces = [f for f in bm.faces if f.select]
+
+ # update UV coordinate
+ for f in sel_faces:
+ n = f.normal
+ for l in f.loops:
+ co = l.vert.co
+ x = co.x * sx
+ y = co.y * sy
+ z = co.z * sz
+
+ # X-plane
+ if abs(n[0]) >= abs(n[1]) and abs(n[0]) >= abs(n[2]):
+ if n[0] >= 0.0:
+ u = (y - ofy) * cos(rx) + (z - ofz) * sin(rx)
+ v = -(y * aspect - ofy) * sin(rx) +\
+ (z * aspect - ofz) * cos(rx)
+ else:
+ u = -(y - ofy) * cos(rx) + (z - ofz) * sin(rx)
+ v = (y * aspect - ofy) * sin(rx) +\
+ (z * aspect - ofz) * cos(rx)
+ # Y-plane
+ elif abs(n[1]) >= abs(n[0]) and abs(n[1]) >= abs(n[2]):
+ if n[1] >= 0.0:
+ u = -(x - ofx) * cos(ry) + (z - ofz) * sin(ry)
+ v = (x * aspect - ofx) * sin(ry) +\
+ (z * aspect - ofz) * cos(ry)
+ else:
+ u = (x - ofx) * cos(ry) + (z - ofz) * sin(ry)
+ v = -(x * aspect - ofx) * sin(ry) +\
+ (z * aspect - ofz) * cos(ry)
+ # Z-plane
+ else:
+ if n[2] >= 0.0:
+ u = (x - ofx) * cos(rz) + (y - ofy) * sin(rz)
+ v = -(x * aspect - ofx) * sin(rz) +\
+ (y * aspect - ofy) * cos(rz)
+ else:
+ u = -(x - ofx) * cos(rz) - (y + ofy) * sin(rz)
+ v = -(x * aspect + ofx) * sin(rz) +\
+ (y * aspect - ofy) * cos(rz)
+
+ l[uv_layer].uv = Vector((u, v))
+
+ bmesh.update_edit_mesh(obj.data)
+
+ return {'FINISHED'}
+
+
+class MUV_UVWBestPlanerMap(bpy.types.Operator):
+ bl_idname = "uv.muv_uvw_best_planer_map"
+ bl_label = "Best Planer Map"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ size = FloatProperty(
+ name="Size",
+ default=1.0,
+ precision=4
+ )
+ rotation = FloatProperty(
+ name="XY Rotation",
+ default=0.0
+ )
+ offset = FloatVectorProperty(
+ name="XY Offset",
+ size=2,
+ default=(0.0, 0.0)
+ )
+ tex_aspect = FloatProperty(
+ name="Texture Aspect",
+ default=1.0,
+ precision=4
+ )
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.active_object
+ return obj and obj.type == 'MESH'
+
+ def execute(self, context):
+ obj = context.active_object
+ bm = bmesh.from_edit_mesh(obj.data)
+ if muv_common.check_version(2, 73, 0) >= 0:
+ bm.faces.ensure_lookup_table()
+
+ # get UV layer
+ 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()
+
+ scale = 1.0 / self.size
+
+ sx = 1.0 * scale
+ sy = 1.0 * scale
+ ofx = self.offset[0]
+ ofy = self.offset[1]
+ rz = self.rotation * pi / 180.0
+ aspect = self.tex_aspect
+
+ sel_faces = [f for f in bm.faces if f.select]
+
+ # calculate average of normal
+ n_ave = Vector((0.0, 0.0, 0.0))
+ for f in sel_faces:
+ n_ave = n_ave + f.normal
+ q = n_ave.rotation_difference(Vector((0.0, 0.0, 1.0)))
+
+ # update UV coordinate
+ for f in sel_faces:
+ for l in f.loops:
+ co = q * l.vert.co
+ x = co.x * sx
+ y = co.y * sy
+
+ u = x * cos(rz) - y * sin(rz) + ofx
+ v = -x * aspect * sin(rz) - y * aspect * cos(rz) + ofy
+
+ l[uv_layer].uv = Vector((u, v))
+
+ bmesh.update_edit_mesh(obj.data)
+
+ return {'FINISHED'}
diff --git a/uv_magic_uv/muv_wsuv_ops.py b/uv_magic_uv/muv_wsuv_ops.py
index 3e47d960..4ee8b4f9 100644
--- a/uv_magic_uv/muv_wsuv_ops.py
+++ b/uv_magic_uv/muv_wsuv_ops.py
@@ -20,12 +20,18 @@
__author__ = "McBuff, Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "4.4"
-__date__ = "2 Aug 2017"
+__version__ = "4.5"
+__date__ = "19 Nov 2017"
import bpy
import bmesh
+from mathutils import Vector
+from bpy.props import (
+ FloatProperty,
+ BoolProperty,
+ EnumProperty
+)
from . import muv_common
@@ -86,6 +92,9 @@ class MUV_WSUVMeasure(bpy.types.Operator):
props.ref_scale = scale / len(sel_faces)
+ self.report(
+ {'INFO'}, "Average face size: {0}".format(props.ref_scale))
+
return {'FINISHED'}
@@ -99,6 +108,44 @@ class MUV_WSUVApply(bpy.types.Operator):
bl_description = "Apply scaled UV based on scale calculation"
bl_options = {'REGISTER', 'UNDO'}
+ proportional_scaling = BoolProperty(
+ name="Proportional Scaling",
+ default=True
+ )
+ scaling_factor = FloatProperty(
+ name="Scaling Factor",
+ default=1.0,
+ max=1000.0,
+ min=0.00001
+ )
+ origin = EnumProperty(
+ name="Origin",
+ description="Aspect Origin",
+ items=[
+ ('CENTER', 'Center', 'Center'),
+ ('LEFT_TOP', 'Left Top', 'Left Bottom'),
+ ('LEFT_CENTER', 'Left Center', 'Left Center'),
+ ('LEFT_BOTTOM', 'Left Bottom', 'Left Bottom'),
+ ('CENTER_TOP', 'Center Top', 'Center Top'),
+ ('CENTER_BOTTOM', 'Center Bottom', 'Center Bottom'),
+ ('RIGHT_TOP', 'Right Top', 'Right Top'),
+ ('RIGHT_CENTER', 'Right Center', 'Right Center'),
+ ('RIGHT_BOTTOM', 'Right Bottom', 'Right Bottom')
+
+ ],
+ default="CENTER"
+ )
+
+ def draw(self, _):
+ layout = self.layout
+
+ row = layout.row()
+ row.prop(self, "proportional_scaling")
+ row = layout.row()
+ row.prop(self, "scaling_factor")
+ if self.proportional_scaling:
+ row.enabled = False
+
def execute(self, context):
props = context.scene.muv_props.wsuv
obj = bpy.context.active_object
@@ -122,26 +169,102 @@ class MUV_WSUVApply(bpy.types.Operator):
scale = scale + calc_face_scale(uv_layer, f)
scale = scale / len(sel_faces)
- ratio = props.ref_scale / scale
-
- orig_area = bpy.context.area.type
- bpy.context.area.type = 'IMAGE_EDITOR'
-
- # select all UV related to the selected faces
- bpy.ops.uv.select_all(action='SELECT')
-
- # apply scaled UV
- bpy.ops.transform.resize(
- value=(ratio, ratio, ratio),
- constraint_axis=(False, False, False),
- constraint_orientation='GLOBAL',
- mirror=False,
- proportional='DISABLED',
- proportional_edit_falloff='SMOOTH',
- proportional_size=1)
-
- bpy.context.area.type = orig_area
+ self.report(
+ {'INFO'}, "Average face size: {0}".format(scale))
+
+ if self.proportional_scaling:
+ factor = props.ref_scale / scale
+ else:
+ factor = self.scaling_factor
+
+ # calculate origin
+ if self.origin == 'CENTER':
+ origin = Vector((0.0, 0.0))
+ num = 0
+ for f in sel_faces:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin = origin + uv
+ num = num + 1
+ origin = origin / num
+ elif self.origin == 'LEFT_TOP':
+ origin = Vector((100000.0, -100000.0))
+ for f in sel_faces:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = min(origin.x, uv.x)
+ origin.y = max(origin.y, uv.y)
+ elif self.origin == 'LEFT_CENTER':
+ origin = Vector((100000.0, 0.0))
+ num = 0
+ for f in sel_faces:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = min(origin.x, uv.x)
+ origin.y = origin.y + uv.y
+ num = num + 1
+ origin.y = origin.y / num
+ elif self.origin == 'LEFT_BOTTOM':
+ origin = Vector((100000.0, 100000.0))
+ for f in sel_faces:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = min(origin.x, uv.x)
+ origin.y = min(origin.y, uv.y)
+ elif self.origin == 'CENTER_TOP':
+ origin = Vector((0.0, -100000.0))
+ num = 0
+ for f in sel_faces:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = origin.x + uv.x
+ origin.y = max(origin.y, uv.y)
+ num = num + 1
+ origin.x = origin.x / num
+ elif self.origin == 'CENTER_BOTTOM':
+ origin = Vector((0.0, 100000.0))
+ num = 0
+ for f in sel_faces:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = origin.x + uv.x
+ origin.y = min(origin.y, uv.y)
+ num = num + 1
+ origin.x = origin.x / num
+ elif self.origin == 'RIGHT_TOP':
+ origin = Vector((-100000.0, -100000.0))
+ for f in sel_faces:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = max(origin.x, uv.x)
+ origin.y = max(origin.y, uv.y)
+ elif self.origin == 'RIGHT_CENTER':
+ origin = Vector((-100000.0, 0.0))
+ num = 0
+ for f in sel_faces:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = max(origin.x, uv.x)
+ origin.y = origin.y + uv.y
+ num = num + 1
+ origin.y = origin.y / num
+ elif self.origin == 'RIGHT_BOTTOM':
+ origin = Vector((-100000.0, 100000.0))
+ for f in sel_faces:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ origin.x = max(origin.x, uv.x)
+ origin.y = min(origin.y, uv.y)
+
+ # update UV coordinate
+ for f in sel_faces:
+ for l in f.loops:
+ uv = l[uv_layer].uv
+ diff = uv - origin
+ l[uv_layer].uv = origin + diff * factor
bmesh.update_edit_mesh(obj.data)
+ self.report({'INFO'}, "Scaling factor: {0}".format(factor))
+
return {'FINISHED'}