mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 16:34:53 +01:00
Merge pull request #494 from tokejepsen/2.x/feature/nuke_build_workfile
Revamp Build Workfile in Nuke.
This commit is contained in:
commit
297fcdc8da
2 changed files with 21 additions and 315 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import getpass
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from avalon import api, io, lib
|
from avalon import api, io, lib
|
||||||
|
|
@ -1060,310 +1059,6 @@ def get_write_node_template_attr(node):
|
||||||
return avalon.nuke.lib.fix_data_for_node_create(correct_data)
|
return avalon.nuke.lib.fix_data_for_node_create(correct_data)
|
||||||
|
|
||||||
|
|
||||||
class BuildWorkfile(WorkfileSettings):
|
|
||||||
"""
|
|
||||||
Building first version of workfile.
|
|
||||||
|
|
||||||
Settings are taken from presets and db. It will add all subsets
|
|
||||||
in last version for defined representaions
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
variable (type): description
|
|
||||||
|
|
||||||
"""
|
|
||||||
xpos = 0
|
|
||||||
ypos = 0
|
|
||||||
xpos_size = 80
|
|
||||||
ypos_size = 90
|
|
||||||
xpos_gap = 50
|
|
||||||
ypos_gap = 50
|
|
||||||
pos_layer = 10
|
|
||||||
|
|
||||||
def __init__(self,
|
|
||||||
root_path=None,
|
|
||||||
root_node=None,
|
|
||||||
nodes=None,
|
|
||||||
to_script=None,
|
|
||||||
**kwargs):
|
|
||||||
"""
|
|
||||||
A short description.
|
|
||||||
|
|
||||||
A bit longer description.
|
|
||||||
|
|
||||||
Argumetns:
|
|
||||||
root_path (str): description
|
|
||||||
root_node (nuke.Node): description
|
|
||||||
nodes (list): list of nuke.Node
|
|
||||||
nodes_effects (dict): dictionary with subsets
|
|
||||||
|
|
||||||
Example:
|
|
||||||
nodes_effects = {
|
|
||||||
"plateMain": {
|
|
||||||
"nodes": [
|
|
||||||
[("Class", "Reformat"),
|
|
||||||
("resize", "distort"),
|
|
||||||
("flip", True)],
|
|
||||||
|
|
||||||
[("Class", "Grade"),
|
|
||||||
("blackpoint", 0.5),
|
|
||||||
("multiply", 0.4)]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
WorkfileSettings.__init__(self,
|
|
||||||
root_node=root_node,
|
|
||||||
nodes=nodes,
|
|
||||||
**kwargs)
|
|
||||||
self.to_script = to_script
|
|
||||||
# collect data for formating
|
|
||||||
self.data_tmp = {
|
|
||||||
"project": {"name": self._project["name"],
|
|
||||||
"code": self._project["data"].get("code", "")},
|
|
||||||
"asset": self._asset or os.environ["AVALON_ASSET"],
|
|
||||||
"task": kwargs.get("task") or api.Session["AVALON_TASK"],
|
|
||||||
"hierarchy": kwargs.get("hierarchy") or pype.get_hierarchy(),
|
|
||||||
"version": kwargs.get("version", {}).get("name", 1),
|
|
||||||
"user": getpass.getuser(),
|
|
||||||
"comment": "firstBuild",
|
|
||||||
"ext": "nk"
|
|
||||||
}
|
|
||||||
|
|
||||||
# get presets from anatomy
|
|
||||||
anatomy = get_anatomy()
|
|
||||||
# format anatomy
|
|
||||||
anatomy_filled = anatomy.format(self.data_tmp)
|
|
||||||
|
|
||||||
# get dir and file for workfile
|
|
||||||
self.work_dir = anatomy_filled["work"]["folder"]
|
|
||||||
self.work_file = anatomy_filled["work"]["file"]
|
|
||||||
|
|
||||||
def save_script_as(self, path=None):
|
|
||||||
# first clear anything in open window
|
|
||||||
nuke.scriptClear()
|
|
||||||
|
|
||||||
if not path:
|
|
||||||
dir = self.work_dir
|
|
||||||
path = os.path.join(
|
|
||||||
self.work_dir,
|
|
||||||
self.work_file).replace("\\", "/")
|
|
||||||
else:
|
|
||||||
dir = os.path.dirname(path)
|
|
||||||
|
|
||||||
# check if folder is created
|
|
||||||
if not os.path.exists(dir):
|
|
||||||
os.makedirs(dir)
|
|
||||||
|
|
||||||
# save script to path
|
|
||||||
nuke.scriptSaveAs(path)
|
|
||||||
|
|
||||||
def process(self,
|
|
||||||
regex_filter=None,
|
|
||||||
version=None,
|
|
||||||
representations=["exr", "dpx", "lutJson", "mov",
|
|
||||||
"preview", "png", "jpeg", "jpg"]):
|
|
||||||
"""
|
|
||||||
A short description.
|
|
||||||
|
|
||||||
A bit longer description.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
regex_filter (raw string): regex pattern to filter out subsets
|
|
||||||
version (int): define a particular version, None gets last
|
|
||||||
representations (list):
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
type: description
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
Exception: description
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not self.to_script:
|
|
||||||
# save the script
|
|
||||||
self.save_script_as()
|
|
||||||
|
|
||||||
# create viewer and reset frame range
|
|
||||||
viewer = self.get_nodes(nodes_filter=["Viewer"])
|
|
||||||
if not viewer:
|
|
||||||
vn = nuke.createNode("Viewer")
|
|
||||||
vn["xpos"].setValue(self.xpos)
|
|
||||||
vn["ypos"].setValue(self.ypos)
|
|
||||||
else:
|
|
||||||
vn = viewer[-1]
|
|
||||||
|
|
||||||
# move position
|
|
||||||
self.position_up()
|
|
||||||
|
|
||||||
wn = self.write_create()
|
|
||||||
wn["xpos"].setValue(self.xpos)
|
|
||||||
wn["ypos"].setValue(self.ypos)
|
|
||||||
wn["render"].setValue(True)
|
|
||||||
vn.setInput(0, wn)
|
|
||||||
|
|
||||||
# adding backdrop under write
|
|
||||||
self.create_backdrop(label="Render write \n\n\n\nOUTPUT",
|
|
||||||
color='0xcc1102ff', layer=-1,
|
|
||||||
nodes=[wn])
|
|
||||||
|
|
||||||
# move position
|
|
||||||
self.position_up(4)
|
|
||||||
|
|
||||||
# set frame range for new viewer
|
|
||||||
self.reset_frame_range_handles()
|
|
||||||
|
|
||||||
# get all available representations
|
|
||||||
subsets = pype.get_subsets(self._asset,
|
|
||||||
regex_filter=regex_filter,
|
|
||||||
version=version,
|
|
||||||
representations=representations)
|
|
||||||
|
|
||||||
for name, subset in subsets.items():
|
|
||||||
log.debug("___________________")
|
|
||||||
log.debug(name)
|
|
||||||
log.debug(subset["version"])
|
|
||||||
|
|
||||||
nodes_backdrop = list()
|
|
||||||
for name, subset in subsets.items():
|
|
||||||
if "lut" in name:
|
|
||||||
continue
|
|
||||||
log.info("Building Loader to: `{}`".format(name))
|
|
||||||
version = subset["version"]
|
|
||||||
log.info("Version to: `{}`".format(version["name"]))
|
|
||||||
representations = subset["representaions"]
|
|
||||||
for repr in representations:
|
|
||||||
rn = self.read_loader(repr)
|
|
||||||
rn["xpos"].setValue(self.xpos)
|
|
||||||
rn["ypos"].setValue(self.ypos)
|
|
||||||
wn.setInput(0, rn)
|
|
||||||
|
|
||||||
# get editional nodes
|
|
||||||
lut_subset = [s for n, s in subsets.items()
|
|
||||||
if "lut{}".format(name.lower()) in n.lower()]
|
|
||||||
log.debug(">> lut_subset: `{}`".format(lut_subset))
|
|
||||||
|
|
||||||
if len(lut_subset) > 0:
|
|
||||||
lsub = lut_subset[0]
|
|
||||||
fxn = self.effect_loader(lsub["representaions"][-1])
|
|
||||||
fxn_ypos = fxn["ypos"].value()
|
|
||||||
fxn["ypos"].setValue(fxn_ypos - 100)
|
|
||||||
nodes_backdrop.append(fxn)
|
|
||||||
|
|
||||||
nodes_backdrop.append(rn)
|
|
||||||
# move position
|
|
||||||
self.position_right()
|
|
||||||
|
|
||||||
# adding backdrop under all read nodes
|
|
||||||
self.create_backdrop(label="Loaded Reads",
|
|
||||||
color='0x2d7702ff', layer=-1,
|
|
||||||
nodes=nodes_backdrop)
|
|
||||||
|
|
||||||
def read_loader(self, representation):
|
|
||||||
"""
|
|
||||||
Gets Loader plugin for image sequence or mov
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
representation (dict): avalon db entity
|
|
||||||
|
|
||||||
"""
|
|
||||||
context = representation["context"]
|
|
||||||
|
|
||||||
loader_name = "LoadSequence"
|
|
||||||
if "mov" in context["representation"]:
|
|
||||||
loader_name = "LoadMov"
|
|
||||||
|
|
||||||
loader_plugin = None
|
|
||||||
for Loader in api.discover(api.Loader):
|
|
||||||
if Loader.__name__ != loader_name:
|
|
||||||
continue
|
|
||||||
|
|
||||||
loader_plugin = Loader
|
|
||||||
|
|
||||||
return api.load(Loader=loader_plugin,
|
|
||||||
representation=representation["_id"])
|
|
||||||
|
|
||||||
def effect_loader(self, representation):
|
|
||||||
"""
|
|
||||||
Gets Loader plugin for effects
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
representation (dict): avalon db entity
|
|
||||||
|
|
||||||
"""
|
|
||||||
loader_name = "LoadLuts"
|
|
||||||
|
|
||||||
loader_plugin = None
|
|
||||||
for Loader in api.discover(api.Loader):
|
|
||||||
if Loader.__name__ != loader_name:
|
|
||||||
continue
|
|
||||||
|
|
||||||
loader_plugin = Loader
|
|
||||||
|
|
||||||
return api.load(Loader=loader_plugin,
|
|
||||||
representation=representation["_id"])
|
|
||||||
|
|
||||||
def write_create(self):
|
|
||||||
"""
|
|
||||||
Create render write
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
representation (dict): avalon db entity
|
|
||||||
|
|
||||||
"""
|
|
||||||
task = self.data_tmp["task"]
|
|
||||||
sanitized_task = re.sub('[^0-9a-zA-Z]+', '', task)
|
|
||||||
subset_name = "render{}Main".format(
|
|
||||||
sanitized_task.capitalize())
|
|
||||||
|
|
||||||
Create_name = "CreateWriteRender"
|
|
||||||
|
|
||||||
creator_plugin = None
|
|
||||||
for Creator in api.discover(api.Creator):
|
|
||||||
if Creator.__name__ != Create_name:
|
|
||||||
continue
|
|
||||||
|
|
||||||
creator_plugin = Creator
|
|
||||||
|
|
||||||
# return api.create()
|
|
||||||
return creator_plugin(subset_name, self._asset).process()
|
|
||||||
|
|
||||||
def create_backdrop(self, label="", color=None, layer=0,
|
|
||||||
nodes=None):
|
|
||||||
"""
|
|
||||||
Create Backdrop node
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
color (str): nuke compatible string with color code
|
|
||||||
layer (int): layer of node usually used (self.pos_layer - 1)
|
|
||||||
label (str): the message
|
|
||||||
nodes (list): list of nodes to be wrapped into backdrop
|
|
||||||
|
|
||||||
"""
|
|
||||||
assert isinstance(nodes, list), "`nodes` should be a list of nodes"
|
|
||||||
layer = self.pos_layer + layer
|
|
||||||
|
|
||||||
create_backdrop(label=label, color=color, layer=layer, nodes=nodes)
|
|
||||||
|
|
||||||
def position_reset(self, xpos=0, ypos=0):
|
|
||||||
self.xpos = xpos
|
|
||||||
self.ypos = ypos
|
|
||||||
|
|
||||||
def position_right(self, multiply=1):
|
|
||||||
self.xpos += (self.xpos_size * multiply) + self.xpos_gap
|
|
||||||
|
|
||||||
def position_left(self, multiply=1):
|
|
||||||
self.xpos -= (self.xpos_size * multiply) + self.xpos_gap
|
|
||||||
|
|
||||||
def position_down(self, multiply=1):
|
|
||||||
self.ypos -= (self.ypos_size * multiply) + self.ypos_gap
|
|
||||||
|
|
||||||
def position_up(self, multiply=1):
|
|
||||||
self.ypos -= (self.ypos_size * multiply) + self.ypos_gap
|
|
||||||
|
|
||||||
|
|
||||||
class ExporterReview:
|
class ExporterReview:
|
||||||
"""
|
"""
|
||||||
Base class object for generating review data from Nuke
|
Base class object for generating review data from Nuke
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@ import nuke
|
||||||
from avalon.api import Session
|
from avalon.api import Session
|
||||||
|
|
||||||
from pype.hosts.nuke import lib
|
from pype.hosts.nuke import lib
|
||||||
|
from ...lib import BuildWorkfile
|
||||||
from pype.api import Logger
|
from pype.api import Logger
|
||||||
|
|
||||||
log = Logger().get_logger(__name__, "nuke")
|
log = Logger().get_logger(__name__, "nuke")
|
||||||
|
|
||||||
|
|
||||||
def install():
|
def install():
|
||||||
menubar = nuke.menu("Nuke")
|
menubar = nuke.menu("Nuke")
|
||||||
menu = menubar.findItem(Session["AVALON_LABEL"])
|
menu = menubar.findItem(Session["AVALON_LABEL"])
|
||||||
|
|
@ -20,7 +22,11 @@ def install():
|
||||||
log.debug("Changing Item: {}".format(rm_item))
|
log.debug("Changing Item: {}".format(rm_item))
|
||||||
# rm_item[1].setEnabled(False)
|
# rm_item[1].setEnabled(False)
|
||||||
menu.removeItem(rm_item[1].name())
|
menu.removeItem(rm_item[1].name())
|
||||||
menu.addCommand(new_name, lambda: workfile_settings().reset_resolution(), index=(rm_item[0]))
|
menu.addCommand(
|
||||||
|
new_name,
|
||||||
|
lambda: workfile_settings().reset_resolution(),
|
||||||
|
index=(rm_item[0])
|
||||||
|
)
|
||||||
|
|
||||||
# replace reset frame range from avalon core to pype's
|
# replace reset frame range from avalon core to pype's
|
||||||
name = "Reset Frame Range"
|
name = "Reset Frame Range"
|
||||||
|
|
@ -31,33 +37,38 @@ def install():
|
||||||
log.debug("Changing Item: {}".format(rm_item))
|
log.debug("Changing Item: {}".format(rm_item))
|
||||||
# rm_item[1].setEnabled(False)
|
# rm_item[1].setEnabled(False)
|
||||||
menu.removeItem(rm_item[1].name())
|
menu.removeItem(rm_item[1].name())
|
||||||
menu.addCommand(new_name, lambda: workfile_settings().reset_frame_range_handles(), index=(rm_item[0]))
|
menu.addCommand(
|
||||||
|
new_name,
|
||||||
|
lambda: workfile_settings().reset_frame_range_handles(),
|
||||||
|
index=(rm_item[0])
|
||||||
|
)
|
||||||
|
|
||||||
# add colorspace menu item
|
# add colorspace menu item
|
||||||
name = "Set colorspace"
|
name = "Set Colorspace"
|
||||||
menu.addCommand(
|
menu.addCommand(
|
||||||
name, lambda: workfile_settings().set_colorspace(),
|
name, lambda: workfile_settings().set_colorspace(),
|
||||||
index=(rm_item[0]+2)
|
index=(rm_item[0] + 2)
|
||||||
)
|
)
|
||||||
log.debug("Adding menu item: {}".format(name))
|
log.debug("Adding menu item: {}".format(name))
|
||||||
|
|
||||||
# add workfile builder menu item
|
# add workfile builder menu item
|
||||||
name = "Build First Workfile.."
|
name = "Build Workfile"
|
||||||
menu.addCommand(
|
menu.addCommand(
|
||||||
name, lambda: lib.BuildWorkfile().process(),
|
name, lambda: BuildWorkfile().process(),
|
||||||
index=(rm_item[0]+7)
|
index=(rm_item[0] + 7)
|
||||||
)
|
)
|
||||||
log.debug("Adding menu item: {}".format(name))
|
log.debug("Adding menu item: {}".format(name))
|
||||||
|
|
||||||
# add item that applies all setting above
|
# add item that applies all setting above
|
||||||
name = "Apply all settings"
|
name = "Apply All Settings"
|
||||||
menu.addCommand(
|
menu.addCommand(
|
||||||
name, lambda: workfile_settings().set_context_settings(), index=(rm_item[0]+3)
|
name,
|
||||||
|
lambda: workfile_settings().set_context_settings(),
|
||||||
|
index=(rm_item[0] + 3)
|
||||||
)
|
)
|
||||||
log.debug("Adding menu item: {}".format(name))
|
log.debug("Adding menu item: {}".format(name))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def uninstall():
|
def uninstall():
|
||||||
|
|
||||||
menubar = nuke.menu("Nuke")
|
menubar = nuke.menu("Nuke")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue