William Harley

william_harley

About Me

I started my career doing lighting, lookdev and VFX in Cape Town. Always looking to streamline the character rigging and animation process I got involved in setting up a rigging tools in houdini and assisting animators to get used to the new tools, I have fallen in love with CFX, building rigs ...  more
EXPERTISE
Generalist
INDUSTRY
Film/TV

Connect

LOCATION
Cape Town, South Africa
WEBSITE

Houdini Skills

ADVANCED
Procedural Modeling  | Digital Assets  | Character Rigging  | Lighting  | Pyro FX  | VEX
INTERMEDIATE
Environments  | Motion Editing  | Animation  | Hair & Fur  | Cloth  | Crowds  | Muscles  | Solaris  | Karma  | Fluids  | Destruction FX  | Realtime FX  | PDG  | Python

Availability

Not Specified

My Badges

SideFX Staff
Since Oct 2023

My Tutorials

obj-image Masterclass
APEX Rigging | Masterclass
obj-image Intermediate
Luchador & Chicken

Recent Forum Posts

The problem about the spare port of Null and AbstractControl July 6, 2026, 8:27 a.m.

Hi,
There are a couple of ways to do this, however it looks like the sorting on the control in the viewport is a
bug.
Copy the snippet into a autorig component.


# create the subnet with the existing names.
def subnet(
    one: Float, 
    two: Float, 
    # three: Float, 
    four: Float,
    five: Float,
):
    one = Float()
    
subnetnode = graph.addSubnet(subnet, 'mySubnet')

node = graph.addOrUpdateNode(
    callback='AbstractControl',
    name='test',
)

# find the ports of the existing subnet
ports = graph.findPorts('mySubnet:*[in]')

# loop over the list
for port in ports:
    portname = port.data()
    # create a null to set the types for the outputs
    node.promoteNodeInput(
        portname='__spare__',
        parmname=portname,
    )
    # connect the output of the abstract control to an existing subnet
    graph.findAndConnectInput(
        srcnode=node,
        srcname=portname,
        dstnode=subnetnode,
        dstname=portname,
        )
Here is another way:
node = graph.AddOrUpdateNode(
    callback='AbstractControl',
    name='test',
)
# create you list
list = ['one', 'two', 'three', 'four']
nulls = ApexNodeIDArray()
# loop over the list
for i in list:
    # create a null to set the types for the outputs
    null = graph.AddOrUpdateNode(
        callback='Null<Float>',
        name=f'null_{i}',
    )
    
    # promote the ports, NB the type of parm inputs are defined 
    # be the connected port. simply promoting them does not give them
    # a type.
    node.promoteNodeInput(
        portname='__spare__',
        parmname=i,
        )

    # Find the new port based on the new name.
    port = node.findPort(f'{i}[out]')
    
    # connect the port to the float null, This will now set the type for 
    # all the ports on the parm and abstract control
    port.connect(null.value_in)
    
    # add the nulls to the nulls array
    nulls.append(null)
# pack the loose nulls into a neat subnet
graph.packSubnet('mySubnet', nulls)

A problem with lookat July 6, 2026, 5:52 a.m.

Hi no worries, you didnt offend anyone
And yes it was a little bit of a oversight on my part.

The sollution is to use the A_armPolevec_ik control as the lookat for the head. That way they will always be in the same plane. I had to also set the multiik tip to not use goal rotation, so the ik drives the rotation of the tip as well. And limited the ik tip so it doesnt tilt the rotation when moving the lookat/polevector.

Lattice Control Orientation Issue July 6, 2026, 5:09 a.m.

To keep the lattice on the ground you can use the ray sop verb to keep the joints to a ground plane.