From c5fba51131edd41b2ed9ee717032ee29e5f64022 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 14 Dec 2006 03:43:02 +0000 Subject: [PATCH] object_apply_def - use new BPy Object API funcs, no error in localview off_export - minor changes uv_archimap - cleanup. slightly slower but less duplicate code uv_from_adjacent - nothing BPY_menus - renamed py slot UvCalculation to UVCalculation to be consistant --- release/scripts/object_apply_def.py | 67 +++++++------- release/scripts/off_export.py | 30 +++---- release/scripts/uv_archimap.py | 132 +++++++++++++--------------- release/scripts/uv_from_adjacent.py | 2 +- source/blender/python/BPY_menus.c | 4 +- 5 files changed, 109 insertions(+), 126 deletions(-) diff --git a/release/scripts/object_apply_def.py b/release/scripts/object_apply_def.py index 6417fe9ec8c..3046f0fea78 100644 --- a/release/scripts/object_apply_def.py +++ b/release/scripts/object_apply_def.py @@ -65,18 +65,37 @@ This script will work with object types: Mesh, Metaballs, Text3d, Curves and Nur import Blender import BPyMesh +def copy_vgroups(source_ob, target_ob): + + source_me = source_ob.getData(mesh=1) + + vgroups= source_me.getVertGroupNames() + if vgroups: + ADD= Blender.Mesh.AssignModes.ADD + target_me = target_ob.getData(mesh=1) + for vgroupname in vgroups: + target_me.addVertGroup(vgroupname) + if len(target_me.verts) == len(source_me.verts): + vlist = source_me.getVertsFromGroup(vgroupname, True) + try: + for vpair in vlist: + target_me.assignVertsToGroup(vgroupname, [vpair[0]], vpair[1], ADD) + except: + pass + + def apply_deform(): scn= Blender.Scene.GetCurrent() - ADD= Blender.Mesh.AssignModes.ADD #Blender.Window.EditMode(0) NAME_LENGTH = 19 - PREFIX = "_def" - PREFIX_LENGTH = len(PREFIX) + SUFFIX = "_def" + SUFFIX_LENGTH = len(SUFFIX) # Get all object and mesh names - ob_list = Blender.Object.GetSelected() + ob_list = list(scn.objects.context) + ob_act = scn.objects.active # Assume no soft body has_sb= False @@ -92,7 +111,7 @@ def apply_deform(): has_sb= True # Remove all numbered metaballs because their disp list is only on the main metaball (un numbered) - if ob.getType()=='MBall': + if ob.type == 'MBall': name= ob.name # is this metaball numbered? dot_idx= name.rfind('.') + 1 @@ -127,49 +146,27 @@ def apply_deform(): name = ob.name - new_name = "%s_def" % name[:NAME_LENGTH-PREFIX_LENGTH] + new_name = "%s_def" % name[:NAME_LENGTH-SUFFIX_LENGTH] num = 0 while new_name in used_names: - new_name = "%s_def.%.3i" % (name[:NAME_LENGTH-(PREFIX_LENGTH+PREFIX_LENGTH)], num) + new_name = "%s_def.%.3i" % (name[:NAME_LENGTH-(SUFFIX_LENGTH+SUFFIX_LENGTH)], num) num += 1 used_names.append(new_name) - - new_me.name= new_name - new_ob= Blender.Object.New('Mesh', new_name) - new_ob.link(new_me) - scn.link(new_ob) + new_ob= scn.objects.new(new_me) new_ob.setMatrix(ob.matrixWorld) - new_ob.Layers= ob.Layers - deformedList.append(new_ob) + # Make the active duplicate also active + if ob == ob_act: + scn.objects.active = new_ob # Original object was a mesh? see if we can copy any vert groups. - if ob.getType()=='Mesh': - orig_me= ob.getData(mesh=1) - - vgroups= orig_me.getVertGroupNames() - if vgroups: - new_me= new_ob.getData(mesh=1) # Do this so we can de vgroup stuff - for vgroupname in vgroups: - new_me.addVertGroup(vgroupname) - if len(new_me.verts) == len(orig_me.verts): - vlist = orig_me.getVertsFromGroup(vgroupname, True) - try: - for vpair in vlist: - new_me.assignVertsToGroup(vgroupname, [vpair[0]], vpair[1], ADD) - except: - pass + if ob.type =='Mesh': + copy_vgroups(ob, new_ob) - for ob in deformedList: - ob.sel = 1 - - if deformedList: - deformedList[0].sel = 1 # Keep the same object active. - Blender.Window.RedrawAll() if __name__=='__main__': diff --git a/release/scripts/off_export.py b/release/scripts/off_export.py index f1c0e397032..236e6195690 100644 --- a/release/scripts/off_export.py +++ b/release/scripts/off_export.py @@ -57,7 +57,7 @@ Notes:
# ***** END GPL LICENCE BLOCK ***** import Blender -#import time +import BPyMessages # Python 2.3 has no reversed. try: @@ -69,14 +69,14 @@ except: # ====== Write OFF Format ====== # ============================== def write(filename): - #start = time.clock() file = open(filename, 'wb') scn= Blender.Scene.GetCurrent() - object= scn.getActiveObject() - if not object or object.getType()!='Mesh': - Blender.Draw.PupMenu('Error%t|Select 1 active mesh object') + object= scn.objects.active + if not object or object.type != 'Mesh': + BPyMessages.Error_NoMeshActive() return - + + Blender.Window.WaitCursor(1) mesh = object.getData(mesh=1) # === OFF Header === @@ -85,24 +85,22 @@ def write(filename): # === Vertex List === for i, v in enumerate(mesh.verts): - file.write('%f %f %f\n' % tuple(v.co)) + file.write('%.6f %.6f %.6f\n' % tuple(v.co)) # === Face List === for i, f in enumerate(mesh.faces): - file.write('%i ' % len(f)) + file.write('%i' % len(f)) for v in reversed(f.v): - file.write('%d ' % v.index) + file.write(' %d' % v.index) file.write('\n') - - - Blender.Window.DrawProgressBar(1.0, '') # clear progressbar + file.close() - #end = time.clock() - #seconds = " in %.2f %s" % (end-start, "seconds") - message = 'Successfully exported "%s"' % Blender.sys.basename(filename)# + seconds + Blender.Window.WaitCursor(0) + message = 'Successfully exported "%s"' % Blender.sys.basename(filename) + def fs_callback(filename): - if filename.find('.off', -4) <= 0: filename += '.off' + if not filename.lower().endswith('.off'): filename += '.off' write(filename) Blender.Window.FileSelector(fs_callback, "Export OFF", Blender.sys.makename(ext='.off')) diff --git a/release/scripts/uv_archimap.py b/release/scripts/uv_archimap.py index 0deebbfb6ab..fa9d37739fe 100644 --- a/release/scripts/uv_archimap.py +++ b/release/scripts/uv_archimap.py @@ -1,9 +1,9 @@ #!BPY """ Registration info for Blender menus: <- these words are ignored -Name: 'ArchiMap UV Projection Unwrapper' +Name: 'Unwrap (smart projections)' Blender: 240 -Group: 'UvCalculation' +Group: 'UVCalculation' Tooltip: 'ArchiMap UV Unwrap mesh faces for all select mesh objects' """ @@ -43,7 +43,7 @@ selected faces, or all faces. from Blender import Object, Scene, Draw, Window, sys, Mesh, Geometry -from Blender.Mathutils import CrossVecs, Matrix, Vector, RotationMatrix, DotVecs, TriangleArea +from Blender.Mathutils import CrossVecs, Matrix, Vector, RotationMatrix, DotVecs from math import cos @@ -57,7 +57,7 @@ USER_FILL_HOLES = None USER_FILL_HOLES_QUALITY = None import boxpack2d -reload(boxpack2d) # for developing. +# reload(boxpack2d) # for developing. dict_matrix = {} @@ -389,12 +389,14 @@ def optiRotateUvIsland(faces): # Now write the vectors back to the face UV's i = 0 # count the serialized uv/vectors for f in faces: - f.uv = [uv for uv in uvVecs[i:len(f)+i] ] - i += len(f) + #f.uv = [uv for uv in uvVecs[i:len(f)+i] ] + for j, k in enumerate(xrange(i, len(f.v)+i)): + f.uv[j][:] = uvVecs[k] + i += len(f.v) # Takes an island list and tries to find concave, hollow areas to pack smaller islands into. -def mergeUvIslands(islandList, islandListArea): +def mergeUvIslands(islandList): global USER_FILL_HOLES global USER_FILL_HOLES_QUALITY @@ -415,11 +417,11 @@ def mergeUvIslands(islandList, islandListArea): totFaceArea = 0 offset= Vector(minx, miny) - for fIdx, f in enumerate(islandList[islandIdx]): + for f in islandList[islandIdx]: for uv in f.uv: uv -= offset - totFaceArea += islandListArea[islandIdx][fIdx] # Use Cached area. dont recalculate. + totFaceArea += f.area islandBoundsArea = w*h efficiency = abs(islandBoundsArea - totFaceArea) @@ -624,7 +626,7 @@ def mergeUvIslands(islandList, islandListArea): def face_ed_keys(f): # Return ordered edge keys per face # used so a face can lookup its edges. - fi = [v.index for v in f] + fi = [v.index for v in f.v] if len(fi) == 3: i1, i2 = fi[0], fi[1] if i1 > i2: i1, i2= i2, i1 @@ -653,8 +655,7 @@ def face_ed_keys(f): return (i1,i2), (i3,i4), (i5,i6), (i7,i8) # Takes groups of faces. assumes face groups are UV groups. -def getUvIslands(faceGroups, faceGroupsArea, me): - +def getUvIslands(faceGroups, me): # Get seams so we dont cross over seams edge_seams = {} # shoudl be a set @@ -669,7 +670,6 @@ def getUvIslands(faceGroups, faceGroupsArea, me): islandList = [] - islandListArea = [] Window.DrawProgressBar(0.0, 'Splitting %d projection groups into UV islands:' % len(faceGroups)) #print '\tSplitting %d projection groups into UV islands:' % len(faceGroups), @@ -680,7 +680,6 @@ def getUvIslands(faceGroups, faceGroupsArea, me): while faceGroupIdx: faceGroupIdx-=1 faces = faceGroups[faceGroupIdx] - facesArea = faceGroupsArea[faceGroupIdx] # Build edge dict edge_users = {} @@ -705,10 +704,8 @@ def getUvIslands(faceGroups, faceGroupsArea, me): face_modes[0] = 1 # start the search with face 1 newIsland = [] - newIslandArea = [] newIsland.append(faces[0]) - newIslandArea.append(facesArea[0]) ok = True @@ -724,21 +721,17 @@ def getUvIslands(faceGroups, faceGroupsArea, me): if i != ii and face_modes[ii] == 0: face_modes[ii] = ok = 1 # mark as searched newIsland.append(faces[ii]) - newIslandArea.append(facesArea[ii]) # mark as searched, dont look again. face_modes[i] = 2 islandList.append(newIsland) - islandListArea.append(newIslandArea) ok = False for i in xrange(len(faces)): if face_modes[i] == 0: newIsland = [] - newIslandArea = [] newIsland.append(faces[i]) - newIslandArea.append(facesArea[i]) face_modes[i] = ok = 1 break @@ -749,13 +742,13 @@ def getUvIslands(faceGroups, faceGroupsArea, me): for island in islandList: optiRotateUvIsland(island) - return islandList, islandListArea + return islandList -def packIslands(islandList, islandListArea): +def packIslands(islandList): if USER_FILL_HOLES: Window.DrawProgressBar(0.1, 'Merging Islands (Ctrl: skip merge)...') - mergeUvIslands(islandList, islandListArea) # Modify in place + mergeUvIslands(islandList) # Modify in place # Now we have UV islands, we need to pack them. @@ -856,6 +849,15 @@ def VectoMat(vec): return Matrix([a1[0], a1[1], a1[2]], [a2[0], a2[1], a2[2]], [a3[0], a3[1], a3[2]]) + +class thickface(object): + __slost__= 'v', 'uv', 'no', 'area' + def __init__(self, face): + self.v = face.v + self.uv = face.uv + self.no = face.no + self.area = face.area + global ob ob = None def main(): @@ -947,8 +949,6 @@ def main(): obList.sort(lambda ob1, ob2: cmp( ob1.getData(name_only=1), ob2.getData(name_only=1) )) collected_islandList= [] - collected_islandListArea= [] - Window.WaitCursor(1) SELECT_FLAG = Mesh.FaceFlags['SELECT'] @@ -960,9 +960,9 @@ def main(): me.faceUV= True if USER_ONLY_SELECTED_FACES: - meshFaces = [f for f in me.faces if f.flag & SELECT_FLAG] + meshFaces = [thickface(f) for f in me.faces if f.flag & SELECT_FLAG] else: - meshFaces = me.faces + meshFaces = map(thickface, me.faces) if not meshFaces: continue @@ -978,23 +978,17 @@ def main(): # make a list of face props that are in sync with meshFaces # Make a Face List that is sorted by area. - faceListProps = [] + # meshFaces = [] - for f in meshFaces: - area = f.area - if area <= SMALL_NUM: - for uv in f.uv: # Assign Dummy UVs - uv.zero() - - print 'found zero area face, removing.' - - else: - # Store all here - faceListProps.append( (f, area, f.no) ) + meshFaces.sort( lambda a, b: cmp(b.area , a.area) ) # Biggest first. + + # remove all zero area faces + while meshFaces and meshFaces[-1].area <= SMALL_NUM: + # Set their UV's to 0,0 + for uv in meshFaces[-1].uv: + uv.zero() + meshFaces.pop() - del meshFaces - - faceListProps.sort( lambda A, B: cmp(B[1] , A[1]) ) # Biggest first. # Smallest first is slightly more efficient, but if the user cancels early then its better we work on the larger data. # Generate Projection Vecs @@ -1003,14 +997,15 @@ def main(): # Initialize projectVecs - newProjectVec = faceListProps[0][2] - newProjectFacePropList = [faceListProps[0]] # Popping stuffs it up. + newProjectVec = meshFaces[0].no + newProjectMeshFaces = [meshFaces[0]] # Popping stuffs it up. + # Predent that the most unique angke is ages away to start the loop off mostUniqueAngle = -1.0 # This is popped - tempFaceListProps = faceListProps[:] + tempMeshFaces = meshFaces[:] while 1: # If theres none there then start with the largest face @@ -1019,7 +1014,7 @@ def main(): mostUniqueAngle = 1.0 # 1.0 is 0d. no difference. mostUniqueIndex = 0 # fake - fIdx = len(tempFaceListProps) + fIdx = len(tempMeshFaces) while fIdx: fIdx-=1 @@ -1027,7 +1022,7 @@ def main(): # Get the closest vec angle we are to. for p in projectVecs: - temp_angle_diff= DotVecs(p, tempFaceListProps[fIdx][2]) + temp_angle_diff= DotVecs(p, tempMeshFaces[fIdx].no) if angleDifference < temp_angle_diff: angleDifference= temp_angle_diff @@ -1039,37 +1034,37 @@ def main(): if mostUniqueAngle < USER_PROJECTION_LIMIT_CONVERTED: - #print 'adding', mostUniqueAngle, USER_PROJECTION_LIMIT, len(newProjectFacePropList) - newProjectVec = tempFaceListProps[mostUniqueIndex][2] - newProjectFacePropList = [tempFaceListProps.pop(mostUniqueIndex)] + #print 'adding', mostUniqueAngle, USER_PROJECTION_LIMIT, len(newProjectMeshFaces) + newProjectVec = tempMeshFaces[mostUniqueIndex].no + newProjectMeshFaces = [tempMeshFaces.pop(mostUniqueIndex)] else: if len(projectVecs) >= 1: # Must have at least 2 projections break # Now we have found the most different vector, add all the faces that are close. - fIdx = len(tempFaceListProps) + fIdx = len(tempMeshFaces) while fIdx: fIdx -= 1 # Use half the angle limit so we dont overweight faces towards this # normal and hog all the faces. - if DotVecs(newProjectVec, tempFaceListProps[fIdx][2]) > USER_PROJECTION_LIMIT_HALF_CONVERTED: - newProjectFacePropList.append(tempFaceListProps.pop(fIdx)) + if DotVecs(newProjectVec, tempMeshFaces[fIdx].no) > USER_PROJECTION_LIMIT_HALF_CONVERTED: + newProjectMeshFaces.append(tempMeshFaces.pop(fIdx)) # Now weight the vector to all its faces, will give a more direct projection # if the face its self was not representive of the normal from surrounding faces. averageVec = Vector(0,0,0) - for fprop in newProjectFacePropList: - averageVec += (fprop[2] * fprop[1]) # / len(newProjectFacePropList) + for fprop in newProjectMeshFaces: + averageVec += (fprop.no * fprop.area) if averageVec.x != 0 or averageVec.y != 0 or averageVec.z != 0: # Avoid NAN averageVec.normalize() projectVecs.append(averageVec) # Now we have used it, ignore it. - newProjectFacePropList = [] + newProjectMeshFaces = [] # If there are only zero area faces then its possible # there are no projectionVecs @@ -1078,16 +1073,12 @@ def main(): return faceProjectionGroupList =[[] for i in xrange(len(projectVecs)) ] - faceProjectionGroupListArea =[[] for i in xrange(len(projectVecs)) ] - - # We need the area later, and we alredy have calculated it. so store it here. - #faceProjectionGroupListArea =[[] for i in xrange(len(projectVecs)) ] # MAP and Arrange # We know there are 3 or 4 faces here - fIdx = len(faceListProps) + fIdx = len(meshFaces) while fIdx: fIdx-=1 - fvec = faceListProps[fIdx][2] + fvec = meshFaces[fIdx].no i = len(projectVecs) # Initialize first @@ -1104,9 +1095,7 @@ def main(): bestAngIdx = i # Store the area for later use. - faceProjectionGroupList[bestAngIdx].append(faceListProps[fIdx][0]) - faceProjectionGroupListArea[bestAngIdx].append(faceListProps[fIdx][1]) - + faceProjectionGroupList[bestAngIdx].append(meshFaces[fIdx]) # Cull faceProjectionGroupList, @@ -1115,7 +1104,6 @@ def main(): i= len(projectVecs) while i: i-=1 - # Account for projectVecs having no faces. if not faceProjectionGroupList[i]: continue @@ -1125,19 +1113,19 @@ def main(): # Get the faces UV's from the projected vertex. for f in faceProjectionGroupList[i]: - f.uv = [MatProj * v.co for v in f] + for j, v in enumerate(f.v): + f.uv[j][:] = (MatProj * v.co)[:2] if USER_SHARE_SPACE: # Should we collect and pack later? - islandList, islandListArea = getUvIslands(faceProjectionGroupList, faceProjectionGroupListArea, me) + islandList = getUvIslands(faceProjectionGroupList, me) collected_islandList.extend(islandList) - collected_islandListArea.extend(islandListArea) else: # Should we pack the islands for this 1 object? - islandList, islandListArea = getUvIslands(faceProjectionGroupList, faceProjectionGroupListArea, me) - packIslands(islandList, islandListArea) + islandList = getUvIslands(faceProjectionGroupList, me) + packIslands(islandList) @@ -1146,7 +1134,7 @@ def main(): # We want to pack all in 1 go, so pack now if USER_SHARE_SPACE: Window.DrawProgressBar(0.9, "Box Packing for all objects...") - packIslands(collected_islandList, collected_islandListArea) + packIslands(collected_islandList) print "ArchiMap time: %.2f" % (sys.time() - time1) Window.DrawProgressBar(0.9, "ArchiMap Done, time: %.2f sec." % (sys.time() - time1)) diff --git a/release/scripts/uv_from_adjacent.py b/release/scripts/uv_from_adjacent.py index 0be5b6382cb..24a90649432 100644 --- a/release/scripts/uv_from_adjacent.py +++ b/release/scripts/uv_from_adjacent.py @@ -2,7 +2,7 @@ """ Name: 'UVs from unselected adjacent' Blender: 242 -Group: 'UvCalculation' +Group: 'UVCalculation' Tooltip: 'Assign UVs to selected faces from surrounding unselected faces.' """ __author__ = "Campbell Barton" diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c index 11dfb4ad792..96b54439a0e 100644 --- a/source/blender/python/BPY_menus.c +++ b/source/blender/python/BPY_menus.c @@ -103,7 +103,7 @@ static int bpymenu_group_atoi( char *str ) return PYMENU_WEIGHTPAINT; else if( !strcmp( str, "VertexPaint" ) ) return PYMENU_VERTEXPAINT; - else if( !strcmp( str, "UvCalculation" ) ) + else if( !strcmp( str, "UVCalculation" ) ) return PYMENU_UVCALCULATION; /* "Misc" or an inexistent group name: use misc */ else @@ -171,7 +171,7 @@ char *BPyMenu_group_itoa( short menugroup ) return "VertexPaint"; break; case PYMENU_UVCALCULATION: - return "UvCalculation"; + return "UVCalculation"; break; case PYMENU_MISC: return "Misc";