All Posts By

Patrick Macdonald

Shotgun – Bootstrapping and Deadline

By | Blog, Hints and Tips, Shotgun | No Comments

Following the release of Shotgun’s new descriptor workflow along with its Bootstrap API I’ve finally got round to updating our pipeline to take advantage of these new features. It has been a big improvement over the old Toolkit pipeline configuration deployment approach and has definitely aided our development and deployment processes.

There has been one hurdle we’ve had to overcome; when bootstrapping in to a Shotgun environment on rendernodes with multiple slaves, it appears that the bootstrap process fails if there are concurrent threads all trying to copy the pipeline config to a shared location.

Thankfully there was a simple solution which involves setting up a custom which appears to have resolved the issue.

  1. Create a file called and save it to your deadline repos /custom/plugins directory. This file will be run before every job that’s loaded by each slave.
  2. Copy the following code in to the file :

What this script does is set a slave-specific SHOTGUN_HOME location(in this case c:\your_studio\shotgun\cache\slaveName ensuring that each slave can bootstrap in to its own folder. Problem solved!


Shotgun Tutorial – Using hooks to configure your renderfarm.

By | Blog, Hints and Tips, Shotgun, Tutorials | No Comments
Note : This post is specifically for a Windows based Shotgun installation, but it should be fairly easy to adapt to other environments.

One of the tricky things about getting Shotgun up and running smoothly, is getting your renderfarm environment configured correctly.

The Shotgun docs offer two approaches that are worth trying here and here but as these are specific to Nuke they may not do everything you need to get all your DCCs configured correctly.

Another approach to try is something that we have implemented here at HaloVFX; using Shotgun hooks to build/set your environments from scratch. This approach was developed largely to avoid the need to use 3rd party tools or scripts to set and update environment variables across the studio and renderfarm.

There are a number of benefits to this approach

  • your environment is set entirely within the Shotgun ecosystem; there is no need to launch Shotgun from a custom in-house launcher.
  • you can take a new workstation, install Shotgun and your DCCs, and without any further configuration or setting of a single environment variable, you can open Shotgun.
  • the studio environment can be configured per-project.
  • workstations/rendernodes require no environment configuration.
  • your entire environment is included in the pipeline configuration for any given project facilitating easy backup and retrieval.
  • your environments are entirely isolated per-project with no risk of changes causing un-expected problems across other projects.

In principle, this approach requires three steps.

  1. set studio-wide environment variables inside your core hook
  2. set project specific environment variables in your hook.
  3. update your deadline submissions scripts to include all required environment variables in the job file.

Update Shotgun ‘’

In your project pipeline config ‘core/hooks’ folder, make a copy of the ‘’ file from your core ‘install/core/hooks’ folder. (whether shared or localized)

You can add project-wide environment variables here by adding entries to the EngineInit ‘execute’ method.

class EngineInit(Hook):
    def execute(self, engine, **kwargs):
        os.environ['NUKE_PATH'] = some_path
        os.environ['NUKE_FONT_PATH'] = some_path
        os.environ['NUKE_LUT_PATH'] = some_path

Update Shotgun ‘’

In your project pipeline config ‘hooks’ folder, make a copy of the ‘’ file from your ‘config/hooks’ folder.

To help identify environment variables we want to keep track of, they are all prefixed with “HV_”. We will use this later in the deadline submission script to choose which environment variables to pass on to our rendernodes.

It’s up to you want variables you need to define for your pipeline, but here are some paths I found useful to have to use in other tools and apps.

import sys, os

def execute(self, app_path, app_args, version, **kwargs):
    self.parent.log_info("\n\n######## #########")

    system = sys.platform
    self.path_sep = os.pathsep
    engine = self.parent.get_setting("engine")

    # Set some utility global environment vars
    os.environ['HV_PROJECT'] = self.parent.tank.project_path
    os.environ['HV_PROJECT_PATH'] = self.parent.tank.project_path
    os.environ['HV_PROJECTCODE'] = os.path.split(self.parent.tank.project_path)[1]

You can define environment variables for specific applications by testing for the engine being called :

if engine in ["tk-houdini"]:
    arnold_path = r'C:/solidangle_houdini/htoa-1.14.2_r8c78c1d_houdini-{0}'.format(version)
    arnold_bin_path = r'C:/solidangle_houdini/htoa-1.14.2_r8c78c1d_houdini-{0}/scripts/bin'.format(version)

For Houdini, you’ll want to set a number of paths including the following.

os.environ['HOUDINI_PATH'] = some_path
os.environ['HOUDINI_OTLSCAN_PATH'] = some_path

And if you need to add paths to your PYTHONPATH you can add the following :

os.environ['PYTHONPATH'] = some_other_path + os.pathsep + os.environ['PYTHONPATH']

Update Deadline submission scripts –

To pass your environment variables through to deadline, you need to edit the submission script and insert something like the following after the jobInfoFile has been opened and assigned to the fileHandle variable;

after :

fileHandle = open( jobInfoFile, "wb" )
fileHandle.write( EncodeAsUTF16String( "Plugin=Nuke\n" ) )

add something like this:

env_vars = ['an_environment_variable','another_environment_variable','etc'] # CREATE A LIST OF ENVIRONMENT VARIABLES YOU WANT TO PASS ON WITH YOUR JOB
            EncodeAsUTF16String("EnvironmentKeyValue{0}={1}={2!s}\n".format(env_index, env_var, os.environ.get(env_var)))

of course, this example is specific to the deadline submission script for Nuke, but you should be able to adapt this code fairly easily for the submission scripts in other applications.

Once you have this implemented successfully, you should see in your ‘job details’ window of your Deadline monitor, the environment variables you defined. When the rendernode launches the job plugin, the environment of the rendernode will be updated with these environment variables.

It’s up to you how far you push this approach; you can theoretically recreate the entire environment of the machine/session submitting the job without having to worry about how the rendernode has been configured.


When implementing this approach. I half expected there to be  a number of unexpected and unwanted consequences, but I’m glad to report that in production this has proven to be very robust. As an added bonus it also provided me with excellent information with which to debug problematic jobs on the farm!

Thanks for reading, and I’ll look forward to hearing your thoughts on how this approach can be further developed. If you have taken another approach to this then I’d love to hear about it!


Soft Instancing and expressions

By | Hints and Tips, Maxscript, Mission Control | No Comments

In advance of more detailed documentation being added to the website, I thought I would share a walkthrough that demonstrates some of the more novel features of Mission Control that I hope some of  you will find to be a huge time-saver. By following these instructions, you will be able to:

  • Quickly ‘instance’ individual parameters between objects (so called soft-instancing)
  • Perform calculations in-cell using values and/or object parameters.
  • Create expression controllers on the fly.


Before you start, please bear in mind that the “Enter” key does not work for ending the editing of cells. You need  to click on another cell or double tap the “tab” key to finish the edit.

  • Create two omni lights; omni001 and omni002.
  • Add the multiplier parameter column to the spreadsheet.
  • Select a float value.
  • Click to start editing the value.
  • Type “=2+2” and click on another cell to end the data entry (double tapping tab also works).
  • The value should now reflect the calculation.
  • You can also submit object parameters eg “$omni002.multiplier” as part of the calculation.
  • In the multiplier for omni001, type “=(omni002.multiplier *2) + 0.5)”
  • You should now see a value that reflects this calculation.
This approach is for single hit operations; eg there is no linking.
Lets try something else :-
  • In the multiplier for omni001, type “==omni002.multiplier” (Notice the double equals sign).
  • Now if you middle-click and adjust the multiplier of omni002, the multiplier for omni001 should also update.
  • You will also notice a blue indicator on the cell. This indicates that the cell now has an animation controller.
  • What has happened is that when entering “==” you are creating a scripted controller with the script entered following this prefix.
  • You can edit this expression in two ways.
    • double click the cell to open the expression editor.
  • or
    • click the status-bar to open the util bar.
    • Select the “Animation” tab.
    • Select the animated cell.
    • you should now see the expression in the ‘Expression’ box below.
    • You can also add notes to the “Notes box” which will be stored in the script controller.
    • You can now copy and paste this scripted cell to other cells as instances to quickly link the multipliers of many lights.

Mission Control : Lighting with VRay RT

By | Uncategorized | No Comments

Mission Control provides an easy way to adjust complex lighting in your scenes, especially when combined with a realtime renderer such as VRay RT. Make adjustments on multiple lights with the drag of a mouse. Apply absolute or relative adjustments (stepping up or down for example). Apply relative or absolute randomisations.

There are a number of ways to edit values.

1. Direct entry. You can click the cell and enter a new value.

2. Copy/Paste. You can copy and paste a value; both as a copy and as an instance. This is a very powerful feature as it allows you to very quickly make soft-instances of objects where only a small number of parameters are instanced, rather than the entire object.

3. Spinner. You can click single or multiple values and whilst holding the middle mouse button down, drag to raise or lower the value. Dragging left and right provides fine adjustment, whilst dragging up and down makes large adjustments.

4. Mass editing. Beyond these standard methods, there are a selection of more powerful tools in the util panel that allow mass editing of values in a number of ways.

Absolute :
You can apply a single value to all the selected cells.

Relative :
You can add, subtract, multiply or divide by the specified value all the selected values. This provides a nice way to adjust values by specific amounts or proportions.

Random relative :
You can set a minimum and maximum of a random value to add to the values of your current selection.

Random absolute :
You can apply a random value to the selected cells between the minimum and maximum values specified.

Stepped :
This allows you to apply a number sequence to the selected cells with the specified step size. Useful for quickly applying material IDs, or for placing objects a set distance apart for example.

Spaced :
This applies a number sequence to the selected cells equally spaced between the minimum and maximum values specified.

All of these operations can be applied to all the selected cells, or using a conditional operator allowing you to only affect values that are equal to, not equal to, greater than or less than a specified value.

Mission Control vs Light-lister : An update

By | Blog, Mission Control, News | No Comments

It has been quite some time since I released a performance comparison between Mission Control and the ‘light-lister’ that ships with 3ds Max.

Since there have been some big performance gains since then so I thought it would be interesting to see how the latest version of Mission Control stacks up.

I’ll leave it to you to draw your own conclusions!


Coke Buildings Making Of

By | Advertising | No Comments
I was lucky enough to work on this great spot at Nexus Productions last year, and I recently came across this making-of that shows a glimpse of the hard work that was involved.
It was a amazing to see, up-close, the incredible attention to detail that the model makers put in to their 1/10th scale that our CG characters were to inhabit.

I was tasked with taking the reference photography and spherical HDRs and generating light rigs for each scene. Ben Cowell went the extra mile to make this process as painless as possible by providing some very cute 3d-printed maquettes of some characters which were placed into reference photography to help us achieve a good match in CG.

This is the first time I had seen 3d printing used in this kind of situation and it is definitely something I would try to do again in the future. You can’t do much better than having your CG characters shot for real in your plates!

Quick Script Controllers

By | Uncategorized | No Comments

I came across a request by Shimakaze on the V-Ray forums for a way to quickly connect many objects on the modifier level without completely instancing them.  Given how long it would take to do this manually; either by wiring parameters, or copying controllers, another approach was required. This is precisely the kind of task that Mission Control aims to simplify.

Mission Control allows you to enter scripts directly in to any float value cell. You can use this to easily instance values between object, modifier, or material values; or you can enter complex scripts that will evaluate on every tick.

Here’s a short clip showing how easy it is to link the radius of a sphere to a slider manipulator.

  • Select the source controller (in this case the slider value cell), and click “copy” in the context menu. This causes MC to hold a reference pointer to this cell.
  • Navigate to the sphere’s class to list the spheres in the scene.
  • In the radius cell of a sphere, click to start editing the value, and then enter the script “=target”. Starting an edit with a “=” symbol tells MC that an expression is being entered. The “target” token is used to grab the controller from the previously copied cell (slider.value.controller). This is then placed within a variable in a script_float controller called “target” and ensures the script remains functional if the object gets renamed.
  • Once the expression has been added, you can edit it by double clicking on the cell which brings up the dialog for the controller.

Quick Script Controllers

Skip to toolbar