Newer
Older
# ##### 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 #####
CoDEmanX
committed
"name": "Easy Lattice Object",
"author": "Kursad Karatas",
"version": (0, 5),
"blender": (2, 66, 0),
"location": "View3D > Easy Lattice",
"description": "Create a lattice for shape editing",
"warning": "",
"wiki_url": "http://wiki.blender.org/index.php/Easy_Lattice_Editing_Addon",
"tracker_url": "https://bitbucket.org/kursad/blender_addons_easylattice/src",
"category": "Mesh"}
CoDEmanX
committed
CoDEmanX
committed
Kursad Karatas
committed
print(mod)
if mod.name == "latticeeasytemp":
try:
if mod.object == bpy.data.objects['LatticeEasytTemp']:
Kursad Karatas
committed
print("applying modifier")
bpy.ops.object.modifier_apply( apply_as = 'DATA', modifier = mod.name )
CoDEmanX
committed
except:
bpy.ops.object.modifier_remove( modifier = mod.name )
CoDEmanX
committed
Kursad Karatas
committed
def modifiersApplyRemove( obj ):
CoDEmanX
committed
Kursad Karatas
committed
# print("passed object is", obj)
# print("current object is", bpy.context.active_object)
CoDEmanX
committed
Kursad Karatas
committed
bpy.ops.object.select_all( action = 'DESELECT' )
bpy.ops.object.select_pattern(pattern=obj.name, extend=False)
bpy.context.scene.objects.active=obj
CoDEmanX
committed
Kursad Karatas
committed
for mod in obj.modifiers:
Kursad Karatas
committed
# print("modifier is ", mod)
Kursad Karatas
committed
if mod.name == "latticeeasytemp":
# try:
if mod.object == bpy.data.objects['LatticeEasytTemp']:
Kursad Karatas
committed
# print("mod object is ", mod.object)
# print("applying modifier", mod," - ", mod.name)
CoDEmanX
committed
Kursad Karatas
committed
#obj.select= True
Kursad Karatas
committed
# print("current object is", bpy.context.active_object)
Kursad Karatas
committed
bpy.ops.object.modifier_apply( apply_as = 'DATA', modifier = mod.name )
#obj.modifiers.remove(mod)
CoDEmanX
committed
Kursad Karatas
committed
# except:
# bpy.ops.object.modifier_remove( modifier = mod.name )
CoDEmanX
committed
Kursad Karatas
committed
# Cleanup
def latticeDelete(obj):
bpy.ops.object.select_all( action = 'DESELECT' )
for ob in bpy.context.scene.objects:
if "LatticeEasytTemp" in ob.name:
ob.select = True
CoDEmanX
committed
bpy.ops.object.delete( use_global = False )
Kursad Karatas
committed
#select the original object back
obj.select=True
def createLattice( obj, size, pos, props ):
# Create lattice and object
lat = bpy.data.lattices.new( 'LatticeEasytTemp' )
ob = bpy.data.objects.new( 'LatticeEasytTemp', lat )
CoDEmanX
committed
CoDEmanX
committed
#get the combined rotation matrix and apply to the lattice
#ob.matrix_world=buildRot_WorldMat(obj)*ob.matrix_world
CoDEmanX
committed
#the position comes from the bbox
CoDEmanX
committed
#the size from bbox
CoDEmanX
committed
#the rotation comes from the combined obj world matrix which was converted to euler pairs.
CoDEmanX
committed
ob.show_x_ray = True
# Link object to scene
scn = bpy.context.scene
scn.objects.link( ob )
scn.objects.active = ob
scn.update()
CoDEmanX
committed
# Set lattice attributes
lat.interpolation_type_u = props[3]
lat.interpolation_type_v = props[3]
lat.interpolation_type_w = props[3]
CoDEmanX
committed
CoDEmanX
committed
lat.points_u = props[0]
lat.points_v = props[1]
lat.points_w = props[2]
Kursad Karatas
committed
#Set lattice points
'''s = 0.0
points = [
(-s,-s,-s), (s,-s,-s), (-s,s,-s), (s,s,-s),
(-s,-s,s), (s,-s,s), (-s,s,s), (s,s,s)
]
for n,pt in enumerate(lat.points):
for k in range(3):
#pt.co[k] = points[n][k]
'''
CoDEmanX
committed
return ob
def selectedVerts_Grp( obj ):
# vertices=bpy.context.active_object.data.vertices
vertices = obj.data.vertices
CoDEmanX
committed
CoDEmanX
committed
if obj.mode == "EDIT":
bpy.ops.object.editmode_toggle()
for grp in obj.vertex_groups:
CoDEmanX
committed
if "templatticegrp" in grp.name:
bpy.ops.object.vertex_group_set_active( group = grp.name )
bpy.ops.object.vertex_group_remove()
CoDEmanX
committed
tempgroup = obj.vertex_groups.new( "templatticegrp" )
CoDEmanX
committed
# selverts=[vert for vert in vertices if vert.select==True]
for vert in vertices:
if vert.select == True:
selverts.append( vert )
tempgroup.add( [vert.index], 1.0, "REPLACE" )
CoDEmanX
committed
CoDEmanX
committed
return selverts
def getTransformations( obj ):
rot = obj.rotation_euler
loc = obj.location
size = obj.scale
return [loc, rot, size]
def findBBox( obj, selvertsarray ):
CoDEmanX
committed
# mat = buildTrnSclMat( obj )
mat =buildTrnScl_WorldMat(obj)
CoDEmanX
committed
CoDEmanX
committed
minx, miny, minz = selvertsarray[0].co
maxx, maxy, maxz = selvertsarray[0].co
CoDEmanX
committed
c = 1
# for vert in selvertsarray:
for c in range( len( selvertsarray ) ):
# co=obj.matrix_world*vert.co.to_4d()
CoDEmanX
committed
CoDEmanX
committed
if co.x < minx: minx = co.x
if co.y < miny: miny = co.y
if co.z < minz: minz = co.z
if co.x > maxx: maxx = co.x
if co.y > maxy: maxy = co.y
if co.z > maxz: maxz = co.z
CoDEmanX
committed
# print("local cord", selvertsarray[c].co)
# print("world cord", co)
c += 1
CoDEmanX
committed
# print("total verts", len(selvertsarray))
# print("counted verts",c)
CoDEmanX
committed
# Based on world coords
# print("-> minx miny minz",minx, miny, minz )
# print("-> maxx maxy maxz",maxx, maxy, maxz )
CoDEmanX
committed
minpoint = mathutils.Vector( ( minx, miny, minz ) )
maxpoint = mathutils.Vector( ( maxx, maxy, maxz ) )
CoDEmanX
committed
# middle point has to be calculated based on the real world matrix
#middle = mat_world * mathutils.Vector((x_sum, y_sum, z_sum))/float(c)
middle = ( ( minpoint + maxpoint ) / 2 )
minpoint = mat * minpoint # Calculate only based on loc/scale
maxpoint = mat * maxpoint # Calculate only based on loc/scale
middle = mat_world * middle # the middle has to be calculated based on the real world matrix
CoDEmanX
committed
size = maxpoint - minpoint
size = mathutils.Vector( ( abs( size.x ), abs( size.y ), abs( size.z ) ) )
CoDEmanX
committed
# local coords
#####################################################
'''minpoint=mathutils.Vector((minx,miny,minz))
maxpoint=mathutils.Vector((maxx,maxy,maxz))
middle=mathutils.Vector( (x_sum/float(len(selvertsarray)), y_sum/float(len(selvertsarray)), z_sum/float(len(selvertsarray))) )
size=maxpoint-minpoint
size=mathutils.Vector((abs(size.x),abs(size.y),abs(size.z)))
'''
#####################################################
CoDEmanX
committed
return [minpoint, maxpoint, size, middle ]
def buildTrnSclMat( obj ):
# This function builds a local matrix that encodes translation and scale and it leaves out the rotation matrix
# The rotation is applied at obejct level if there is any
mat_trans = mathutils.Matrix.Translation( obj.location )
mat_scale = mathutils.Matrix.Scale( obj.scale[0], 4, ( 1, 0, 0 ) )
mat_scale *= mathutils.Matrix.Scale( obj.scale[1], 4, ( 0, 1, 0 ) )
mat_scale *= mathutils.Matrix.Scale( obj.scale[2], 4, ( 0, 0, 1 ) )
CoDEmanX
committed
CoDEmanX
committed
CoDEmanX
committed
def buildTrnScl_WorldMat( obj ):
# This function builds a real world matrix that encodes translation and scale and it leaves out the rotation matrix
# The rotation is applied at obejct level if there is any
loc,rot,scl=obj.matrix_world.decompose()
mat_trans = mathutils.Matrix.Translation( loc)
CoDEmanX
committed
mat_scale = mathutils.Matrix.Scale( scl[0], 4, ( 1, 0, 0 ) )
mat_scale *= mathutils.Matrix.Scale( scl[1], 4, ( 0, 1, 0 ) )
mat_scale *= mathutils.Matrix.Scale( scl[2], 4, ( 0, 0, 1 ) )
CoDEmanX
committed
CoDEmanX
committed
CoDEmanX
committed
#Feature use
# This function builds a real world matrix that encodes rotation and it leaves out translation and scale matrices
loc,rot,scl=obj.matrix_world.decompose()
rot=rot.to_euler()
CoDEmanX
committed
mat_rot = mathutils.Matrix.Rotation(rot[0], 4,'X')
mat_rot *= mathutils.Matrix.Rotation(rot[1],4,'Z')
mat_rot *= mathutils.Matrix.Rotation(rot[2], 4,'Y')
return mat_rot
#Feature use
def buildTrn_WorldMat( obj ):
# This function builds a real world matrix that encodes translation and scale and it leaves out the rotation matrix
# The rotation is applied at obejct level if there is any
loc,rot,scl=obj.matrix_world.decompose()
mat_trans = mathutils.Matrix.Translation( loc)
CoDEmanX
committed
return mat_trans
#Feature use
def buildScl_WorldMat( obj ):
# This function builds a real world matrix that encodes translation and scale and it leaves out the rotation matrix
# The rotation is applied at obejct level if there is any
loc,rot,scl=obj.matrix_world.decompose()
CoDEmanX
committed
mat_scale = mathutils.Matrix.Scale( scl[0], 4, ( 1, 0, 0 ) )
mat_scale *= mathutils.Matrix.Scale( scl[1], 4, ( 0, 1, 0 ) )
mat_scale *= mathutils.Matrix.Scale( scl[2], 4, ( 0, 0, 1 ) )
CoDEmanX
committed
CoDEmanX
committed
loc,rot,scl=obj.matrix_world.decompose()
rot=rot.to_euler()
CoDEmanX
committed
CoDEmanX
committed
Kursad Karatas
committed
# print("<-------------------------------->")
Kursad Karatas
committed
#obj = bpy.context.active_object
obj = bpy.context.object
CoDEmanX
committed
Kursad Karatas
committed
# set global property for the currently active latticed object
bpy.types.Scene.activelatticeobject = bpy.props.StringProperty( name = "currentlatticeobject", default = "" )
bpy.types.Scene.activelatticeobject = obj.name
CoDEmanX
committed
modifiersDelete( obj )
selvertsarray = selectedVerts_Grp( obj )
bbox = findBBox( obj, selvertsarray )
CoDEmanX
committed
CoDEmanX
committed
Kursad Karatas
committed
latticeDelete(obj)
CoDEmanX
committed
modif = obj.modifiers.new( "latticeeasytemp", "LATTICE" )
modif.object = lat
modif.vertex_group = "templatticegrp"
CoDEmanX
committed
Kursad Karatas
committed
bpy.ops.object.select_all( action = 'DESELECT' )
bpy.ops.object.select_pattern(pattern=lat.name, extend=False)
bpy.context.scene.objects.active=lat
CoDEmanX
committed
bpy.context.scene.update()
bpy.ops.object.mode_set( mode = 'EDIT' )
CoDEmanX
committed
Kursad Karatas
committed
if obj.type == "LATTICE":
CoDEmanX
committed
Kursad Karatas
committed
if bpy.types.Scene.activelatticeobject:
name = bpy.types.Scene.activelatticeobject
print("last active latticed object", name)
CoDEmanX
committed
Kursad Karatas
committed
#Are we in edit lattice mode? If so move on to object mode
if obj.mode=="EDIT":
bpy.ops.object.editmode_toggle()
CoDEmanX
committed
Kursad Karatas
committed
for ob in bpy.context.scene.objects:
if ob.name == name: # found the object with the lattice mod
print("apply mod on", ob)
object = ob
modifiersApplyRemove(object)
#modifiersDelete( object ) # apply the modifier and delete the lattice
latticeDelete(obj)
CoDEmanX
committed
return
def main( context, latticeprops ):
run( latticeprops )
class EasyLattice( bpy.types.Operator ):
"""Tooltip"""
bl_idname = "object.easy_lattice"
bl_label = "Easy Lattice Creator"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
CoDEmanX
committed
lat_u = bpy.props.IntProperty( name = "Lattice u", default = 3 )
lat_w = bpy.props.IntProperty( name = "Lattice w", default = 3 )
lat_m = bpy.props.IntProperty( name = "Lattice m", default = 3 )
CoDEmanX
committed
lat_types = ( ( '0', 'KEY_LINEAR', '0' ), ( '1', 'KEY_CARDINAL', '1' ), ( '2', 'KEY_BSPLINE', '2' ) )
lat_type = bpy.props.EnumProperty( name = "Lattice Type", items = lat_types, default = '0' )
CoDEmanX
committed
@classmethod
def poll( cls, context ):
return context.active_object is not None
def execute( self, context ):
CoDEmanX
committed
lat_u = self.lat_u
lat_w = self.lat_w
lat_m = self.lat_m
CoDEmanX
committed
# this is a reference to the "items" used to generate the
# enum property.
lat_type = self.lat_types[int( self.lat_type )][1]
lat_props = [lat_u, lat_w, lat_m, lat_type]
main( context, lat_props )
return {'FINISHED'}
def invoke( self, context, event ):
wm = context.window_manager
return wm.invoke_props_dialog( self )
CoDEmanX
committed
def menu_draw( self, context ):
self.layout.operator_context = 'INVOKE_REGION_WIN'
self.layout.operator( EasyLattice.bl_idname, "Easy Lattice" )
def register():
bpy.utils.register_class( EasyLattice )
# bpy.utils.register
# menu_func = (lambda self, context: self.layout.operator('EasyLattice'))
# bpy.types.VIEW3D_PT_tools_objectmode.append(menu_draw)
CoDEmanX
committed
bpy.types.VIEW3D_MT_edit_mesh_specials.append( menu_draw )
def unregister():
bpy.utils.unregister_class( EasyLattice )
# bpy.types.VIEW3D_PT_tools_objectmode.remove(menu_draw)
CoDEmanX
committed
bpy.types.VIEW3D_MT_edit_mesh_specials.remove( menu_draw )