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

Royal Render: Maya and Nuke support #5191

Merged
merged 124 commits into from
Jul 17, 2023
Merged
Show file tree
Hide file tree
Changes from 250 commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
450c027
:construction: wip on maya royalrender submit plugin
antirotor Oct 26, 2022
635fe48
:recycle: move functions to common lib
antirotor Oct 26, 2022
3c026c3
:twisted_rightwards_arrows: Merge remote-tracking branch 'origin/deve…
antirotor Jan 11, 2023
aaafcd6
:construction: redoing publishing flow for multiple rr roots
antirotor Jan 11, 2023
0eb7da3
:recycle: optimizing enum classes
antirotor Jan 11, 2023
2cc688f
:construction: render job submission
antirotor Jan 16, 2023
b3b2667
:construction: refactor RR job flow
antirotor Jan 18, 2023
60eaf28
:bug: fix default for ShotGrid
antirotor Jan 18, 2023
b4f1574
:rotating_light: hound fixes
antirotor Jan 18, 2023
56f404e
:rotating_light: hound fixes 2
antirotor Jan 18, 2023
e079549
Merge branch 'develop' into feature/OP-3933_RR-support
antirotor Feb 6, 2023
ba1bb56
Merge remote-tracking branch 'origin/develop' into feature/OP-3933_RR…
antirotor Feb 6, 2023
61fe2ac
:construction: work on publish job
antirotor Feb 7, 2023
085d803
:construction: wip on maya royalrender submit plugin
antirotor Oct 26, 2022
77315d3
:recycle: move functions to common lib
antirotor Oct 26, 2022
ca552a7
:construction: redoing publishing flow for multiple rr roots
antirotor Jan 11, 2023
7e4b3cb
:recycle: optimizing enum classes
antirotor Jan 11, 2023
7d212c0
:construction: render job submission
antirotor Jan 16, 2023
7ab4e0f
:construction: refactor RR job flow
antirotor Jan 18, 2023
e49cbf3
:bug: fix default for ShotGrid
antirotor Jan 18, 2023
8ebef52
:rotating_light: hound fixes
antirotor Jan 18, 2023
5dda835
:rotating_light: hound fixes 2
antirotor Jan 18, 2023
cc8732a
:construction: work on publish job
antirotor Feb 7, 2023
5595712
:art: add cmd line arguments attribute to job
antirotor Mar 23, 2023
076e5c4
Merge remote-tracking branch 'origin/feature/OP-3933_RR-support' into…
antirotor Mar 23, 2023
4e14e0b
:art: add render configuration
antirotor Mar 24, 2023
f328c98
:heavy_minus_sign: remove old plugin
antirotor Mar 24, 2023
de5bca4
:art: add openpype version
antirotor Mar 24, 2023
226039f
:recycle: handling of jobs
antirotor Mar 24, 2023
03b3d2f
:art: better publish job render config
antirotor Mar 24, 2023
09876a6
Merge branch 'develop' into feature/OP-3933_RR-support
antirotor Mar 29, 2023
8adb053
:recycle: handle OP versions better
antirotor Mar 29, 2023
79a9deb
Merge remote-tracking branch 'origin/develop' into feature/OP-3933_RR…
antirotor Apr 13, 2023
547fe50
:rotating_light: fix hound :dog:
antirotor Apr 13, 2023
23f90ec
:construction: wip on skeleton instance
antirotor Apr 17, 2023
c9b6179
:construction: move common code out from deadline
antirotor Apr 21, 2023
7f588ee
:heavy_plus_sign: add mypy
antirotor Apr 21, 2023
2e2aaae
Merge remote-tracking branch 'origin/develop' into feature/OP-3933_RR…
antirotor Apr 28, 2023
3a91094
:art: update code from upstream
antirotor Apr 28, 2023
92bb47e
:art: add nuke job creator
antirotor Apr 28, 2023
1f0572a
:recycle: refactor deadline code to make use of abstracted code
antirotor Apr 28, 2023
806b925
Fix wrong family
kalisp May 3, 2023
ddab924
Extract iter_expected_files
kalisp May 3, 2023
7fe4820
Renamed file
kalisp May 3, 2023
266d34b
Fix querying anatomy
kalisp May 3, 2023
7913276
Fix typo, wrong parentheses
kalisp May 3, 2023
87eb1ed
Fix wrong method
kalisp May 3, 2023
c284908
Fix attr.s for Python2
kalisp May 3, 2023
1b4f452
Extracted prepare_representations
kalisp May 3, 2023
fb06a2e
Extracted create_metadata_path
kalisp May 4, 2023
dded3e1
Added missing variables
kalisp May 4, 2023
3bbab45
Removed usage of legacy_io
kalisp May 4, 2023
9a95fac
Changed to use os env OPENPYPE_VERSION
kalisp May 4, 2023
cace4f2
Used correct function
kalisp May 4, 2023
b18e6ad
Proper serialization
kalisp May 4, 2023
050c11e
Fix adding
kalisp May 4, 2023
c8451d1
Fix copy
kalisp May 4, 2023
ac02eac
Small fixes
kalisp May 4, 2023
4e455ea
Instance data might not contain "publish" key
kalisp May 5, 2023
8858c0c
Get proper rrPathName
kalisp May 5, 2023
d8e8e10
Remove unwanted logging code
kalisp May 9, 2023
45894da
Fix frame placeholder
kalisp May 9, 2023
97043fe
Use absolute path instead of rootless
kalisp May 9, 2023
07139db
Implemented waiting on job id
kalisp May 10, 2023
ddf0b3b
Added RequiredMemory
kalisp May 10, 2023
449157f
Fix executable placeholder
kalisp May 10, 2023
edcc1cc
Fix content of metadata file
kalisp May 10, 2023
0ad2e21
Add logging to log file
kalisp May 10, 2023
a10bf73
Fix batching of publish job
kalisp May 10, 2023
0a6fd30
Remove unneeded import
kalisp May 10, 2023
b001266
Clean up
kalisp May 10, 2023
540981d
Clean up
kalisp May 10, 2023
ddb227b
Remove unfinished file
kalisp May 10, 2023
f3ce4c6
Hound
kalisp May 10, 2023
36ef2b5
Hound
kalisp May 10, 2023
fe08d8d
Merge branch 'develop' into feature/OP-3933_RR-support
kalisp May 10, 2023
b654b10
Handle conflict with recent develop
kalisp May 11, 2023
c302b61
Removed _extend_frames
kalisp May 11, 2023
1aef4c5
Fix missing import
kalisp May 11, 2023
78f9a68
Fix aov handling
kalisp May 11, 2023
a4434d9
Fix adding review to families
kalisp May 11, 2023
d745ebc
Fix missing colorspaceTemplate key
kalisp May 11, 2023
162b58c
Fix access to anatomy
kalisp May 11, 2023
ad488c7
Fix use proper families
kalisp May 11, 2023
c1f3201
Fix use proper subset name
kalisp May 11, 2023
6df0fbc
OP-1066 - fix changed imports
kalisp May 12, 2023
2c3cd1c
OP-1066 - renamed file
kalisp May 12, 2023
86a1357
OP-1066 - sanitize version
kalisp May 12, 2023
226b088
Merge branch 'develop' into feature/OP-3933_RR-support
antirotor May 16, 2023
56f2edf
Add prerender family to collector for RR path
kalisp May 17, 2023
c83bc48
Merge remote-tracking branch 'origin/feature/OP-3933_RR-support' into…
kalisp May 18, 2023
f6118ed
Added docuumentation
kalisp May 18, 2023
81cca7f
Merge develop
kalisp May 30, 2023
694cec5
Merge remote-tracking branch 'origin/develop' into feature/OP-3933_RR…
antirotor Jun 5, 2023
d7fd9c8
:recycle: non-optional access to rep data
antirotor Jun 5, 2023
7053688
:bug: fix rendering from published file in Deadline
antirotor Jun 7, 2023
2851b32
:bug: fix collections
antirotor Jun 7, 2023
01b5e6b
OP-6037 - extracted generic logic from working Nuke implementation
kalisp Jun 9, 2023
644b734
OP-6037 - first iteration of Maya to RR
kalisp Jun 9, 2023
9cb1216
Resolved conflict
kalisp Jun 14, 2023
23c4a1d
Merge branch 'maya_new_publisher' of github.com:BigRoy/OpenPype into …
kalisp Jun 26, 2023
c83589b
Merge maya_new_publisher
kalisp Jun 26, 2023
6619be9
Fix append job
kalisp Jun 27, 2023
d6b0b9c
Remove outputDir
kalisp Jun 27, 2023
d0e1d5c
Fix cleanup of camera info
kalisp Jun 27, 2023
ec54515
Fix - correct resolution of published workile path
kalisp Jun 28, 2023
0df104b
Fix - proper padding of file name
kalisp Jun 28, 2023
4a672c5
Hound
kalisp Jun 28, 2023
307580f
Merge branch 'develop' into maye_new_publisher_with_RR
kalisp Jun 28, 2023
b24db55
Merge remote-tracking branch 'BigRoy/maya_new_publisher' into maye_ne…
kalisp Jul 3, 2023
a2cd44d
Merge branch 'maye_new_publisher_with_RR' of github.com:ynput/OpenPyp…
kalisp Jul 3, 2023
b9e362d
Fix - Nuke needs to have multiple jobs
kalisp Jul 3, 2023
614d600
Refactor - removed unnecessary variable
kalisp Jul 4, 2023
8754345
Fix - Nuke needs to have multiple jobs got accidentally reverted
kalisp Jul 4, 2023
708819f
Refactor - renamed replace_published_scene
Jul 5, 2023
26cd4f0
Hound
Jul 5, 2023
0134134
Merge branch 'develop' into maye_new_publisher_with_RR
kalisp Jul 10, 2023
892758b
Added missed colorspace injection for image sequences
kalisp Jul 12, 2023
681ff3a
Merge remote-tracking branch 'origin/maye_new_publisher_with_RR' into…
kalisp Jul 12, 2023
48f06ba
Fix - removed wrong argument
kalisp Jul 12, 2023
abc6a1e
Fix - context must be passe to set_representation_colorspace
kalisp Jul 12, 2023
7939836
Merge branch 'develop' into maye_new_publisher_with_RR
kalisp Jul 17, 2023
2be5b33
Fix wrong merge
kalisp Jul 17, 2023
b90d1c9
Fix wrong merge
kalisp Jul 17, 2023
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
6 changes: 3 additions & 3 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ body:
label: Version
description: What version are you running? Look to OpenPype Tray
options:
- 3.15.12-nightly.4
- 3.15.12-nightly.3
- 3.15.12-nightly.2
- 3.15.12-nightly.1
- 3.15.11
- 3.15.11-nightly.5
Expand Down Expand Up @@ -132,9 +135,6 @@ body:
- 3.14.5-nightly.1
- 3.14.4
- 3.14.4-nightly.4
- 3.14.4-nightly.3
- 3.14.4-nightly.2
- 3.14.4-nightly.1
validations:
required: true
- type: dropdown
Expand Down
12 changes: 5 additions & 7 deletions openpype/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ def wrapper(*args, **kwargs):


@deprecated("openpype.pipeline.publish.get_errored_instances_from_context")
def get_errored_instances_from_context(context):
def get_errored_instances_from_context(context, plugin=None):
"""
Deprecated:
Since 3.14.* will be removed in 3.16.* or later.
"""

from openpype.pipeline.publish import get_errored_instances_from_context

return get_errored_instances_from_context(context)
return get_errored_instances_from_context(context, plugin=plugin)


@deprecated("openpype.pipeline.publish.get_errored_plugins_from_context")
Expand Down Expand Up @@ -97,11 +97,9 @@ def process(self, context, plugin):

# Get the errored instances
self.log.info("Finding failed instances..")
errored_instances = get_errored_instances_from_context(context)

# Apply pyblish.logic to get the instances for the plug-in
instances = pyblish.api.instances_by_plugin(errored_instances, plugin)
for instance in instances:
errored_instances = get_errored_instances_from_context(context,
plugin=plugin)
for instance in errored_instances:
plugin.repair(instance)


Expand Down
6 changes: 3 additions & 3 deletions openpype/hosts/blender/api/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ class SelectInvalidAction(pyblish.api.Action):
icon = "search"

def process(self, context, plugin):
errored_instances = get_errored_instances_from_context(context)
instances = pyblish.api.instances_by_plugin(errored_instances, plugin)
errored_instances = get_errored_instances_from_context(context,
plugin=plugin)

# Get the invalid nodes for the plug-ins
self.log.info("Finding invalid nodes...")
invalid = list()
for instance in instances:
for instance in errored_instances:
invalid_nodes = plugin.get_invalid(instance)
if invalid_nodes:
if isinstance(invalid_nodes, (list, tuple)):
Expand Down
8 changes: 3 additions & 5 deletions openpype/hosts/fusion/api/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@ class SelectInvalidAction(pyblish.api.Action):
icon = "search" # Icon from Awesome Icon

def process(self, context, plugin):
errored_instances = get_errored_instances_from_context(context)

# Apply pyblish.logic to get the instances for the plug-in
instances = pyblish.api.instances_by_plugin(errored_instances, plugin)
errored_instances = get_errored_instances_from_context(context,
plugin=plugin)

# Get the invalid nodes for the plug-ins
self.log.info("Finding invalid nodes..")
invalid = list()
for instance in instances:
for instance in errored_instances:
invalid_nodes = plugin.get_invalid(instance)
if invalid_nodes:
if isinstance(invalid_nodes, (list, tuple)):
Expand Down
47 changes: 42 additions & 5 deletions openpype/hosts/houdini/api/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@ class SelectInvalidAction(pyblish.api.Action):

def process(self, context, plugin):

errored_instances = get_errored_instances_from_context(context)

# Apply pyblish.logic to get the instances for the plug-in
instances = pyblish.api.instances_by_plugin(errored_instances, plugin)
errored_instances = get_errored_instances_from_context(context,
plugin=plugin)

# Get the invalid nodes for the plug-ins
self.log.info("Finding invalid nodes..")
invalid = list()
for instance in instances:
for instance in errored_instances:
invalid_nodes = plugin.get_invalid(instance)
if invalid_nodes:
if isinstance(invalid_nodes, (list, tuple)):
Expand All @@ -44,3 +42,42 @@ def process(self, context, plugin):
node.setCurrent(True)
else:
self.log.info("No invalid nodes found.")


class SelectROPAction(pyblish.api.Action):
"""Select ROP.

It's used to select the associated ROPs with the errored instances.
"""

label = "Select ROP"
on = "failed" # This action is only available on a failed plug-in
icon = "mdi.cursor-default-click"

def process(self, context, plugin):
errored_instances = get_errored_instances_from_context(context, plugin)

# Get the invalid nodes for the plug-ins
self.log.info("Finding ROP nodes..")
rop_nodes = list()
for instance in errored_instances:
node_path = instance.data.get("instance_node")
if not node_path:
continue

node = hou.node(node_path)
if not node:
continue

rop_nodes.append(node)

hou.clearAllSelected()
if rop_nodes:
self.log.info("Selecting ROP nodes: {}".format(
", ".join(node.path() for node in rop_nodes)
))
for node in rop_nodes:
node.setSelected(True)
node.setCurrent(True)
else:
self.log.info("No ROP nodes found.")
23 changes: 4 additions & 19 deletions openpype/hosts/houdini/api/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,23 +633,8 @@ def replace(match):

def get_color_management_preferences():
"""Get default OCIO preferences"""
data = {
"config": hou.Color.ocio_configPath()

return {
"config": hou.Color.ocio_configPath(),
"display": hou.Color.ocio_defaultDisplay(),
"view": hou.Color.ocio_defaultView()
}

# Get default display and view from OCIO
display = hou.Color.ocio_defaultDisplay()
disp_regex = re.compile(r"^(?P<name>.+-)(?P<display>.+)$")
disp_match = disp_regex.match(display)

view = hou.Color.ocio_defaultView()
view_regex = re.compile(r"^(?P<name>.+- )(?P<view>.+)$")
view_match = view_regex.match(view)
data.update({
"display": disp_match.group("display"),
"view": view_match.group("view")

})

return data
2 changes: 1 addition & 1 deletion openpype/hosts/houdini/api/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def install(self):
import hdefereval # noqa, hdefereval is only available in ui mode
hdefereval.executeDeferred(creator_node_shelves.install)

def has_unsaved_changes(self):
def workfile_has_unsaved_changes(self):
return hou.hipFile.hasUnsavedChanges()

def get_workfile_extensions(self):
Expand Down
68 changes: 58 additions & 10 deletions openpype/hosts/houdini/plugins/create/create_pointcache.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
"""Creator plugin for creating pointcache alembics."""
from openpype.hosts.houdini.api import plugin
from openpype.pipeline import CreatedInstance

import hou

Expand All @@ -14,15 +13,13 @@ class CreatePointCache(plugin.HoudiniCreator):
icon = "gears"

def create(self, subset_name, instance_data, pre_create_data):
import hou

instance_data.pop("active", None)
instance_data.update({"node_type": "alembic"})

instance = super(CreatePointCache, self).create(
subset_name,
instance_data,
pre_create_data) # type: CreatedInstance
pre_create_data)

instance_node = hou.node(instance.get("instance_node"))
parms = {
Expand All @@ -37,13 +34,44 @@ def create(self, subset_name, instance_data, pre_create_data):
}

if self.selected_nodes:
parms["sop_path"] = self.selected_nodes[0].path()
selected_node = self.selected_nodes[0]

# Although Houdini allows ObjNode path on `sop_path` for the
# the ROP node we prefer it set to the SopNode path explicitly

# Allow sop level paths (e.g. /obj/geo1/box1)
if isinstance(selected_node, hou.SopNode):
parms["sop_path"] = selected_node.path()
self.log.debug(
"Valid SopNode selection, 'SOP Path' in ROP will be set to '%s'."
% selected_node.path()
)

# Allow object level paths to Geometry nodes (e.g. /obj/geo1)
# but do not allow other object level nodes types like cameras, etc.
elif isinstance(selected_node, hou.ObjNode) and \
selected_node.type().name() in ["geo"]:

# get the output node with the minimum
# 'outputidx' or the node with display flag
sop_path = self.get_obj_output(selected_node)

if sop_path:
parms["sop_path"] = sop_path.path()
self.log.debug(
"Valid ObjNode selection, 'SOP Path' in ROP will be set to "
"the child path '%s'."
% sop_path.path()
)

# try to find output node
for child in self.selected_nodes[0].children():
if child.type().name() == "output":
parms["sop_path"] = child.path()
break
if not parms.get("sop_path", None):
self.log.debug(
"Selection isn't valid. 'SOP Path' in ROP will be empty."
)
else:
self.log.debug(
"No Selection. 'SOP Path' in ROP will be empty."
)

instance_node.setParms(parms)
instance_node.parm("trange").set(1)
Expand All @@ -57,3 +85,23 @@ def get_network_categories(self):
hou.ropNodeTypeCategory(),
hou.sopNodeTypeCategory()
]

def get_obj_output(self, obj_node):
"""Find output node with the smallest 'outputidx'."""

outputs = obj_node.subnetOutputs()

# if obj_node is empty
if not outputs:
return

# if obj_node has one output child whether its
# sop output node or a node with the render flag
elif len(outputs) == 1:
return outputs[0]

# if there are more than one, then it have multiple ouput nodes
# return the one with the minimum 'outputidx'
else:
return min(outputs,
key=lambda node: node.evalParm('outputidx'))
2 changes: 1 addition & 1 deletion openpype/hosts/houdini/plugins/publish/save_scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def process(self, context):
"Collected filename from current scene name."
)

if host.has_unsaved_changes():
if host.workfile_has_unsaved_changes():
self.log.info("Saving current file: {}".format(current_file))
host.save_workfile(current_file)
else:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ def get_invalid(cls, instance):
cls.log.debug("Checking Primitive to Detail pattern: %s" % pattern)
cls.log.debug("Checking with path attribute: %s" % path_attr)

if not hasattr(output_node, "geometry"):
# In the case someone has explicitly set an Object
# node instead of a SOP node in Geometry context
# then for now we ignore - this allows us to also
# export object transforms.
cls.log.warning("No geometry output node found, skipping check..")
return

# Check if the primitive attribute exists
frame = instance.data.get("frameStart", 0)
geo = output_node.geometryAtFrame(frame)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ def get_invalid(cls, instance):

cls.log.debug("Checking for attribute: %s" % path_attr)

if not hasattr(output_node, "geometry"):
# In the case someone has explicitly set an Object
# node instead of a SOP node in Geometry context
# then for now we ignore - this allows us to also
# export object transforms.
cls.log.warning("No geometry output node found, skipping check..")
return

# Check if the primitive attribute exists
frame = instance.data.get("frameStart", 0)
geo = output_node.geometryAtFrame(frame)
Expand Down
18 changes: 11 additions & 7 deletions openpype/hosts/houdini/plugins/publish/validate_sop_output_node.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# -*- coding: utf-8 -*-
import pyblish.api
from openpype.pipeline import PublishValidationError
from openpype.hosts.houdini.api.action import (
SelectInvalidAction,
SelectROPAction,
)

import hou


class ValidateSopOutputNode(pyblish.api.InstancePlugin):
Expand All @@ -19,6 +25,7 @@ class ValidateSopOutputNode(pyblish.api.InstancePlugin):
families = ["pointcache", "vdbcache"]
hosts = ["houdini"]
label = "Validate Output Node"
actions = [SelectROPAction, SelectInvalidAction]

def process(self, instance):

Expand All @@ -31,9 +38,6 @@ def process(self, instance):

@classmethod
def get_invalid(cls, instance):

import hou

output_node = instance.data.get("output_node")

if output_node is None:
Expand All @@ -43,7 +47,7 @@ def get_invalid(cls, instance):
"Ensure a valid SOP output path is set." % node.path()
)

return [node.path()]
return [node]

# Output node must be a Sop node.
if not isinstance(output_node, hou.SopNode):
Expand All @@ -53,7 +57,7 @@ def get_invalid(cls, instance):
"instead found category type: %s"
% (output_node.path(), output_node.type().category().name())
)
return [output_node.path()]
return [output_node]

# For the sake of completeness also assert the category type
# is Sop to avoid potential edge case scenarios even though
Expand All @@ -73,11 +77,11 @@ def get_invalid(cls, instance):
except hou.Error as exc:
cls.log.error("Cook failed: %s" % exc)
cls.log.error(output_node.errors()[0])
return [output_node.path()]
return [output_node]

# Ensure the output node has at least Geometry data
if not output_node.geometry():
cls.log.error(
"Output node `%s` has no geometry data." % output_node.path()
)
return [output_node.path()]
return [output_node]
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ def update_mode_context(mode):

def get_geometry_at_frame(sop_node, frame, force=True):
"""Return geometry at frame but force a cooked value."""
if not hasattr(sop_node, "geometry"):
return
with update_mode_context(hou.updateMode.AutoUpdate):
sop_node.cook(force=force, frame_range=(frame, frame))
return sop_node.geometryAtFrame(frame)
Expand Down
Loading