A simple tutorial on using expressions with Paint Strokes.

  Nuke TCL


Using TCL expressions in Nuke can help us to evaluate mathematical operations, as well as link values together to create something new. However, an often forgotten feature in Nuke is the ability to add expressions to RotoShapes and Paint strokes (which are also splines under the hood).

tracklinkdialog

Nuke's built-in "Tracker linking dialog" (pictured above), helps us to link individual vertices to various things in a Tracker node, and is doing so by automatically adding TCL expressions for us! However, what if we wanted to link things the other way around?

Every time you create a paint stroke, vertex points are created, and each one is assigned a unique index number. You can visualize these by first enabling vertex selection, and then enabling the label points option in the RotoPaint node's Viewer toolbar, as shown below.

spline

We can add an expression to any of these points by right-clicking and choosing "add expression".

addexpr

When the dialog box first opens, you can type "curve" to return the current value, as is the case with any other knob. However, if you simply type the name of the curve, curve.3.main.x in this example, you'll get an error...

expr1

In order to access the coordinates of any vertex point on a spline, you must type the full path, like so:

expr2

As you can see, the Syntax is: <nameOfNode>.curves.<nameOfBrushStrokeOrSpline>.curve.<vertexNumber>.main.<axis>

As a quick example to demonstrate a few concepts: let's create an animated Snake with nothing but expressions.

We'll start by creating the head with a Roto node:

snake_head

We should also create a transform node underneath, with the center-point automatically aligned to the center of the bbox. We can do that by adding an expression to the Transform node's center knob:

centrepoint

Bounding boxes in Nuke have a single X and Y coordinate, as well as W (width) and H (height) amounts. We're finding the bbox's center point by first getting the input node's bbox coordinates, and then adding half the width and height. No matter how our rotoshape changes, our center point will remain in the center!

snakehead_centreadjust

Let's give our snake a body with a RotoPaint node. I'm painting a rough stroke, reducing the number of vertices, and then adjusting the brush strokes hardness to match with the head.

snakebody-2

Now let's add some expressions to our paint stroke's vertices. Firstly, we'll link vertex 0 to the snake's head by adding the Transform node's center point and translate values.

firstlink snakebody_test

It works! Secondly, we want the rest of the brush strokes vertices to move the same way, just offset in time.

expr3

For vertex 1, we're returning vertex 0's coordinates from 6 frames earlier. We're also offsetting the X value by -250, to move it to the left of the snake's head.

We will do the same thing for vertex 2, except we need to double the values...

expr4-1

Go ahead and do this for every vertex in the paint stroke, incrementing the frame + x-position offset each time.

Now we can animate the snake's head with our Transform node, and watch what happens! In the spirit of only using expressions, I'm using my bm_NoiseGen gizmo to generate a random animation curve, and am expression-linking the output to our Transform node's Y translate knob.

snake_exprmove One again, click the GIF to view full-res!

We can also make our snake's head rotate so that it's pointing in the direction it's travelling, by using the derivative expression. This expression returns the slope, or speed of a curve on any given frame.

derivative headrotate

Lastly, our snake is just missing one thing: a name. I, for one, don't want to be held responsible for naming our snake. After all, we want the computer to do all the work for us, right? I grabbed a big list of names starting with S from the internet, and keeping with the snake theme, I wrote a couple of lines of Python to get Nuke to choose a name for me:

 1import random
 2
 3names = """Saban Sabas Sabastian Sabelo Saber Sabien Sabin Sabino Sacha Sachiel 
 4Sachin Sachio Sadaat Saddam Sadiri Sadler Saerys Sagan Sagar Sage 
 5Sahak Sai Said Sailor Saimir Saint Sajiv Sajiva Sakai Sakari 
 6Samson Samu Samuel Samuele Samuli Samus Samvel Samwise Sanaullah Sancho 
 7Sandeep Sander Sanders Sanderson Sándor Sandro Sandy Sanford Sangeet Sani Sanjay Sanjeev Sanjeewa Sanjiv 
 8Sansao Sansleon Sansone Santana Santhosh Santiago Santino Santo Santonio Santos 
 9Sarantis Sarat Sarell Sargent Sargis Sargon Sarkis Sarp Sarpong Sascha 
10Sasha Sasuke Satchel Sathish Satia Satin Saturn Saturnino Satwant Saul 
11Saulo Saurabh Sava Saviero Savio Savion Savit Savvas Sawyer Saxby 
12Saxon Saxton Sayers Saylor Scent Scevola Schroder Schroeder Schuler Schuyler 
13Schylar Scipio Scooter Scorewin Scorpius Scot Scott Scottie Scotty Scout 
14Scully Seabern Seager Seamus Sean Seanan Seanix Seath Seathrún Seaton Seattle Seaver Seb Sebastian Sebastiano Sebastião Sébastien Sebastion Sebi Seder Sedrick Seeger Seeley Seger Sehun Seiji 
15Selassie Selby Selevan Selim Selleck Selmer Selwyn Sem Semaj Semih 
16Senan Sendhelp Seneca Seoras Seph Sephiroth Sepp Septimus Serafin Serafino 
17Seraph Seraphim Serge Sergei Sergio Serhat Serri Rafael Serry Rafael 
18Servando Seryozha Seth Seton Sevan Sevastian Sevastyan Seven Severiano Severin 
19Severn Severo Severus Sevin Seymarion Seymour Shad Shadden Shaddock Shade 
20Shaden Shadi Shadley Shadow Shadrach Shae Shafer Shai Shaikh Shainen 
21Shakespeare Shalev Shalom Shaman Shamar Shamus Shandy Shane Shannon Shanon 
22Shantanu Shaokun Shaquille Sharif Sharnovon Shasta Shauftan Shaughnessy Shaun Shauni 
23Shaw Shawinook Shawn Shay Shaydon Shayne Shea Shearjashub Shedrick Shelby 
24Sheldon Shelton Shem Shemar Shep Shepard Shephard Shepherd Shepley Sheppard 
25Sheraga Sheridan Sherlock Sherman Sherrill Sherwin Sherwood Shia Shiloh Shimon 
26Shimshon Shinon Shipley Shirley Shiva Shivam Shiwoo Shlomo Shmuel Shohta 
27Shola Sholom Sholto Shomari Shon Showles Shrikant Shukur Shulem Shye 
28Shyloh Shylon Si Sian Siarl Siarles Siavash Sid Siddarth Siddharth 
29Sidney Siegfried Sierra-117 Sierre Siger Sigge Sigismund Sigmund Sigurd Sigurdur Silas Siler Sillan 
30Silvan Silvano Silvanus Silven Silver Silverio Silvestre Silviano Silvio Sim 
31Simão Simba Simbiah Simcha Simen Simeon Simeus Simkha Simo Simon 
32Simone Simpson Sinan Sinbad Sincere Sinclair Sindre Sindri Sinhue Sinjin 
33Sinqua Sione Sipho Sir Sire Sirius Sisamila Sitka Sivan Sivert 
34Sixten Sixto Sixtus Siyu Sjoerd Skandar Skate Skia Skip Skipper 
35Skofi Sky Skye Skylar Skyler Slade Slaid Slane Slate Slater 
36Slavko Slayden Slayton Sloan Slobodan Sly Smith Smokey Snowden Snyder 
37Socrates Sodapop Soeren Sofian Sofiane Sofien Sogoro Sohan Söhnke Sohrab Sol Solace Solan Solanus Soleil Soloman Solomon Solon 
38Somerled Somerset Sondre Sonnen Sonny Sony Sophian Sora Soren Sorin 
39Sorley Sorrell Sorren Sotiris Soumil Soumyadeep Souta Spade Spalding Sparrow 
40Spartacus Spearman Spellman Spence Spencer Spenser Spike SPinach Spirit Spiro 
41Spiros Springer Spurgeon Spurrier Spyder Spyridon Squandro Squeag Squire St. John Stacey Stacy Stafford Stahley Stamm Stampley Stan Stanford Stanimir 
42Stanislas Stanislaus Stanislav Stanislaw Stanley Stannis Stanton Star Stark Starlin 
43Starsky Staton Stavrianos Stavros Steele Stefan Stefano Stefanos Stefen Steffan 
44Stein Steinar Stejonte Stelios Stellan Sten Steno Stephan Stephanos Stephen 
45Stephon Sterling Stetson Stevan Steve Steven Stevenson Stevie Stevieray Stewart 
46Stian Stieg Stig Stijn Stiles Stirling Stjepan Stockholm Stockman Stockton 
47Stohn Stojan Stokely Stone Stoney Storm Stormalong Strand Stratton Strauss 
48Street Strider Striker Stringer Striver Strom Struan Stryker Stuart Sturt 
49Stuyvesant Sudhir Sueban Sufjan Sufyan Suhail Suhas Sukhdeep Sukhvinder Sukhwinder 
50Sukrajan Sulaiman Sulien Sullivan Sully Sulo Sultan Suman Sumit Summit 
51Sumner Sun Sundara Sunil Sunjit Sunny Suraj Sutter Sutton Suvo 
52Suzaku Svein Sveinn Sven Sverre Swain Swaine Sweeney Swinton Sy 
53Sydney Syed Sykes Sylar Sylas Sylvain Sylvan Sylvana Sylver Sylvester 
54Sylvestre Sylvio Symeon Synclair Szczepan Szebasztián Szymon Søren"""
55
56names_list = names.split()
57
58print "Your snake's name is "+random.choice(names_list)

Running this code in Nuke's script editor returned this:

nukepython

Nice to meet you, Serge! May your handy expressions slither into everyone's workflow.

You can download an example nuke script here (right-click > save link as).

While this is a silly little demo, there are numerous ways you can take this knowledge and apply it in your every day work. Perhaps you're doing beauty work or costume fixes and need to track a texture to a specific RotoPaint vertex point? Maybe you need to expression-link a rotoshape from a Roto node to another rotoshape in a SplineWarp node to improve efficiency? Or maybe you just need a snake friend to keep you company during the COVID pandemic... The list is endless!