Copy / Paste Bundles

For your productions, bundles are still an important scene-structure-tool. Since the Houdini 18 and solaris, this is a legacy workflow which will be less important over the next years. Anyway, we found it a little bit to early to jump to solaris – we’ll stay on the known workflows for a while.

When working with a huge amount of objects we organize our scenes with bundles. There are bundles for ogl capturings, rendering bundles, simulation bundles or light bundles. The downside of bundles is, that they are not copy- and pasteable. So I decided to create two scripts – One for copying and one for pasting bundles.

Feel free to download the scripts and to try them.

 

Copy Bundles

import hou
import xml.etree.cElementTree as ET
import xml.dom.minidom as minidom

#set a counter
bNR = 0
#create an empty bundle list
crrBNodes = []
#setup elementtree root and sublement
root = ET.Element("scene")
doc = ET.SubElement(root, "bundles")
#check if an bundle is selected
if len(hou.selectedNodeBundles()) != 0:
    #loop over the selected bundles
    for currB in hou.selectedNodeBundles():
        #loop over the bundle elements
        for currNode in currB.nodes():
            #appand the current node to the bundle list
            crrBNodes.append(currNode.path())
        #appand the new bundle subelement to the elment tree
        ET.SubElement(doc, "bundle", name=str(currB.name())).text = str(crrBNodes)
        #reset the bundle list
        crrBNodes = []    
    
    #format the elementtree
    rough_string = ET.tostring(root, 'utf-8')
    reparsed = minidom.parseString(rough_string)
    formatedTree = reparsed.toprettyxml(indent="\t")
   
    #setup the output path for the xml file
    outputDIR = hou.hscriptExpression("$TEMP") + "\\BUNDLE_Copy.xml"
    #write the xml file to the users temp direction
    with open(outputDIR, "w") as f:
        f.write(formatedTree)

Paste Bundles

#import modules
import hou
import os.path
import xml.etree.cElementTree as ET

#setup the output path for the xml file
imputDIR = hou.hscriptExpression("$TEMP") + "/BUNDLE_Copy.xml"
#check if the xml file exists
if(os.path.exists(imputDIR)):
    #import the element tree from file
    tree = ET.parse(imputDIR)
    #get the root
    root = tree.getroot()
    #loop over the root
    for child in root:
        #loop over the bundles
        for elm in child:
            #create an checker variable
            oCheckBundleExists = 0
            #loop over the scene bundles
            for currB in hou.nodeBundles():
                #check if there is already a bundle with t
                if(elm.get('name') == currB.name()):
                    #if ther is an existing bundle, set the checker to 1
                    oCheckBundleExists  = 1
            #convert sting to array
            oBundleMembers = elm.text
            oBundleMembers = oBundleMembers.replace("[","")
            oBundleMembers = oBundleMembers.replace("]","")
            oBundleMembers = oBundleMembers.replace("'","")
            oBundleMembers = oBundleMembers.replace(" ","")
            oBundleMembers = oBundleMembers.split(",")
            #check if the bundle exists
            if oCheckBundleExists == 1:  
                #if it exists, create a bundle with _1
                oCurrentBundle = hou.addNodeBundle(str(elm.get('name') + "_1"))
            else:
                #if it not exists create a the bundle wit the proper name
                oCurrentBundle = hou.addNodeBundle(str(elm.get('name')))
            #Loop over the created array oBundleMembers
            for oNode in oBundleMembers:
                #assign the Node to add the the oNodeToAdd Variable
                oNodeToAdd = hou.node(oNode)
                #check if the node to add is valid
                if oNodeToAdd:
                    #if yes add the node to the current bundle
                    oCurrentBundle.addNode(oNodeToAdd)
                else:
                    #if no put an error to the console
                    print "Node not found " + oNode +  ". Skip adding to Bundele: " + str(elm.get('name'))

Instance Objects By Bundle Members

Hey!

I made a simple setup that reads the members of a bundle and copies the oppath as an instance attribute to points. When dealing with a huge amount of instances, it’s super easy to manage those instance masters. Click here to download the scene. InstanceByBundleMembers

Quick Edit: Please add the line oInstances.sort() to the Python SOP. With this line, the instaces will stay the same. Otherwhise it could be, that python reads the bundle members in another way from time to time.