New Mirror Vertex group Script

Ok this is the third script in a series dealing with vertex groups-

Batch delete Vertex Groups:
http://blenderartists.org/forum/showthread.php?t=158240

Bulk Cut Vertex Groups
(which is also useful for renaming your groups)
http://blenderartists.org/forum/showthread.php?t=158223

and now this one to mirror vertex groups

with a combination of these 3 scripts and the
mesh/scripts/mirror vertex locations & weight script found in blender, you should be able to sort out any vertex mirroring/naming issues you come across

here is the script

what it does is similar to the above mentioned mirror vertex locations & weight script- in that it mirrors all selected vertex weights to the other side of the model
some limitations- only works if the vertices are exactly mirrored, if they are even slightly off, those verts will be ignored

ok so now you may be asking what is the point of this script then-

  1. because it has little functionality, it may be easier for some people- like myself to figure out
  2. well I couldnt for the life of me figure out how to get the above script to actually create the vertex groups if the didnt already exist- ie if Hand.R didnt exist, but Hand.L did, I tried every combination and nothing seemed to add Hand.R
    so you can run this script of mine, it will create all the mirrored vert groups, and then you can run the MVL&W script to finish it off

how to use it

select the verts that you would like to mirror
run the script

all the groups that contain the selected verts will appear in a list
from that list check or uncheck the vertex groups that you would like to mirror

select the mirror button

quite simple.

please bare in mind that there are 2 string boxes that allow you to specify which side you are mirroring- ie .L to .R or .R to .L



#!BPY 
""" 
Name: 'Mirror Vertex Groups' 
Blender: 248 
Group: 'Mesh' 
Tooltip: 'Batch Mirror Vertex Groups' 
""" 
 
__author__ = "Brad Gonsalves AKA AVE" 
__url__ = ["blenderartists.org", "www.blender.org"] 
__version__ = "1.0 2009/06/09" 
 
# --------------------------------------------------------------------------  
# ***** 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.  
#  
# ***** END GPL LICENCE BLOCK *****  
# -------------------------------------------------------------------------- 
 
 
 
import Blender 
from Blender import Draw, BGL, Scene, Mesh, Window, sys, Object 
 
import bpy 
 
 
 
 
GroupList=[] 
ToggleState=[] 
VGListRunning=1 
co=[0,0] 
GEventNumBase=20 
VGColumns=3 
GError=False 
GStr=[".L",".R"] 
 
 
scn = Scene.GetCurrent() 
obj= scn.getActiveObject() 
 
if obj.getType()!='Mesh': 
    obj= None 
     
sel= [ob for ob in Object.GetSelected() if ob.getType()=='Mesh' if ob != obj] 
if not sel and not obj: 
    Draw.PupMenu('Error, select a mesh as your active object') 
    GError=True 
else: 
    me = obj.getData(mesh=1)  
     
    InEditMode = Window.EditMode()     
     
    co=Window.GetMouseCoords() 
 
    Window.EditMode(0) 
    Window.EditMode(1) 
 
 
def ToggleButton(event, val): 
    global ToggleState 
    global VGListRunning 
    Found=False 
    for x in ToggleState: 
        if x[0]==event: 
            Found=True 
            x[1]=val 
    if Found==False: 
        ToggleState.append([event,val]) 
    VGListRunning=1 
 
def FindToggleState(event): 
    Found=False 
    for x in ToggleState: 
        if x[0]==event: 
            Found=True 
            return(x[1]) 
    if Found==False: 
        return(0) 
 
def MirrorVGroups(event, val): 
    global VGListRunning 
    AssignMode = Blender.Mesh.AssignModes.ADD 
    Window.EditMode(0) 
    VertGroups=me.getVertGroupNames() 
    if event==1: 
        EventNum=GEventNumBase 
        for a in GroupList: 
            AddVerts=[] 
            if FindToggleState(EventNum) and GStr[0] in a: 
                AllVerts=me.getVertsFromGroup(a,1) 
                for b in AllVerts: 
                    if me.verts[b[0]].sel: 
                        for OppVerts in me.verts: 
                            if me.verts[b[0]].co.z==OppVerts.co.z and me.verts[b[0]].co.y==OppVerts.co.y and me.verts[b[0]].co.x==(0-OppVerts.co.x): 
                                AddVerts.append([OppVerts.index,b[1]]) 
                NewGroup=a.replace(GStr[0],GStr[1])                 
                if NewGroup not in VertGroups: 
                    me.addVertGroup(NewGroup) 
                else: 
                    me.removeVertsFromGroup(NewGroup,me.getVertsFromGroup(NewGroup,0)) 
                for d in AddVerts: 
                    VList=[d[0]] 
                    me.assignVertsToGroup(NewGroup,VList,d[1],AssignMode) 
                #me.assignVertsToGroup(group, vertList, weight, assignmode=1)     
                 
                 
                 
            EventNum+=1 
    VGListRunning=0 
 
def GetVertNames(): 
    GList=[] 
    VList=[] 
    SelVerts=[] 
    # Get a list of all selected Verts 
    for x in me.verts: 
        if x.sel: 
            SelVerts.append(x.index) 
    # return a list of all vert names 
    for x in me.getVertGroupNames(): 
        # if any selected verts are in this group, add the group to a list 
        VList=me.getVertsFromGroup(x,1,SelVerts) 
        if len(VList)>0: 
            GList.append(x) 
    return(GList) 
 
def ChangeString(event, val): 
    global GStr 
    global VGListRunning 
    if event==2: 
        GStr[0]=val 
    elif event==3: 
        GStr[1]=val 
         
    VGListRunning=1 
 
def buttons(): 
    global GroupList 
    global co 
    global VGListRunning 
    global GEventNumBase 
     
    ColHeight=20 
    ColWidth=105 
     
    GroupList=GetVertNames() 
    #GroupList=me.getVertGroupNames() 
     
    EventNum=GEventNumBase 
    if len(GroupList)<VGColumns: 
        CenWidth=0 
        CenHeight=0 
    else: 
        CenWidth=(VGColumns*ColWidth)/2 
        CenHeight=(((len(GroupList)/VGColumns)*ColHeight)+6*ColHeight)/2 
     
    BaseCoX=co[0]-CenWidth 
    BaseCoY=co[1]+CenHeight 
    coY=BaseCoY 
    coX=BaseCoX 
     
     
    Draw.Label("Available Vertex Groups:",BaseCoX,BaseCoY,310,18) 
    coY-=ColHeight     
    for x in GroupList: 
        Toggle=FindToggleState(EventNum) 
        Draw.Toggle(x,EventNum,coX,coY,100,15,Toggle, "Mirror: "+x,ToggleButton) 
        coX+=ColWidth 
        EventNum+=1 
        if coX>=BaseCoX+(ColWidth*VGColumns): 
            coX=BaseCoX 
            coY-=ColHeight 
                 
    if coX!=BaseCoX:         
        coY-=ColHeight 
    coY-=10 
    #BGL.glRasterPos2i(BaseCoX,coY) 
    #Draw.Text("Find all Vertex Groups containing the following text:") 
    Draw.Label("Find:",BaseCoX,coY,310,18) 
    #Label(string, x, y, w, h) 
    coY-=ColHeight     
    Draw.String("Text: ", 2, BaseCoX, coY, 310, 18, GStr[0], 20, "Find Groups containing this Text",ChangeString) 
    coY-=ColHeight 
    BGL.glRasterPos2i(BaseCoX,coY) 
    #Draw.Text("Mirror them to the following groups:") 
    Draw.Label("Mirror with:",BaseCoX,coY,310,18) 
    coY-=ColHeight             
    Draw.String("Text: ", 3, BaseCoX, coY, 310, 18, GStr[1], 20, "Replace with this Text",ChangeString) 
    coY-=(ColHeight+10) 
    Draw.PushButton("Mirror", 1, BaseCoX, coY, 100, 15,"Mirror all selected Vertex Groups", MirrorVGroups) 
     
         
    VGListRunning=0 
 
 
def main(): 
     
    if GError: return         
    while VGListRunning == 1: 
        Draw.UIBlock(buttons, 0) 
         
    Window.EditMode(1) 
    Window.EditMode(0) 
     
    if InEditMode: 
        Window.EditMode(1) 
 
 
if __name__ == '__main__': 
    main() 


nice, seems helpful to me. personally i’m just missing a select-all-groups-button in all of your scripts. :wink:

What I would like to see is a divide this vertex group into X number of groups. This could be very usefull for terrain based tree distribution. I have been working with the new ANT landscape script and I often put Blender in side view and select only the top parts of the landscape and assign those vertices to a single group. But it would be nice if a script could look at a group and divide the vertices in the group in to more groups, avoiding creating duplicates. Then the multiple particle system could be used to distribute particles across those groups. (Instant forest with multiple plants - all you would need would be a few different plant textures)

thats a great idea, and it would be really easy to implement

I am not that familiar with the particle system, so I dont really undestand the need- when you say divide up the group are you talking about in a grid type format, or each vert being placed in its own group

Consider the second image in this post, the one with the trees.
http://blenderartists.org/forum/showthread.php?t=156948&highlight=ant+landscape

This is using a single particle system to distribute the trees across a vertex group. One particle system to one group to one plant type. Now image if you could sub-divide the groups? The sub division should be a random sample from the original group, a master pool of vertices. Then remove that set from the pool and assign it to a new group, revise the pool and repeat till sub-division count is reached. You could add more particle systems each with it’s own image map. I imagine this as a quick way to create a forest, or make the texture an image map of small plants and you have a meadow along side a path.

I have put together a framework for my script description.


#!BPY
"""
Name: 'Subdivide Group'
Blender: 249
Group: 'EditMesh'
"""
import Blender
from Blender import Draw, BGL, Scene, Mesh, Window, sys, Object

def GetVertNames(passedMesh): 
    GList=[] 
    VList=[] 
    SelVerts=[] 
    # Get a list of all selected Verts 
    for x in passedMesh.verts: 
        if x.sel: 
            SelVerts.append(x.index) 
    # return a list of all vert names 
    for x in passedMesh.getVertGroupNames(): 
        # if any selected verts are in this group, add the group to a list 
        VList= passedMesh.getVertsFromGroup(x,1,SelVerts) 
        if len(VList)>0: 
            GList.append(x) 
    return(GList) 

def removeSetFromGroup (removeGroup, sourceGroup):
    return None

def returnNewSetFrom (sourceVertGroup, newCount):
    return None

def returnVertsInGroup (passedName):
    return None

def subdivide_group(groupName, newGroupCount, passedMesh):
    result = None
    vertsInGroup = returnVertsInGroup(groupName)
    if vertsInGroup != None:
        l = len(vertsInGroup)
        if l > newGroupCount:
            vertsPerGroup = l/newGroupCount
            if vertsPerGroup > 0:
                # There must be at least one vert in each group.
                er = 0
                for n in range(newGroupCount-1):
                    newVertGroup = returnNewSetFrom (vertsInGroup, vertPerGroup)
                    if newVertGroup != None:
                        if len(newVertGroup) > 0:
                            #Assign this new group to a vertex group.
                            tempGroup = removeSetFromGroup (newVertGroup, vertsInGroup)
                            if tempGroup != None:
                                vertsInGroup = tempGroup
                            else:
                                er = er + 1
                                print "subdivide_group: ERROR-removeSetFromGroup returned None."
                        else:
                            er = er + 1
                            print "subdivide_group: ERROR-Recieved a new set with no verts."
                    else:
                        er = er + 1
                        print "subdivide_group: ERROR-returnNewSetFrom returned None."
                print "subdivide_group: Done with " + str(er) + " errors."
                
            else:
                print "subdivide_group: ERROR-Vertices per group is less than 1."
        else:
            print "subdivide_group: ERROR-Vertices count is less than requested group count."
    else:
        print "subdivide_group: ERROR-returnVertsInGroup returned None for group [" + groupName + "]."
    return result

def main():
    scn = Scene.GetCurrent() 
    obj= scn.getActiveObject() 
     
    if obj.getType()!='Mesh': 
        obj= None 
         
    sel= [ob for ob in Object.GetSelected() if ob.getType()=='Mesh' if ob != obj] 
    if not sel and not obj: 
        Draw.PupMenu('Error, select a mesh as your active object.') 
        GError=True 
    else: 
        me = obj.getData(mesh=1)
        InEditMode = Window.EditMode()
        co=Window.GetMouseCoords() 
        Window.EditMode(0) 
        Window.EditMode(1) 
    
        Draw = Blender.Draw
        groupName = Draw.Create("Group")
        groupCount = Draw.Create(5)
        
        block = [\
        ("Group Name: ", groupName, 0, 21, "Name of group to subdivide."),\
        ('Count:', groupCount,  2, 42, 'Number of new groups to create.'),\
        ]
        result = Blender.Draw.PupBlock("Subdivide Group", block)
        if result == 0:
            # User canceled.
            return None
        else:
            result = subdivide_group (groupName.val, groupCount.val, me)
            # Return edit mode state.
            Window.EditMode(InEditMode) 
            return

main()

I guess I need a little help with those three blank functions. I also need to find a way to create a new group under code.

I was not able to get Mirror Vertex Groups Sccript work for me. When I discovered it via my internet search I got esctatic as it sounded like it could automate one painful riggging process. I have already created all my .L vertex groups. Now I hoped I could just hit a button and have my vertex selections mirrored from the Left side to the Right side.
I use Blender version 2.46 compiled with Python 2.5. Each time I attempt to run the script I have encountered script errors, a few times the Python consolu contained enough information to move forward to fix outdated syntax. However, it has now reached a point that surpuses my superficial understanding of how Python work.
I had also tried using Blender provided Mirror Vertex Locations and Weights in hopes it would automatically mirror the vertex groups from the Left side to the Right side. It did not do anything for me.
Could someone help? Does anyone have working script?
Ah on a side note, Once rigging is done, that is all bones have their vertex groups assigned to them. If I reduce polygon count after rigging, would poly reduction scripts be smart enough to correct the vertex groups? Some vertices might be absolute?