Monday, September 25, 2017

Thursday, September 7, 2017

Houville :: how to not go insane with Nuke vs Houdini hotkeys

Display shortcuts: I have these set as F9-F12
import os,glob
def visualise(flag):
    if flag ==1: hou.selectedNodes()[0].setDisplayFlag(1)
    if flag ==2: hou.selectedNodes()[0].setRenderFlag(1)
    if flag ==3:
        if len(hou.selectedNodes())>0:
            state = 1-hou.selectedNodes()[0].isTemplateFlagSet()
            for i in hou.node(os.path.dirname(hou.selectedNodes()[0].path())).glob('*'): i.setTemplateFlag(0)
            for i in hou.selectedNodes():
                i.setTemplateFlag(state)
    if flag ==4:
        state = 1-hou.selectedNodes()[0].isBypassed()
        for i in hou.selectedNodes():
            i.bypass(state)

visualise(4)


This is straight out of Nukeland for snapping your nodes to the grid intersections. I have it set as Shift+\
offsetDict = {'Sop alembic':[0.0, 0.21440000000000037],'Sop merge':[-0.0011499999999999844, -0.021300000000000013], 'Object hlight::2.0':[0.002100000000000435, -0.0016000000000002679],'Object envlight':[0.002100021578371525, -0.0015999939292665744], 'Object null':[0.0, -0.005000004917383172], 'Object cam':[0,-0.045350006222724976]}

def tidyNodes(nodes=hou.selectedNodes()):
    for i in nodes:
        nodeOffset = [0,0]
        oldPos = i.position()
        iType = str(i.type()).split(' for ')[-1][:-1]
        if iType in offsetDict: nodeOffset = offsetDict[iType]
        newPos = i.position()
        newPos[0] = ((2*round(0.5*oldPos[0]+0.25))-0.5) + nodeOffset[0]
        newPos[1]= round(oldPos[1]+0.15)-0.15 + nodeOffset[1]
        i.setPosition(newPos)
        #print "'" + str(i.type()).split(' for ')[-1][:-1] + '\':' + str([x-y for x,y in zip(oldPos,newPos)])+', '
tidyNodes()


And finally the most common one I need to not yell at the everlasting cookfests. I have it set to Alt+Shift+U, which is a bit Vulcan MindMeldy but it works. I also set Alt+U to "/Houdini/Force Update"
import hou
mode = hou.updateModeSetting().name()
if mode == 'AutoUpdate':
    hou.setUpdateMode(hou.updateMode.Manual)
if mode == 'Manual':
    hou.setUpdateMode(hou.updateMode.OnMouseUp)
if mode == 'OnMouseUp':
    hou.setUpdateMode(hou.updateMode.AutoUpdate)

Friday, June 2, 2017

NukeStudio :: Return the source path for a selected clip

from hiero.core import TrackItem
seq = hiero.ui.activeSequence()
te = hiero.ui.getTimelineEditor(seq)
t =te.selection()[-1]
print t.source().mediaSource().fileinfos()[0].filename()

Sunday, May 14, 2017

NukeStudio :: Text expression to display media info

Use this to get file name of the displayed media in NukeStudio:
[lindex [split [metadata input/filename] "/"] end]

Saturday, April 1, 2017

Houville :: nice up vectors

This is for arranging your geo for nice behaviour with the copy sop. If you want to distibute geo, like trees or whatever, and control orientation but still respect the angle to the surface this is for you.


You'll need some way to connect the target points with the surface prim they relate to. Scatter has the sourceprim option which is cool, but if you want to manually do it you'll need a pre-pass. Here's an example using the 'stick a point in the middle of the face' technique. This should run over prims.
int newPtNum = addpoint(0,@P);
addpointattrib(0,"sourceprim", 0);
setpointattrib(0,"sourceprim", newPtNum, @primnum, 'set');
removeprim(0,@primnum,1);


Now lets get the surface geo ready. Here we will sneakily say normals run along the U direction and Up is what would typically be considered a normal. This makes sure our orientation makes sense.

Run this over points, assuming point source is in OpInput1, and reference geo for orientation is OpInput2.
vector center = primuv(s@OpInput2, 'P', i@sourceprim, {0.5,0.5,0.0});
vector dPdu = primuv(s@OpInput2, 'P', i@sourceprim, {0.51,0.5,0.0});
vector dPdv = primuv(s@OpInput2, 'P', i@sourceprim, {0.5,0.51,0.0});

vector u = normalize(dPdu - center);
vector v = normalize(dPdv - center);

v@up = normalize(cross(u,v));
v@N = u;

//matrix rotation shiz!
vector rot[];
rot[0] = u;
rot[1] = v@up;
rot[2] = v;
matrix3 mtx[] = unserialize(serialize(rot));
rotate(mtx[0], radians(chf('heading')), v@up);
rot = unserialize(serialize(mtx));
v@N = rot[0];
v@up = rot[1];



** for another post - passing colour information through points to be picked up by "Point Instance Procedural" as material overrides:
string r = sprintf("%d", @Cd.x);
string g = sprintf("%d", @Cd.y);
string b = sprintf("%d", @Cd.z);


s@shop_materialpath = chs('../theInstancesShaderPath');
s@material_override = "{'basecolorr':" + r + ",'basecolorg':" + g + ",'basecolorb':" + b + ",}";



Soooooo.. some of that was overkill. Here are a few ways to optimise that.

You can for example dispense with the serialise/unserialise phase by seting to the matrix directly. Also you can use quarternion to directly pull rotation information out of the matrix. Bear in mind Houdini understands '@orient' as a vector4 aka p@orient.
## direct casting and assignment of a matrix, rotation, extraction as a quaternion.
matrix3 rot = set(u,v@up,v)
rotate(rot, radians(chf('heading')), v@up);
p@orient = quaternion(rot)


And finally, you don't have to derive a @up if you have a normal. Have the points (scattered or otherwise) pick up their normals from the source they are based on. addpointattrib(0,"N",{0,0,0}); setpointattrib(0,"N",newPtNum,@N,"set");

Saturday, March 25, 2017

Python: copy paste buffer

Seems like PyQt4 is the ideal way to go:

Two styles:
##how to get something into the clipboard / copy/paste buffer
from PyQt4 import QtGui
QtGui.QApplication.clipboard().setText(textString)

##and to get it back out
text = QtGui.QApplication.clipboard().text()

##but it will be a QString so you'll probably want to 
textString = str(text)


In some cases PyQt4 seems to be crippled, so you can also use Tkinter, which seems to work well for extracting from clipboard. Haven't had luck putting stuff in though:
import Tkinter
root = Tkinter.Tk()
root.withdraw() # Hide the main window (optional)
rawClip = root.clipboard_get()