mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge remote-tracking branch 'origin/bugfix/list_appending_fix' into feature/#649-Slack-integration
This commit is contained in:
commit
c9dc9ab69c
14 changed files with 73 additions and 150 deletions
10
.github/workflows/nightly_merge.yml
vendored
10
.github/workflows/nightly_merge.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: Nightly Merge
|
||||
name: Dev -> Main
|
||||
|
||||
on:
|
||||
schedule:
|
||||
|
|
@ -20,4 +20,10 @@ jobs:
|
|||
github_token: ${{ secrets.ADMIN_TOKEN }}
|
||||
source_ref: 'develop'
|
||||
target_branch: 'main'
|
||||
commit_message_template: '[Automated] Merged {source_ref} into {target_branch}'
|
||||
commit_message_template: '[Automated] Merged {source_ref} into {target_branch}'
|
||||
|
||||
- name: Invoke pre-release workflow
|
||||
uses: benc-uk/workflow-dispatch@v1
|
||||
with:
|
||||
workflow: Nightly Prerelease
|
||||
token: ${{ secrets.ADMIN_TOKEN }}
|
||||
3
.github/workflows/prerelease.yml
vendored
3
.github/workflows/prerelease.yml
vendored
|
|
@ -1,15 +1,12 @@
|
|||
name: Nightly Prerelease
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
jobs:
|
||||
create_nightly:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.actor != 'pypebot'
|
||||
|
||||
steps:
|
||||
- name: 🚛 Checkout Code
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
# Changelog
|
||||
|
||||
## [3.1.0-nightly.1](https://github.com/pypeclub/OpenPype/tree/HEAD)
|
||||
## [3.1.0-nightly.2](https://github.com/pypeclub/OpenPype/tree/HEAD)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.0.0...HEAD)
|
||||
|
||||
#### 🚀 Enhancements
|
||||
|
||||
- Nuke - Publish simplification [\#1653](https://github.com/pypeclub/OpenPype/pull/1653)
|
||||
- \#1333 - added tooltip hints to Pyblish buttons [\#1649](https://github.com/pypeclub/OpenPype/pull/1649)
|
||||
|
||||
#### 🐛 Bug fixes
|
||||
|
||||
- Mac launch arguments fix [\#1660](https://github.com/pypeclub/OpenPype/pull/1660)
|
||||
- Fix missing dbm python module [\#1652](https://github.com/pypeclub/OpenPype/pull/1652)
|
||||
- Transparent branches in view on Mac [\#1648](https://github.com/pypeclub/OpenPype/pull/1648)
|
||||
- Add asset on task item [\#1646](https://github.com/pypeclub/OpenPype/pull/1646)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
OpenPype
|
||||
====
|
||||
|
||||
[](https://github.com/pypeclub/pype/actions/workflows/documentation.yml)  
|
||||
[](https://github.com/pypeclub/pype/actions/workflows/documentation.yml) 
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -31,4 +31,4 @@ class LaunchWithTerminal(PreLaunchHook):
|
|||
if len(self.launch_context.launch_args) > 1:
|
||||
self.launch_context.launch_args.insert(1, "--args")
|
||||
# Prepend open arguments
|
||||
self.launch_context.launch_args.insert(0, ["open", "-a"])
|
||||
self.launch_context.launch_args.insert(0, ["open", "-na"])
|
||||
|
|
|
|||
|
|
@ -298,18 +298,21 @@ def create_write_node(name, data, input=None, prenodes=None, review=True):
|
|||
review (bool): adding review knob
|
||||
|
||||
Example:
|
||||
prenodes = [(
|
||||
"NameNode", # string
|
||||
"NodeClass", # string
|
||||
( # OrderDict: knob and values pairs
|
||||
("knobName", "knobValue"),
|
||||
("knobName", "knobValue")
|
||||
),
|
||||
( # list outputs
|
||||
"firstPostNodeName",
|
||||
"secondPostNodeName"
|
||||
)
|
||||
)
|
||||
prenodes = [
|
||||
{
|
||||
"nodeName": {
|
||||
"class": "" # string
|
||||
"knobs": [
|
||||
("knobName": value),
|
||||
...
|
||||
],
|
||||
"dependent": [
|
||||
following_node_01,
|
||||
...
|
||||
]
|
||||
}
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
Return:
|
||||
|
|
@ -385,35 +388,42 @@ def create_write_node(name, data, input=None, prenodes=None, review=True):
|
|||
prev_node.hideControlPanel()
|
||||
# creating pre-write nodes `prenodes`
|
||||
if prenodes:
|
||||
for name, klass, properties, set_output_to in prenodes:
|
||||
for node in prenodes:
|
||||
# get attributes
|
||||
name = node["name"]
|
||||
klass = node["class"]
|
||||
knobs = node["knobs"]
|
||||
dependent = node["dependent"]
|
||||
|
||||
# create node
|
||||
now_node = nuke.createNode(klass, "name {}".format(name))
|
||||
now_node.hideControlPanel()
|
||||
|
||||
# add data to knob
|
||||
for k, v in properties:
|
||||
for _knob in knobs:
|
||||
knob, value = _knob
|
||||
try:
|
||||
now_node[k].value()
|
||||
now_node[knob].value()
|
||||
except NameError:
|
||||
log.warning(
|
||||
"knob `{}` does not exist on node `{}`".format(
|
||||
k, now_node["name"].value()
|
||||
knob, now_node["name"].value()
|
||||
))
|
||||
continue
|
||||
|
||||
if k and v:
|
||||
now_node[k].setValue(str(v))
|
||||
if knob and value:
|
||||
now_node[knob].setValue(value)
|
||||
|
||||
# connect to previous node
|
||||
if set_output_to:
|
||||
if isinstance(set_output_to, (tuple or list)):
|
||||
for i, node_name in enumerate(set_output_to):
|
||||
if dependent:
|
||||
if isinstance(dependent, (tuple or list)):
|
||||
for i, node_name in enumerate(dependent):
|
||||
input_node = nuke.createNode(
|
||||
"Input", "name {}".format(node_name))
|
||||
input_node.hideControlPanel()
|
||||
now_node.setInput(1, input_node)
|
||||
|
||||
elif isinstance(set_output_to, str):
|
||||
elif isinstance(dependent, str):
|
||||
input_node = nuke.createNode(
|
||||
"Input", "name {}".format(node_name))
|
||||
input_node.hideControlPanel()
|
||||
|
|
|
|||
|
|
@ -99,10 +99,28 @@ class CreateWriteRender(plugin.PypeCreator):
|
|||
"fpath_template": ("{work}/renders/nuke/{subset}"
|
||||
"/{subset}.{frame}.{ext}")})
|
||||
|
||||
# add crop node to cut off all outside of format bounding box
|
||||
_prenodes = [
|
||||
{
|
||||
"name": "Crop01",
|
||||
"class": "Crop",
|
||||
"knobs": [
|
||||
("box", [
|
||||
0.0,
|
||||
0.0,
|
||||
selected_node.width(),
|
||||
selected_node.height()
|
||||
])
|
||||
],
|
||||
"dependent": None
|
||||
}
|
||||
]
|
||||
|
||||
write_node = lib.create_write_node(
|
||||
self.data["subset"],
|
||||
write_data,
|
||||
input=selected_node)
|
||||
input=selected_node,
|
||||
prenodes=_prenodes)
|
||||
|
||||
# relinking to collected connections
|
||||
for i, input in enumerate(inputs):
|
||||
|
|
|
|||
|
|
@ -1,106 +0,0 @@
|
|||
import nuke
|
||||
|
||||
import pyblish.api
|
||||
|
||||
|
||||
class RepairNukeBoundingBoxAction(pyblish.api.Action):
|
||||
|
||||
label = "Repair"
|
||||
icon = "wrench"
|
||||
on = "failed"
|
||||
|
||||
def process(self, context, plugin):
|
||||
|
||||
# Get the errored instances
|
||||
failed = []
|
||||
for result in context.data["results"]:
|
||||
if (result["error"] is not None and result["instance"] is not None
|
||||
and result["instance"] not in failed):
|
||||
failed.append(result["instance"])
|
||||
|
||||
# Apply pyblish.logic to get the instances for the plug-in
|
||||
instances = pyblish.api.instances_by_plugin(failed, plugin)
|
||||
|
||||
for instance in instances:
|
||||
crop = instance[0].dependencies()[0]
|
||||
if crop.Class() != "Crop":
|
||||
crop = nuke.nodes.Crop(inputs=[instance[0].input(0)])
|
||||
|
||||
xpos = instance[0].xpos()
|
||||
ypos = instance[0].ypos() - 26
|
||||
|
||||
dependent_ypos = instance[0].dependencies()[0].ypos()
|
||||
if (instance[0].ypos() - dependent_ypos) <= 51:
|
||||
xpos += 110
|
||||
|
||||
crop.setXYpos(xpos, ypos)
|
||||
|
||||
instance[0].setInput(0, crop)
|
||||
|
||||
crop["box"].setValue(
|
||||
(
|
||||
0.0,
|
||||
0.0,
|
||||
instance[0].input(0).width(),
|
||||
instance[0].input(0).height()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class ValidateNukeWriteBoundingBox(pyblish.api.InstancePlugin):
|
||||
"""Validates write bounding box.
|
||||
|
||||
Ffmpeg does not support bounding boxes outside of the image
|
||||
resolution a crop is needed. This needs to validate all frames, as each
|
||||
rendered exr can break the ffmpeg transcode.
|
||||
"""
|
||||
|
||||
order = pyblish.api.ValidatorOrder
|
||||
optional = True
|
||||
families = ["render", "render.local", "render.farm"]
|
||||
label = "Write Bounding Box"
|
||||
hosts = ["nuke"]
|
||||
actions = [RepairNukeBoundingBoxAction]
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
# Skip bounding box check if a crop node exists.
|
||||
if instance[0].dependencies()[0].Class() == "Crop":
|
||||
return
|
||||
|
||||
msg = "Bounding box is outside the format."
|
||||
assert self.check_bounding_box(instance), msg
|
||||
|
||||
def check_bounding_box(self, instance):
|
||||
node = instance[0]
|
||||
|
||||
first_frame = instance.data["frameStart"]
|
||||
last_frame = instance.data["frameEnd"]
|
||||
|
||||
format_width = node.format().width()
|
||||
format_height = node.format().height()
|
||||
|
||||
# The trick is that we need to execute() some node every time we go to
|
||||
# a next frame, to update the context.
|
||||
# So we create a CurveTool that we can execute() on every frame.
|
||||
temporary_node = nuke.nodes.CurveTool()
|
||||
bbox_check = True
|
||||
for frame in range(first_frame, last_frame + 1):
|
||||
# Workaround to update the tree
|
||||
nuke.execute(temporary_node, frame, frame)
|
||||
|
||||
x = node.bbox().x()
|
||||
y = node.bbox().y()
|
||||
w = node.bbox().w()
|
||||
h = node.bbox().h()
|
||||
|
||||
if x < 0 or (x + w) > format_width:
|
||||
bbox_check = False
|
||||
break
|
||||
|
||||
if y < 0 or (y + h) > format_height:
|
||||
bbox_check = False
|
||||
break
|
||||
|
||||
nuke.delete(temporary_node)
|
||||
return bbox_check
|
||||
|
|
@ -37,7 +37,7 @@ class StandAlonePublishAction(PypeModule, ITrayAction):
|
|||
args = get_pype_execute_args("standalonepublisher")
|
||||
kwargs = {}
|
||||
if platform.system().lower() == "darwin":
|
||||
new_args = ["open", "-a", args.pop(0), "--args"]
|
||||
new_args = ["open", "-na", args.pop(0), "--args"]
|
||||
new_args.extend(args)
|
||||
args = new_args
|
||||
|
||||
|
|
|
|||
|
|
@ -43,11 +43,6 @@
|
|||
"optional": true,
|
||||
"active": true
|
||||
},
|
||||
"ValidateNukeWriteBoundingBox": {
|
||||
"enabled": true,
|
||||
"optional": true,
|
||||
"active": true
|
||||
},
|
||||
"ExtractThumbnail": {
|
||||
"enabled": true,
|
||||
"nodes": {
|
||||
|
|
|
|||
|
|
@ -467,7 +467,7 @@ class DictMutableKeysEntity(EndpointEntity):
|
|||
if self.store_as_list:
|
||||
output = []
|
||||
for key, child_entity in self.children_by_key.items():
|
||||
output.append(key, child_entity.value)
|
||||
output.append([key, child_entity.value])
|
||||
return output
|
||||
|
||||
output = {}
|
||||
|
|
|
|||
|
|
@ -64,10 +64,6 @@
|
|||
{
|
||||
"key": "ValidateScript",
|
||||
"label": "Validate script settings"
|
||||
},
|
||||
{
|
||||
"key": "ValidateNukeWriteBoundingBox",
|
||||
"label": "Validate and Write Bounding Box"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -100,7 +100,6 @@ class ListItem(QtWidgets.QWidget):
|
|||
self.input_field = self.create_ui_for_entity(
|
||||
self.category_widget, self.entity, self
|
||||
)
|
||||
self.input_field.set_entity_value()
|
||||
|
||||
spacer_widget = QtWidgets.QWidget(self)
|
||||
spacer_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground)
|
||||
|
|
@ -337,6 +336,12 @@ class ListWidget(InputWidget):
|
|||
self.content_layout.insertWidget(row + 1, item_widget)
|
||||
self.input_fields.insert(row, item_widget)
|
||||
|
||||
# Change to entity value after item is added to `input_fields`
|
||||
# - may cause recursion error as setting a value may cause input field
|
||||
# change which will trigger this validation if entity is already
|
||||
# added as widget here which won't because is not in input_fields
|
||||
item_widget.input_field.set_entity_value()
|
||||
|
||||
if previous_field:
|
||||
previous_field.order_changed()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Package declaring Pype version."""
|
||||
__version__ = "3.1.0-nightly.1"
|
||||
__version__ = "3.1.0-nightly.2"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue