Magic UV: release v4.5
This commit is contained in:
parent
c21b887882
commit
85a2b50e0e
|
@ -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):
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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'}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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]
|
||||
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)
|
||||
# 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 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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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'}
|
|
@ -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
|
||||
self.report(
|
||||
{'INFO'}, "Average face size: {0}".format(scale))
|
||||
|
||||
orig_area = bpy.context.area.type
|
||||
bpy.context.area.type = 'IMAGE_EDITOR'
|
||||
if self.proportional_scaling:
|
||||
factor = props.ref_scale / scale
|
||||
else:
|
||||
factor = self.scaling_factor
|
||||
|
||||
# select all UV related to the selected faces
|
||||
bpy.ops.uv.select_all(action='SELECT')
|
||||
# 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)
|
||||
|
||||
# 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
|
||||
# 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'}
|
||||
|
|
Loading…
Reference in New Issue