mirror of
https://github.com/drewcassidy/TexTools-Blender
synced 2024-09-01 14:54:44 +00:00
132 lines
3.2 KiB
Python
132 lines
3.2 KiB
Python
|
import bpy
|
||
|
import bmesh
|
||
|
import operator
|
||
|
from mathutils import Vector
|
||
|
from collections import defaultdict
|
||
|
from math import pi
|
||
|
|
||
|
from . import utilities_uv
|
||
|
|
||
|
|
||
|
class op(bpy.types.Operator):
|
||
|
bl_idname = "uv.textools_align"
|
||
|
bl_label = "Align"
|
||
|
bl_description = "Align vertices, edges or shells"
|
||
|
bl_options = {'REGISTER', 'UNDO'}
|
||
|
|
||
|
direction : bpy.props.StringProperty(name="Direction", default="top")
|
||
|
|
||
|
@classmethod
|
||
|
def poll(cls, context):
|
||
|
if not bpy.context.active_object:
|
||
|
return False
|
||
|
|
||
|
#Only in Edit mode
|
||
|
if bpy.context.active_object.mode != 'EDIT':
|
||
|
return False
|
||
|
|
||
|
#Only in UV editor mode
|
||
|
if bpy.context.area.type != 'IMAGE_EDITOR':
|
||
|
return False
|
||
|
|
||
|
#Requires UV map
|
||
|
if not bpy.context.object.data.uv_layers:
|
||
|
return False #self.report({'WARNING'}, "Object must have more than one UV map")
|
||
|
|
||
|
# Not in Synced mode
|
||
|
if bpy.context.scene.tool_settings.use_uv_select_sync:
|
||
|
return False
|
||
|
|
||
|
return True
|
||
|
|
||
|
|
||
|
def execute(self, context):
|
||
|
|
||
|
align(context, self.direction)
|
||
|
return {'FINISHED'}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
def align(context, direction):
|
||
|
#Store selection
|
||
|
utilities_uv.selection_store()
|
||
|
|
||
|
if bpy.context.tool_settings.transform_pivot_point != 'CURSOR':
|
||
|
bpy.context.tool_settings.transform_pivot_point = 'CURSOR'
|
||
|
|
||
|
#B-Mesh
|
||
|
obj = bpy.context.active_object
|
||
|
bm = bmesh.from_edit_mesh(obj.data);
|
||
|
uv_layers = bm.loops.layers.uv.verify();
|
||
|
|
||
|
if len(obj.data.uv_layers) == 0:
|
||
|
print("There is no UV channel or UV data set")
|
||
|
return
|
||
|
|
||
|
# Collect BBox sizes
|
||
|
boundsAll = utilities_uv.getSelectionBBox()
|
||
|
|
||
|
mode = bpy.context.scene.tool_settings.uv_select_mode
|
||
|
if mode == 'FACE' or mode == 'ISLAND':
|
||
|
print("____ Align Islands")
|
||
|
|
||
|
#Collect UV islands
|
||
|
islands = utilities_uv.getSelectionIslands()
|
||
|
|
||
|
for island in islands:
|
||
|
|
||
|
bpy.ops.uv.select_all(action='DESELECT')
|
||
|
utilities_uv.set_selected_faces(island)
|
||
|
bounds = utilities_uv.getSelectionBBox()
|
||
|
|
||
|
# print("Island "+str(len(island))+"x faces, delta: "+str(delta.y))
|
||
|
|
||
|
if direction == "bottom":
|
||
|
delta = boundsAll['min'] - bounds['min']
|
||
|
bpy.ops.transform.translate(value=(0, delta.y, 0))
|
||
|
elif direction == "top":
|
||
|
delta = boundsAll['max'] - bounds['max']
|
||
|
bpy.ops.transform.translate(value=(0, delta.y, 0))
|
||
|
elif direction == "left":
|
||
|
delta = boundsAll['min'] - bounds['min']
|
||
|
bpy.ops.transform.translate(value=(delta.x, 0, 0))
|
||
|
elif direction == "right":
|
||
|
delta = boundsAll['max'] - bounds['max']
|
||
|
bpy.ops.transform.translate(value=(delta.x, 0, 0))
|
||
|
else:
|
||
|
print("Unkown direction: "+str(direction))
|
||
|
|
||
|
|
||
|
elif mode == 'EDGE' or mode == 'VERTEX':
|
||
|
print("____ Align Verts")
|
||
|
|
||
|
for f in bm.faces:
|
||
|
if f.select:
|
||
|
for l in f.loops:
|
||
|
luv = l[uv_layers]
|
||
|
if luv.select:
|
||
|
# print("Idx: "+str(luv.uv))
|
||
|
if direction == "top":
|
||
|
luv.uv[1] = boundsAll['max'].y
|
||
|
elif direction == "bottom":
|
||
|
luv.uv[1] = boundsAll['min'].y
|
||
|
elif direction == "left":
|
||
|
luv.uv[0] = boundsAll['min'].x
|
||
|
elif direction == "right":
|
||
|
luv.uv[0] = boundsAll['max'].x
|
||
|
|
||
|
|
||
|
bmesh.update_edit_mesh(obj.data)
|
||
|
|
||
|
#Restore selection
|
||
|
utilities_uv.selection_restore()
|
||
|
|
||
|
bpy.utils.register_class(op)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|