Merge branch 'develop' into feature/validation_exceptions_nuke

This commit is contained in:
Jakub Jezek 2022-07-25 08:46:48 +02:00
commit 7cb68975d3
No known key found for this signature in database
GPG key ID: 730D7C02726179A7
756 changed files with 106335 additions and 13100 deletions

View file

@ -27,6 +27,10 @@ class CreateWritePrerender(plugin.AbstractWriteRender):
# add fpath_template
write_data["fpath_template"] = self.fpath_template
write_data["use_range_limit"] = self.use_range_limit
write_data["frame_range"] = (
nuke.root()["first_frame"].value(),
nuke.root()["last_frame"].value()
)
if not self.is_legacy():
return create_write_node(

View file

@ -2,7 +2,20 @@ import nuke
from openpype.hosts.nuke.api import plugin
from openpype.hosts.nuke.api.lib import (
create_write_node, create_write_node_legacy)
create_write_node,
create_write_node_legacy,
get_created_node_imageio_setting_legacy
)
# HACK: just to disable still image on projects which
# are not having anatomy imageio preset for CreateWriteStill
# TODO: remove this code as soon as it will be obsolete
imageio_writes = get_created_node_imageio_setting_legacy(
"Write",
"CreateWriteStill",
"stillMain"
)
print(imageio_writes["knobs"])
class CreateWriteStill(plugin.AbstractWriteRender):

View file

@ -1,6 +1,10 @@
import nuke
import nukescripts
from openpype.client import (
get_version_by_id,
get_last_version_by_subset_id,
)
from openpype.pipeline import (
legacy_io,
load,
@ -188,18 +192,17 @@ class LoadBackdropNodes(load.LoaderPlugin):
# get main variables
# Get version from io
version = legacy_io.find_one({
"type": "version",
"_id": representation["parent"]
})
project_name = legacy_io.active_project()
version_doc = get_version_by_id(project_name, representation["parent"])
# get corresponding node
GN = nuke.toNode(container['objectName'])
file = get_representation_path(representation).replace("\\", "/")
context = representation["context"]
name = container['name']
version_data = version.get("data", {})
vname = version.get("name", None)
version_data = version_doc.get("data", {})
vname = version_doc.get("name", None)
first = version_data.get("frameStart", None)
last = version_data.get("frameEnd", None)
namespace = container['namespace']
@ -237,20 +240,18 @@ class LoadBackdropNodes(load.LoaderPlugin):
GN["name"].setValue(object_name)
# get all versions in list
versions = legacy_io.find({
"type": "version",
"parent": version["parent"]
}).distinct('name')
max_version = max(versions)
last_version_doc = get_last_version_by_subset_id(
project_name, version_doc["parent"], fields=["_id"]
)
# change color of node
if version.get("name") not in [max_version]:
GN["tile_color"].setValue(int("0xd88467ff", 16))
if version_doc["_id"] == last_version_doc["_id"]:
color_value = self.node_color
else:
GN["tile_color"].setValue(int(self.node_color, 16))
color_value = "0xd88467ff"
GN["tile_color"].setValue(int(color_value, 16))
self.log.info("updated to version: {}".format(version.get("name")))
self.log.info("updated to version: {}".format(version_doc.get("name")))
return update_container(GN, data_imprint)

View file

@ -1,5 +1,9 @@
import nuke
from openpype.client import (
get_version_by_id,
get_last_version_by_subset_id
)
from openpype.pipeline import (
legacy_io,
load,
@ -102,17 +106,16 @@ class AlembicCameraLoader(load.LoaderPlugin):
None
"""
# Get version from io
version = legacy_io.find_one({
"type": "version",
"_id": representation["parent"]
})
project_name = legacy_io.active_project()
version_doc = get_version_by_id(project_name, representation["parent"])
object_name = container['objectName']
# get corresponding node
camera_node = nuke.toNode(object_name)
# get main variables
version_data = version.get("data", {})
vname = version.get("name", None)
version_data = version_doc.get("data", {})
vname = version_doc.get("name", None)
first = version_data.get("frameStart", None)
last = version_data.get("frameEnd", None)
fps = version_data.get("fps") or nuke.root()["fps"].getValue()
@ -165,28 +168,27 @@ class AlembicCameraLoader(load.LoaderPlugin):
d.setInput(index, camera_node)
# color node by correct color by actual version
self.node_version_color(version, camera_node)
self.node_version_color(version_doc, camera_node)
self.log.info("updated to version: {}".format(version.get("name")))
self.log.info("updated to version: {}".format(version_doc.get("name")))
return update_container(camera_node, data_imprint)
def node_version_color(self, version, node):
def node_version_color(self, version_doc, node):
""" Coloring a node by correct color by actual version
"""
# get all versions in list
versions = legacy_io.find({
"type": "version",
"parent": version["parent"]
}).distinct('name')
max_version = max(versions)
project_name = legacy_io.active_project()
last_version_doc = get_last_version_by_subset_id(
project_name, version_doc["parent"], fields=["_id"]
)
# change color of node
if version.get("name") not in [max_version]:
node["tile_color"].setValue(int("0xd88467ff", 16))
if version_doc["_id"] == last_version_doc["_id"]:
color_value = self.node_color
else:
node["tile_color"].setValue(int(self.node_color, 16))
color_value = "0xd88467ff"
node["tile_color"].setValue(int(color_value, 16))
def switch(self, container, representation):
self.update(container, representation)

View file

@ -1,6 +1,10 @@
import nuke
import qargparse
from openpype.client import (
get_version_by_id,
get_last_version_by_subset_id,
)
from openpype.pipeline import (
legacy_io,
get_representation_path,
@ -50,20 +54,28 @@ class LoadClip(plugin.NukeLoader):
script_start = int(nuke.root()["first_frame"].value())
# option gui
defaults = {
"start_at_workfile": True
options_defaults = {
"start_at_workfile": True,
"add_retime": True
}
options = [
qargparse.Boolean(
"start_at_workfile",
help="Load at workfile start frame",
default=True
)
]
node_name_template = "{class_name}_{ext}"
@classmethod
def get_options(cls, *args):
return [
qargparse.Boolean(
"start_at_workfile",
help="Load at workfile start frame",
default=cls.options_defaults["start_at_workfile"]
),
qargparse.Boolean(
"add_retime",
help="Load with retime",
default=cls.options_defaults["add_retime"]
)
]
@classmethod
def get_representations(cls):
return (
@ -82,7 +94,10 @@ class LoadClip(plugin.NukeLoader):
file = self.fname.replace("\\", "/")
start_at_workfile = options.get(
"start_at_workfile", self.defaults["start_at_workfile"])
"start_at_workfile", self.options_defaults["start_at_workfile"])
add_retime = options.get(
"add_retime", self.options_defaults["add_retime"])
version = context['version']
version_data = version.get("data", {})
@ -147,7 +162,7 @@ class LoadClip(plugin.NukeLoader):
data_imprint = {}
for k in add_keys:
if k == 'version':
data_imprint.update({k: context["version"]['name']})
data_imprint[k] = context["version"]['name']
elif k == 'colorspace':
colorspace = repre["data"].get(k)
colorspace = colorspace or version_data.get(k)
@ -155,10 +170,13 @@ class LoadClip(plugin.NukeLoader):
if used_colorspace:
data_imprint["used_colorspace"] = used_colorspace
else:
data_imprint.update(
{k: context["version"]['data'].get(k, str(None))})
data_imprint[k] = context["version"]['data'].get(
k, str(None))
data_imprint.update({"objectName": read_name})
data_imprint["objectName"] = read_name
if add_retime and version_data.get("retime", None):
data_imprint["addRetime"] = True
read_node["tile_color"].setValue(int("0x4ecd25ff", 16))
@ -170,7 +188,7 @@ class LoadClip(plugin.NukeLoader):
loader=self.__class__.__name__,
data=data_imprint)
if version_data.get("retime", None):
if add_retime and version_data.get("retime", None):
self._make_retimes(read_node, version_data)
self.set_as_member(read_node)
@ -194,13 +212,17 @@ class LoadClip(plugin.NukeLoader):
read_node = nuke.toNode(container['objectName'])
file = get_representation_path(representation).replace("\\", "/")
start_at_workfile = bool("start at" in read_node['frame_mode'].value())
start_at_workfile = "start at" in read_node['frame_mode'].value()
version = legacy_io.find_one({
"type": "version",
"_id": representation["parent"]
})
version_data = version.get("data", {})
add_retime = [
key for key in read_node.knobs().keys()
if "addRetime" in key
]
project_name = legacy_io.active_project()
version_doc = get_version_by_id(project_name, representation["parent"])
version_data = version_doc.get("data", {})
repre_id = representation["_id"]
repre_cont = representation["context"]
@ -251,7 +273,7 @@ class LoadClip(plugin.NukeLoader):
"representation": str(representation["_id"]),
"frameStart": str(first),
"frameEnd": str(last),
"version": str(version.get("name")),
"version": str(version_doc.get("name")),
"db_colorspace": colorspace,
"source": version_data.get("source"),
"handleStart": str(self.handle_start),
@ -264,28 +286,26 @@ class LoadClip(plugin.NukeLoader):
if used_colorspace:
updated_dict["used_colorspace"] = used_colorspace
last_version_doc = get_last_version_by_subset_id(
project_name, version_doc["parent"], fields=["_id"]
)
# change color of read_node
# get all versions in list
versions = legacy_io.find({
"type": "version",
"parent": version["parent"]
}).distinct('name')
max_version = max(versions)
if version.get("name") not in [max_version]:
read_node["tile_color"].setValue(int("0xd84f20ff", 16))
if version_doc["_id"] == last_version_doc["_id"]:
color_value = "0x4ecd25ff"
else:
read_node["tile_color"].setValue(int("0x4ecd25ff", 16))
color_value = "0xd84f20ff"
read_node["tile_color"].setValue(int(color_value, 16))
# Update the imprinted representation
update_container(
read_node,
updated_dict
)
self.log.info("updated to version: {}".format(version.get("name")))
self.log.info(
"updated to version: {}".format(version_doc.get("name"))
)
if version_data.get("retime", None):
if add_retime and version_data.get("retime", None):
self._make_retimes(read_node, version_data)
else:
self.clear_members(read_node)

View file

@ -3,6 +3,10 @@ from collections import OrderedDict
import nuke
import six
from openpype.client import (
get_version_by_id,
get_last_version_by_subset_id,
)
from openpype.pipeline import (
legacy_io,
load,
@ -148,17 +152,16 @@ class LoadEffects(load.LoaderPlugin):
"""
# get main variables
# Get version from io
version = legacy_io.find_one({
"type": "version",
"_id": representation["parent"]
})
project_name = legacy_io.active_project()
version_doc = get_version_by_id(project_name, representation["parent"])
# get corresponding node
GN = nuke.toNode(container['objectName'])
file = get_representation_path(representation).replace("\\", "/")
name = container['name']
version_data = version.get("data", {})
vname = version.get("name", None)
version_data = version_doc.get("data", {})
vname = version_doc.get("name", None)
first = version_data.get("frameStart", None)
last = version_data.get("frameEnd", None)
workfile_first_frame = int(nuke.root()["first_frame"].getValue())
@ -243,21 +246,19 @@ class LoadEffects(load.LoaderPlugin):
# try to find parent read node
self.connect_read_node(GN, namespace, json_f["assignTo"])
# get all versions in list
versions = legacy_io.find({
"type": "version",
"parent": version["parent"]
}).distinct('name')
max_version = max(versions)
last_version_doc = get_last_version_by_subset_id(
project_name, version_doc["parent"], fields=["_id"]
)
# change color of node
if version.get("name") not in [max_version]:
GN["tile_color"].setValue(int("0xd84f20ff", 16))
if version_doc["_id"] == last_version_doc["_id"]:
color_value = "0x3469ffff"
else:
GN["tile_color"].setValue(int("0x3469ffff", 16))
color_value = "0xd84f20ff"
self.log.info("updated to version: {}".format(version.get("name")))
GN["tile_color"].setValue(int(color_value, 16))
self.log.info("updated to version: {}".format(version_doc.get("name")))
def connect_read_node(self, group_node, asset, subset):
"""

View file

@ -3,6 +3,10 @@ from collections import OrderedDict
import six
import nuke
from openpype.client import (
get_version_by_id,
get_last_version_by_subset_id,
)
from openpype.pipeline import (
legacy_io,
load,
@ -153,17 +157,16 @@ class LoadEffectsInputProcess(load.LoaderPlugin):
# get main variables
# Get version from io
version = legacy_io.find_one({
"type": "version",
"_id": representation["parent"]
})
project_name = legacy_io.active_project()
version_doc = get_version_by_id(project_name, representation["parent"])
# get corresponding node
GN = nuke.toNode(container['objectName'])
file = get_representation_path(representation).replace("\\", "/")
name = container['name']
version_data = version.get("data", {})
vname = version.get("name", None)
version_data = version_doc.get("data", {})
vname = version_doc.get("name", None)
first = version_data.get("frameStart", None)
last = version_data.get("frameEnd", None)
workfile_first_frame = int(nuke.root()["first_frame"].getValue())
@ -251,20 +254,18 @@ class LoadEffectsInputProcess(load.LoaderPlugin):
# return
# get all versions in list
versions = legacy_io.find({
"type": "version",
"parent": version["parent"]
}).distinct('name')
max_version = max(versions)
last_version_doc = get_last_version_by_subset_id(
project_name, version_doc["parent"], fields=["_id"]
)
# change color of node
if version.get("name") not in [max_version]:
GN["tile_color"].setValue(int("0xd84f20ff", 16))
if version_doc["_id"] == last_version_doc["_id"]:
color_value = "0x3469ffff"
else:
GN["tile_color"].setValue(int("0x3469ffff", 16))
color_value = "0xd84f20ff"
GN["tile_color"].setValue(int(color_value, 16))
self.log.info("updated to version: {}".format(version.get("name")))
self.log.info("updated to version: {}".format(version_doc.get("name")))
def connect_active_viewer(self, group_node):
"""

View file

@ -1,5 +1,9 @@
import nuke
from openpype.client import (
get_version_by_id,
get_last_version_by_subset_id,
)
from openpype.pipeline import (
legacy_io,
load,
@ -101,17 +105,16 @@ class LoadGizmo(load.LoaderPlugin):
# get main variables
# Get version from io
version = legacy_io.find_one({
"type": "version",
"_id": representation["parent"]
})
project_name = legacy_io.active_project()
version_doc = get_version_by_id(project_name, representation["parent"])
# get corresponding node
GN = nuke.toNode(container['objectName'])
file = get_representation_path(representation).replace("\\", "/")
name = container['name']
version_data = version.get("data", {})
vname = version.get("name", None)
version_data = version_doc.get("data", {})
vname = version_doc.get("name", None)
first = version_data.get("frameStart", None)
last = version_data.get("frameEnd", None)
namespace = container['namespace']
@ -148,21 +151,18 @@ class LoadGizmo(load.LoaderPlugin):
GN.setXYpos(xpos, ypos)
GN["name"].setValue(object_name)
# get all versions in list
versions = legacy_io.find({
"type": "version",
"parent": version["parent"]
}).distinct('name')
max_version = max(versions)
last_version_doc = get_last_version_by_subset_id(
project_name, version_doc["parent"], fields=["_id"]
)
# change color of node
if version.get("name") not in [max_version]:
GN["tile_color"].setValue(int("0xd88467ff", 16))
if version_doc["_id"] == last_version_doc["_id"]:
color_value = self.node_color
else:
GN["tile_color"].setValue(int(self.node_color, 16))
color_value = "0xd88467ff"
GN["tile_color"].setValue(int(color_value, 16))
self.log.info("updated to version: {}".format(version.get("name")))
self.log.info("updated to version: {}".format(version_doc.get("name")))
return update_container(GN, data_imprint)

View file

@ -1,6 +1,10 @@
import nuke
import six
from openpype.client import (
get_version_by_id,
get_last_version_by_subset_id,
)
from openpype.pipeline import (
legacy_io,
load,
@ -108,17 +112,16 @@ class LoadGizmoInputProcess(load.LoaderPlugin):
# get main variables
# Get version from io
version = legacy_io.find_one({
"type": "version",
"_id": representation["parent"]
})
project_name = legacy_io.active_project()
version_doc = get_version_by_id(project_name, representation["parent"])
# get corresponding node
GN = nuke.toNode(container['objectName'])
file = get_representation_path(representation).replace("\\", "/")
name = container['name']
version_data = version.get("data", {})
vname = version.get("name", None)
version_data = version_doc.get("data", {})
vname = version_doc.get("name", None)
first = version_data.get("frameStart", None)
last = version_data.get("frameEnd", None)
namespace = container['namespace']
@ -155,21 +158,18 @@ class LoadGizmoInputProcess(load.LoaderPlugin):
GN.setXYpos(xpos, ypos)
GN["name"].setValue(object_name)
# get all versions in list
versions = legacy_io.find({
"type": "version",
"parent": version["parent"]
}).distinct('name')
max_version = max(versions)
last_version_doc = get_last_version_by_subset_id(
project_name, version_doc["parent"], fields=["_id"]
)
# change color of node
if version.get("name") not in [max_version]:
GN["tile_color"].setValue(int("0xd88467ff", 16))
if version_doc["_id"] == last_version_doc["_id"]:
color_value = self.node_color
else:
GN["tile_color"].setValue(int(self.node_color, 16))
color_value = "0xd88467ff"
GN["tile_color"].setValue(int(color_value, 16))
self.log.info("updated to version: {}".format(version.get("name")))
self.log.info("updated to version: {}".format(version_doc.get("name")))
return update_container(GN, data_imprint)

View file

@ -2,6 +2,10 @@ import nuke
import qargparse
from openpype.client import (
get_version_by_id,
get_last_version_by_subset_id,
)
from openpype.pipeline import (
legacy_io,
load,
@ -186,20 +190,13 @@ class LoadImage(load.LoaderPlugin):
format(frame_number, "0{}".format(padding)))
# Get start frame from version data
version = legacy_io.find_one({
"type": "version",
"_id": representation["parent"]
})
project_name = legacy_io.active_project()
version_doc = get_version_by_id(project_name, representation["parent"])
last_version_doc = get_last_version_by_subset_id(
project_name, version_doc["parent"], fields=["_id"]
)
# get all versions in list
versions = legacy_io.find({
"type": "version",
"parent": version["parent"]
}).distinct('name')
max_version = max(versions)
version_data = version.get("data", {})
version_data = version_doc.get("data", {})
last = first = int(frame_number)
@ -215,7 +212,7 @@ class LoadImage(load.LoaderPlugin):
"representation": str(representation["_id"]),
"frameStart": str(first),
"frameEnd": str(last),
"version": str(version.get("name")),
"version": str(version_doc.get("name")),
"colorspace": version_data.get("colorspace"),
"source": version_data.get("source"),
"fps": str(version_data.get("fps")),
@ -223,17 +220,18 @@ class LoadImage(load.LoaderPlugin):
})
# change color of node
if version.get("name") not in [max_version]:
node["tile_color"].setValue(int("0xd84f20ff", 16))
if version_doc["_id"] == last_version_doc["_id"]:
color_value = "0x4ecd25ff"
else:
node["tile_color"].setValue(int("0x4ecd25ff", 16))
color_value = "0xd84f20ff"
node["tile_color"].setValue(int(color_value, 16))
# Update the imprinted representation
update_container(
node,
updated_dict
)
self.log.info("updated to version: {}".format(version.get("name")))
self.log.info("updated to version: {}".format(version_doc.get("name")))
def remove(self, container):
node = nuke.toNode(container['objectName'])

View file

@ -1,5 +1,9 @@
import nuke
from openpype.client import (
get_version_by_id,
get_last_version_by_subset_id,
)
from openpype.pipeline import (
legacy_io,
load,
@ -15,13 +19,13 @@ from openpype.hosts.nuke.api import (
class AlembicModelLoader(load.LoaderPlugin):
"""
This will load alembic model into script.
This will load alembic model or anim into script.
"""
families = ["model"]
families = ["model", "pointcache", "animation"]
representations = ["abc"]
label = "Load Alembic Model"
label = "Load Alembic"
icon = "cube"
color = "orange"
node_color = "0x4ecd91ff"
@ -60,6 +64,12 @@ class AlembicModelLoader(load.LoaderPlugin):
inpanel=False
)
model_node.forceValidate()
# Ensure all items are imported and selected.
scene_view = model_node.knob('scene_view')
scene_view.setImportedItems(scene_view.getAllItems())
scene_view.setSelectedItems(scene_view.getAllItems())
model_node["frame_rate"].setValue(float(fps))
# workaround because nuke's bug is not adding
@ -100,17 +110,15 @@ class AlembicModelLoader(load.LoaderPlugin):
None
"""
# Get version from io
version = legacy_io.find_one({
"type": "version",
"_id": representation["parent"]
})
project_name = legacy_io.active_project()
version_doc = get_version_by_id(project_name, representation["parent"])
object_name = container['objectName']
# get corresponding node
model_node = nuke.toNode(object_name)
# get main variables
version_data = version.get("data", {})
vname = version.get("name", None)
version_data = version_doc.get("data", {})
vname = version_doc.get("name", None)
first = version_data.get("frameStart", None)
last = version_data.get("frameEnd", None)
fps = version_data.get("fps") or nuke.root()["fps"].getValue()
@ -142,6 +150,11 @@ class AlembicModelLoader(load.LoaderPlugin):
model_node["frame_rate"].setValue(float(fps))
model_node["file"].setValue(file)
# Ensure all items are imported and selected.
scene_view = model_node.knob('scene_view')
scene_view.setImportedItems(scene_view.getAllItems())
scene_view.setSelectedItems(scene_view.getAllItems())
# workaround because nuke's bug is
# not adding animation keys properly
xpos = model_node.xpos()
@ -163,28 +176,26 @@ class AlembicModelLoader(load.LoaderPlugin):
d.setInput(index, model_node)
# color node by correct color by actual version
self.node_version_color(version, model_node)
self.node_version_color(version_doc, model_node)
self.log.info("updated to version: {}".format(version.get("name")))
self.log.info("updated to version: {}".format(version_doc.get("name")))
return update_container(model_node, data_imprint)
def node_version_color(self, version, node):
""" Coloring a node by correct color by actual version
"""
# get all versions in list
versions = legacy_io.find({
"type": "version",
"parent": version["parent"]
}).distinct('name')
""" Coloring a node by correct color by actual version"""
max_version = max(versions)
project_name = legacy_io.active_project()
last_version_doc = get_last_version_by_subset_id(
project_name, version["parent"], fields=["_id"]
)
# change color of node
if version.get("name") not in [max_version]:
node["tile_color"].setValue(int("0xd88467ff", 16))
if version["_id"] == last_version_doc["_id"]:
color_value = self.node_color
else:
node["tile_color"].setValue(int(self.node_color, 16))
color_value = "0xd88467ff"
node["tile_color"].setValue(int(color_value, 16))
def switch(self, container, representation):
self.update(container, representation)

View file

@ -1,5 +1,9 @@
import nuke
from openpype.client import (
get_version_by_id,
get_last_version_by_subset_id,
)
from openpype.pipeline import (
legacy_io,
load,
@ -116,29 +120,23 @@ class LinkAsGroup(load.LoaderPlugin):
root = get_representation_path(representation).replace("\\", "/")
# Get start frame from version data
version = legacy_io.find_one({
"type": "version",
"_id": representation["parent"]
})
# get all versions in list
versions = legacy_io.find({
"type": "version",
"parent": version["parent"]
}).distinct('name')
max_version = max(versions)
project_name = legacy_io.active_project()
version_doc = get_version_by_id(project_name, representation["parent"])
last_version_doc = get_last_version_by_subset_id(
project_name, version_doc["parent"], fields=["_id"]
)
updated_dict = {}
version_data = version_doc["data"]
updated_dict.update({
"representation": str(representation["_id"]),
"frameEnd": version["data"].get("frameEnd"),
"version": version.get("name"),
"colorspace": version["data"].get("colorspace"),
"source": version["data"].get("source"),
"handles": version["data"].get("handles"),
"fps": version["data"].get("fps"),
"author": version["data"].get("author")
"frameEnd": version_data.get("frameEnd"),
"version": version_doc.get("name"),
"colorspace": version_data.get("colorspace"),
"source": version_data.get("source"),
"handles": version_data.get("handles"),
"fps": version_data.get("fps"),
"author": version_data.get("author")
})
# Update the imprinted representation
@ -150,12 +148,13 @@ class LinkAsGroup(load.LoaderPlugin):
node["file"].setValue(root)
# change color of node
if version.get("name") not in [max_version]:
node["tile_color"].setValue(int("0xd84f20ff", 16))
if version_doc["_id"] == last_version_doc["_id"]:
color_value = "0xff0ff0ff"
else:
node["tile_color"].setValue(int("0xff0ff0ff", 16))
color_value = "0xd84f20ff"
node["tile_color"].setValue(int(color_value, 16))
self.log.info("updated to version: {}".format(version.get("name")))
self.log.info("updated to version: {}".format(version_doc.get("name")))
def remove(self, container):
node = nuke.toNode(container['objectName'])

View file

@ -3,6 +3,7 @@ import re
import nuke
import pyblish.api
from openpype.client import get_asset_by_name
from openpype.pipeline import legacy_io
@ -16,12 +17,11 @@ class CollectNukeReads(pyblish.api.InstancePlugin):
families = ["source"]
def process(self, instance):
asset_data = legacy_io.find_one({
"type": "asset",
"name": legacy_io.Session["AVALON_ASSET"]
})
project_name = legacy_io.active_project()
asset_name = legacy_io.Session["AVALON_ASSET"]
asset_doc = get_asset_by_name(project_name, asset_name)
self.log.debug("asset_data: {}".format(asset_data["data"]))
self.log.debug("asset_doc: {}".format(asset_doc["data"]))
self.log.debug("checking instance: {}".format(instance))
@ -127,7 +127,7 @@ class CollectNukeReads(pyblish.api.InstancePlugin):
"frameStart": first_frame,
"frameEnd": last_frame,
"colorspace": colorspace,
"handles": int(asset_data["data"].get("handles", 0)),
"handles": int(asset_doc["data"].get("handles", 0)),
"step": 1,
"fps": int(nuke.root()['fps'].value())
})

View file

@ -7,7 +7,7 @@ import clique
class NukeRenderLocal(openpype.api.Extractor):
# TODO: rewrite docstring to nuke
"""Render the current Fusion composition locally.
"""Render the current Nuke composition locally.
Extract the result of savers by starting a comp render
This will run the local render of Fusion.
@ -42,12 +42,22 @@ class NukeRenderLocal(openpype.api.Extractor):
self.log.info("Start frame: {}".format(first_frame))
self.log.info("End frame: {}".format(last_frame))
# write node url might contain nuke's ctl expressin
# as [python ...]/path...
path = node["file"].evaluate()
node_file = node["file"]
# Collecte expected filepaths for each frame
# - for cases that output is still image is first created set of
# paths which is then sorted and converted to list
expected_paths = list(sorted({
node_file.evaluate(frame)
for frame in range(first_frame, last_frame + 1)
}))
# Extract only filenames for representation
filenames = [
os.path.basename(filepath)
for filepath in expected_paths
]
# Ensure output directory exists.
out_dir = os.path.dirname(path)
out_dir = os.path.dirname(expected_paths[0])
if not os.path.exists(out_dir):
os.makedirs(out_dir)
@ -67,12 +77,11 @@ class NukeRenderLocal(openpype.api.Extractor):
if "representations" not in instance.data:
instance.data["representations"] = []
collected_frames = os.listdir(out_dir)
if len(collected_frames) == 1:
if len(filenames) == 1:
repre = {
'name': ext,
'ext': ext,
'files': collected_frames.pop(),
'files': filenames[0],
"stagingDir": out_dir
}
else:
@ -81,7 +90,7 @@ class NukeRenderLocal(openpype.api.Extractor):
'ext': ext,
'frameStart': "%0{}d".format(
len(str(last_frame))) % first_frame,
'files': collected_frames,
'files': filenames,
"stagingDir": out_dir
}
instance.data["representations"].append(repre)
@ -105,7 +114,7 @@ class NukeRenderLocal(openpype.api.Extractor):
families.remove('still.local')
instance.data["families"] = families
collections, remainder = clique.assemble(collected_frames)
collections, remainder = clique.assemble(filenames)
self.log.info('collections: {}'.format(str(collections)))
if collections:

View file

@ -1,4 +1,5 @@
import os
from pprint import pformat
import re
import pyblish.api
import openpype
@ -50,6 +51,8 @@ class ExtractReviewDataMov(openpype.api.Extractor):
with maintained_selection():
generated_repres = []
for o_name, o_data in self.outputs.items():
self.log.debug(
"o_name: {}, o_data: {}".format(o_name, pformat(o_data)))
f_families = o_data["filter"]["families"]
f_task_types = o_data["filter"]["task_types"]
f_subsets = o_data["filter"]["subsets"]
@ -88,14 +91,23 @@ class ExtractReviewDataMov(openpype.api.Extractor):
# check if settings have more then one preset
# so we dont need to add outputName to representation
# in case there is only one preset
multiple_presets = bool(len(self.outputs.keys()) > 1)
multiple_presets = len(self.outputs.keys()) > 1
# adding bake presets to instance data for other plugins
if not instance.data.get("bakePresets"):
instance.data["bakePresets"] = {}
# add preset to bakePresets
instance.data["bakePresets"][o_name] = o_data
# create exporter instance
exporter = plugin.ExporterReviewMov(
self, instance, o_name, o_data["extension"],
multiple_presets)
if "render.farm" in families:
if (
"render.farm" in families or
"prerender.farm" in families
):
if "review" in instance.data["families"]:
instance.data["families"].remove("review")

View file

@ -1,12 +1,17 @@
import os
from pprint import pformat
import nuke
import copy
import pyblish.api
import six
import openpype
from openpype.hosts.nuke.api.lib import maintained_selection
from openpype.hosts.nuke.api import (
maintained_selection,
duplicate_node,
get_view_process_node
)
class ExtractSlateFrame(openpype.api.Extractor):
"""Extracts movie and thumbnail with baked in luts
@ -15,14 +20,13 @@ class ExtractSlateFrame(openpype.api.Extractor):
"""
order = pyblish.api.ExtractorOrder - 0.001
order = pyblish.api.ExtractorOrder + 0.011
label = "Extract Slate Frame"
families = ["slate"]
hosts = ["nuke"]
# Settings values
# - can be extended by other attributes from node in the future
key_value_mapping = {
"f_submission_note": [True, "{comment}"],
"f_submitting_for": [True, "{intent[value]}"],
@ -30,44 +34,107 @@ class ExtractSlateFrame(openpype.api.Extractor):
}
def process(self, instance):
if hasattr(self, "viewer_lut_raw"):
self.viewer_lut_raw = self.viewer_lut_raw
else:
self.viewer_lut_raw = False
if "representations" not in instance.data:
instance.data["representations"] = []
self._create_staging_dir(instance)
with maintained_selection():
self.log.debug("instance: {}".format(instance))
self.log.debug("instance.data[families]: {}".format(
instance.data["families"]))
self.render_slate(instance)
if instance.data.get("bakePresets"):
for o_name, o_data in instance.data["bakePresets"].items():
self.log.info("_ o_name: {}, o_data: {}".format(
o_name, pformat(o_data)))
self.render_slate(
instance,
o_name,
o_data["bake_viewer_process"],
o_data["bake_viewer_input_process"]
)
else:
# backward compatibility
self.render_slate(instance)
# also render image to sequence
self._render_slate_to_sequence(instance)
def _create_staging_dir(self, instance):
def render_slate(self, instance):
node_subset_name = instance.data.get("name", None)
node = instance[0] # group node
self.log.info("Creating staging dir...")
if "representations" not in instance.data:
instance.data["representations"] = list()
staging_dir = os.path.normpath(
os.path.dirname(instance.data['path']))
os.path.dirname(instance.data["path"]))
instance.data["stagingDir"] = staging_dir
self.log.info(
"StagingDir `{0}`...".format(instance.data["stagingDir"]))
frame_start = instance.data["frameStart"]
frame_end = instance.data["frameEnd"]
handle_start = instance.data["handleStart"]
handle_end = instance.data["handleEnd"]
def _check_frames_exists(self, instance):
# rendering path from group write node
fpath = instance.data["path"]
frame_length = int(
(frame_end - frame_start + 1) + (handle_start + handle_end)
)
# instance frame range with handles
first = instance.data["frameStartHandle"]
last = instance.data["frameEndHandle"]
padding = fpath.count('#')
test_path_template = fpath
if padding:
repl_string = "#" * padding
test_path_template = fpath.replace(
repl_string, "%0{}d".format(padding))
for frame in range(first, last + 1):
test_file = test_path_template % frame
if not os.path.exists(test_file):
self.log.debug("__ test_file: `{}`".format(test_file))
return None
return True
def render_slate(
self,
instance,
output_name=None,
bake_viewer_process=True,
bake_viewer_input_process=True
):
"""Slate frame renderer
Args:
instance (PyblishInstance): Pyblish instance with subset data
output_name (str, optional):
Slate variation name. Defaults to None.
bake_viewer_process (bool, optional):
Switch for viewer profile baking. Defaults to True.
bake_viewer_input_process (bool, optional):
Switch for input process node baking. Defaults to True.
"""
slate_node = instance.data["slateNode"]
# rendering path from group write node
fpath = instance.data["path"]
# instance frame range with handles
first_frame = instance.data["frameStartHandle"]
last_frame = instance.data["frameEndHandle"]
# fill slate node with comments
self.add_comment_slate_node(instance, slate_node)
# solve output name if any is set
_output_name = output_name or ""
if _output_name:
_output_name = "_" + _output_name
slate_first_frame = first_frame - 1
temporary_nodes = []
collection = instance.data.get("collection", None)
if collection:
@ -75,100 +142,153 @@ class ExtractSlateFrame(openpype.api.Extractor):
fname = os.path.basename(collection.format(
"{head}{padding}{tail}"))
fhead = collection.format("{head}")
collected_frames_len = int(len(collection.indexes))
# get first and last frame
first_frame = min(collection.indexes) - 1
self.log.info('frame_length: {}'.format(frame_length))
self.log.info(
'len(collection.indexes): {}'.format(collected_frames_len)
)
if ("slate" in instance.data["families"]) \
and (frame_length != collected_frames_len):
first_frame += 1
last_frame = first_frame
else:
fname = os.path.basename(instance.data.get("path", None))
fname = os.path.basename(fpath)
fhead = os.path.splitext(fname)[0] + "."
first_frame = instance.data.get("frameStartHandle", None) - 1
last_frame = first_frame
if "#" in fhead:
fhead = fhead.replace("#", "")[:-1]
previous_node = node
self.log.debug("__ first_frame: {}".format(first_frame))
self.log.debug("__ slate_first_frame: {}".format(slate_first_frame))
# get input process and connect it to baking
ipn = self.get_view_process_node()
if ipn is not None:
ipn.setInput(0, previous_node)
previous_node = ipn
temporary_nodes.append(ipn)
above_slate_node = slate_node.dependencies().pop()
# fallback if files does not exists
if self._check_frames_exists(instance):
# Read node
r_node = nuke.createNode("Read")
r_node["file"].setValue(fpath)
r_node["first"].setValue(first_frame)
r_node["origfirst"].setValue(first_frame)
r_node["last"].setValue(last_frame)
r_node["origlast"].setValue(last_frame)
r_node["colorspace"].setValue(instance.data["colorspace"])
previous_node = r_node
temporary_nodes = [previous_node]
if not self.viewer_lut_raw:
# adding copy metadata node for correct frame metadata
cm_node = nuke.createNode("CopyMetaData")
cm_node.setInput(0, previous_node)
cm_node.setInput(1, above_slate_node)
previous_node = cm_node
temporary_nodes.append(cm_node)
else:
previous_node = above_slate_node
temporary_nodes = []
# only create colorspace baking if toggled on
if bake_viewer_process:
if bake_viewer_input_process:
# get input process and connect it to baking
ipn = get_view_process_node()
if ipn is not None:
ipn.setInput(0, previous_node)
previous_node = ipn
temporary_nodes.append(ipn)
# add duplicate slate node and connect to previous
duply_slate_node = duplicate_node(slate_node)
duply_slate_node.setInput(0, previous_node)
previous_node = duply_slate_node
temporary_nodes.append(duply_slate_node)
# add viewer display transformation node
dag_node = nuke.createNode("OCIODisplay")
dag_node.setInput(0, previous_node)
previous_node = dag_node
temporary_nodes.append(dag_node)
else:
# add duplicate slate node and connect to previous
duply_slate_node = duplicate_node(slate_node)
duply_slate_node.setInput(0, previous_node)
previous_node = duply_slate_node
temporary_nodes.append(duply_slate_node)
# create write node
write_node = nuke.createNode("Write")
file = fhead + "slate.png"
path = os.path.join(staging_dir, file).replace("\\", "/")
instance.data["slateFrame"] = path
file = fhead[:-1] + _output_name + "_slate.png"
path = os.path.join(
instance.data["stagingDir"], file).replace("\\", "/")
# add slate path to `slateFrames` instance data attr
if not instance.data.get("slateFrames"):
instance.data["slateFrames"] = {}
instance.data["slateFrames"][output_name or "*"] = path
# create write node
write_node["file"].setValue(path)
write_node["file_type"].setValue("png")
write_node["raw"].setValue(1)
write_node.setInput(0, previous_node)
temporary_nodes.append(write_node)
# fill slate node with comments
self.add_comment_slate_node(instance)
# Render frames
nuke.execute(write_node.name(), int(first_frame), int(last_frame))
# also render slate as sequence frame
nuke.execute(node_subset_name, int(first_frame), int(last_frame))
self.log.debug(
"slate frame path: {}".format(instance.data["slateFrame"]))
nuke.execute(
write_node.name(), int(slate_first_frame), int(slate_first_frame))
# Clean up
for node in temporary_nodes:
nuke.delete(node)
def get_view_process_node(self):
# Select only the target node
if nuke.selectedNodes():
[n.setSelected(False) for n in nuke.selectedNodes()]
def _render_slate_to_sequence(self, instance):
# set slate frame
first_frame = instance.data["frameStartHandle"]
slate_first_frame = first_frame - 1
ipn_orig = None
for v in [n for n in nuke.allNodes()
if "Viewer" in n.Class()]:
ip = v['input_process'].getValue()
ipn = v['input_process_node'].getValue()
if "VIEWER_INPUT" not in ipn and ip:
ipn_orig = nuke.toNode(ipn)
ipn_orig.setSelected(True)
# render slate as sequence frame
nuke.execute(
instance.data["name"],
int(slate_first_frame),
int(slate_first_frame)
)
if ipn_orig:
nuke.nodeCopy('%clipboard%')
# Add file to representation files
# - get write node
write_node = instance.data["writeNode"]
# - evaluate filepaths for first frame and slate frame
first_filename = os.path.basename(
write_node["file"].evaluate(first_frame))
slate_filename = os.path.basename(
write_node["file"].evaluate(slate_first_frame))
[n.setSelected(False) for n in nuke.selectedNodes()] # Deselect all
# Find matching representation based on first filename
matching_repre = None
is_sequence = None
for repre in instance.data["representations"]:
files = repre["files"]
if (
not isinstance(files, six.string_types)
and first_filename in files
):
matching_repre = repre
is_sequence = True
break
nuke.nodePaste('%clipboard%')
elif files == first_filename:
matching_repre = repre
is_sequence = False
break
ipn = nuke.selectedNode()
return ipn
def add_comment_slate_node(self, instance):
node = instance.data.get("slateNode")
if not node:
if not matching_repre:
self.log.info((
"Matching reresentaion was not found."
" Representation files were not filled with slate."
))
return
# Add frame to matching representation files
if not is_sequence:
matching_repre["files"] = [first_filename, slate_filename]
elif slate_filename not in matching_repre["files"]:
matching_repre["files"].insert(0, slate_filename)
self.log.warning("Added slate frame to representation files")
def add_comment_slate_node(self, instance, node):
comment = instance.context.data.get("comment")
intent = instance.context.data.get("intent")
if not isinstance(intent, dict):
@ -186,8 +306,8 @@ class ExtractSlateFrame(openpype.api.Extractor):
"intent": intent
})
for key, value in self.key_value_mapping.items():
enabled, template = value
for key, _values in self.key_value_mapping.items():
enabled, template = _values
if not enabled:
self.log.debug("Key \"{}\" is disabled".format(key))
continue
@ -221,5 +341,5 @@ class ExtractSlateFrame(openpype.api.Extractor):
))
except NameError:
self.log.warning((
"Failed to set value \"{}\" on node attribute \"{}\""
"Failed to set value \"{0}\" on node attribute \"{0}\""
).format(value))

View file

@ -3,7 +3,10 @@ import os
import nuke
import pyblish.api
import openpype
from openpype.hosts.nuke.api.lib import maintained_selection
from openpype.hosts.nuke.api import (
maintained_selection,
get_view_process_node
)
if sys.version_info[0] >= 3:
@ -17,15 +20,19 @@ class ExtractThumbnail(openpype.api.Extractor):
"""
order = pyblish.api.ExtractorOrder + 0.01
order = pyblish.api.ExtractorOrder + 0.011
label = "Extract Thumbnail"
families = ["review"]
hosts = ["nuke"]
# presets
# settings
use_rendered = False
bake_viewer_process = True
bake_viewer_input_process = True
nodes = {}
def process(self, instance):
if "render.farm" in instance.data["families"]:
return
@ -35,14 +42,37 @@ class ExtractThumbnail(openpype.api.Extractor):
self.log.debug("instance.data[families]: {}".format(
instance.data["families"]))
self.render_thumbnail(instance)
if instance.data.get("bakePresets"):
for o_name, o_data in instance.data["bakePresets"].items():
self.render_thumbnail(instance, o_name, **o_data)
else:
viewer_process_swithes = {
"bake_viewer_process": True,
"bake_viewer_input_process": True
}
self.render_thumbnail(instance, None, **viewer_process_swithes)
def render_thumbnail(self, instance, output_name=None, **kwargs):
first_frame = instance.data["frameStartHandle"]
last_frame = instance.data["frameEndHandle"]
# find frame range and define middle thumb frame
mid_frame = int((last_frame - first_frame) / 2)
# solve output name if any is set
output_name = output_name or ""
if output_name:
output_name = "_" + output_name
bake_viewer_process = kwargs["bake_viewer_process"]
bake_viewer_input_process_node = kwargs[
"bake_viewer_input_process"]
def render_thumbnail(self, instance):
node = instance[0] # group node
self.log.info("Creating staging dir...")
if "representations" not in instance.data:
instance.data["representations"] = list()
instance.data["representations"] = []
staging_dir = os.path.normpath(
os.path.dirname(instance.data['path']))
@ -53,7 +83,11 @@ class ExtractThumbnail(openpype.api.Extractor):
"StagingDir `{0}`...".format(instance.data["stagingDir"]))
temporary_nodes = []
# try to connect already rendered images
previous_node = node
collection = instance.data.get("collection", None)
self.log.debug("__ collection: `{}`".format(collection))
if collection:
# get path
@ -61,43 +95,38 @@ class ExtractThumbnail(openpype.api.Extractor):
"{head}{padding}{tail}"))
fhead = collection.format("{head}")
# get first and last frame
first_frame = min(collection.indexes)
last_frame = max(collection.indexes)
thumb_fname = list(collection)[mid_frame]
else:
fname = os.path.basename(instance.data.get("path", None))
fname = thumb_fname = os.path.basename(
instance.data.get("path", None))
fhead = os.path.splitext(fname)[0] + "."
first_frame = instance.data.get("frameStart", None)
last_frame = instance.data.get("frameEnd", None)
self.log.debug("__ fhead: `{}`".format(fhead))
if "#" in fhead:
fhead = fhead.replace("#", "")[:-1]
path_render = os.path.join(staging_dir, fname).replace("\\", "/")
# check if file exist otherwise connect to write node
if os.path.isfile(path_render):
path_render = os.path.join(
staging_dir, thumb_fname).replace("\\", "/")
self.log.debug("__ path_render: `{}`".format(path_render))
if self.use_rendered and os.path.isfile(path_render):
# check if file exist otherwise connect to write node
rnode = nuke.createNode("Read")
rnode["file"].setValue(path_render)
rnode["first"].setValue(first_frame)
rnode["origfirst"].setValue(first_frame)
rnode["last"].setValue(last_frame)
rnode["origlast"].setValue(last_frame)
# turn it raw if none of baking is ON
if all([
not self.bake_viewer_input_process,
not self.bake_viewer_process
]):
rnode["raw"].setValue(True)
temporary_nodes.append(rnode)
previous_node = rnode
else:
previous_node = node
# get input process and connect it to baking
ipn = self.get_view_process_node()
if ipn is not None:
ipn.setInput(0, previous_node)
previous_node = ipn
temporary_nodes.append(ipn)
reformat_node = nuke.createNode("Reformat")
ref_node = self.nodes.get("Reformat", None)
if ref_node:
for k, v in ref_node:
@ -110,14 +139,24 @@ class ExtractThumbnail(openpype.api.Extractor):
previous_node = reformat_node
temporary_nodes.append(reformat_node)
dag_node = nuke.createNode("OCIODisplay")
dag_node.setInput(0, previous_node)
previous_node = dag_node
temporary_nodes.append(dag_node)
# only create colorspace baking if toggled on
if bake_viewer_process:
if bake_viewer_input_process_node:
# get input process and connect it to baking
ipn = get_view_process_node()
if ipn is not None:
ipn.setInput(0, previous_node)
previous_node = ipn
temporary_nodes.append(ipn)
dag_node = nuke.createNode("OCIODisplay")
dag_node.setInput(0, previous_node)
previous_node = dag_node
temporary_nodes.append(dag_node)
# create write node
write_node = nuke.createNode("Write")
file = fhead + "jpg"
file = fhead[:-1] + output_name + ".jpg"
name = "thumbnail"
path = os.path.join(staging_dir, file).replace("\\", "/")
instance.data["thumbnail"] = path
@ -128,26 +167,18 @@ class ExtractThumbnail(openpype.api.Extractor):
temporary_nodes.append(write_node)
tags = ["thumbnail", "publish_on_farm"]
# retime for
mid_frame = int((int(last_frame) - int(first_frame)) / 2) \
+ int(first_frame)
first_frame = int(last_frame) / 2
last_frame = int(last_frame) / 2
repre = {
'name': name,
'ext': "jpg",
"outputName": "thumb",
'files': file,
"stagingDir": staging_dir,
"frameStart": first_frame,
"frameEnd": last_frame,
"tags": tags
}
instance.data["representations"].append(repre)
# Render frames
nuke.execute(write_node.name(), int(mid_frame), int(mid_frame))
nuke.execute(write_node.name(), mid_frame, mid_frame)
self.log.debug(
"representations: {}".format(instance.data["representations"]))
@ -155,30 +186,3 @@ class ExtractThumbnail(openpype.api.Extractor):
# Clean up
for node in temporary_nodes:
nuke.delete(node)
def get_view_process_node(self):
# Select only the target node
if nuke.selectedNodes():
[n.setSelected(False) for n in nuke.selectedNodes()]
ipn_orig = None
for v in [n for n in nuke.allNodes()
if "Viewer" == n.Class()]:
ip = v['input_process'].getValue()
ipn = v['input_process_node'].getValue()
if "VIEWER_INPUT" not in ipn and ip:
ipn_orig = nuke.toNode(ipn)
ipn_orig.setSelected(True)
if ipn_orig:
nuke.nodeCopy('%clipboard%')
# Deselect all
[n.setSelected(False) for n in nuke.selectedNodes()]
nuke.nodePaste('%clipboard%')
ipn = nuke.selectedNode()
return ipn

View file

@ -1,7 +1,6 @@
import nuke
import pyblish.api
from openpype.pipeline import legacy_io
from openpype.hosts.nuke.api.lib import (
add_publish_knob,
get_avalon_knob_data
@ -20,12 +19,6 @@ class PreCollectNukeInstances(pyblish.api.ContextPlugin):
sync_workfile_version_on_families = []
def process(self, context):
asset_data = legacy_io.find_one({
"type": "asset",
"name": legacy_io.Session["AVALON_ASSET"]
})
self.log.debug("asset_data: {}".format(asset_data["data"]))
instances = []
root = nuke.root()
@ -151,15 +144,11 @@ class PreCollectNukeInstances(pyblish.api.ContextPlugin):
"resolutionWidth": resolution_width,
"resolutionHeight": resolution_height,
"pixelAspect": pixel_aspect,
"review": review
"review": review,
"representations": []
})
self.log.info("collected instance: {}".format(instance.data))
instances.append(instance)
# create instances in context data if not are created yet
if not context.data.get("instances"):
context.data["instances"] = list()
context.data["instances"].extend(instances)
self.log.debug("context: {}".format(context))

View file

@ -17,7 +17,7 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
label = "Pre-collect Workfile"
hosts = ['nuke']
def process(self, context):
def process(self, context): # sourcery skip: avoid-builtin-shadow
root = nuke.root()
current_file = os.path.normpath(nuke.root().name())
@ -74,20 +74,6 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
}
context.data.update(script_data)
# creating instance data
instance.data.update({
"subset": subset,
"label": base_name,
"name": base_name,
"publish": root.knob('publish').value(),
"family": family,
"families": [family],
"representations": list()
})
# adding basic script data
instance.data.update(script_data)
# creating representation
representation = {
'name': 'nk',
@ -96,12 +82,18 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
"stagingDir": staging_dir,
}
instance.data["representations"].append(representation)
# creating instance data
instance.data.update({
"subset": subset,
"label": base_name,
"name": base_name,
"publish": root.knob('publish').value(),
"family": family,
"families": [family],
"representations": [representation]
})
# adding basic script data
instance.data.update(script_data)
self.log.info('Publishing script version')
# create instances in context data if not are created yet
if not context.data.get("instances"):
context.data["instances"] = list()
context.data["instances"].append(instance)

View file

@ -4,7 +4,10 @@ from pprint import pformat
import nuke
import pyblish.api
import openpype.api as pype
from openpype.client import (
get_last_version_by_subset_name,
get_representations,
)
from openpype.pipeline import (
legacy_io,
get_representation_path,
@ -32,6 +35,7 @@ class CollectNukeWrites(pyblish.api.InstancePlugin):
if node is None:
return
instance.data["writeNode"] = node
self.log.debug("checking instance: {}".format(instance))
# Determine defined file type
@ -53,9 +57,21 @@ class CollectNukeWrites(pyblish.api.InstancePlugin):
first_frame = int(node["first"].getValue())
last_frame = int(node["last"].getValue())
# get path
# Prepare expected output paths by evaluating each frame of write node
# - paths are first collected to set to avoid duplicated paths, then
# sorted and converted to list
node_file = node["file"]
expected_paths = list(sorted({
node_file.evaluate(frame)
for frame in range(first_frame, last_frame + 1)
}))
expected_filenames = [
os.path.basename(filepath)
for filepath in expected_paths
]
path = nuke.filename(node)
output_dir = os.path.dirname(path)
self.log.debug('output dir: {}'.format(output_dir))
# create label
@ -72,16 +88,19 @@ class CollectNukeWrites(pyblish.api.InstancePlugin):
if "representations" not in instance.data:
instance.data["representations"] = list()
representation = {
'name': ext,
'ext': ext,
"stagingDir": output_dir,
"tags": list()
}
representation = {
'name': ext,
'ext': ext,
"stagingDir": output_dir,
"tags": list()
}
try:
collected_frames = [f for f in os.listdir(output_dir)
if ext in f]
collected_frames = [
filename
for filename in os.listdir(output_dir)
if filename in expected_filenames
]
if collected_frames:
collected_frames_len = len(collected_frames)
frame_start_str = "%0{}d".format(
@ -175,17 +194,31 @@ class CollectNukeWrites(pyblish.api.InstancePlugin):
"frameEndHandle": last_frame,
})
# make sure rendered sequence on farm will
# be used for exctract review
if not instance.data["review"]:
instance.data["useSequenceForReview"] = False
project_name = legacy_io.active_project()
asset_name = instance.data["asset"]
# * Add audio to instance if exists.
# Find latest versions document
version_doc = pype.get_latest_version(
instance.data["asset"], "audioMain"
last_version_doc = get_last_version_by_subset_name(
project_name, "audioMain", asset_name=asset_name, fields=["_id"]
)
repre_doc = None
if version_doc:
if last_version_doc:
# Try to find it's representation (Expected there is only one)
repre_doc = legacy_io.find_one(
{"type": "representation", "parent": version_doc["_id"]}
)
repre_docs = list(get_representations(
project_name, version_ids=[last_version_doc["_id"]]
))
if not repre_docs:
self.log.warning(
"Version document does not contain any representations"
)
else:
repre_doc = repre_docs[0]
# Add audio to instance if representation was found
if repre_doc:

View file

@ -1,6 +1,6 @@
import pyblish.api
from openpype import lib
from openpype.client import get_project, get_asset_by_id, get_asset_by_name
from openpype.pipeline import legacy_io
@ -16,8 +16,10 @@ class ValidateScript(pyblish.api.InstancePlugin):
def process(self, instance):
ctx_data = instance.context.data
project_name = legacy_io.active_project()
asset_name = ctx_data["asset"]
asset = lib.get_asset(asset_name)
# TODO repace query with using 'instance.data["assetEntity"]'
asset = get_asset_by_name(project_name, asset_name)
asset_data = asset["data"]
# These attributes will be checked
@ -48,12 +50,19 @@ class ValidateScript(pyblish.api.InstancePlugin):
asset_attributes[attr] = asset_data[attr]
elif attr in hierarchical_attributes:
# Try to find fps on parent
parent = asset['parent']
if asset_data['visualParent'] is not None:
parent = asset_data['visualParent']
# TODO this should be probably removed
# Hierarchical attributes is not a thing since Pype 2?
value = self.check_parent_hierarchical(parent, attr)
# Try to find attribute on parent
parent_id = asset['parent']
parent_type = "project"
if asset_data['visualParent'] is not None:
parent_type = "asset"
parent_id = asset_data['visualParent']
value = self.check_parent_hierarchical(
project_name, parent_type, parent_id, attr
)
if value is None:
missing_attributes.append(attr)
else:
@ -113,12 +122,35 @@ class ValidateScript(pyblish.api.InstancePlugin):
message = msg.format(", ".join(not_matching))
raise ValueError(message)
def check_parent_hierarchical(self, entityId, attr):
if entityId is None:
def check_parent_hierarchical(
self, project_name, parent_type, parent_id, attr
):
if parent_id is None:
return None
entity = legacy_io.find_one({"_id": entityId})
if attr in entity['data']:
doc = None
if parent_type == "project":
doc = get_project(project_name)
elif parent_type == "asset":
doc = get_asset_by_id(project_name, parent_id)
if not doc:
return None
doc_data = doc["data"]
if attr in doc_data:
self.log.info(attr)
return entity['data'][attr]
else:
return self.check_parent_hierarchical(entity['parent'], attr)
return doc_data[attr]
if parent_type == "project":
return None
parent_id = doc_data.get("visualParent")
new_parent_type = "asset"
if parent_id is None:
parent_id = doc["parent"]
new_parent_type = "project"
return self.check_parent_hierarchical(
project_name, new_parent_type, parent_id, attr
)