Merge branch 'develop' into enhancement/OP-8268_AOV-filter-for-Ftrack-family

This commit is contained in:
Kayla Man 2024-02-22 17:23:23 +08:00 committed by GitHub
commit 9a6bb10f33
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 690 additions and 225 deletions

View file

@ -35,6 +35,9 @@ body:
label: Version
description: What version are you running? Look to OpenPype Tray
options:
- 3.18.8-nightly.1
- 3.18.7
- 3.18.7-nightly.5
- 3.18.7-nightly.4
- 3.18.7-nightly.3
- 3.18.7-nightly.2
@ -132,9 +135,6 @@ body:
- 3.15.11-nightly.3
- 3.15.11-nightly.2
- 3.15.11-nightly.1
- 3.15.10
- 3.15.10-nightly.2
- 3.15.10-nightly.1
validations:
required: true
- type: dropdown

View file

@ -1,6 +1,407 @@
# Changelog
## [3.18.7](https://github.com/ynput/OpenPype/tree/3.18.7)
[Full Changelog](https://github.com/ynput/OpenPype/compare/3.18.6...3.18.7)
### **🆕 New features**
<details>
<summary>Chore: Wrapper for click proposal <a href="https://github.com/ynput/OpenPype/pull/5928">#5928</a></summary>
This is a proposal how to resolve issues with `click` python module. Issue https://github.com/ynput/OpenPype/issues/5921 reported that in Houdini 20+ is our click clashing with click in houdini, where is expected higher version. We can't update our version to support older pythons (NOTE older Python 3).
___
</details>
### **🚀 Enhancements**
<details>
<summary>Maya: Add repair action to hidden joints validator <a href="https://github.com/ynput/OpenPype/pull/6214">#6214</a></summary>
Joints Hidden is missing repair action, this adds it back
___
</details>
<details>
<summary>Blender: output node and EXR <a href="https://github.com/ynput/OpenPype/pull/6086">#6086</a></summary>
Output node now works correctly for Multilayer EXR and keeps existing links. The output now is handled entirely by the compositor node tree.
___
</details>
<details>
<summary>AYON Switch tool: Keep version after switch <a href="https://github.com/ynput/OpenPype/pull/6104">#6104</a></summary>
Keep version if only representation did change. The AYON variant of https://github.com/ynput/OpenPype/pull/4629
___
</details>
<details>
<summary>Loader AYON: Reset loader window on open <a href="https://github.com/ynput/OpenPype/pull/6170">#6170</a></summary>
Make sure loader tool is reset on each show.
___
</details>
<details>
<summary>Publisher: Show message with error on action failure <a href="https://github.com/ynput/OpenPype/pull/6179">#6179</a></summary>
This PR adds support for the publisher to show error message from running actions.Errors from actions will otherwise be hidden from user in various console outputs.Also include card for when action is finished.
___
</details>
<details>
<summary>AYON Applications: Remove djvview group from default applications <a href="https://github.com/ynput/OpenPype/pull/6188">#6188</a></summary>
The djv does not have group defined in models so the values are not used anywhere.
___
</details>
<details>
<summary>General: added fallback for broken ffprobe return <a href="https://github.com/ynput/OpenPype/pull/6189">#6189</a></summary>
Customer provided .exr returned width and height equal to 0 which caused error in `extract_thumbnail`. This tries to use oiiotool to get metadata about file, in our case it read it correctly.
___
</details>
<details>
<summary>Photoshop: High scaling in UIs <a href="https://github.com/ynput/OpenPype/pull/6190">#6190</a></summary>
Use `get_openpype_qt_app` to create `QApplication` in Photoshop.
___
</details>
<details>
<summary>Ftrack: Status update settings are not case insensitive. <a href="https://github.com/ynput/OpenPype/pull/6195">#6195</a></summary>
Make values for project_settings/ftrack/events/status_update case insensitive.
___
</details>
<details>
<summary>Thumbnail product filtering <a href="https://github.com/ynput/OpenPype/pull/6197">#6197</a></summary>
This PR introduces subset filtering for thumbnail extraction. This is to skip passes like zdepth which is not needed and can cause issues with extraction. Also speeds up publishing.
___
</details>
<details>
<summary>TimersManager: Idle dialog always on top <a href="https://github.com/ynput/OpenPype/pull/6201">#6201</a></summary>
Make stop timer dialog always on tophttps://app.clickup.com/t/6658547/OP-8033
___
</details>
<details>
<summary>AfterEffects: added toggle for applying values from DB during creation <a href="https://github.com/ynput/OpenPype/pull/6204">#6204</a></summary>
Previously values (resolution, duration) from Asset (eg. DB) were applied explicitly when instance of `render` product type was created. This PR adds toggle to Settings to disable this. (This allows artist to publish non standard length of composition, disabling of `Validate Scene Settings` is still required.)
___
</details>
<details>
<summary>Unreal: Update plugin commit <a href="https://github.com/ynput/OpenPype/pull/6208">#6208</a></summary>
Updated unreal plugin to latest main.
___
</details>
### **🐛 Bug fixes**
<details>
<summary>Traypublisher: editorial avoid audio tracks processing <a href="https://github.com/ynput/OpenPype/pull/6038">#6038</a></summary>
Avoiding audio tracks from EDL editorial publishing.
___
</details>
<details>
<summary>Resolve Inventory offsets clips when swapping versions <a href="https://github.com/ynput/OpenPype/pull/6128">#6128</a></summary>
Swapped version retain the offset and IDT of the timelime clip.closes: https://github.com/ynput/OpenPype/issues/6125
___
</details>
<details>
<summary>Publisher window as dialog <a href="https://github.com/ynput/OpenPype/pull/6176">#6176</a></summary>
Changing back Publisher window to QDialog.
___
</details>
<details>
<summary>Nuke: Validate write node fix error report - OP-8088 <a href="https://github.com/ynput/OpenPype/pull/6183">#6183</a></summary>
Report error was not printing the expected values from settings, but instead the values on the write node, leading to confusing messages like:
```
Traceback (most recent call last):
File "C:\Users\tokejepsen\AppData\Local\Ynput\AYON\dependency_packages\ayon_2310271602_windows.zip\dependencies\pyblish\plugin.py", line 527, in __explicit_process
runner(*args)
File "C:\Users\tokejepsen\OpenPype\openpype\hosts\nuke\plugins\publish\validate_write_nodes.py", line 135, in process
self._make_error(check)
File "C:\Users\tokejepsen\OpenPype\openpype\hosts\nuke\plugins\publish\validate_write_nodes.py", line 149, in _make_error
raise PublishXmlValidationError(
openpype.pipeline.publish.publish_plugins.PublishXmlValidationError: Write node's knobs values are not correct!
Knob 'channels' > Correct: `rgb` > Wrong: `rgb`
```
This PR changes the error report to:
```
Traceback (most recent call last):
File "C:\Users\tokejepsen\AppData\Local\Ynput\AYON\dependency_packages\ayon_2310271602_windows.zip\dependencies\pyblish\plugin.py", line 527, in __explicit_process
runner(*args)
File "C:\Users\tokejepsen\OpenPype\openpype\hosts\nuke\plugins\publish\validate_write_nodes.py", line 135, in process
self._make_error(check)
File "C:\Users\tokejepsen\OpenPype\openpype\hosts\nuke\plugins\publish\validate_write_nodes.py", line 149, in _make_error
raise PublishXmlValidationError(
openpype.pipeline.publish.publish_plugins.PublishXmlValidationError: Write node's knobs values are not correct!
Knob 'channels' > Expected: `['rg']` > Current: `rgb`
```
___
</details>
<details>
<summary>Nuke: Camera product type loaded is not updating - OP-7973 <a href="https://github.com/ynput/OpenPype/pull/6184">#6184</a></summary>
When updating the camera this error would appear:
```
(...)openpype/hosts/nuke/plugins/load/load_camera_abc.py", line 142, in update
camera_node = nuke.toNode(object_name)
TypeError: toNode() argument 1 must be str, not Node
```
___
</details>
<details>
<summary>AYON settings: Use bundle name as variant in dev mode <a href="https://github.com/ynput/OpenPype/pull/6187">#6187</a></summary>
Make sure the bundle name is used in dev mode for settings variant.
___
</details>
<details>
<summary>Fusion: fix unwanted change to field name in Settings <a href="https://github.com/ynput/OpenPype/pull/6193">#6193</a></summary>
It should be `image_format` but in previous refactoring PR it fell back to original `output_formats` which caused enum not to show up and propagate into plugin.
___
</details>
<details>
<summary>Bugfix: AYON menu disappeared when the workspace has been changed in 3dsMax <a href="https://github.com/ynput/OpenPype/pull/6200">#6200</a></summary>
AYON plugins are not correctly registered when switching to different workspaces.
___
</details>
<details>
<summary>TrayPublisher: adding settings category to base creator classes <a href="https://github.com/ynput/OpenPype/pull/6202">#6202</a></summary>
Settings are resolving correctly as they suppose to.
___
</details>
<details>
<summary>Nuke: expose knobs backward compatibility fix - OP-8164 <a href="https://github.com/ynput/OpenPype/pull/6211">#6211</a></summary>
Fix backwards compatibility for settings `project_settings/nuke/create/CreateWriteRender/exposed_knobs`.
___
</details>
<details>
<summary>AE: fix local render doesn't push thumbnail to Ftrack <a href="https://github.com/ynput/OpenPype/pull/6212">#6212</a></summary>
Without thumbnail review is not clickable from main Versions list
___
</details>
<details>
<summary>Nuke: openpype expose knobs validator - OP-8166 <a href="https://github.com/ynput/OpenPype/pull/6213">#6213</a></summary>
Fix exposed knobs validator for backwards compatibility with missing settings.
___
</details>
<details>
<summary>Ftrack: Post-launch hook fix value lowering <a href="https://github.com/ynput/OpenPype/pull/6221">#6221</a></summary>
Fix lowerin of values in status mapping.
___
</details>
### **🔀 Refactored code**
<details>
<summary>Maya: Remove `shelf` class and shelf build on maya `userSetup.py` <a href="https://github.com/ynput/OpenPype/pull/5837">#5837</a></summary>
Remove shelf builder logic. It appeared to be unused and had bugs.
___
</details>
### **Merged pull requests**
<details>
<summary>Max: updated implementation of save_scene + small QOL improvements to host <a href="https://github.com/ynput/OpenPype/pull/6186">#6186</a></summary>
- Removed `has_unsaved_changes` from Max host as it looks to have been unused and unimplemented.
- Added and implemented `workfile_has_unsaved_changes` to Max host.
- Mirrored the Houdini host to implement the above into `save_scene` publish for Max.
- Added a line to `startup.ms` which opens the usual 'default' menu inside of Max (see screenshots).Current (Likely opens this menu due to one or more of the startup scripts used to insert OP menu):New:
___
</details>
<details>
<summary>Fusion: Use better resolution of Ayon apps on 4k display <a href="https://github.com/ynput/OpenPype/pull/6199">#6199</a></summary>
Changes size (makes it smaller) of Ayon apps (Workfiles, Loader) in Fusion on high definitions displays.
___
</details>
<details>
<summary>Update CONTRIBUTING.md <a href="https://github.com/ynput/OpenPype/pull/6210">#6210</a></summary>
Updating contributing guidelines to reflect the EOL state of repository
___
</details>
<details>
<summary>Deadline: Remove redundant instance_skeleton_data code - OP-8269 <a href="https://github.com/ynput/OpenPype/pull/6219">#6219</a></summary>
This PR https://github.com/ynput/OpenPype/pull/5186 re-introduced code about for the `instance_skeleton_data` but its actually not used since this variable gets overwritten later.
___
</details>
## [3.18.6](https://github.com/ynput/OpenPype/tree/3.18.6)

View file

@ -2,6 +2,7 @@ from pathlib import Path
import bpy
from openpype import AYON_SERVER_ENABLED
from openpype.settings import get_project_settings
from openpype.pipeline import get_current_project_name
@ -47,6 +48,22 @@ def get_multilayer(settings):
["multilayer_exr"])
def get_renderer(settings):
"""Get renderer from blender settings."""
return (settings["blender"]
["RenderSettings"]
["renderer"])
def get_compositing(settings):
"""Get compositing from blender settings."""
return (settings["blender"]
["RenderSettings"]
["compositing"])
def get_render_product(output_path, name, aov_sep):
"""
Generate the path to the render product. Blender interprets the `#`
@ -91,66 +108,121 @@ def set_render_format(ext, multilayer):
image_settings.file_format = "TIFF"
def set_render_passes(settings):
aov_list = (settings["blender"]
["RenderSettings"]
["aov_list"])
custom_passes = (settings["blender"]
["RenderSettings"]
["custom_passes"])
def set_render_passes(settings, renderer):
aov_list = set(settings["blender"]["RenderSettings"]["aov_list"])
custom_passes = settings["blender"]["RenderSettings"]["custom_passes"]
# Common passes for both renderers
vl = bpy.context.view_layer
# Data Passes
vl.use_pass_combined = "combined" in aov_list
vl.use_pass_z = "z" in aov_list
vl.use_pass_mist = "mist" in aov_list
vl.use_pass_normal = "normal" in aov_list
# Light Passes
vl.use_pass_diffuse_direct = "diffuse_light" in aov_list
vl.use_pass_diffuse_color = "diffuse_color" in aov_list
vl.use_pass_glossy_direct = "specular_light" in aov_list
vl.use_pass_glossy_color = "specular_color" in aov_list
vl.eevee.use_pass_volume_direct = "volume_light" in aov_list
vl.use_pass_emit = "emission" in aov_list
vl.use_pass_environment = "environment" in aov_list
vl.use_pass_shadow = "shadow" in aov_list
vl.use_pass_ambient_occlusion = "ao" in aov_list
cycles = vl.cycles
# Cryptomatte Passes
vl.use_pass_cryptomatte_object = "cryptomatte_object" in aov_list
vl.use_pass_cryptomatte_material = "cryptomatte_material" in aov_list
vl.use_pass_cryptomatte_asset = "cryptomatte_asset" in aov_list
cycles.denoising_store_passes = "denoising" in aov_list
cycles.use_pass_volume_direct = "volume_direct" in aov_list
cycles.use_pass_volume_indirect = "volume_indirect" in aov_list
if renderer == "BLENDER_EEVEE":
# Eevee exclusive passes
eevee = vl.eevee
# Light Passes
vl.use_pass_shadow = "shadow" in aov_list
eevee.use_pass_volume_direct = "volume_light" in aov_list
# Effects Passes
eevee.use_pass_bloom = "bloom" in aov_list
eevee.use_pass_transparent = "transparent" in aov_list
# Cryptomatte Passes
vl.use_pass_cryptomatte_accurate = "cryptomatte_accurate" in aov_list
elif renderer == "CYCLES":
# Cycles exclusive passes
cycles = vl.cycles
# Data Passes
vl.use_pass_position = "position" in aov_list
vl.use_pass_vector = "vector" in aov_list
vl.use_pass_uv = "uv" in aov_list
cycles.denoising_store_passes = "denoising" in aov_list
vl.use_pass_object_index = "object_index" in aov_list
vl.use_pass_material_index = "material_index" in aov_list
cycles.pass_debug_sample_count = "sample_count" in aov_list
# Light Passes
vl.use_pass_diffuse_indirect = "diffuse_indirect" in aov_list
vl.use_pass_glossy_indirect = "specular_indirect" in aov_list
vl.use_pass_transmission_direct = "transmission_direct" in aov_list
vl.use_pass_transmission_indirect = "transmission_indirect" in aov_list
vl.use_pass_transmission_color = "transmission_color" in aov_list
cycles.use_pass_volume_direct = "volume_light" in aov_list
cycles.use_pass_volume_indirect = "volume_indirect" in aov_list
cycles.use_pass_shadow_catcher = "shadow" in aov_list
aovs_names = [aov.name for aov in vl.aovs]
for cp in custom_passes:
cp_name = cp[0]
cp_name = cp["attribute"] if AYON_SERVER_ENABLED else cp[0]
if cp_name not in aovs_names:
aov = vl.aovs.add()
aov.name = cp_name
else:
aov = vl.aovs[cp_name]
aov.type = cp[1].get("type", "VALUE")
aov.type = (cp["value"]
if AYON_SERVER_ENABLED else cp[1].get("type", "VALUE"))
return aov_list, custom_passes
return list(aov_list), custom_passes
def set_node_tree(output_path, name, aov_sep, ext, multilayer):
def _create_aov_slot(name, aov_sep, slots, rpass_name, multi_exr, output_path):
filename = f"{name}{aov_sep}{rpass_name}.####"
slot = slots.new(rpass_name if multi_exr else filename)
filepath = str(output_path / filename.lstrip("/"))
return slot, filepath
def set_node_tree(
output_path, render_product, name, aov_sep, ext, multilayer, compositing
):
# Set the scene to use the compositor node tree to render
bpy.context.scene.use_nodes = True
tree = bpy.context.scene.node_tree
# Get the Render Layers node
rl_node = None
comp_layer_type = "CompositorNodeRLayers"
output_type = "CompositorNodeOutputFile"
compositor_type = "CompositorNodeComposite"
# Get the Render Layer, Composite and the previous output nodes
render_layer_node = None
composite_node = None
old_output_node = None
for node in tree.nodes:
if node.bl_idname == "CompositorNodeRLayers":
rl_node = node
if node.bl_idname == comp_layer_type:
render_layer_node = node
elif node.bl_idname == compositor_type:
composite_node = node
elif node.bl_idname == output_type and "AYON" in node.name:
old_output_node = node
if render_layer_node and composite_node and old_output_node:
break
# If there's not a Render Layers node, we create it
if not rl_node:
rl_node = tree.nodes.new("CompositorNodeRLayers")
if not render_layer_node:
render_layer_node = tree.nodes.new(comp_layer_type)
# Get the enabled output sockets, that are the active passes for the
# render.
@ -158,48 +230,81 @@ def set_node_tree(output_path, name, aov_sep, ext, multilayer):
exclude_sockets = ["Image", "Alpha", "Noisy Image"]
passes = [
socket
for socket in rl_node.outputs
for socket in render_layer_node.outputs
if socket.enabled and socket.name not in exclude_sockets
]
# Remove all output nodes
for node in tree.nodes:
if node.bl_idname == "CompositorNodeOutputFile":
tree.nodes.remove(node)
# Create a new output node
output = tree.nodes.new("CompositorNodeOutputFile")
output = tree.nodes.new(output_type)
image_settings = bpy.context.scene.render.image_settings
output.format.file_format = image_settings.file_format
slots = None
# In case of a multilayer exr, we don't need to use the output node,
# because the blender render already outputs a multilayer exr.
if ext == "exr" and multilayer:
output.layer_slots.clear()
return []
multi_exr = ext == "exr" and multilayer
slots = output.layer_slots if multi_exr else output.file_slots
output.base_path = render_product if multi_exr else str(output_path)
output.file_slots.clear()
output.base_path = str(output_path)
slots.clear()
aov_file_products = []
old_links = {
link.from_socket.name: link for link in tree.links
if link.to_node == old_output_node}
# Create a new socket for the beauty output
pass_name = "rgba" if multi_exr else "beauty"
slot, _ = _create_aov_slot(
name, aov_sep, slots, pass_name, multi_exr, output_path)
tree.links.new(render_layer_node.outputs["Image"], slot)
if compositing:
# Create a new socket for the composite output
pass_name = "composite"
comp_socket, filepath = _create_aov_slot(
name, aov_sep, slots, pass_name, multi_exr, output_path)
aov_file_products.append(("Composite", filepath))
# For each active render pass, we add a new socket to the output node
# and link it
for render_pass in passes:
filepath = f"{name}{aov_sep}{render_pass.name}.####"
for rpass in passes:
slot, filepath = _create_aov_slot(
name, aov_sep, slots, rpass.name, multi_exr, output_path)
aov_file_products.append((rpass.name, filepath))
output.file_slots.new(filepath)
# If the rpass was not connected with the old output node, we connect
# it with the new one.
if not old_links.get(rpass.name):
tree.links.new(rpass, slot)
filename = str(output_path / filepath.lstrip("/"))
for link in list(old_links.values()):
# Check if the socket is still available in the new output node.
socket = output.inputs.get(link.to_socket.name)
# If it is, we connect it with the new output node.
if socket:
tree.links.new(link.from_socket, socket)
# Then, we remove the old link.
tree.links.remove(link)
aov_file_products.append((render_pass.name, filename))
# If there's a composite node, we connect its input with the new output
if compositing and composite_node:
for link in tree.links:
if link.to_node == composite_node:
tree.links.new(link.from_socket, comp_socket)
break
node_input = output.inputs[-1]
if old_output_node:
output.location = old_output_node.location
tree.nodes.remove(old_output_node)
tree.links.new(render_pass, node_input)
output.name = "AYON File Output"
output.label = "AYON File Output"
return aov_file_products
return [] if multi_exr else aov_file_products
def imprint_render_settings(node, data):
@ -228,17 +333,23 @@ def prepare_rendering(asset_group):
aov_sep = get_aov_separator(settings)
ext = get_image_format(settings)
multilayer = get_multilayer(settings)
renderer = get_renderer(settings)
compositing = get_compositing(settings)
set_render_format(ext, multilayer)
aov_list, custom_passes = set_render_passes(settings)
bpy.context.scene.render.engine = renderer
aov_list, custom_passes = set_render_passes(settings, renderer)
output_path = Path.joinpath(dirpath, render_folder, file_name)
render_product = get_render_product(output_path, name, aov_sep)
aov_file_product = set_node_tree(
output_path, name, aov_sep, ext, multilayer)
output_path, render_product, name, aov_sep,
ext, multilayer, compositing)
bpy.context.scene.render.filepath = render_product
# Clear the render filepath, so that the output is handled only by the
# output node in the compositor.
bpy.context.scene.render.filepath = ""
render_settings = {
"render_folder": render_folder,

View file

@ -1,8 +1,10 @@
"""Create render."""
import bpy
from openpype.lib import version_up
from openpype.hosts.blender.api import plugin
from openpype.hosts.blender.api.render_lib import prepare_rendering
from openpype.hosts.blender.api.workio import save_file
class CreateRenderlayer(plugin.BaseCreator):
@ -37,6 +39,7 @@ class CreateRenderlayer(plugin.BaseCreator):
# settings. Even the validator to check that the file is saved will
# detect the file as saved, even if it isn't. The only solution for
# now it is to force the file to be saved.
bpy.ops.wm.save_as_mainfile(filepath=bpy.data.filepath)
filepath = version_up(bpy.data.filepath)
save_file(filepath, copy=False)
return collection

View file

@ -28,15 +28,27 @@ class ValidateDeadlinePublish(pyblish.api.InstancePlugin,
def process(self, instance):
if not self.is_active(instance.data):
return
tree = bpy.context.scene.node_tree
output_type = "CompositorNodeOutputFile"
output_node = None
# Remove all output nodes that inlcude "AYON" in the name.
# There should be only one.
for node in tree.nodes:
if node.bl_idname == output_type and "AYON" in node.name:
output_node = node
break
if not output_node:
raise PublishValidationError(
"No output node found in the compositor tree."
)
filepath = bpy.data.filepath
file = os.path.basename(filepath)
filename, ext = os.path.splitext(file)
if filename not in bpy.context.scene.render.filepath:
if filename not in output_node.base_path:
raise PublishValidationError(
"Render output folder "
"doesn't match the blender scene name! "
"Use Repair action to "
"fix the folder file path."
"Render output folder doesn't match the blender scene name! "
"Use Repair action to fix the folder file path."
)
@classmethod

View file

@ -321,7 +321,6 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin,
return deadline_publish_job_id
def process(self, instance):
# type: (pyblish.api.Instance) -> None
"""Process plugin.
@ -338,151 +337,6 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin,
self.log.debug("Skipping local instance.")
return
data = instance.data.copy()
context = instance.context
self.context = context
self.anatomy = instance.context.data["anatomy"]
asset = data.get("asset") or context.data["asset"]
subset = data.get("subset")
start = instance.data.get("frameStart")
if start is None:
start = context.data["frameStart"]
end = instance.data.get("frameEnd")
if end is None:
end = context.data["frameEnd"]
handle_start = instance.data.get("handleStart")
if handle_start is None:
handle_start = context.data["handleStart"]
handle_end = instance.data.get("handleEnd")
if handle_end is None:
handle_end = context.data["handleEnd"]
fps = instance.data.get("fps")
if fps is None:
fps = context.data["fps"]
if data.get("extendFrames", False):
start, end = self._extend_frames(
asset,
subset,
start,
end,
data["overrideExistingFrame"])
try:
source = data["source"]
except KeyError:
source = context.data["currentFile"]
success, rootless_path = (
self.anatomy.find_root_template_from_path(source)
)
if success:
source = rootless_path
else:
# `rootless_path` is not set to `source` if none of roots match
self.log.warning((
"Could not find root path for remapping \"{}\"."
" This may cause issues."
).format(source))
family = "render"
if ("prerender" in instance.data["families"] or
"prerender.farm" in instance.data["families"]):
family = "prerender"
families = [family]
# pass review to families if marked as review
do_not_add_review = False
if data.get("review"):
families.append("review")
elif data.get("review") is False:
self.log.debug("Instance has review explicitly disabled.")
do_not_add_review = True
instance_skeleton_data = {
"family": family,
"subset": subset,
"families": families,
"asset": asset,
"frameStart": start,
"frameEnd": end,
"handleStart": handle_start,
"handleEnd": handle_end,
"frameStartHandle": start - handle_start,
"frameEndHandle": end + handle_end,
"comment": instance.data["comment"],
"fps": fps,
"source": source,
"extendFrames": data.get("extendFrames"),
"overrideExistingFrame": data.get("overrideExistingFrame"),
"pixelAspect": data.get("pixelAspect", 1),
"resolutionWidth": data.get("resolutionWidth", 1920),
"resolutionHeight": data.get("resolutionHeight", 1080),
"multipartExr": data.get("multipartExr", False),
"jobBatchName": data.get("jobBatchName", ""),
"useSequenceForReview": data.get("useSequenceForReview", True),
# map inputVersions `ObjectId` -> `str` so json supports it
"inputVersions": list(map(str, data.get("inputVersions", []))),
"colorspace": instance.data.get("colorspace"),
"stagingDir_persistent": instance.data.get(
"stagingDir_persistent", False
)
}
# skip locking version if we are creating v01
instance_version = instance.data.get("version") # take this if exists
if instance_version != 1:
instance_skeleton_data["version"] = instance_version
# transfer specific families from original instance to new render
for item in self.families_transfer:
if item in instance.data.get("families", []):
instance_skeleton_data["families"] += [item]
# transfer specific properties from original instance based on
# mapping dictionary `instance_transfer`
for key, values in self.instance_transfer.items():
if key in instance.data.get("families", []):
for v in values:
instance_skeleton_data[v] = instance.data.get(v)
# look into instance data if representations are not having any
# which are having tag `publish_on_farm` and include them
for repre in instance.data.get("representations", []):
staging_dir = repre.get("stagingDir")
if staging_dir:
success, rootless_staging_dir = (
self.anatomy.find_root_template_from_path(
staging_dir
)
)
if success:
repre["stagingDir"] = rootless_staging_dir
else:
self.log.warning((
"Could not find root path for remapping \"{}\"."
" This may cause issues on farm."
).format(staging_dir))
repre["stagingDir"] = staging_dir
if "publish_on_farm" in repre.get("tags"):
# create representations attribute of not there
if "representations" not in instance_skeleton_data.keys():
instance_skeleton_data["representations"] = []
instance_skeleton_data["representations"].append(repre)
instances = None
assert data.get("expectedFiles"), ("Submission from old Pype version"
" - missing expectedFiles")
anatomy = instance.context.data["anatomy"]
instance_skeleton_data = create_skeleton_instance(

View file

@ -132,7 +132,7 @@ class PostFtrackHook(PostLaunchHook):
if key in already_tested:
continue
value = value.lower()
value = [i.lower() for i in value]
if actual_status in value or "__any__" in value:
if key != "__ignore__":
next_status_name = key

View file

@ -22,7 +22,9 @@
"aov_separator": "underscore",
"image_format": "exr",
"multilayer_exr": true,
"aov_list": [],
"renderer": "CYCLES",
"compositing": true,
"aov_list": ["combined"],
"custom_passes": []
},
"workfile_builder": {

View file

@ -103,6 +103,22 @@
"type": "label",
"label": "Note: Multilayer EXR is only used when output format type set to EXR."
},
{
"key": "renderer",
"label": "Renderer",
"type": "enum",
"multiselection": false,
"defaults": "CYCLES",
"enum_items": [
{"CYCLES": "Cycles"},
{"BLENDER_EEVEE": "Eevee"}
]
},
{
"key": "compositing",
"type": "boolean",
"label": "Enable Compositing"
},
{
"key": "aov_list",
"label": "AOVs to create",
@ -110,23 +126,38 @@
"multiselection": true,
"defaults": "empty",
"enum_items": [
{"empty": "< empty >"},
{"combined": "Combined"},
{"z": "Z"},
{"mist": "Mist"},
{"normal": "Normal"},
{"diffuse_light": "Diffuse Light"},
{"position": "Position (Cycles Only)"},
{"vector": "Vector (Cycles Only)"},
{"uv": "UV (Cycles Only)"},
{"denoising": "Denoising Data (Cycles Only)"},
{"object_index": "Object Index (Cycles Only)"},
{"material_index": "Material Index (Cycles Only)"},
{"sample_count": "Sample Count (Cycles Only)"},
{"diffuse_light": "Diffuse Light/Direct"},
{"diffuse_indirect": "Diffuse Indirect (Cycles Only)"},
{"diffuse_color": "Diffuse Color"},
{"specular_light": "Specular Light"},
{"specular_color": "Specular Color"},
{"volume_light": "Volume Light"},
{"specular_light": "Specular (Glossy) Light/Direct"},
{"specular_indirect": "Specular (Glossy) Indirect (Cycles Only)"},
{"specular_color": "Specular (Glossy) Color"},
{"transmission_light": "Transmission Light/Direct (Cycles Only)"},
{"transmission_indirect": "Transmission Indirect (Cycles Only)"},
{"transmission_color": "Transmission Color (Cycles Only)"},
{"volume_light": "Volume Light/Direct"},
{"volume_indirect": "Volume Indirect (Cycles Only)"},
{"emission": "Emission"},
{"environment": "Environment"},
{"shadow": "Shadow"},
{"shadow": "Shadow/Shadow Catcher"},
{"ao": "Ambient Occlusion"},
{"denoising": "Denoising"},
{"volume_direct": "Direct Volumetric Scattering"},
{"volume_indirect": "Indirect Volumetric Scattering"}
{"bloom": "Bloom (Eevee Only)"},
{"transparent": "Transparent (Eevee Only)"},
{"cryptomatte_object": "Cryptomatte Object"},
{"cryptomatte_material": "Cryptomatte Material"},
{"cryptomatte_asset": "Cryptomatte Asset"},
{"cryptomatte_accurate": "Cryptomatte Accurate Mode (Eevee Only)"}
]
},
{

View file

@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
"""Package declaring Pype version."""
__version__ = "3.18.7-nightly.4"
__version__ = "3.18.8-nightly.1"

View file

@ -1,6 +1,6 @@
[tool.poetry]
name = "OpenPype"
version = "3.18.6" # OpenPype
version = "3.18.7" # OpenPype
description = "Open VFX and Animation pipeline with support."
authors = ["OpenPype Team <info@openpype.io>"]
license = "MIT License"

View file

@ -23,6 +23,13 @@ def image_format_enum():
]
def renderers_enum():
return [
{"value": "CYCLES", "label": "Cycles"},
{"value": "BLENDER_EEVEE", "label": "Eevee"},
]
def aov_list_enum():
return [
{"value": "empty", "label": "< none >"},
@ -30,18 +37,52 @@ def aov_list_enum():
{"value": "z", "label": "Z"},
{"value": "mist", "label": "Mist"},
{"value": "normal", "label": "Normal"},
{"value": "diffuse_light", "label": "Diffuse Light"},
{"value": "position", "label": "Position (Cycles Only)"},
{"value": "vector", "label": "Vector (Cycles Only)"},
{"value": "uv", "label": "UV (Cycles Only)"},
{"value": "denoising", "label": "Denoising Data (Cycles Only)"},
{"value": "object_index", "label": "Object Index (Cycles Only)"},
{"value": "material_index", "label": "Material Index (Cycles Only)"},
{"value": "sample_count", "label": "Sample Count (Cycles Only)"},
{"value": "diffuse_light", "label": "Diffuse Light/Direct"},
{
"value": "diffuse_indirect",
"label": "Diffuse Indirect (Cycles Only)"
},
{"value": "diffuse_color", "label": "Diffuse Color"},
{"value": "specular_light", "label": "Specular Light"},
{"value": "specular_color", "label": "Specular Color"},
{"value": "volume_light", "label": "Volume Light"},
{"value": "specular_light", "label": "Specular (Glossy) Light/Direct"},
{
"value": "specular_indirect",
"label": "Specular (Glossy) Indirect (Cycles Only)"
},
{"value": "specular_color", "label": "Specular (Glossy) Color"},
{
"value": "transmission_light",
"label": "Transmission Light/Direct (Cycles Only)"
},
{
"value": "transmission_indirect",
"label": "Transmission Indirect (Cycles Only)"
},
{
"value": "transmission_color",
"label": "Transmission Color (Cycles Only)"
},
{"value": "volume_light", "label": "Volume Light/Direct"},
{"value": "volume_indirect", "label": "Volume Indirect (Cycles Only)"},
{"value": "emission", "label": "Emission"},
{"value": "environment", "label": "Environment"},
{"value": "shadow", "label": "Shadow"},
{"value": "shadow", "label": "Shadow/Shadow Catcher"},
{"value": "ao", "label": "Ambient Occlusion"},
{"value": "denoising", "label": "Denoising"},
{"value": "volume_direct", "label": "Direct Volumetric Scattering"},
{"value": "volume_indirect", "label": "Indirect Volumetric Scattering"}
{"value": "bloom", "label": "Bloom (Eevee Only)"},
{"value": "transparent", "label": "Transparent (Eevee Only)"},
{"value": "cryptomatte_object", "label": "Cryptomatte Object"},
{"value": "cryptomatte_material", "label": "Cryptomatte Material"},
{"value": "cryptomatte_asset", "label": "Cryptomatte Asset"},
{
"value": "cryptomatte_accurate",
"label": "Cryptomatte Accurate Mode (Eevee Only)"
},
]
@ -81,6 +122,14 @@ class RenderSettingsModel(BaseSettingsModel):
multilayer_exr: bool = SettingsField(
title="Multilayer (EXR)"
)
renderer: str = SettingsField(
"CYCLES",
title="Renderer",
enum_resolver=renderers_enum
)
compositing: bool = SettingsField(
title="Enable Compositing"
)
aov_list: list[str] = SettingsField(
default_factory=list,
enum_resolver=aov_list_enum,
@ -102,6 +151,8 @@ DEFAULT_RENDER_SETTINGS = {
"aov_separator": "underscore",
"image_format": "exr",
"multilayer_exr": True,
"aov_list": [],
"renderer": "CYCLES",
"compositing": True,
"aov_list": ["combined"],
"custom_passes": []
}

View file

@ -1 +1 @@
__version__ = "0.1.5"
__version__ = "0.1.6"