121 lines
3.8 KiB
Python
121 lines
3.8 KiB
Python
#!BPY
|
|
"""
|
|
Name: 'Vertex Groups Island Average'
|
|
Blender: 243
|
|
Group: 'WeightPaint'
|
|
Tooltip: 'Average the vertex weights for each connected set of verts'
|
|
"""
|
|
|
|
# --------------------------------------------------------------------------
|
|
# ***** 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 Scene, Mesh, Window, sys, Draw
|
|
from BPyMesh import meshWeight2List, list2MeshWeight, mesh2linkedFaces
|
|
|
|
import BPyMessages
|
|
import bpy
|
|
|
|
def faceGroups2VertSets(face_groups):
|
|
''' Return the face groups as sets of vert indicies '''
|
|
return [set([v.index for f in fg for v in f]) for fg in face_groups]
|
|
|
|
|
|
def vgroup_average(ob_orig, me, sce, PREF_ALL_VGROUPS=True):
|
|
if not me.getVertGroupNames():
|
|
return
|
|
|
|
weight_names, weight_list = meshWeight2List(me)
|
|
|
|
weight_names_len = len(weight_names)
|
|
vgroup_dummy = [0.0] * weight_names_len
|
|
vgroup_range = range(weight_names_len)
|
|
|
|
if not PREF_ALL_VGROUPS:
|
|
weight_active_index = weight_names.index(me.activeGroup)
|
|
|
|
for vert_set in faceGroups2VertSets( mesh2linkedFaces(me) ):
|
|
if not vert_set:
|
|
continue
|
|
|
|
|
|
if PREF_ALL_VGROUPS:
|
|
# We need to average the vgroups
|
|
collected_group = vgroup_dummy[:]
|
|
for i in vert_set:
|
|
vert_group = weight_list[i] # get the original weight
|
|
weight_list[i] = collected_group # replace with the collected group
|
|
|
|
for j in vgroup_range: # iter through the vgroups
|
|
collected_group[j] += vert_group[j]
|
|
|
|
for j in vgroup_range:
|
|
collected_group[j] /= len(vert_set)
|
|
else:
|
|
# Active group only
|
|
vert_weight = 0.0
|
|
for i in vert_set:
|
|
vert_weight += weight_list[i][weight_active_index]
|
|
|
|
vert_weight /= len(vert_set)
|
|
|
|
for i in vert_set:
|
|
weight_list[i][weight_active_index] = vert_weight
|
|
|
|
list2MeshWeight(me, weight_names, weight_list)
|
|
|
|
def main():
|
|
|
|
# Gets the current scene, there can be many scenes in 1 blend file.
|
|
sce = bpy.data.scenes.active
|
|
|
|
# Get the active object, there can only ever be 1
|
|
# and the active object is always the editmode object.
|
|
ob_act = sce.objects.active
|
|
|
|
if not ob_act or ob_act.type != 'Mesh':
|
|
BPyMessages.Error_NoMeshActive()
|
|
return
|
|
|
|
# Saves the editmode state and go's out of
|
|
# editmode if its enabled, we cant make
|
|
# changes to the mesh data while in editmode.
|
|
is_editmode = Window.EditMode()
|
|
Window.EditMode(0)
|
|
|
|
PREF_ALL_VGROUPS = Draw.PupMenu("All Groups?%t|All Groups%x1|Active Group Only%x0")
|
|
if PREF_ALL_VGROUPS==-1:
|
|
return
|
|
|
|
Window.WaitCursor(1)
|
|
me = ob_act.getData(mesh=1) # old NMesh api is default
|
|
t = sys.time()
|
|
|
|
# Run the mesh editing function
|
|
vgroup_average(ob_act, me, sce, PREF_ALL_VGROUPS)
|
|
|
|
# Timing the script is a good way to be aware on any speed hits when scripting
|
|
print 'Average VGroups in %.2f seconds' % (sys.time()-t)
|
|
Window.WaitCursor(0)
|
|
if is_editmode: Window.EditMode(1)
|
|
|
|
|
|
# This lets you can import the script without running it
|
|
if __name__ == '__main__':
|
|
main() |