User functions in Janus

Back somewhere around v1.6 I started developing the pre-/post-breakout script feature, where a script is run contextually to coincide with the breakout of a render pass. This matured to the script system in Janus in 1.7. But it was back then when I was in the mental thoroughfare thinking of ways to get user-created scripts to work with Janus. Specifically, I wanted to call functions from within the render pass cmd line; these functions should be completely user-defined, and obviously, referred to at run-time. This meant that I needed Janus to dynamically call a script. The wall I encountered was that because Janus is sourced and compiled, it can’t source (e.g. include/insert) any other script once it is distributed. I thought the gate was closed at the time.

Recently, I’ve broken through the wall by going through a surprisingly obvious route. In a word, the solution was to execute a single pre-defined script (at least for the initial implementation of the feature) which the user modifies or adds user functions.

The first step was to re-use the structure of how subcommand variables are processed, since they share pretty much the same procedure.

The second bit was to implement the Queue Object Agent in LScript into the procedure. The Queue creates slots which serve to communicate to the user-defined functions the function call name and its argument(s). The function name and arguments are derived from parsing the cmd line. Once the function name is located, and arguments identified, this information is inserted into the slots of the Queue.

Then comes the third step, which was to create the base user function script that Janus will call once the Queue is populated. This base script calls upon the Queue that Janus has created, and starts querying the slots for information. It gets the function name and arguments, then checks if the function name exists; runs the function within and expects a return; the return value is passed on back to a reserved Queue slot, whereby Janus picks it up again and replaces the whole function call with the return value.

Neat.

It took about thirty minutes to prototype and two and half hours to implement. More tests required, but I was surprised that I got it working that night.

I suppose it also bears noting that the motive of this effort didn’t just come out from the blue. I received an email from a client very recently asking how he can fine-tune his output file paths. He wanted to be able to rearrange the output path so that his version number stuck at the end. Because filenames are just single strings, there is no inbuilt way of identifying which is the base name against the version number; the whole filename is effectively the base name. A parsing solution is needed. But because this is Janus, hard-coding is frowned upon. The solution must come in a form of being able to programmatically process the render pass parameters so that the user can do anything with it, and free to modify it in case their circumstances change.