Jump to content
Sign in to follow this  
julienmargelin

NetworkImage

Recommended Posts

Hello everyone,

I'm trying to make a screenShot script with python that load my image in the network view

Well everything goes well until the end of the script:

editor = hou.ui.paneTabOfType(hou.paneTabType.NetworkEditor)
image = hou.NetworkImage()
image.setPath('$HFS/houdini/pic/Mandril.pic')
image.setRect(hou.BoundingRect(0, 0, 5, 5))
editor.setBackgroundImages([image])

I found this piece of code in the houdini documentation. The problem is when navigate from /obj/geo to /obj and go back to /obj/geo the image is gone.

is anybody has an idea ?

Thanks !

here is my full script:

def screenShot():
    """take a screen shot of the current viewport at the current frame"""
    help(screenShot)
    import hou
    import toolutils
    import os
    #selected node
    nodeSelect = hou.selectedNodes()
    path = hou.expandString("$HIP")
    frame = hou.expandString("$F")
    frame = int(frame)
    black=hou.Color((0,0,0))
    #name check there is a node selected
    if len(nodeSelect)<1:
        print ("!!!    error: select a node    !!!")
    else:
        for node in nodeSelect:
            name = node.name()
            node.setColor(black)
        #Get the current Desktop
        desktop = hou.ui.curDesktop()
        # Get the scene viewer
        scene= toolutils.sceneViewer()
        flipbook_options = scene.flipbookSettings().stash()
        # set frame range
        flipbook_options.frameRange((frame,frame))
        #set output path
        root ="{1}/{2}/{0}/".format(name,path,"screenShot")
        if os.path.exists(root):
            listPath = os.listdir(root)
            inc = len(listPath)
            inc = int(inc)   
            outputPath = "{}{}.{:04d}.jpg".format(root,name,inc)
        else:
            os.makedirs(root)
            inc = 0
            outputPath = "{}{}.{:04d}.jpg".format(root,name,inc)
        #set flipbook current path     
        flipbook_options.output(outputPath)
        #run flipbook
        scene.flipbook(scene.curViewport(),flipbook_options)
        # reload image
        print (outputPath)
        editor = hou.ui.paneTabOfType(hou.paneTabType.NetworkEditor)
        image = hou.NetworkImage()
        image.setPath(outputPath)
        image.setRect(hou.BoundingRect(0, 0, 5, 5))
        image.setRelativeToPath(node.path())
        editor.setBackgroundImages([image])

 

 

 

Share this post


Link to post
Share on other sites

Afaik when you add a background image via their snippet, the .userDataDict() of the node is not being registered/saved (you can try adding a network bg image by hand and calling 

hou.node('/obj/mynode/').userDataDict()

You'll get something like:

{'___Version___': '16.0.736', 'backgroundimages': '[{"relativetopath": "volumevisualization24", "path": "/path/to/image.png", "rect": [-202.1, -265.1, 60.2, -85.3], "brightness": 0.54}]'}

Pretty sure this is a bug not a feature. Adding these values to the userDict works but if you screw up the formatting you can corrupt a node and houdini doesn't like it.

  • Like 1

Share this post


Link to post
Share on other sites

Sent a RFE and it's normal behaviour, if anyone googles the problem:

Quote

Our developers comment:
That is correct, setting the image on the network editor does not automatically save the change to the current network's userDataDict. On the other hand if you edit the network's userDataDict, the network editor should automatically update with the change. So you can either edit the userDataDict to make your desired changes, or you can use the nodegraphutils.saveBackgroundImages() method to save the backgroun image from the network editor into the network's userDataDict.

All the best,
Jenny.
(ID# 90646)

(i hope it's ok to post this. they are super responsive!)

  • Like 1

Share this post


Link to post
Share on other sites

For anyone who googles out there I made a tool that I think matches what Julien wanted to do:

 

kuc1PnO.gif

 

https://berniebernie.fr/wiki/Houdini_Python#screenshot_to_background_image
 

Code as of 22/07/2019 if my website goes down:

 

import hou
import os
import subprocess
import nodegraphutils as utils
from time import gmtime, strftime

widthRatio = 4                      # change to make screenshot bigger or smaller, this is ~x4 node width

def takeScreenShot(savePath):
    '''change to your preferred capture app /!\ no error checking for now '''
    subprocess.check_call([r"C:\Users\me\MiniCap.exe","-captureregselect","-save",savePath,"-exit"])

def removeBackgroundImage(**kwargs):
    ''' erases bg image from tuples of backgroundImages() if it can find it, updates bg '''
    deletingNode = [x[1] for x in  kwargs.items()][0]
    image = deletingNode.parm('houdinipath').eval()
    editor = hou.ui.paneTabOfType(hou.paneTabType.NetworkEditor)
    backgroundImagesDic = editor.backgroundImages()
    backgroundImagesDic = tuple(x for x in backgroundImagesDic if x.path() != image)
    editor.setBackgroundImages(backgroundImagesDic)
    utils.saveBackgroundImages(editor.pwd(), backgroundImagesDic)

def changeBackgroundImageBrightness(event_type,**kwargs):
    ''' changes brightness/visibility if template or bypass flags are checked -- its poorly written/thought but i was tired'''
    nullNode = [x[1] for x in  kwargs.items()][0]
    image = nullNode.parm('houdinipath').eval()
    brightness = 1.0
    if nullNode.isBypassed():
        brightness = 0.0
    elif nullNode.isTemplateFlagSet():
        brightness = 0.5
    editor = hou.ui.paneTabOfType(hou.paneTabType.NetworkEditor)
    backgroundImagesDic = editor.backgroundImages()
    i = 0
    for item in backgroundImagesDic:
        if item.path() == image:
            backgroundImagesDic[i].setBrightness(brightness)
            break
        i = i + 1
    editor.setBackgroundImages(backgroundImagesDic)
    utils.saveBackgroundImages(editor.pwd(), backgroundImagesDic)
    
#generate unique(ish) path for screenshot
timestamp = strftime('%Y%m%d_%H%M%S', gmtime())
hipname = str(hou.getenv('HIPNAME'))
hippath = str(hou.getenv('HIP')) + '/screenshots'
screenshotName = hipname + '.' + timestamp + '.png'
systempath = hippath + '\\' + screenshotName
houdinipath = '$HIP/screenshots/'+screenshotName

#take screenshot with capture region
takeScreenShot(systempath)


#set up background image plane
editor = hou.ui.paneTabOfType(hou.paneTabType.NetworkEditor)
image = hou.NetworkImage()
image.setPath(houdinipath)
sel = hou.selectedNodes()
nullNode = ''

if sel:
    lastSel = sel[-1]
    nullNode = lastSel.parent().createNode('null','screenshot')
    if lastSel.outputConnections():
        nullNode.setInput(0,lastSel)                   

else:
    nullNode = editor.pwd().createNode('null','screenshot') 
    nullNode.moveToGoodPosition()
    lastSel = nullNode

#configure image plane placement
nullNode.setUserData('nodeshape','task')
nullNode.setPosition(lastSel.position())
nullNode.setColor(hou.Color(.3,.3,.3))
nullNode.move([lastSel.size()[0]*2,-lastSel.size()[1]*2])

rez = hou.imageResolution(systempath)
ratio = 1.0*rez[1]/rez[0]
rect = hou.BoundingRect(0,-lastSel.size()[1]*1.1,widthRatio,-widthRatio*ratio-lastSel.size()[1]*1.1)
image.setRelativeToPath(nullNode.path())
image.setRect(rect)

#following is adding a spare parm with image path to be able to know which node corresponds to which background image
#could have used a user attribute or relativeToPath() and smarter logic but it works and it helps me visualize filepath

hou_parm_template_group = hou.ParmTemplateGroup()
hou_parm_template = hou.LabelParmTemplate("houdinipath", "Label", column_labels=(['\\'+houdinipath]))
hou_parm_template.hideLabel(True)
hou_parm_template_group.append(hou_parm_template)
nullNode.setParmTemplateGroup(hou_parm_template_group)


#attach a function that deletes the background image plane if the corresponding node is deleted (faster than doing it by hand)
nullNode.addEventCallback((hou.nodeEventType.BeingDeleted,), removeBackgroundImage)

#attach a function to change visibility or opacity if corresponding node flags are changed
nullNode.addEventCallback((hou.nodeEventType.FlagChanged,), changeBackgroundImageBrightness)

#add image to network background
backgroundImagesDic = editor.backgroundImages()
backgroundImagesDic = backgroundImagesDic + (image,)
editor.setBackgroundImages(backgroundImagesDic)
utils.saveBackgroundImages(editor.pwd(), backgroundImagesDic)

 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
Posted (edited)

I don't know if it is of any use but here is a linux version...

DISCLAIMER, I have ignored accounting for the outputConnections() as I don't really understand the purpose... also I have commented a bit further and expand strings to support variables vs absolute paths discrepancies... should work ok.

 

import hou
import os
import subprocess
import nodegraphutils as utils
from time import gmtime, strftime

widthRatio = 4           # change to make screenshot bigger or smaller, this is ~x4 node width


# --------------------------------------------------------------------------------------------    
# FUNCTIONS
# --------------------------------------------------------------------------------------------    

def createScreenshotFolder(saveFolder):
    '''create screenshot folder under $HIP folder '''
    
    # System call to create the necessary folder
    subprocess.check_call([r"mkdir", r"-p", saveFolder])

def takeScreenShot(savePath):
    '''change to your preferred capture app /!\ no error checking for now '''
    
    # System call using ImageMagik import command that requests an interactive region to operate
    subprocess.check_call([r"import", savePath])
    

def removeBackgroundImage(**kwargs):
    ''' erases bg image from tuples of backgroundImages() if it can find it, updates bg '''
    
    # find the node that is meant to be deleted
    deletingNode = [x[1] for x in  kwargs.items()][0]
    
    # find the image in the spare tab
    image = deletingNode.parm('houdinipath').eval()
    
    # find the network
    editor = hou.ui.paneTabOfType(hou.paneTabType.NetworkEditor)

    # collect the images stored in it
    backgroundImagesDic = editor.backgroundImages()
    
    # find the one image to be deleted
    backgroundImagesDic = tuple(x for x in backgroundImagesDic if hou.expandString(x.path()) != hou.expandString(image))
    
    # update the images
    editor.setBackgroundImages(backgroundImagesDic)
    utils.saveBackgroundImages(editor.pwd(), backgroundImagesDic)

    
def changeBackgroundImageBrightness(event_type,**kwargs):
    ''' changes brightness/visibility if template or bypass flags are checked -- its poorly written/thought but i was tired'''

    # find the null holding the image
    nullNode = [x[1] for x in  kwargs.items()][0]
    
    # find the image in the spare tab
    image = nullNode.parm('houdinipath').eval()

    # define color based on flags
    if nullNode.isBypassed():
        brightness = 0.0
    elif nullNode.isTemplateFlagSet():
        brightness = 0.5
    else:
        brightness = 1.0

    # find the network
    editor = hou.ui.paneTabOfType(hou.paneTabType.NetworkEditor)
    
    # collect the images stored in it
    backgroundImagesDic = editor.backgroundImages()
    
    # traverse all images, find the one we have actioned and set the brightness
    i = 0
    for item in backgroundImagesDic:
        if hou.expandString(item.path()) == hou.expandString(image):
            backgroundImagesDic[i].setBrightness(brightness)
            break
        i = i + 1

    # update the visibility values
    editor.setBackgroundImages(backgroundImagesDic)
    utils.saveBackgroundImages(editor.pwd(), backgroundImagesDic)

 

# --------------------------------------------------------------------------------------------    
# MAIN
# --------------------------------------------------------------------------------------------    

# generate unique(ish) path for screenshot
timestamp = strftime('%Y%m%d_%H%M%S', gmtime())
hipname = str(hou.getenv('HIPNAME'))
hippath = str(hou.getenv('HIP')) + '/screenshots'
screenshotName = hipname + '.' + timestamp + '.png'
systempath = hippath + '/' + screenshotName
houdinipath = '$HIP/screenshots/' + screenshotName


# take screenshot with capture region
createScreenshotFolder(hippath)
takeScreenShot(systempath)


# set up background image plane
editor = hou.ui.paneTabOfType(hou.paneTabType.NetworkEditor)
image = hou.NetworkImage()
image.setPath(houdinipath)
sel = hou.selectedNodes()
nullNode = ''

if sel:
    lastSel = sel[-1]
    nullNode = lastSel.parent().createNode('null','screenshot')

    nullNode.setInput(0,lastSel)
    #if lastSel.outputConnections():
    #    nullNode.setInput(0,lastSel)               

else:
    nullNode = editor.pwd().createNode('null','screenshot')
    nullNode.moveToGoodPosition()
    lastSel = nullNode
    

# configure image plane placement
nullNode.setUserData('nodeshape','task')
nullNode.setPosition(lastSel.position())
nullNode.setColor(hou.Color(.3,.3,.3))
nullNode.move([lastSel.size()[0]*2,-lastSel.size()[1]*2])

rez = hou.imageResolution(systempath)
ratio = 1.0*rez[1]/rez[0]
rect = hou.BoundingRect(0,-lastSel.size()[1]*1.1,widthRatio,-widthRatio*ratio-lastSel.size()[1]*1.1)
image.setRelativeToPath(nullNode.path())
image.setRect(rect)


# following is adding a spare parm with image path to be able to know which node corresponds to which background image
# could have used a user attribute or relativeToPath() and smarter logic but it works and it helps visualize filepath
hou_parm_template_group = hou.ParmTemplateGroup()
hou_parm_template = hou.LabelParmTemplate("houdinipath", "Label", column_labels=([houdinipath]))
hou_parm_template.hideLabel(True)
hou_parm_template_group.append(hou_parm_template)
nullNode.setParmTemplateGroup(hou_parm_template_group)


# attach a function that deletes the background image plane if the corresponding node is deleted (faster than doing it by hand)
nullNode.addEventCallback((hou.nodeEventType.BeingDeleted,), removeBackgroundImage)
# attach a function to change visibility or opacity if corresponding node flags are changed
nullNode.addEventCallback((hou.nodeEventType.FlagChanged,), changeBackgroundImageBrightness)


# add image to network background
backgroundImagesDic = editor.backgroundImages()
backgroundImagesDic = backgroundImagesDic + (image,)
editor.setBackgroundImages(backgroundImagesDic)
utils.saveBackgroundImages(editor.pwd(), backgroundImagesDic)

 

  

 

Edited by jordibares
  • Thanks 1

Share this post


Link to post
Share on other sites
Posted (edited)

Really useful script, thanks for sharing!

Got an error when bypassing the null using the Linux version, got it fixed by replacing line 77 with,

            backgroundImagesDic[i].setBrightness(brightness)

Seemed to just miss the

[i] 

 

Edited by AslakKS
missing [i]

Share this post


Link to post
Share on other sites

Fixed, the code snippet now incorporates your fix... I did have it on my text editor correctly but something went wrong on the copy I think... thanks once again.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×