getavalon / core

The safe post-production pipeline - https://getavalon.github.io/2.0
MIT License
218 stars 49 forks source link

Toon Boom Harmony Integration #527

Open tokejepsen opened 4 years ago

tokejepsen commented 4 years ago

Issue

This is about an Avalon integration for Toon Boom Harmony

This issue is to serve as a discussion for the integration.

Implementation

Harmony uses Qt Script which is a Javascript variant; https://docs.toonboom.com/help/harmony-17/scripting/script/index.html

tokejepsen commented 4 years ago

One of the issues with Harmony is the management of workfiles. A Harmony scene file is not a single file, but a folder of files and subfolders.

Read/writing lots of small files from the network has been reported as slow and taxing for the network.

A possible solution could be to wrap the scene folder up as a zip file. When using the workfiles app, we could manage this so in a project folder there are only zip files, but these get unpacked locally.

tokejepsen commented 4 years ago

Harmony has groups; https://docs.toonboom.com/help/harmony-16/essentials/layers/group-layers.html, so could possibly follow the #516 for creating instances.

tokejepsen commented 4 years ago

Harmony has a global scripts environment variable; https://docs.toonboom.com/help/harmony-16/essentials/scripting/store-script-custom-folder.html

tokejepsen commented 4 years ago

Interesting integration with Shotgun; https://github.com/diegogarciahuerta/tk-harmony

tokejepsen commented 4 years ago

Functions in TB_sceneOpened.js, TB_sceneOpenPreUI.js, TB_sceneCreated.js, TB_sceneAboutToClose.js are run as startup. These functions can be overridden with scripts in the environment variable: TOONBOOM_GLOBAL_SCRIPT_LOCATION.

tokejepsen commented 4 years ago

Got some progress on this. Have been taking the Shotgun integration apart to figure out the process;

Untitled_ Feb 25, 2020 10_41 AM

This is the wrong way around with the server in Harmony and the client in Python, but at least the concept works.

tokejepsen commented 4 years ago

Menu

Annotation 2020-02-25 131634

Since Harmony is built with Qt its surprisingly easy to add a menu.

tokejepsen commented 4 years ago

Think I have a two way communication planned out now:

This makes the communication standardized and you only have to understand either Qt Script (Javascript) or Python to know what is happening.

tokejepsen commented 4 years ago

Working Prototype Untitled_ Mar 10, 2020 1_01 PM

tokejepsen commented 4 years ago

Workfiles

Untitled_ Mar 19, 2020 3_48 PM

The Workfiles app and workio code proved tricky and showed where the framework was failing. I ended up on a framework that looks similar to how pyblish-qml works:

+------------+
|            |
|   Python   |
|   Process  |
|            |
| +--------+ |
| |        | |
| |  Main  | |
| | Thread | |
| |        | |
| +----^---+ |
|     ||     |
|     ||     |
| +---v----+ |     +---------+
| |        | |     |         |
| | Server +-------> Harmony |
| | Thread <-------+ Process |
| |        | |     |         |
| +--------+ |     +---------+
+------------+

The server communicates over a single connection, same as in the previous post. The main difference from previous post, is that the server is threaded so communication with Harmony is still valid when the main thread is busy with for example showing a GUI.

Another issue was with how Harmony opens scenes. I'm still querying this with support but it seems like you can only open a new scene by launching a new process. To make this work with the Workfiles I'm killing the Toon Boom process and the server thread, then starting new ones.

tokejepsen commented 4 years ago

Forgot to mention that I've also "hacked" the Workfiles app so Harmony project folders are saved as zip files on the network. When loading zip workfiles, they get unpacked and opened.

tokejepsen commented 4 years ago

Saving

Because I'm "hacking" the Workfiles app to zip a project directory, I've also needed to have a callback when the user is saving the scene. In Harmony there aren't any callbacks for saving a scene, but can watch the scene file for changes with QFileSystemWatcher.

function on_file_changed_callback()
{
  var self = this;

  // Attach the client to the QApplication to preserve.
  var app = QCoreApplication.instance();

  // Watch scene file for changes.
  self.on_file_changed = function(path)
  {
    var app = QCoreApplication.instance();
    MessageLog.trace(path);
    app.watcher.addPath(path);
  }

    app.watcher = new QFileSystemWatcher();
    scene_path = scene.currentProjectPath() +"/" + scene.currentVersionName() + ".xstage";
    app.watcher.addPath(scene_path);
    app.watcher.fileChanged.connect(on_file_changed);
}

The zipping and move (locally) can take as long as the saving, so in order to reduce user impact, we just thread off this so it happens in the background.

Create

Untitled_ Mar 23, 2020 12_56 PM

Have opted for composite nodes in Harmony since you can connect any number of nodes simultaneously to composites. For imprinting and metadata, we can create attributes on the nodes which is currently named "avalon". This holds a json serialized dictionary.

Also found out that *.xstage files are xml formatted, so you can inspect this metadata with text editor.

tokejepsen commented 4 years ago

Publishing

Untitled_ Mar 25, 2020 12_33 PM

Still querying whether is a way to script the rendering of the write nodes without the dialog.