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/impl/texture_lock_impl.py')
-rw-r--r--uv_magic_uv/impl/texture_lock_impl.py455
1 files changed, 0 insertions, 455 deletions
diff --git a/uv_magic_uv/impl/texture_lock_impl.py b/uv_magic_uv/impl/texture_lock_impl.py
deleted file mode 100644
index c14eddb0..00000000
--- a/uv_magic_uv/impl/texture_lock_impl.py
+++ /dev/null
@@ -1,455 +0,0 @@
-# <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__ = "Nutti <nutti.metro@gmail.com>"
-__status__ = "production"
-__version__ = "5.2"
-__date__ = "17 Nov 2018"
-
-import math
-from math import atan2, cos, sqrt, sin, fabs
-
-import bpy
-import bmesh
-from mathutils import Vector
-
-from .. import common
-
-
-def _get_vco(verts_orig, loop):
- """
- Get vertex original coordinate from loop
- """
- for vo in verts_orig:
- if vo["vidx"] == loop.vert.index and vo["moved"] is False:
- return vo["vco"]
- return loop.vert.co
-
-
-def _get_link_loops(vert):
- """
- Get loop linked to vertex
- """
- link_loops = []
- for f in vert.link_faces:
- adj_loops = []
- for loop in f.loops:
- # self loop
- if loop.vert == vert:
- l = loop
- # linked loop
- else:
- for e in loop.vert.link_edges:
- if e.other_vert(loop.vert) == vert:
- adj_loops.append(loop)
- if len(adj_loops) < 2:
- return None
-
- link_loops.append({"l": l, "l0": adj_loops[0], "l1": adj_loops[1]})
- return link_loops
-
-
-def _get_ini_geom(link_loop, uv_layer, verts_orig, v_orig):
- """
- Get initial geometory
- (Get interior angle of face in vertex/UV space)
- """
- u = link_loop["l"][uv_layer].uv
- v0 = _get_vco(verts_orig, link_loop["l0"])
- u0 = link_loop["l0"][uv_layer].uv
- v1 = _get_vco(verts_orig, link_loop["l1"])
- u1 = link_loop["l1"][uv_layer].uv
-
- # get interior angle of face in vertex space
- v0v1 = v1 - v0
- v0v = v_orig["vco"] - v0
- v1v = v_orig["vco"] - v1
- theta0 = v0v1.angle(v0v)
- theta1 = v0v1.angle(-v1v)
- if (theta0 + theta1) > math.pi:
- theta0 = v0v1.angle(-v0v)
- theta1 = v0v1.angle(v1v)
-
- # get interior angle of face in UV space
- u0u1 = u1 - u0
- u0u = u - u0
- u1u = u - u1
- phi0 = u0u1.angle(u0u)
- phi1 = u0u1.angle(-u1u)
- if (phi0 + phi1) > math.pi:
- phi0 = u0u1.angle(-u0u)
- phi1 = u0u1.angle(u1u)
-
- # get direction of linked UV coordinate
- # this will be used to judge whether angle is more or less than 180 degree
- dir0 = u0u1.cross(u0u) > 0
- dir1 = u0u1.cross(u1u) > 0
-
- return {
- "theta0": theta0,
- "theta1": theta1,
- "phi0": phi0,
- "phi1": phi1,
- "dir0": dir0,
- "dir1": dir1}
-
-
-def _get_target_uv(link_loop, uv_layer, verts_orig, v, ini_geom):
- """
- Get target UV coordinate
- """
- v0 = _get_vco(verts_orig, link_loop["l0"])
- lo0 = link_loop["l0"]
- v1 = _get_vco(verts_orig, link_loop["l1"])
- lo1 = link_loop["l1"]
-
- # get interior angle of face in vertex space
- v0v1 = v1 - v0
- v0v = v.co - v0
- v1v = v.co - v1
- theta0 = v0v1.angle(v0v)
- theta1 = v0v1.angle(-v1v)
- if (theta0 + theta1) > math.pi:
- theta0 = v0v1.angle(-v0v)
- theta1 = v0v1.angle(v1v)
-
- # calculate target interior angle in UV space
- phi0 = theta0 * ini_geom["phi0"] / ini_geom["theta0"]
- phi1 = theta1 * ini_geom["phi1"] / ini_geom["theta1"]
-
- uv0 = lo0[uv_layer].uv
- uv1 = lo1[uv_layer].uv
-
- # calculate target vertex coordinate from target interior angle
- tuv0, tuv1 = _calc_tri_vert(uv0, uv1, phi0, phi1)
-
- # target UV coordinate depends on direction, so judge using direction of
- # linked UV coordinate
- u0u1 = uv1 - uv0
- u0u = tuv0 - uv0
- u1u = tuv0 - uv1
- dir0 = u0u1.cross(u0u) > 0
- dir1 = u0u1.cross(u1u) > 0
- if (ini_geom["dir0"] != dir0) or (ini_geom["dir1"] != dir1):
- return tuv1
-
- return tuv0
-
-
-def _calc_tri_vert(v0, v1, angle0, angle1):
- """
- Calculate rest coordinate from other coordinates and angle of end
- """
- angle = math.pi - angle0 - angle1
-
- alpha = atan2(v1.y - v0.y, v1.x - v0.x)
- d = (v1.x - v0.x) / cos(alpha)
- a = d * sin(angle0) / sin(angle)
- b = d * sin(angle1) / sin(angle)
- s = (a + b + d) / 2.0
- if fabs(d) < 0.0000001:
- xd = 0
- yd = 0
- else:
- r = s * (s - a) * (s - b) * (s - d)
- if r < 0:
- xd = 0
- yd = 0
- else:
- xd = (b * b - a * a + d * d) / (2 * d)
- yd = 2 * sqrt(r) / d
- x1 = xd * cos(alpha) - yd * sin(alpha) + v0.x
- y1 = xd * sin(alpha) + yd * cos(alpha) + v0.y
- x2 = xd * cos(alpha) + yd * sin(alpha) + v0.x
- y2 = xd * sin(alpha) - yd * cos(alpha) + v0.y
-
- return Vector((x1, y1)), Vector((x2, y2))
-
-
-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
-
- # 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
-
-
-class LockImpl:
- @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)
-
- @classmethod
- def is_ready(cls, context):
- sc = context.scene
- props = sc.muv_props.texture_lock
- if props.verts_orig:
- return True
- return False
-
- def execute(self, ops_obj, context):
- props = context.scene.muv_props.texture_lock
- obj = bpy.context.active_object
- bm = bmesh.from_edit_mesh(obj.data)
- if common.check_version(2, 73, 0) >= 0:
- bm.verts.ensure_lookup_table()
- bm.edges.ensure_lookup_table()
- bm.faces.ensure_lookup_table()
-
- if not bm.loops.layers.uv:
- ops_obj.report(
- {'WARNING'}, "Object must have more than one UV map")
- return {'CANCELLED'}
-
- props.verts_orig = [
- {"vidx": v.index, "vco": v.co.copy(), "moved": False}
- for v in bm.verts if v.select]
-
- return {'FINISHED'}
-
-
-class UnlockImpl:
- @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.texture_lock
- if not props.verts_orig:
- return False
- if not LockImpl.is_ready(context):
- return False
- if not _is_valid_context(context):
- return False
- return True
-
- def execute(self, ops_obj, context):
- sc = context.scene
- props = sc.muv_props.texture_lock
- obj = bpy.context.active_object
- bm = bmesh.from_edit_mesh(obj.data)
- if common.check_version(2, 73, 0) >= 0:
- bm.verts.ensure_lookup_table()
- bm.edges.ensure_lookup_table()
- bm.faces.ensure_lookup_table()
-
- if not bm.loops.layers.uv:
- ops_obj.report(
- {'WARNING'}, "Object must have more than one UV map")
- return {'CANCELLED'}
- uv_layer = bm.loops.layers.uv.verify()
-
- verts = [v.index for v in bm.verts if v.select]
- verts_orig = props.verts_orig
-
- # move UV followed by vertex coordinate
- for vidx, v_orig in zip(verts, verts_orig):
- if vidx != v_orig["vidx"]:
- ops_obj.report({'ERROR'}, "Internal Error")
- return {"CANCELLED"}
-
- v = bm.verts[vidx]
- link_loops = _get_link_loops(v)
-
- result = []
-
- for ll in link_loops:
- ini_geom = _get_ini_geom(ll, uv_layer, verts_orig, v_orig)
- target_uv = _get_target_uv(
- ll, uv_layer, verts_orig, v, ini_geom)
- result.append({"l": ll["l"], "uv": target_uv})
-
- # connect other face's UV
- if ops_obj.connect:
- ave = Vector((0.0, 0.0))
- for r in result:
- ave = ave + r["uv"]
- ave = ave / len(result)
- for r in result:
- r["l"][uv_layer].uv = ave
- else:
- for r in result:
- r["l"][uv_layer].uv = r["uv"]
- v_orig["moved"] = True
- bmesh.update_edit_mesh(obj.data)
-
- props.verts_orig = None
-
- return {'FINISHED'}
-
-
-class IntrImpl:
- __timer = None
-
- @classmethod
- def poll(cls, context):
- # we can not get area/space/region from console
- if common.is_console_mode():
- return False
- return _is_valid_context(context)
-
- @classmethod
- def is_running(cls, _):
- return 1 if cls.__timer else 0
-
- @classmethod
- def handle_add(cls, ops_obj, context):
- if cls.__timer is None:
- cls.__timer = context.window_manager.event_timer_add(
- 0.10, window=context.window)
- context.window_manager.modal_handler_add(ops_obj)
-
- @classmethod
- def handle_remove(cls, context):
- if cls.__timer is not None:
- context.window_manager.event_timer_remove(cls.__timer)
- cls.__timer = None
-
- def __init__(self):
- self.__intr_verts_orig = []
- self.__intr_verts = []
-
- def __sel_verts_changed(self, context):
- obj = context.active_object
- bm = bmesh.from_edit_mesh(obj.data)
- if common.check_version(2, 73, 0) >= 0:
- bm.verts.ensure_lookup_table()
- bm.edges.ensure_lookup_table()
- bm.faces.ensure_lookup_table()
-
- prev = set(self.__intr_verts)
- now = set([v.index for v in bm.verts if v.select])
-
- return prev != now
-
- def __reinit_verts(self, context):
- obj = context.active_object
- bm = bmesh.from_edit_mesh(obj.data)
- if common.check_version(2, 73, 0) >= 0:
- bm.verts.ensure_lookup_table()
- bm.edges.ensure_lookup_table()
- bm.faces.ensure_lookup_table()
-
- self.__intr_verts_orig = [
- {"vidx": v.index, "vco": v.co.copy(), "moved": False}
- for v in bm.verts if v.select]
- self.__intr_verts = [v.index for v in bm.verts if v.select]
-
- def __update_uv(self, ops_obj, context):
- """
- Update UV when vertex coordinates are changed
- """
- obj = context.active_object
- bm = bmesh.from_edit_mesh(obj.data)
- if common.check_version(2, 73, 0) >= 0:
- bm.verts.ensure_lookup_table()
- bm.edges.ensure_lookup_table()
- bm.faces.ensure_lookup_table()
-
- if not bm.loops.layers.uv:
- ops_obj.report({'WARNING'},
- "Object must have more than one UV map")
- return
- uv_layer = bm.loops.layers.uv.verify()
-
- verts = [v.index for v in bm.verts if v.select]
- verts_orig = self.__intr_verts_orig
-
- for vidx, v_orig in zip(verts, verts_orig):
- if vidx != v_orig["vidx"]:
- ops_obj.report({'ERROR'}, "Internal Error")
- return
-
- v = bm.verts[vidx]
- link_loops = _get_link_loops(v)
-
- result = []
- for ll in link_loops:
- ini_geom = _get_ini_geom(ll, uv_layer, verts_orig, v_orig)
- target_uv = _get_target_uv(
- ll, uv_layer, verts_orig, v, ini_geom)
- result.append({"l": ll["l"], "uv": target_uv})
-
- # UV connect option is always true, because it raises
- # unexpected behavior
- ave = Vector((0.0, 0.0))
- for r in result:
- ave = ave + r["uv"]
- ave = ave / len(result)
- for r in result:
- r["l"][uv_layer].uv = ave
- v_orig["moved"] = True
- bmesh.update_edit_mesh(obj.data)
-
- common.redraw_all_areas()
- self.__intr_verts_orig = [
- {"vidx": v.index, "vco": v.co.copy(), "moved": False}
- for v in bm.verts if v.select]
-
- def modal(self, ops_obj, context, event):
- if not _is_valid_context(context):
- IntrImpl.handle_remove(context)
- return {'FINISHED'}
-
- if not IntrImpl.is_running(context):
- return {'FINISHED'}
-
- if context.area:
- context.area.tag_redraw()
-
- if event.type == 'TIMER':
- if self.__sel_verts_changed(context):
- self.__reinit_verts(context)
- else:
- self.__update_uv(ops_obj, context)
-
- return {'PASS_THROUGH'}
-
- def invoke(self, ops_obj, context, _):
- if not _is_valid_context(context):
- return {'CANCELLED'}
-
- if not IntrImpl.is_running(context):
- IntrImpl.handle_add(ops_obj, context)
- return {'RUNNING_MODAL'}
- else:
- IntrImpl.handle_remove(context)
-
- if context.area:
- context.area.tag_redraw()
-
- return {'FINISHED'}