On 18/12/2017 at 12:25, xxxxxxxx wrote:
Hi Pim,
As gr4ph0s already told you, it's not allowed to interact with a tool from an object plugin. Also the Paint Tool can't be used with SendModelingCommand().
The solution is to manually smooth the weights just like the Paint Tool does when clicking the Apply buttons.
Don't be afraid, the needed code isn't complex.
You can find a script below. It first initializes the selected points with a weight of 1.0. Then it performs the smoothing with the average of the neighboring points weight.
Code works with a polygon object which has polygons selected.
Note if you'll be using this code in a generator, then don't call SetBit(c4d.BIT_ACTIVE) on the vertex map tag and EventAdd().
These functions are forbidden there and also it would not make sense to call these as the vertex map tag is used virtually.
import c4d
def main() :
# Requirements
if op is None:
return
if op.GetType() != c4d.Opolygon:
return
if doc.GetMode() != c4d.Mpolygons:
return
# Retrieve polygon object information
allPolys = op.GetAllPolygons()
polyCount = op.GetPolygonCount()
if len(allPolys) != polyCount:
return
polySel = op.GetPolygonS()
# Select points from polygon selection
pointSel = c4d.BaseSelect()
for polyIdx in xrange(polyCount) :
if not polySel.IsSelected(polyIdx) :
continue
pointSel.Select(allPolys[polyIdx].a)
pointSel.Select(allPolys[polyIdx].b)
pointSel.Select(allPolys[polyIdx].c)
pointSel.Select(allPolys[polyIdx].d)
# Add vertex map tag to polygon object
pointCount = op.GetPointCount()
vmapTag = op.MakeVariableTag(c4d.Tvertexmap, pointCount)
if vmapTag is None:
return
# Initialize vertex map for selected points with 1.0 weight
vmapData = vmapTag.GetAllHighlevelData()
for pointIdx in xrange(pointCount) :
if not pointSel.IsSelected(pointIdx) :
continue
vmapData[pointIdx] = 1.0
# Create list for the new vertex map data
newData = [0.0] * pointCount
# Strength of weight application (Opacity in Paint Tool)
applyStrength = 1.0
# Create neighbor to obtain information on neighboring polygons for each point
nb = c4d.utils.Neighbor()
if not nb.Init(op) :
return
# Smooth calculation loop
for pointIdx in xrange(pointCount) :
if not pointSel.IsSelected(pointIdx) :
continue
# Get neighboring polygons
polys = nb.GetPointPolys(pointIdx)
if len(polys) == 0:
newData[pointIdx] = vmapData[pointIdx]
continue
# Select points from neighboring polygons
sel = c4d.BaseSelect()
for poly in polys:
sel.Select(allPolys[poly].a)
sel.Select(allPolys[poly].b)
sel.Select(allPolys[poly].c)
sel.Select(allPolys[poly].d)
weight = 0.0
num = 0
# Calculate average weight from neighboring points
segCount = sel.GetSegments()
for segIdx in xrange(segCount) :
first, last = sel.GetRange(segIdx, pointCount)
for idx in range(first, last+1) :
weight += vmapData[idx]
num += 1
if num > 0:
weight /= float(num)
# Blend weight
data = vmapData[idx]
value = data + (weight - data) * applyStrength
# Set new weight
newData[pointIdx] = c4d.utils.ClampValue(value, 0.0, 1.0)
# Finally set the new vertex map data
vmapTag.SetAllHighlevelData(newData)
# Update polygon object
op.Message(c4d.MSG_UPDATE)
vmapTag.SetBit(c4d.BIT_ACTIVE)
c4d.EventAdd()
if __name__=='__main__':
main()