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/align_uv.py')
-rw-r--r--uv_magic_uv/op/align_uv.py389
1 files changed, 306 insertions, 83 deletions
diff --git a/uv_magic_uv/op/align_uv.py b/uv_magic_uv/op/align_uv.py
index dcfb57c3..90168a56 100644
--- a/uv_magic_uv/op/align_uv.py
+++ b/uv_magic_uv/op/align_uv.py
@@ -20,8 +20,8 @@
__author__ = "imdjs, Nutti <nutti.metro@gmail.com>"
__status__ = "production"
-__version__ = "5.1"
-__date__ = "24 Feb 2018"
+__version__ = "5.2"
+__date__ = "17 Nov 2018"
import math
from math import atan2, tan, sin, cos
@@ -29,11 +29,42 @@ from math import atan2, tan, sin, cos
import bpy
import bmesh
from mathutils import Vector
-from bpy.props import EnumProperty, BoolProperty
+from bpy.props import EnumProperty, BoolProperty, FloatProperty
from .. import common
+__all__ = [
+ 'Properties',
+ 'OperatorCircle',
+ 'OperatorStraighten',
+ 'OperatorAxis',
+]
+
+
+def is_valid_context(context):
+ obj = context.object
+
+ # only edit mode is allowed to execute
+ if obj is None:
+ return False
+ if obj.type != 'MESH':
+ return False
+ if context.object.mode != 'EDIT':
+ return False
+
+ # 'IMAGE_EDITOR' and 'VIEW_3D' space is allowed to execute.
+ # If 'View_3D' space is not allowed, you can't find option in Tool-Shelf
+ # after the execution
+ for space in context.area.spaces:
+ if (space.type == 'IMAGE_EDITOR') or (space.type == 'VIEW_3D'):
+ break
+ else:
+ return False
+
+ return True
+
+
# get sum vertex length of loop sequences
def get_loop_vert_len(loops):
length = 0
@@ -86,10 +117,69 @@ def calc_v_on_circle(v, center, radius):
return new_v
-class MUV_AUVCircle(bpy.types.Operator):
+class Properties:
+ @classmethod
+ def init_props(cls, scene):
+ scene.muv_align_uv_enabled = BoolProperty(
+ name="Align UV Enabled",
+ description="Align UV is enabled",
+ default=False
+ )
+ scene.muv_align_uv_transmission = BoolProperty(
+ name="Transmission",
+ description="Align linked UVs",
+ default=False
+ )
+ scene.muv_align_uv_select = BoolProperty(
+ name="Select",
+ description="Select UVs which are aligned",
+ default=False
+ )
+ scene.muv_align_uv_vertical = BoolProperty(
+ name="Vert-Infl (Vertical)",
+ description="Align vertical direction influenced "
+ "by mesh vertex proportion",
+ default=False
+ )
+ scene.muv_align_uv_horizontal = BoolProperty(
+ name="Vert-Infl (Horizontal)",
+ description="Align horizontal direction influenced "
+ "by mesh vertex proportion",
+ default=False
+ )
+ scene.muv_align_uv_mesh_infl = FloatProperty(
+ name="Mesh Influence",
+ description="Influence rate of mesh vertex",
+ min=0.0,
+ max=1.0,
+ default=0.0
+ )
+ scene.muv_align_uv_location = EnumProperty(
+ name="Location",
+ description="Align location",
+ items=[
+ ('LEFT_TOP', "Left/Top", "Align to Left or Top"),
+ ('MIDDLE', "Middle", "Align to middle"),
+ ('RIGHT_BOTTOM', "Right/Bottom", "Align to Right or Bottom")
+ ],
+ default='MIDDLE'
+ )
+
+ @classmethod
+ def del_props(cls, scene):
+ del scene.muv_align_uv_enabled
+ del scene.muv_align_uv_transmission
+ del scene.muv_align_uv_select
+ del scene.muv_align_uv_vertical
+ del scene.muv_align_uv_horizontal
+ del scene.muv_align_uv_mesh_infl
+ del scene.muv_align_uv_location
+
+
+class OperatorCircle(bpy.types.Operator):
- bl_idname = "uv.muv_auv_circle"
- bl_label = "Circle"
+ bl_idname = "uv.muv_align_uv_operator_circle"
+ bl_label = "Align UV (Circle)"
bl_description = "Align UV coordinates to Circle"
bl_options = {'REGISTER', 'UNDO'}
@@ -106,7 +196,10 @@ class MUV_AUVCircle(bpy.types.Operator):
@classmethod
def poll(cls, context):
- return context.mode == 'EDIT_MESH'
+ # we can not get area/space/region from console
+ if common.is_console_mode():
+ return True
+ return is_valid_context(context)
def execute(self, context):
obj = context.active_object
@@ -167,66 +260,164 @@ class MUV_AUVCircle(bpy.types.Operator):
return {'FINISHED'}
+# get accumulate vertex lengths of loop sequences
+def get_loop_vert_accum_len(loops):
+ accum_lengths = [0.0]
+ length = 0
+ for l1, l2 in zip(loops[:-1], loops[1:]):
+ diff = l2.vert.co - l1.vert.co
+ length = length + abs(diff.length)
+ accum_lengths.extend([length])
+
+ return accum_lengths
+
+
+# get sum uv length of loop sequences
+def get_loop_uv_accum_len(loops, uv_layer):
+ accum_lengths = [0.0]
+ length = 0
+ for l1, l2 in zip(loops[:-1], loops[1:]):
+ diff = l2[uv_layer].uv - l1[uv_layer].uv
+ length = length + abs(diff.length)
+ accum_lengths.extend([length])
+
+ return accum_lengths
+
+
# get horizontal differential of UV influenced by mesh vertex
-def get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, pair_idx):
+def get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, pidx, infl):
common.debug_print(
- "vidx={0}, hidx={1}, pair_idx={2}".format(vidx, hidx, pair_idx))
+ "loop_seqs[hidx={0}][vidx={1}][pidx={2}]".format(hidx, vidx, pidx))
- # get total vertex length
- hloops = []
- for s in loop_seqs:
- hloops.extend([s[vidx][0], s[vidx][1]])
- vert_total_hlen = get_loop_vert_len(hloops)
- common.debug_print(vert_total_hlen)
+ base_uv = loop_seqs[0][vidx][0][uv_layer].uv.copy()
- # target vertex length
+ # calculate original length
hloops = []
- for s in loop_seqs[:hidx]:
+ for s in loop_seqs:
hloops.extend([s[vidx][0], s[vidx][1]])
- for pidx, l in enumerate(loop_seqs[hidx][vidx]):
- if pidx > pair_idx:
+ total_vlen = get_loop_vert_len(hloops)
+ accum_vlens = get_loop_vert_accum_len(hloops)
+ total_uvlen = get_loop_uv_len(hloops, uv_layer)
+ accum_uvlens = get_loop_uv_accum_len(hloops, uv_layer)
+ orig_uvs = [l[uv_layer].uv.copy() for l in hloops]
+
+ # calculate target length
+ tgt_noinfl = total_uvlen * (hidx + pidx) / len(loop_seqs)
+ tgt_infl = total_uvlen * accum_vlens[hidx * 2 + pidx] / total_vlen
+ target_length = tgt_noinfl * (1 - infl) + tgt_infl * infl
+ common.debug_print(target_length)
+ common.debug_print(accum_uvlens)
+
+ # calculate target UV
+ for i in range(len(accum_uvlens[:-1])):
+ # get line segment which UV will be placed
+ if ((accum_uvlens[i] <= target_length) and
+ (accum_uvlens[i + 1] > target_length)):
+ tgt_seg_len = target_length - accum_uvlens[i]
+ seg_len = accum_uvlens[i + 1] - accum_uvlens[i]
+ uv1 = orig_uvs[i]
+ uv2 = orig_uvs[i + 1]
+ target_uv = (uv1 - base_uv) + (uv2 - uv1) * tgt_seg_len / seg_len
+ break
+ elif i == (len(accum_uvlens[:-1]) - 1):
+ if accum_uvlens[i + 1] != target_length:
+ raise Exception(
+ "Internal Error: horizontal_target_length={}"
+ " is not equal to {}"
+ .format(target_length, accum_uvlens[-1]))
+ tgt_seg_len = target_length - accum_uvlens[i]
+ seg_len = accum_uvlens[i + 1] - accum_uvlens[i]
+ uv1 = orig_uvs[i]
+ uv2 = orig_uvs[i + 1]
+ target_uv = (uv1 - base_uv) + (uv2 - uv1) * tgt_seg_len / seg_len
break
- hloops.append(l)
- vert_hlen = get_loop_vert_len(hloops)
- common.debug_print(vert_hlen)
+ else:
+ raise Exception("Internal Error: horizontal_target_length={}"
+ " is not in range {} to {}"
+ .format(target_length, accum_uvlens[0],
+ accum_uvlens[-1]))
- # get total UV length
- # uv_all_hdiff = loop_seqs[-1][0][-1][uv_layer].uv -
- # loop_seqs[0][0][0][uv_layer].uv
- uv_total_hlen = loop_seqs[-1][vidx][-1][uv_layer].uv -\
- loop_seqs[0][vidx][0][uv_layer].uv
- common.debug_print(uv_total_hlen)
+ return target_uv
- return uv_total_hlen * vert_hlen / vert_total_hlen
+
+# --------------------- LOOP STRUCTURE ----------------------
+#
+# loops[hidx][vidx][pidx]
+# hidx: horizontal index
+# vidx: vertical index
+# pidx: pair index
+#
+# <----- horizontal ----->
+#
+# (hidx, vidx, pidx) = (0, 3, 0)
+# | (hidx, vidx, pidx) = (1, 3, 0)
+# v v
+# ^ o --- oo --- o
+# | | || |
+# vertical | o --- oo --- o <- (hidx, vidx, pidx)
+# | o --- oo --- o = (1, 2, 1)
+# | | || |
+# v o --- oo --- o
+# ^ ^
+# | (hidx, vidx, pidx) = (1, 0, 1)
+# (hidx, vidx, pidx) = (0, 0, 0)
+#
+# -----------------------------------------------------------
# get vertical differential of UV influenced by mesh vertex
-def get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, pair_idx):
+def get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, pidx, infl):
common.debug_print(
- "vidx={0}, hidx={1}, pair_idx={2}".format(vidx, hidx, pair_idx))
-
- # get total vertex length
- hloops = []
- for s in loop_seqs[hidx]:
- hloops.append(s[pair_idx])
- vert_total_hlen = get_loop_vert_len(hloops)
- common.debug_print(vert_total_hlen)
+ "loop_seqs[hidx={0}][vidx={1}][pidx={2}]".format(hidx, vidx, pidx))
- # target vertex length
- hloops = []
- for s in loop_seqs[hidx][:vidx + 1]:
- hloops.append(s[pair_idx])
- vert_hlen = get_loop_vert_len(hloops)
- common.debug_print(vert_hlen)
+ base_uv = loop_seqs[hidx][0][pidx][uv_layer].uv.copy()
- # get total UV length
- # uv_all_hdiff = loop_seqs[0][-1][pair_idx][uv_layer].uv - \
- # loop_seqs[0][0][pair_idx][uv_layer].uv
- uv_total_hlen = loop_seqs[hidx][-1][pair_idx][uv_layer].uv -\
- loop_seqs[hidx][0][pair_idx][uv_layer].uv
- common.debug_print(uv_total_hlen)
+ # calculate original length
+ vloops = []
+ for s in loop_seqs[hidx]:
+ vloops.append(s[pidx])
+ total_vlen = get_loop_vert_len(vloops)
+ accum_vlens = get_loop_vert_accum_len(vloops)
+ total_uvlen = get_loop_uv_len(vloops, uv_layer)
+ accum_uvlens = get_loop_uv_accum_len(vloops, uv_layer)
+ orig_uvs = [l[uv_layer].uv.copy() for l in vloops]
+
+ # calculate target length
+ tgt_noinfl = total_uvlen * int((vidx + 1) / 2) / len(loop_seqs)
+ tgt_infl = total_uvlen * accum_vlens[vidx] / total_vlen
+ target_length = tgt_noinfl * (1 - infl) + tgt_infl * infl
+ common.debug_print(target_length)
+ common.debug_print(accum_uvlens)
+
+ # calculate target UV
+ for i in range(len(accum_uvlens[:-1])):
+ # get line segment which UV will be placed
+ if ((accum_uvlens[i] <= target_length) and
+ (accum_uvlens[i + 1] > target_length)):
+ tgt_seg_len = target_length - accum_uvlens[i]
+ seg_len = accum_uvlens[i + 1] - accum_uvlens[i]
+ uv1 = orig_uvs[i]
+ uv2 = orig_uvs[i + 1]
+ target_uv = (uv1 - base_uv) + (uv2 - uv1) * tgt_seg_len / seg_len
+ break
+ elif i == (len(accum_uvlens[:-1]) - 1):
+ if accum_uvlens[i + 1] != target_length:
+ raise Exception("Internal Error: horizontal_target_length={}"
+ " is not equal to {}"
+ .format(target_length, accum_uvlens[-1]))
+ tgt_seg_len = target_length - accum_uvlens[i]
+ seg_len = accum_uvlens[i + 1] - accum_uvlens[i]
+ uv1 = orig_uvs[i]
+ uv2 = orig_uvs[i + 1]
+ target_uv = (uv1 - base_uv) + (uv2 - uv1) * tgt_seg_len / seg_len
+ break
+ else:
+ raise Exception("Internal Error: horizontal_target_length={}"
+ " is not in range {} to {}"
+ .format(target_length, accum_uvlens[0],
+ accum_uvlens[-1]))
- return uv_total_hlen * vert_hlen / vert_total_hlen
+ return target_uv
# get horizontal differential of UV no influenced
@@ -246,10 +437,10 @@ def get_vdiff_uv(uv_layer, loop_seqs, vidx, hidx):
return int((vidx + 1) / 2) * v_uv / (len(hseq) / 2)
-class MUV_AUVStraighten(bpy.types.Operator):
+class OperatorStraighten(bpy.types.Operator):
- bl_idname = "uv.muv_auv_straighten"
- bl_label = "Straighten"
+ bl_idname = "uv.muv_align_uv_operator_straighten"
+ bl_label = "Align UV (Straighten)"
bl_description = "Straighten UV coordinates"
bl_options = {'REGISTER', 'UNDO'}
@@ -275,10 +466,20 @@ class MUV_AUVStraighten(bpy.types.Operator):
"by mesh vertex proportion",
default=False
)
+ mesh_infl = FloatProperty(
+ name="Mesh Influence",
+ description="Influence rate of mesh vertex",
+ min=0.0,
+ max=1.0,
+ default=0.0
+ )
@classmethod
def poll(cls, context):
- return context.mode == 'EDIT_MESH'
+ # we can not get area/space/region from console
+ if common.is_console_mode():
+ return True
+ return is_valid_context(context)
# selected and paralleled UV loop sequence will be aligned
def __align_w_transmission(self, loop_seqs, uv_layer):
@@ -293,12 +494,14 @@ class MUV_AUVStraighten(bpy.types.Operator):
for vidx in range(0, len(hseq), 2):
if self.horizontal:
hdiff_uvs = [
- get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 0),
- get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 1),
+ get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 0,
+ self.mesh_infl),
+ get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 1,
+ self.mesh_infl),
get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx + 1,
- hidx, 0),
+ hidx, 0, self.mesh_infl),
get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx + 1,
- hidx, 1),
+ hidx, 1, self.mesh_infl),
]
else:
hdiff_uvs = [
@@ -309,12 +512,14 @@ class MUV_AUVStraighten(bpy.types.Operator):
]
if self.vertical:
vdiff_uvs = [
- get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 0),
- get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 1),
+ get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 0,
+ self.mesh_infl),
+ get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 1,
+ self.mesh_infl),
get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx + 1,
- hidx, 0),
+ hidx, 0, self.mesh_infl),
get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx + 1,
- hidx, 1),
+ hidx, 1, self.mesh_infl),
]
else:
vdiff_uvs = [
@@ -382,10 +587,10 @@ class MUV_AUVStraighten(bpy.types.Operator):
return {'FINISHED'}
-class MUV_AUVAxis(bpy.types.Operator):
+class OperatorAxis(bpy.types.Operator):
- bl_idname = "uv.muv_auv_axis"
- bl_label = "XY-Axis"
+ bl_idname = "uv.muv_align_uv_operator_axis"
+ bl_label = "Align UV (XY-Axis)"
bl_description = "Align UV to XY-axis"
bl_options = {'REGISTER', 'UNDO'}
@@ -421,10 +626,20 @@ class MUV_AUVAxis(bpy.types.Operator):
],
default='MIDDLE'
)
+ mesh_infl = FloatProperty(
+ name="Mesh Influence",
+ description="Influence rate of mesh vertex",
+ min=0.0,
+ max=1.0,
+ default=0.0
+ )
@classmethod
def poll(cls, context):
- return context.mode == 'EDIT_MESH'
+ # we can not get area/space/region from console
+ if common.is_console_mode():
+ return True
+ return is_valid_context(context)
# get min/max of UV
def __get_uv_max_min(self, loop_seqs, uv_layer):
@@ -579,12 +794,14 @@ class MUV_AUVAxis(bpy.types.Operator):
for vidx in range(0, len(hseq), 2):
if self.horizontal:
hdiff_uvs = [
- get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 0),
- get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 1),
+ get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 0,
+ self.mesh_infl),
+ get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 1,
+ self.mesh_infl),
get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx + 1,
- hidx, 0),
+ hidx, 0, self.mesh_infl),
get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx + 1,
- hidx, 1),
+ hidx, 1, self.mesh_infl),
]
hdiff_uvs[0].y = hdiff_uvs[0].y + offset_uvs[hidx][0].y
hdiff_uvs[1].y = hdiff_uvs[1].y + offset_uvs[hidx][1].y
@@ -599,12 +816,14 @@ class MUV_AUVAxis(bpy.types.Operator):
]
if self.vertical:
vdiff_uvs = [
- get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 0),
- get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 1),
+ get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 0,
+ self.mesh_infl),
+ get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 1,
+ self.mesh_infl),
get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx + 1,
- hidx, 0),
+ hidx, 0, self.mesh_infl),
get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx + 1,
- hidx, 1),
+ hidx, 1, self.mesh_infl),
]
else:
vdiff_uvs = [
@@ -664,12 +883,14 @@ class MUV_AUVAxis(bpy.types.Operator):
for vidx in range(0, len(hseq), 2):
if self.horizontal:
hdiff_uvs = [
- get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 0),
- get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 1),
+ get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 0,
+ self.mesh_infl),
+ get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 1,
+ self.mesh_infl),
get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx + 1,
- hidx, 0),
+ hidx, 0, self.mesh_infl),
get_hdiff_uv_vinfl(uv_layer, loop_seqs, vidx + 1,
- hidx, 1),
+ hidx, 1, self.mesh_infl),
]
hdiff_uvs[0].x = hdiff_uvs[0].x + offset_uvs[hidx][0].x
hdiff_uvs[1].x = hdiff_uvs[1].x + offset_uvs[hidx][1].x
@@ -684,12 +905,14 @@ class MUV_AUVAxis(bpy.types.Operator):
]
if self.vertical:
vdiff_uvs = [
- get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 0),
- get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 1),
+ get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 0,
+ self.mesh_infl),
+ get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx, hidx, 1,
+ self.mesh_infl),
get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx + 1,
- hidx, 0),
+ hidx, 0, self.mesh_infl),
get_vdiff_uv_vinfl(uv_layer, loop_seqs, vidx + 1,
- hidx, 1),
+ hidx, 1, self.mesh_infl),
]
else:
vdiff_uvs = [