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>2018-02-16 15:04:36 +0300
committerNutti <nutti.metro@gmail.com>2018-02-16 15:04:36 +0300
commitfdc914d653d4cf9e8c6ad5ea3d71fdefb9529491 (patch)
treef06d9e4b851a39c62ee8d4308a3587211df23bfa /uv_magic_uv/op/world_scale_uv.py
parentbfab29085ca84ad74125aa18a26a0025a1e09ace (diff)
Magic UV: Release v5.0
* Add features - Align UV Cursor - UV Cursor Location - Align UV - Smooth UV - UV Inspection - Select UV - Texture Wrap - UV Sculpt * Improve features - Copy/Paste UV: Add menu to UV/Image Editor - World Scale UV: Add information about Texel Density - UV Bounding Box: Add option "Bound" - Texture Projection: Add option "Assign UVMap" - UVW: Add option "Assign UVMap" * Improve UI * Fixed bugs * Optimization/Refactoring
Diffstat (limited to 'uv_magic_uv/op/world_scale_uv.py')
-rw-r--r--uv_magic_uv/op/world_scale_uv.py236
1 files changed, 236 insertions, 0 deletions
diff --git a/uv_magic_uv/op/world_scale_uv.py b/uv_magic_uv/op/world_scale_uv.py
new file mode 100644
index 00000000..f1539ddb
--- /dev/null
+++ b/uv_magic_uv/op/world_scale_uv.py
@@ -0,0 +1,236 @@
+# <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__ = "McBuff, Nutti <nutti.metro@gmail.com>"
+__status__ = "production"
+__version__ = "5.0"
+__date__ = "16 Feb 2018"
+
+from math import sqrt
+
+import bpy
+import bmesh
+from mathutils import Vector
+from bpy.props import EnumProperty
+
+from .. import common
+
+
+def measure_wsuv_info(obj):
+ mesh_area = common.measure_mesh_area(obj)
+ uv_area = common.measure_uv_area(obj)
+
+ if not uv_area:
+ return None, None, None
+
+ if mesh_area == 0.0:
+ density = 0.0
+ else:
+ density = sqrt(uv_area) / sqrt(mesh_area)
+
+ return uv_area, mesh_area, density
+
+
+class MUV_WSUVMeasure(bpy.types.Operator):
+ """
+ Operation class: Measure face size
+ """
+
+ bl_idname = "uv.muv_wsuv_measure"
+ bl_label = "Measure"
+ bl_description = "Measure face size for scale calculation"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ def execute(self, context):
+ sc = context.scene
+ obj = context.active_object
+
+ uv_area, mesh_area, density = measure_wsuv_info(obj)
+ if not uv_area:
+ self.report({'WARNING'},
+ "Object must have more than one UV map and texture")
+ return {'CANCELLED'}
+
+ sc.muv_wsuv_src_uv_area = uv_area
+ sc.muv_wsuv_src_mesh_area = mesh_area
+ sc.muv_wsuv_src_density = density
+
+ self.report({'INFO'},
+ "UV Area: {0}, Mesh Area: {1}, Texel Density: {2}"
+ .format(uv_area, mesh_area, density))
+
+ return {'FINISHED'}
+
+
+class MUV_WSUVApply(bpy.types.Operator):
+ """
+ Operation class: Apply scaled UV
+ """
+
+ bl_idname = "uv.muv_wsuv_apply"
+ bl_label = "Apply"
+ bl_description = "Apply scaled UV based on scale calculation"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ 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
+
+ layout.prop(self, "origin")
+
+ def execute(self, context):
+ sc = context.scene
+ 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()
+
+ sel_faces = [f for f in bm.faces if f.select]
+
+ uv_area, mesh_area, density = measure_wsuv_info(obj)
+ if not uv_area:
+ self.report({'WARNING'},
+ "Object must have more than one UV map and texture")
+ return {'CANCELLED'}
+
+ uv_layer = bm.loops.layers.uv.verify()
+
+ if sc.muv_wsuv_mode == 'PROPORTIONAL':
+ tgt_density = sc.muv_wsuv_src_density * sqrt(mesh_area) / \
+ sqrt(sc.muv_wsuv_src_mesh_area)
+ elif sc.muv_wsuv_mode == 'SCALING':
+ tgt_density = sc.muv_wsuv_src_density * sc.muv_wsuv_scaling_factor
+ elif sc.muv_wsuv_mode == 'USER':
+ tgt_density = sc.muv_wsuv_tgt_density
+ elif sc.muv_wsuv_mode == 'CONSTANT':
+ tgt_density = sc.muv_wsuv_src_density
+
+ factor = tgt_density / density
+
+ # 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'}