feat(nukestudio): work on plugins

This commit is contained in:
Jakub Jezek 2019-05-11 18:20:14 +02:00
parent b586383a0c
commit 2cf60c1fbb
13 changed files with 245 additions and 181 deletions

View file

@ -9,7 +9,7 @@ class CollectAssumedDestination(pyblish.api.ContextPlugin):
label = "Collect Assumed Destination"
order = pyblish.api.CollectorOrder + 0.498
exclude_families = ["clip"]
exclude_families = ["clip", "trackItem"]
def process(self, context):
for instance in context:

View file

@ -0,0 +1,191 @@
from pyblish import api
class CollectFramerate(api.ContextPlugin):
"""Collect framerate from selected sequence."""
order = api.CollectorOrder
label = "Collect Framerate"
hosts = ["nukestudio"]
def process(self, context):
for item in context.data.get("selection", []):
context.data["framerate"] = item.sequence().framerate().toFloat()
return
class CollectTrackItems(api.ContextPlugin):
"""Collect all tasks from submission."""
order = api.CollectorOrder
label = "Collect Track Items"
hosts = ["nukestudio"]
def process(self, context):
import os
submission = context.data.get("submission", None)
data = {}
# Set handles
handles = 0
if submission:
for task in submission.getLeafTasks():
if task._cutHandles:
handles = task._cutHandles
self.log.info("__ handles: '{}'".format(handles))
# Skip audio track items
media_type = "core.Hiero.Python.TrackItem.MediaType.kAudio"
if str(task._item.mediaType()) == media_type:
continue
item = task._item
if item.name() not in data:
data[item.name()] = {"item": item, "tasks": [task]}
else:
data[item.name()]["tasks"].append(task)
data[item.name()]["startFrame"] = task.outputRange()[0]
data[item.name()]["endFrame"] = task.outputRange()[1]
else:
for item in context.data.get("selection", []):
# Skip audio track items
# Try/Except is to handle items types, like EffectTrackItem
try:
media_type = "core.Hiero.Python.TrackItem.MediaType.kVideo"
if str(item.mediaType()) != media_type:
continue
except:
continue
data[item.name()] = {
"item": item,
"tasks": [],
"startFrame": item.timelineIn(),
"endFrame": item.timelineOut()
}
for key, value in data.items():
context.create_instance(
name=key,
subset="trackItem",
asset=value["item"].name(),
item=value["item"],
family="trackItem",
tasks=value["tasks"],
startFrame=value["startFrame"] + handles,
endFrame=value["endFrame"] - handles,
handles=handles
)
context.create_instance(
name=key + "_review",
subset="reviewItem",
asset=value["item"].name(),
item=value["item"],
family="trackItem_review",
families=["output"],
handles=handles,
output_path=os.path.abspath(
os.path.join(
context.data["activeProject"].path(),
"..",
"workspace",
key + ".mov"
)
)
)
class CollectTasks(api.ContextPlugin):
"""Collect all tasks from submission."""
order = api.CollectorOrder + 0.01
label = "Collect Tasks"
hosts = ["nukestudio"]
def process(self, context):
import os
import re
import hiero.exporters as he
import clique
for parent in context:
if "trackItem" != parent.data["family"]:
continue
for task in parent.data["tasks"]:
asset_type = None
hiero_cls = he.FnSymLinkExporter.SymLinkExporter
if isinstance(task, hiero_cls):
asset_type = "img"
movie_formats = [".mov", ".R3D"]
ext = os.path.splitext(task.resolvedExportPath())[1]
if ext in movie_formats:
asset_type = "mov"
hiero_cls = he.FnTranscodeExporter.TranscodeExporter
if isinstance(task, hiero_cls):
asset_type = "img"
if task.resolvedExportPath().endswith(".mov"):
asset_type = "mov"
hiero_cls = he.FnNukeShotExporter.NukeShotExporter
if isinstance(task, hiero_cls):
asset_type = "scene"
hiero_cls = he.FnAudioExportTask.AudioExportTask
if isinstance(task, hiero_cls):
asset_type = "audio"
# Skip all non supported export types
if not asset_type:
continue
resolved_path = task.resolvedExportPath()
# Formatting the basename to not include frame padding or
# extension.
name = os.path.splitext(os.path.basename(resolved_path))[0]
name = name.replace(".", "")
name = name.replace("#", "")
name = re.sub(r"%.*d", "", name)
instance = context.create_instance(name=name, parent=parent)
instance.data["task"] = task
instance.data["item"] = parent.data["item"]
instance.data["family"] = "trackItem.task"
instance.data["families"] = [asset_type, "local", "task"]
label = "{1}/{0} - {2} - local".format(
name, parent, asset_type
)
instance.data["label"] = label
instance.data["handles"] = parent.data["handles"]
# Add collection or output
if asset_type == "img":
collection = None
if "#" in resolved_path:
head = resolved_path.split("#")[0]
padding = resolved_path.count("#")
tail = resolved_path.split("#")[-1]
collection = clique.Collection(
head=head, padding=padding, tail=tail
)
if "%" in resolved_path:
collection = clique.parse(
resolved_path, pattern="{head}{padding}{tail}"
)
instance.data["collection"] = collection
else:
instance.data["output_path"] = resolved_path

View file

@ -1,11 +1,10 @@
from pyblish import api
from pyblish_bumpybox import inventory
class ExtractTasks(api.InstancePlugin):
"""Extract tasks."""
order = inventory.get_order(__file__, "ExtractTasks")
order = api.ExtractorOrder
label = "Tasks"
hosts = ["nukestudio"]
families = ["trackItem.task"]

View file

@ -1,12 +1,10 @@
from pyblish import api
from pyblish_bumpybox import inventory
class CollectFramerate(api.ContextPlugin):
"""Collect framerate from selected sequence."""
order = inventory.get_order(__file__, "CollectFramerate")
label = "Framerate"
order = api.CollectorOrder
label = "Collect Framerate"
hosts = ["nukestudio"]
def process(self, context):
@ -16,173 +14,44 @@ class CollectFramerate(api.ContextPlugin):
class CollectTrackItems(api.ContextPlugin):
"""Collect all tasks from submission."""
"""Collect all Track items selection."""
order = inventory.get_order(__file__, "CollectTrackItems")
label = "Track Items"
order = api.CollectorOrder
label = "Collect Track Items"
hosts = ["nukestudio"]
def process(self, context):
import os
submission = context.data.get("submission", None)
data = {}
# Set handles
handles = 0
if submission:
for task in submission.getLeafTasks():
if task._cutHandles:
handles = task._cutHandles
# Skip audio track items
media_type = "core.Hiero.Python.TrackItem.MediaType.kAudio"
if str(task._item.mediaType()) == media_type:
for item in context.data.get("selection", []):
self.log.info("__ item: {}".format(item))
# Skip audio track items
# Try/Except is to handle items types, like EffectTrackItem
try:
media_type = "core.Hiero.Python.TrackItem.MediaType.kVideo"
if str(item.mediaType()) != media_type:
continue
except:
continue
item = task._item
if item.name() not in data:
data[item.name()] = {"item": item, "tasks": [task]}
else:
data[item.name()]["tasks"].append(task)
data[item.name()] = {
"item": item,
"tasks": [],
"startFrame": item.timelineIn(),
"endFrame": item.timelineOut()
}
data[item.name()]["startFrame"] = task.outputRange()[0]
data[item.name()]["endFrame"] = task.outputRange()[1]
else:
for item in context.data.get("selection", []):
# Skip audio track items
# Try/Except is to handle items types, like EffectTrackItem
try:
media_type = "core.Hiero.Python.TrackItem.MediaType.kVideo"
if str(item.mediaType()) != media_type:
continue
except:
continue
data[item.name()] = {
"item": item,
"tasks": [],
"startFrame": item.timelineIn(),
"endFrame": item.timelineOut()
}
for key, value in data.iteritems():
for key, value in data.items():
context.create_instance(
name=key,
subset="trackItem",
asset=value["item"].name(),
item=value["item"],
family="trackItem",
tasks=value["tasks"],
startFrame=value["startFrame"] + handles,
endFrame=value["endFrame"] - handles,
handles=handles
startFrame=value["startFrame"],
endFrame=value["endFrame"],
handles=0
)
context.create_instance(
name=key + "_review",
item=value["item"],
family="review",
families=["output"],
handles=handles,
output_path=os.path.abspath(
os.path.join(
context.data["activeProject"].path(),
"..",
"workspace",
key + ".mov"
)
)
)
class CollectTasks(api.ContextPlugin):
"""Collect all tasks from submission."""
order = inventory.get_order(__file__, "CollectTasks")
label = "Tasks"
hosts = ["nukestudio"]
def process(self, context):
import os
import re
import hiero.exporters as he
import clique
for parent in context:
if "trackItem" != parent.data["family"]:
continue
for task in parent.data["tasks"]:
asset_type = None
hiero_cls = he.FnSymLinkExporter.SymLinkExporter
if isinstance(task, hiero_cls):
asset_type = "img"
movie_formats = [".mov", ".R3D"]
ext = os.path.splitext(task.resolvedExportPath())[1]
if ext in movie_formats:
asset_type = "mov"
hiero_cls = he.FnTranscodeExporter.TranscodeExporter
if isinstance(task, hiero_cls):
asset_type = "img"
if task.resolvedExportPath().endswith(".mov"):
asset_type = "mov"
hiero_cls = he.FnNukeShotExporter.NukeShotExporter
if isinstance(task, hiero_cls):
asset_type = "scene"
hiero_cls = he.FnAudioExportTask.AudioExportTask
if isinstance(task, hiero_cls):
asset_type = "audio"
# Skip all non supported export types
if not asset_type:
continue
resolved_path = task.resolvedExportPath()
# Formatting the basename to not include frame padding or
# extension.
name = os.path.splitext(os.path.basename(resolved_path))[0]
name = name.replace(".", "")
name = name.replace("#", "")
name = re.sub(r"%.*d", "", name)
instance = context.create_instance(name=name, parent=parent)
instance.data["task"] = task
instance.data["item"] = parent.data["item"]
instance.data["family"] = "trackItem.task"
instance.data["families"] = [asset_type, "local", "task"]
label = "{1}/{0} - {2} - local".format(
name, parent, asset_type
)
instance.data["label"] = label
instance.data["handles"] = parent.data["handles"]
# Add collection or output
if asset_type == "img":
collection = None
if "#" in resolved_path:
head = resolved_path.split("#")[0]
padding = resolved_path.count("#")
tail = resolved_path.split("#")[-1]
collection = clique.Collection(
head=head, padding=padding, tail=tail
)
if "%" in resolved_path:
collection = clique.parse(
resolved_path, pattern="{head}{padding}{tail}"
)
instance.data["collection"] = collection
else:
instance.data["output_path"] = resolved_path

View file

@ -0,0 +1,14 @@
from pyblish import api
class CollectTrackItemTags(api.InstancePlugin):
"""Collect Tags from selected track items."""
order = api.CollectorOrder
label = "Collect Tags"
hosts = ["nukestudio"]
def process(self, instance):
instance.data["tags"] = instance.data["item"].tags()
self.log.info(instance.data["tags"])
return

View file

@ -1,11 +1,10 @@
from pyblish import api
from pyblish_bumpybox import inventory
class ExtractReview(api.InstancePlugin):
"""Extracts movie for review"""
order = inventory.get_order(__file__, "ExtractReview")
order = api.ExtractorOrder
label = "NukeStudio Review"
optional = True
hosts = ["nukestudio"]

View file

@ -1,5 +1,4 @@
from pyblish import api
from pyblish_bumpybox import inventory
class ValidateNames(api.InstancePlugin):
@ -10,7 +9,7 @@ class ValidateNames(api.InstancePlugin):
Exact matching to optimize processing.
"""
order = inventory.get_order(__file__, "ValidateNames")
order = api.ValidatorOrder
families = ["trackItem"]
match = api.Exact
label = "Names"
@ -39,5 +38,5 @@ class ValidateNamesFtrack(ValidateNames):
accommodate for the ftrack family addition.
"""
order = inventory.get_order(__file__, "ValidateNamesFtrack")
order = api.ValidatorOrder
families = ["trackItem", "ftrack"]

View file

@ -1,5 +1,4 @@
from pyblish import api
from pyblish_bumpybox import inventory
class RepairProjectRoot(api.Action):
@ -32,7 +31,7 @@ class RepairProjectRoot(api.Action):
class ValidateProjectRoot(api.ContextPlugin):
"""Validate the project root to the workspace directory."""
order = inventory.get_order(__file__, "ValidateProjectRoot")
order = api.ValidatorOrder
label = "Project Root"
hosts = ["nukestudio"]
actions = [RepairProjectRoot]

View file

@ -1,11 +1,9 @@
from pyblish import api
from pyblish_bumpybox import inventory
class ValidateResolvedPaths(api.ContextPlugin):
"""Validate there are no overlapping resolved paths."""
order = inventory.get_order(__file__, "ValidateResolvedPaths")
order = api.ValidatorOrder
label = "Resolved Paths"
hosts = ["nukestudio"]

View file

@ -1,5 +1,4 @@
from pyblish import api
from pyblish_bumpybox import inventory
class ValidateOutputRange(api.InstancePlugin):
@ -11,7 +10,7 @@ class ValidateOutputRange(api.InstancePlugin):
do.
"""
order = inventory.get_order(__file__, "ValidateOutputRange")
order = api.ValidatorOrder
families = ["trackItem.task"]
label = "Output Range"
hosts = ["nukestudio"]
@ -40,7 +39,7 @@ class ValidateOutputRange(api.InstancePlugin):
class ValidateImageSequence(api.InstancePlugin):
"""Validate image sequence output path is setup correctly."""
order = inventory.get_order(__file__, "ValidateImageSequence")
order = api.ValidatorOrder
families = ["trackItem.task", "img"]
match = api.Subset
label = "Image Sequence"

View file

@ -1,6 +1,4 @@
from pyblish import api
from pyblish_bumpybox import inventory
class ValidateTrackItem(api.InstancePlugin):
"""Validate the track item to the sequence.
@ -8,10 +6,10 @@ class ValidateTrackItem(api.InstancePlugin):
Exact matching to optimize processing.
"""
order = inventory.get_order(__file__, "ValidateTrackItem")
order = api.ValidatorOrder
families = ["trackItem"]
match = api.Exact
label = "Track Item"
label = "Validate Track Item"
hosts = ["nukestudio"]
optional = True
@ -21,7 +19,7 @@ class ValidateTrackItem(api.InstancePlugin):
self.log.info("__ item: {}".format(item))
media_source = item.source().mediaSource()
self.log.info("__ media_source: {}".format(media_source))
msg = (
'A setting does not match between track item "{0}" and sequence '
'"{1}".'.format(item.name(), item.sequence().name()) +
@ -55,5 +53,5 @@ class ValidateTrackItem(api.InstancePlugin):
# accommodate for the ftrack family addition.
# """
#
# order = inventory.get_order(__file__, "ValidateTrackItemFtrack")
# order = api.ValidatorOrder
# families = ["trackItem", "ftrack"]

View file

@ -1,11 +1,10 @@
from pyblish import api
from pyblish_bumpybox import inventory
class ValidateViewerLut(api.ContextPlugin):
"""Validate viewer lut in NukeStudio is the same as in Nuke."""
order = inventory.get_order(__file__, "ValidateViewerLut")
order = api.ValidatorOrder
label = "Viewer LUT"
hosts = ["nukestudio"]
optional = True