Today kids, I tell you how to split imported Sihlouette shapes into Nuke RotoPaint nodes.

In SihlouetteFX select several nodes. Go File->Export->nuke 6.2+ Shapes  and save Nuke project

I tried to use also File->Export->Nuke Shapes but in Nuke 7.0 it wasn’t opened properly

Open saved project in Nuke. There is a single RotoPaint node. It contains several layers with several shapes in each. I need separate layers into many nodes to use them separately.

To do this I wrote following script:

::::
import nuke, nuke.rotopaint as rp

def rptsw_walker(obj, list):
    # loop wor each subitem in Rotopaint
    for i in obj:
        # if there is a layer
        if isinstance(i, nuke.rotopaint.Layer):
            # create new RotoPaint object
            paintNode = nuke.createNode('RotoPaint')
            curvesKnob = paintNode['curves']
            rotoRoot = curvesKnob.rootLayer

            list1 = []

            # for each bezier shape we add it to the list. I don't know why
            # adding it to a list causes deleting shape from origin
            # if adding directly to the new roto object some shapes were not copied
            for j in i:
                if isinstance(j, nuke.rotopaint.Shape):
                    list1.append(j)

            # copy all shapes from list to new roto node
            for j in list1:
               rotoRoot.append(j)

# find selected node
rotoNode = nuke.selectedNode()
rptsw_shapeList = []
rotoCurve = rotoNode['curves']
rotoRoot = rotoCurve.rootLayer
# run
rptsw_walker(rotoRoot, rptsw_shapeList)       

Don’t forget to select  source RotoPaint node !! Attention! This script deletes shapes from original RotoPaint!

Does anybody know why copying shape to another node causes deleting it from original one?

Another not working solution found in google: Source: http://www.mail-archive.com/nuke-python@support.thefoundry.co.uk/msg02905/convert_shapetostroke.py

#***********************************************************
#Boundary Visual Effects - Silhouette Stroke Importer
#Version 0.98
#
#Created by Magno Borgo
#For greeting, bugs, and requests email me at mborgo[at]boundaryvfx.com
#Compatibility: Nuke 6.3 and up (not tested on previous versions)
#If you like and use the script frequently, please consider a small donation via Paypal to the same email above.
#
#Legal stuff:
#This script is provided "as is," without warranty of any kind, expressed
#or implied. In no event shall the author be held liable for any damages 
#arising in any way from the use of this script.
#***********************************************************
#Changelog
#v1.0
#initial release.
#***********************************************************
# Usage: Import the shapes exported from Silhouette, select the roto node and the group, and run.
# The stroke  precision can be set on the script, increase precision if you need to subdivide the stroke further.
#silhouetteStrokeImporter(2) (default = 2) 
#silhouetteStrokeImporter(5)
#***********************************************************

import nuke, nuke.rotopaint as rp, math, re
import threading, time
import profile

def rptsw_walker(obj, list):  
    for i in obj:
        if isinstance(i, nuke.rotopaint.Shape):
            list.append([i, obj]) 
        if isinstance(i, nuke.rotopaint.Layer):
            list.append([i, obj])
            rptsw_walker(i, list)
    return list


    
def strokeMap(value):
    return 1

  
def copyTransforms(oldT,newT):
    oldT = oldT.getTransform() 
    newT = newT.getTransform()   
    for i in range(3):
        newT.setTranslationAnimCurve(i,oldT.getTranslationAnimCurve(i))
        newT.setScaleAnimCurve(i,oldT.getScaleAnimCurve(i))
        newT.setSkewXAnimCurve(i,oldT.getSkewXAnimCurve(i))
        newT.setPivotPointAnimCurve(i,oldT.getPivotPointAnimCurve(i))
        newT.setRotationAnimCurve(i,oldT.getRotationAnimCurve(i))
    for i in range(4):
        for j in range(4):
            newT.setExtraMatrixAnimCurve(i,j,oldT.getExtraMatrixAnimCurve(i,j))

def copyAttributes(oldshape, newshape):
    old = oldshape.getAttributes()
    new= newshape.getAttributes()
    for i in range(len(old)):
        new.setCurve(i, old.getCurve(i))
        
        

def createLayer(shape, rotoRoot, newRotoNode, shapeInfos, task):
    newRotoNodeCurve = newRotoNode['curves']
    newRotoRoot = newRotoNodeCurve.rootLayer
    silhouetteData = matchShapeInfo(shape[0],shapeInfos)
    newLayer = rp.Layer(newRotoNodeCurve)
    newLayer.name = silhouetteData['LABEL']
    
    
    #task related code
    task.setMessage( 'Creating Layer: ' + silhouetteData['LABEL']  )
    if task.isCancelled():
        taskCancel = True
    #end of task related code   
    

    if shape[1] == rotoRoot:
        newRotoRoot.append(newLayer)
    else:
        parentLayer = matchShapeInfo(shape[1],shapeInfos)
        newlayerList = []                
        newlayerList = rptsw_walker(newRotoRoot, newlayerList)
        for layer in newlayerList:
            if isinstance(layer[0], nuke.rotopaint.Layer):
                if layer[0].name == parentLayer['LABEL']:
                    assignParent = layer[0]
        
        assignParent.append(newLayer)
    copyTransforms(shape[0],newLayer)
    
    


def createStroke(shape, rotoRoot, newRotoNode, shapeInfos, precision, task):
    cancel = False
    silhouetteData = 1 #dummy stroke width/size
    newRotoNodeCurve = newRotoNode['curves']
    newRotoRoot = newRotoNodeCurve.rootLayer
    newlayerList = []                
    newlayerList = rptsw_walker(newRotoRoot, newlayerList)
    newstroke = rp.Stroke(newRotoNodeCurve)
    keysTimes = shape[0][0].center.getControlPointKeyTimes()
    taskcount =0
    for i in range((len(shape[0]) *precision)+1):
        #task related code
        task.setMessage( 'Creating Stroke: ' +  '\npoint ' + str(taskcount+1) + " of " + str(len(shape[0]) *precision) )
        taskcount +=1
        if task.isCancelled():
            taskCancel = True
            break           
        #end of task related code        


        newPoint = rp.AnimControlPoint(0,0,1)
        for key in keysTimes:
           
            if i == 0: # or n ==  (len(shape[0]) *precision): #extra points on begin/end

                pos = 0
                point = [shape[0][0].center.getPositionAnimCurve(0).evaluate(key),shape[0][0].center.getPositionAnimCurve(1).evaluate(key),0]
            elif i == (len(shape[0]) *precision):
                pos = 1
                point = [shape[0][-1].center.getPositionAnimCurve(0).evaluate(key),shape[0][-1].center.getPositionAnimCurve(1).evaluate(key),0]
            else:    
                pos = float((i)* 1.0/(len(shape[0])*precision))
                cubicCurve = shape[0].evaluate(0, key)
                point = cubicCurve.getPoint(pos)
            vector = nuke.math.Vector3(point[0],point[1], 1)
            newPoint.addPositionKey(key,vector)
        
        newstroke.append(newPoint)
    copyTransforms(shape[0],newstroke)
#    newstroke.name = silhouetteData['LABEL']
    newstroke.setVisible(0, shape[0].getVisible(0))
    
    if shape[1] == rotoRoot:
        newRotoRoot.append(newstroke)
    else:
        parentLayer = matchShapeInfo(shape[1],shapeInfos)
        for layer in newlayerList:
            if isinstance(layer[0], nuke.rotopaint.Layer):
                if layer[0].name == parentLayer['LABEL']:
                    assignParent = layer[0]
        assignParent.append(newstroke)

    attrs = newstroke.getAttributes()
    oldattrs = shape[0].getAttributes()
    attrs.setCurve(9,oldattrs.getCurve('opc')) #opacity
    
    if float(silhouetteData) >= 3:
        attrs.set("bs",float(silhouetteData)) 
    else:
        if float(silhouetteData) < 2:
            attrs.set("bs",2) #value of 1 created problems on stroke rendering
            
        else:
            attrs.set("bs",float(silhouetteData)) 
        keys = attrs.getNumberOfKeys('opc')
        if keys == 0:
            attrs.set("opc", strokeMap(round(float(silhouetteData),1)))
        for i in range(keys):
            t = attrs.getKeyTime(9, i)
            currentValue = attrs.getValue(t,"opc")
            attrs.set(t,"opc", currentValue*strokeMap(round(float(silhouetteData),1)))
    attrs.set("h",0.5) #hardness
    
    
        
def createShape(shape, rotoRoot, newRotoNode, shapeInfos, task):
    cancel = False
    newRotoNodeCurve = newRotoNode['curves']
    newRotoRoot = newRotoNodeCurve.rootLayer
    newlayerList = []                
    newlayerList = rptsw_walker(newRotoRoot, newlayerList)
    silhouetteData = matchShapeInfo(shape[0],shapeInfos)
    
    shapeattr = shape[0].getAttributes()
    if shapeattr.getValue(0, "tt") == 5:
        newstroke = rp.Shape(newRotoNodeCurve, type="bspline")
    else:
        newstroke = rp.Shape(newRotoNodeCurve)

    taskcount = 0
    for point in shape[0]:

        #task related code
        task.setMessage( 'Creating Shape: ' + silhouetteData['LABEL'] + '\npoint ' + str(taskcount+1) + " of " + str(len(shape[0])) )
        taskcount +=1
        if task.isCancelled():
            taskCancel = True
            break           
        #end of task related code        
        
        
        
        newPoint = rp.ShapeControlPoint()
        for i in range(2):
            newPoint.featherCenter.setPositionAnimCurve(i, point.featherCenter.getPositionAnimCurve(i))
            newPoint.featherLeftTangent.setPositionAnimCurve(i, point.featherLeftTangent.getPositionAnimCurve(i))
            newPoint.featherLeftTangent.setPositionAnimCurve(i, point.featherLeftTangent.getPositionAnimCurve(i))
            newPoint.featherRightTangent.setPositionAnimCurve(i, point.featherRightTangent.getPositionAnimCurve(i))
            newPoint.leftTangent.setPositionAnimCurve(i, point.leftTangent.getPositionAnimCurve(i))
            newPoint.rightTangent.setPositionAnimCurve(i, point.rightTangent.getPositionAnimCurve(i))
            newPoint.center.setPositionAnimCurve(i, point.center.getPositionAnimCurve(i))       
        newstroke.append(newPoint)
 
    newstroke.name = silhouetteData['LABEL']
    copyTransforms(shape[0],newstroke)
    copyAttributes(shape[0],newstroke)
    
    if shape[1] == rotoRoot:
        newRotoRoot.append(newstroke)
    else:
        parentLayer = matchShapeInfo(shape[1],shapeInfos)
        for layer in newlayerList:
            if isinstance(layer[0], nuke.rotopaint.Layer):
                if layer[0].name == parentLayer['LABEL']:
                    assignParent = layer[0]
        assignParent.append(newstroke)

    

        
 
def silhouetteStrokeImporter(precision=2):
    
    selection = nuke.selectedNodes()
    taskCancel = False
    for node in selection:
        if node.Class() not in ('Roto', 'RotoPaint','Group'):
            if nuke.GUI:
                nuke.message( 'You must select the Roto node and the Group with metadata' )
            raise TypeError, 'You must select the Roto node and the Group with metadata'
        if node.Class() in ('Roto', 'RotoPaint'):
            rotoNode = node
        else:
            groupNodes = node.nodes()
            stickyNode = groupNodes[0]
    start_time = time.time()
    rptsw_shapeList = []
    silhouetteData =[] 
    rotoCurve = rotoNode['curves']
    rotoRoot = rotoCurve.rootLayer
    newRotoNode = nuke.createNode('RotoPaint')
    newRotoNode.setName(rotoNode.name()+ "_STROKE_IMPORTER_" +  newRotoNode.name())
    newRotoNodeCurve = newRotoNode['curves']
    newRotoRoot = newRotoNodeCurve.rootLayer
    rptsw_shapeList = rptsw_walker(rotoRoot, rptsw_shapeList)
    newRotoNode.knob('format').setValue(rotoNode.knob('format').value())
    newRotoNode.knob('output').setValue(rotoNode.knob('output').value())
    start_time = time.time()
    taskCount = 0.0
    task = nuke.ProgressTask( 'Silhouette Stroke\nImporter\n' )
    for shape in rptsw_shapeList:
        #BEGIN some UI task related settings
        if task.isCancelled():
            taskCancel = True
            break                
        if taskCancel:
            break
        task.setProgress(taskCount/len(rptsw_shapeList) * 100)
        taskCount +=1
        #END UI task related settings       

        if isinstance(shape[0], nuke.rotopaint.Layer):
            createLayer(shape, rotoRoot, newRotoNode, shapeInfos, task)

    for shape in rptsw_shapeList:
        #BEGIN some UI task related settings
        if task.isCancelled():
            taskCancel = True
            break                
        if taskCancel:
            break
        task.setProgress(taskCount/len(rptsw_shapeList) * 100)
        taskCount +=1
        #END UI task related settings 
                    
        if isinstance(shape[0], nuke.rotopaint.Shape):
            shapeInfos ="dummy"
            silhouetteData = 1 #dummy stroke width/size
            if float(silhouetteData) > 0:
                threading.Thread(None, createStroke, args=(shape, rotoRoot, newRotoNode, shapeInfos, precision, task)).start()
            else:
        
                threading.Thread(None, createShape, args=(shape, rotoRoot, newRotoNode, shapeInfos, task)).start()
                

         
          
    newRotoNodeCurve.changed()
    rptsw_shapeList = []
    print "Time elapsed:",time.time() - start_time, "seconds"

#remove the line below if you are using the script with menu.py (in menus/DAG/etc)
silhouetteStrokeImporter()