Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Initial render publishing #172

Merged
merged 5 commits into from
May 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions pype/harmony/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os

import avalon.api
from avalon import api, harmony
import pyblish.api


Expand All @@ -14,9 +14,26 @@ def install():
pyblish.api.register_plugin_path(
os.path.join(plugins_directory, "publish")
)
avalon.api.register_plugin_path(
avalon.api.Loader, os.path.join(plugins_directory, "load")
api.register_plugin_path(
api.Loader, os.path.join(plugins_directory, "load")
)
avalon.api.register_plugin_path(
avalon.api.Creator, os.path.join(plugins_directory, "create")
api.register_plugin_path(
api.Creator, os.path.join(plugins_directory, "create")
)

pyblish.api.register_callback(
"instanceToggled", on_pyblish_instance_toggled
)


def on_pyblish_instance_toggled(instance, old_value, new_value):
"""Toggle node enabling on instance toggles."""
func = """function func(args)
{
node.setEnable(args[0], args[1])
}
func
"""
harmony.send(
{"function": func, "args": [instance[0], new_value]}
)
2 changes: 1 addition & 1 deletion pype/plugins/global/publish/extract_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class ExtractReview(pyblish.api.InstancePlugin):
label = "Extract Review"
order = pyblish.api.ExtractorOrder + 0.02
families = ["review"]
hosts = ["nuke", "maya", "shell", "nukestudio", "premiere"]
hosts = ["nuke", "maya", "shell", "nukestudio", "premiere", "harmony"]

# Supported extensions
image_exts = ["exr", "jpg", "jpeg", "png", "dpx"]
Expand Down
25 changes: 25 additions & 0 deletions pype/plugins/harmony/create/create_render.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from avalon import harmony


class CreateRender(harmony.Creator):
"""Composite node for publishing renders."""

name = "renderDefault"
label = "Render"
family = "render"
node_type = "WRITE"

def __init__(self, *args, **kwargs):
super(CreateRender, self).__init__(*args, **kwargs)

def setup_node(self, node):
func = """function func(args)
{
node.setTextAttr(args[0], "DRAWING_TYPE", 1, "PNG4");
node.setTextAttr(args[0], "DRAWING_NAME", 1, args[1]);
node.setTextAttr(args[0], "MOVIE_PATH", 1, args[1]);
}
func
"""
path = "{0}/{0}".format(node.split("/")[-1])
harmony.send({"function": func, "args": [node, path]})
22 changes: 17 additions & 5 deletions pype/plugins/harmony/publish/collect_instances.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json

import pyblish.api
from avalon import harmony

Expand All @@ -15,10 +17,14 @@ class CollectInstances(pyblish.api.ContextPlugin):
label = "Instances"
order = pyblish.api.CollectorOrder
hosts = ["harmony"]
families_mapping = {
"render": ["imagesequence", "review"],
"harmony.template": []
}

def process(self, context):
nodes = harmony.send(
{"function": "node.getNodes", "args": [["COMPOSITE"]]}
{"function": "node.subNodes", "args": ["Top"]}
)["result"]

for node in nodes:
Expand All @@ -32,13 +38,19 @@ def process(self, context):
if "container" in data["id"]:
continue

# Adding families if missing.
data["families"] = data.get("families", [])

instance = context.create_instance(node.split("/")[-1])
instance.append(node)
instance.data.update(data)
instance.data["publish"] = harmony.send(
{"function": "node.getEnable", "args": [node]}
)["result"]
instance.data["families"] = self.families_mapping[data["family"]]
instance.data["families"].append("ftrack")

# Produce diagnostic message for any graphical
# user interface interested in visualising it.
self.log.info("Found: \"%s\" " % instance.data["name"])
self.log.info(
"Found: \"{0}\": \n{1}".format(
instance.data["name"], json.dumps(instance.data, indent=4)
)
)
100 changes: 100 additions & 0 deletions pype/plugins/harmony/publish/extract_render.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import os
import tempfile

import pyblish.api
from avalon import harmony
import pype.lib

import clique


class ExtractRender(pyblish.api.InstancePlugin):
"""Produce a flattened image file from instance.
This plug-in only takes into account the nodes connected to the composite.
"""

label = "Extract Render"
order = pyblish.api.ExtractorOrder
hosts = ["harmony"]
families = ["render"]

def process(self, instance):
# Collect scene data.
func = """function func(write_node)
{
return [
about.getApplicationPath(),
scene.currentProjectPath(),
scene.currentScene(),
scene.getFrameRate(),
scene.getStartFrame(),
scene.getStopFrame()
]
}
func
"""
result = harmony.send(
{"function": func, "args": [instance[0]]}
)["result"]
application_path = result[0]
project_path = result[1]
scene_path = os.path.join(result[1], result[2] + ".xstage")
frame_rate = result[3]
frame_start = result[4]
frame_end = result[5]

# Set output path to temp folder.
path = tempfile.mkdtemp()
func = """function func(args)
{
node.setTextAttr(args[0], "DRAWING_NAME", 1, args[1]);
}
func
"""
result = harmony.send(
{
"function": func,
"args": [instance[0], path + "/" + instance.data["name"]]
}
)
harmony.save_scene()

# Execute rendering.
output = pype.lib._subprocess([application_path, "-batch", scene_path])
self.log.info(output)

# Collect rendered files.
files = os.listdir(path)
collections, remainder = clique.assemble(files, minimum_items=1)
assert not remainder, (
"There should not be a remainder for {0}: {1}".format(
instance[0], remainder
)
)
assert len(collections) == 1, (
"There should only be one image sequence in {}. Found: {}".format(
path, len(collections)
)
)

extension = os.path.splitext(list(collections[0])[0])[-1][1:]
representation = {
"name": extension,
"ext": extension,
"files": list(collections[0]),
"stagingDir": path,
"frameStart": frame_start,
"frameEnd": frame_end,
"fps": frame_rate,
"preview": True,
"tags": ["review"]
}
instance.data["representations"] = [representation]
self.log.info(frame_rate)

# Required for extract_review plugin (L222 onwards).
instance.data["frameStart"] = frame_start
instance.data["frameEnd"] = frame_end
instance.data["fps"] = frame_rate

self.log.info("Extracted {instance} to {path}".format(**locals()))