2020-07-12 21:04:38 +08:00
import bpy , bmesh
2020-10-07 15:20:51 +08:00
import mathutils
2020-10-06 23:57:21 +08:00
import bpy . types
from . import utils , preferences
2020-07-12 21:04:38 +08:00
2020-09-02 23:04:21 +08:00
class BALLANCE_OT_rail_uv ( bpy . types . Operator ) :
2020-07-20 10:13:18 +08:00
""" Create a UV for rail """
bl_idname = " ballance.rail_uv "
bl_label = " Create Rail UV "
bl_options = { ' UNDO ' }
2020-10-06 23:57:21 +08:00
uv_type : bpy . props . EnumProperty (
name = " Type " ,
description = " Define how to create UV " ,
items = (
( " POINT " , " Point " , " All UV will be created in a specific point " ) ,
( " UNIFORM " , " Uniform " , " All UV will be created within 1x1 " ) ,
( " SCALE " , " Scale " , " Give a scale number to scale UV " )
) ,
)
uv_scale : bpy . props . FloatProperty (
name = " Scale " ,
description = " The scale of UV " ,
min = 0.0 ,
default = 1.0 ,
)
2020-07-20 10:13:18 +08:00
@classmethod
def poll ( self , context ) :
return check_rail_target ( )
2020-10-06 23:57:21 +08:00
def invoke ( self , context , event ) :
wm = context . window_manager
return wm . invoke_props_dialog ( self )
2020-07-20 10:13:18 +08:00
def execute ( self , context ) :
2020-10-07 15:20:51 +08:00
if context . scene . BallanceBlenderPluginProperty . material_picker == None :
utils . ShowMessageBox ( ( " No specific material " , ) , " Lost parameter " , ' ERROR ' )
else :
create_rail_uv ( self . uv_type , context . scene . BallanceBlenderPluginProperty . material_picker , self . uv_scale )
2020-07-20 10:13:18 +08:00
return { ' FINISHED ' }
2020-10-06 23:57:21 +08:00
def draw ( self , context ) :
layout = self . layout
layout . prop ( self , " uv_type " )
layout . prop ( context . scene . BallanceBlenderPluginProperty , " material_picker " )
if self . uv_type == ' SCALE ' :
layout . prop ( self , " uv_scale " )
2020-07-20 10:13:18 +08:00
# ====================== method
def check_rail_target ( ) :
for obj in bpy . context . selected_objects :
if obj . type != ' MESH ' :
continue
if obj . mode != ' OBJECT ' :
continue
return True
return False
2020-10-07 15:20:51 +08:00
def create_rail_uv ( rail_type , material_pointer , scale_size ) :
objList = [ ]
2020-07-20 10:13:18 +08:00
ignoredObj = [ ]
2020-07-12 21:04:38 +08:00
for obj in bpy . context . selected_objects :
if obj . type != ' MESH ' :
2020-07-20 10:13:18 +08:00
ignoredObj . append ( obj . name )
continue
if obj . mode != ' OBJECT ' :
ignoredObj . append ( obj . name )
2020-07-12 21:04:38 +08:00
continue
2020-08-31 21:56:08 +08:00
if obj . data . uv_layers . active is None :
2020-09-02 23:04:21 +08:00
# create a empty uv for it.
obj . data . uv_layers . new ( do_init = False )
2020-07-12 21:04:38 +08:00
2020-10-07 15:20:51 +08:00
objList . append ( obj )
2020-07-12 21:04:38 +08:00
2020-10-07 15:20:51 +08:00
for obj in objList :
mesh = obj . data
# clean it material and set rail first
obj . data . materials . clear ( )
obj . data . materials . append ( material_pointer )
real_scale = 1.0
if rail_type == ' SCALE ' :
real_scale = scale_size
elif rail_type == ' UNIFORM ' :
# calc proper scale
targetObjBbox = [ mathutils . Vector ( corner ) for corner in obj . bound_box ]
maxLength = max (
max ( [ vec . x for vec in targetObjBbox ] ) - min ( [ vec . x for vec in targetObjBbox ] ) ,
max ( [ vec . y for vec in targetObjBbox ] ) - min ( [ vec . y for vec in targetObjBbox ] )
)
real_scale = 1.0 / maxLength
# copy mesh vec for scale or uniform mode
vecList = mesh . vertices [ : ]
2020-07-12 21:04:38 +08:00
uv_layer = mesh . uv_layers . active . data
for poly in mesh . polygons :
for loop_index in range ( poly . loop_start , poly . loop_start + poly . loop_total ) :
2020-10-07 15:20:51 +08:00
# get correspond vec index
index = mesh . loops [ loop_index ] . vertex_index
if rail_type == ' POINT ' :
# set to 1 point
uv_layer [ loop_index ] . uv [ 0 ] = 0
uv_layer [ loop_index ] . uv [ 1 ] = 1
else :
# following xy -> uv scale
uv_layer [ loop_index ] . uv [ 0 ] = vecList [ index ] . co [ 0 ] * real_scale
uv_layer [ loop_index ] . uv [ 1 ] = vecList [ index ] . co [ 1 ] * real_scale
2020-07-12 21:04:38 +08:00
2020-07-20 10:13:18 +08:00
if len ( ignoredObj ) != 0 :
2020-10-07 15:20:51 +08:00
utils . ShowMessageBox ( ( " Following objects are not processed due to they are not suit for this function now: " , ) + tuple ( ignoredObj ) , " Execution result " , ' INFO ' )