mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-02 00:44:52 +01:00
[Automated] Merged develop into main
This commit is contained in:
commit
f2a68abf6e
33 changed files with 417 additions and 183 deletions
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
|
@ -1,33 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
**Running version**
|
||||
[ex. 3.14.1-nightly.2]
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. windows]
|
||||
- Host: [e.g. Maya, Nuke, Houdini]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
108
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
108
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
name: Bug Report
|
||||
description: File a bug report
|
||||
title: 'bug: '
|
||||
labels:
|
||||
- 'type: bug'
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
description: >-
|
||||
Please search to see if an issue already exists for the bug you
|
||||
encountered.
|
||||
options:
|
||||
- label: I have searched the existing issues
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 'Current Behavior:'
|
||||
description: A concise description of what you're experiencing.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 'Expected Behavior:'
|
||||
description: A concise description of what you expected to happen.
|
||||
validations:
|
||||
required: false
|
||||
- type: dropdown
|
||||
id: _version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version are you running? Look to OpenPype Tray
|
||||
options:
|
||||
- 3.15.3
|
||||
- 3.15.2
|
||||
- 3.15.1
|
||||
- 3.15.0
|
||||
- 3.14.10
|
||||
- 3.14.9
|
||||
- 3.14.8
|
||||
- 3.14.7
|
||||
- 3.14.6
|
||||
- 3.14.5
|
||||
- 3.14.4
|
||||
- 3.14.3
|
||||
- 3.14.2
|
||||
- 3.14.1
|
||||
- 3.14.0
|
||||
- 3.13.0
|
||||
- 3.12.2
|
||||
- 3.12.1
|
||||
- 3.12.0
|
||||
- 3.11.1
|
||||
- 3.11.0
|
||||
- 3.10.0
|
||||
- 3.9.8
|
||||
- 3.9.7
|
||||
- 3.9.6
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: What platform you are running OpenPype on?
|
||||
description: |
|
||||
Please specify the operating systems you are running OpenPype with.
|
||||
multiple: true
|
||||
options:
|
||||
- Windows
|
||||
- Linux / Centos
|
||||
- Linux / Ubuntu
|
||||
- Linux / RedHat
|
||||
- MacOS
|
||||
- type: textarea
|
||||
id: to-reproduce
|
||||
attributes:
|
||||
label: 'Steps To Reproduce:'
|
||||
description: Steps to reproduce the behavior.
|
||||
placeholder: |
|
||||
1. How did the configuration look like
|
||||
2. What type of action was made
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there any more labels you wish to add?
|
||||
description: Please search labels and identify those related to your bug.
|
||||
options:
|
||||
- label: I have searched labels and added any
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: 'Relevant log output:'
|
||||
description: >-
|
||||
Please copy and paste any relevant log output. This will be
|
||||
automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: 'Additional context:'
|
||||
description: Add any other context about the problem here.
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Ynput Discord Server
|
||||
url: https://discord.gg/ynput
|
||||
about: For community quick chats.
|
||||
52
.github/ISSUE_TEMPLATE/enhancement_request.yml
vendored
Normal file
52
.github/ISSUE_TEMPLATE/enhancement_request.yml
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
name: Enhancement Request
|
||||
description: Create a report to help us enhance a particular feature
|
||||
title: "enhancement: "
|
||||
labels:
|
||||
- "type: enhancement"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this enhancement request report!
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
description: Please search to see if an issue already exists for the bug you encountered.
|
||||
options:
|
||||
- label: I have searched the existing issues
|
||||
required: true
|
||||
- type: textarea
|
||||
id: related-feature
|
||||
attributes:
|
||||
label: Please state which of feature you have in mind and describe what are its shortcomings?
|
||||
description: A clear and concise description of what the problem is.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: enhancement-proposal
|
||||
attributes:
|
||||
label: How would you imagine the enhancement of the feature?
|
||||
description: A clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there any more labels you wish to add?
|
||||
description: Please search labels and identify those related to your enhancement.
|
||||
options:
|
||||
- label: I have searched labels and added any
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: "Describe alternatives you've considered:"
|
||||
description: A clear and concise description of any alternative solutions or features you've considered.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: "Additional context:"
|
||||
description: Add any other context or screenshots about the enhancement request here.
|
||||
validations:
|
||||
required: false
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
2
.github/workflows/documentation.yml
vendored
2
.github/workflows/documentation.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: documentation
|
||||
name: 📜 Documentation
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
|
|
|||
2
.github/workflows/milestone_assign.yml
vendored
2
.github/workflows/milestone_assign.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: Milestone - assign to PRs
|
||||
name: 👉🏻 Milestone - assign to PRs
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
|
|
|
|||
2
.github/workflows/milestone_create.yml
vendored
2
.github/workflows/milestone_create.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: Milestone - create default
|
||||
name: ➕ Milestone - create default
|
||||
|
||||
on:
|
||||
milestone:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
name: Milestone Release [trigger]
|
||||
name: 🚩 Milestone Release [trigger]
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
|
|
|||
2
.github/workflows/nightly_merge.yml
vendored
2
.github/workflows/nightly_merge.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: Dev -> Main
|
||||
name: 🔀 Dev -> Main
|
||||
|
||||
on:
|
||||
schedule:
|
||||
|
|
|
|||
49
.github/workflows/pr_labels.yml
vendored
Normal file
49
.github/workflows/pr_labels.yml
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
name: 🔖 PR labels
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, assigned]
|
||||
|
||||
jobs:
|
||||
size-label:
|
||||
name: pr_size_label
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'assigned' || github.event.action == 'opened'
|
||||
steps:
|
||||
- name: Add size label
|
||||
uses: "pascalgn/size-label-action@v0.4.3"
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.YNPUT_BOT_TOKEN }}"
|
||||
IGNORED: ".gitignore\n*.md\n*.json"
|
||||
with:
|
||||
sizes: >
|
||||
{
|
||||
"0": "XS",
|
||||
"100": "S",
|
||||
"500": "M",
|
||||
"1000": "L",
|
||||
"1500": "XL",
|
||||
"2500": "XXL"
|
||||
}
|
||||
|
||||
label_prs_branch:
|
||||
name: pr_branch_label
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'assigned' || github.event.action == 'opened'
|
||||
steps:
|
||||
- name: Label PRs - Branch name detection
|
||||
uses: ffittschen/pr-branch-labeler@v1
|
||||
with:
|
||||
repo-token: ${{ secrets.YNPUT_BOT_TOKEN }}
|
||||
|
||||
label_prs_globe:
|
||||
name: pr_globe_label
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'assigned' || github.event.action == 'opened'
|
||||
steps:
|
||||
- name: Label PRs - Globe detection
|
||||
uses: actions/labeler@v4.0.3
|
||||
with:
|
||||
repo-token: ${{ secrets.YNPUT_BOT_TOKEN }}
|
||||
configuration-path: ".github/pr-glob-labeler.yml"
|
||||
sync-labels: false
|
||||
2
.github/workflows/prerelease.yml
vendored
2
.github/workflows/prerelease.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: Nightly Prerelease
|
||||
name: ⏳ Nightly Prerelease
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
name: project-actions
|
||||
name: 📊 Project task statuses
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, assigned]
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
issue_comment:
|
||||
|
|
@ -25,7 +23,11 @@ jobs:
|
|||
if: |
|
||||
(github.event_name == 'issue_comment' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.comment.user.id != 82967070) ||
|
||||
(github.event_name == 'pull_request_review_comment' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.comment.user.type != 'Bot') ||
|
||||
(github.event_name == 'pull_request_review' && github.event.pull_request.head.repo.owner.login == 'ynput' && github.event.review.state != 'changes_requested' && github.event.review.user.type != 'Bot')
|
||||
(github.event_name == 'pull_request_review' &&
|
||||
github.event.pull_request.head.repo.owner.login == 'ynput' &&
|
||||
github.event.review.state != 'changes_requested' &&
|
||||
github.event.review.state != 'approved' &&
|
||||
github.event.review.user.type != 'Bot')
|
||||
steps:
|
||||
- name: Move PR to 'Review In Progress'
|
||||
uses: leonsteinhaeuser/project-beta-automations@v2.1.0
|
||||
|
|
@ -66,53 +68,3 @@ jobs:
|
|||
-d '{
|
||||
"status": "in progress"
|
||||
}'
|
||||
|
||||
size-label:
|
||||
name: pr_size_label
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
(github.event_name == 'pull_request' && github.event.action == 'assigned') ||
|
||||
(github.event_name == 'pull_request' && github.event.action == 'opened')
|
||||
|
||||
steps:
|
||||
- name: Add size label
|
||||
uses: "pascalgn/size-label-action@v0.4.3"
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.YNPUT_BOT_TOKEN }}"
|
||||
IGNORED: ".gitignore\n*.md\n*.json"
|
||||
with:
|
||||
sizes: >
|
||||
{
|
||||
"0": "XS",
|
||||
"100": "S",
|
||||
"500": "M",
|
||||
"1000": "L",
|
||||
"1500": "XL",
|
||||
"2500": "XXL"
|
||||
}
|
||||
|
||||
label_prs_branch:
|
||||
name: pr_branch_label
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
(github.event_name == 'pull_request' && github.event.action == 'assigned') ||
|
||||
(github.event_name == 'pull_request' && github.event.action == 'opened')
|
||||
steps:
|
||||
- name: Label PRs - Branch name detection
|
||||
uses: ffittschen/pr-branch-labeler@v1
|
||||
with:
|
||||
repo-token: ${{ secrets.YNPUT_BOT_TOKEN }}
|
||||
|
||||
label_prs_globe:
|
||||
name: pr_globe_label
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
(github.event_name == 'pull_request' && github.event.action == 'assigned') ||
|
||||
(github.event_name == 'pull_request' && github.event.action == 'opened')
|
||||
steps:
|
||||
- name: Label PRs - Globe detection
|
||||
uses: actions/labeler@v4.0.3
|
||||
with:
|
||||
repo-token: ${{ secrets.YNPUT_BOT_TOKEN }}
|
||||
configuration-path: ".github/pr-glob-labeler.yml"
|
||||
sync-labels: false
|
||||
2
.github/workflows/test_build.yml
vendored
2
.github/workflows/test_build.yml
vendored
|
|
@ -1,7 +1,7 @@
|
|||
# This workflow will upload a Python Package using Twine when a release is created
|
||||
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
|
||||
|
||||
name: Test Build
|
||||
name: 🏗️ Test Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
|
|
|||
25
.github/workflows/update_bug_report.yml
vendored
Normal file
25
.github/workflows/update_bug_report.yml
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
name: 🐞 Update Bug Report
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
update-bug-report:
|
||||
runs-on: ubuntu-latest
|
||||
name: Update bug report
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.release.target_commitish }}
|
||||
- name: Update version
|
||||
uses: ShaMan123/gha-populate-form-version@v2.0.2
|
||||
with:
|
||||
github_token: ${{ secrets.YNPUT_BOT_TOKEN }}
|
||||
registry: github
|
||||
dropdown: _version
|
||||
limit_to: 25
|
||||
form: .github/ISSUE_TEMPLATE/bug_report.yml
|
||||
commit_message: 'chore(): update bug report / version'
|
||||
|
|
@ -242,9 +242,15 @@ def launch_zip_file(filepath):
|
|||
print(f"Localizing {filepath}")
|
||||
|
||||
temp_path = get_local_harmony_path(filepath)
|
||||
scene_name = os.path.basename(temp_path)
|
||||
if os.path.exists(os.path.join(temp_path, scene_name)):
|
||||
# unzipped with duplicated scene_name
|
||||
temp_path = os.path.join(temp_path, scene_name)
|
||||
|
||||
scene_path = os.path.join(
|
||||
temp_path, os.path.basename(temp_path) + ".xstage"
|
||||
temp_path, scene_name + ".xstage"
|
||||
)
|
||||
|
||||
unzip = False
|
||||
if os.path.exists(scene_path):
|
||||
# Check remote scene is newer than local.
|
||||
|
|
@ -262,6 +268,10 @@ def launch_zip_file(filepath):
|
|||
with _ZipFile(filepath, "r") as zip_ref:
|
||||
zip_ref.extractall(temp_path)
|
||||
|
||||
if os.path.exists(os.path.join(temp_path, scene_name)):
|
||||
# unzipped with duplicated scene_name
|
||||
temp_path = os.path.join(temp_path, scene_name)
|
||||
|
||||
# Close existing scene.
|
||||
if ProcessContext.pid:
|
||||
os.kill(ProcessContext.pid, signal.SIGTERM)
|
||||
|
|
@ -309,7 +319,7 @@ def launch_zip_file(filepath):
|
|||
)
|
||||
|
||||
if not os.path.exists(scene_path):
|
||||
print("error: cannot determine scene file")
|
||||
print("error: cannot determine scene file {}".format(scene_path))
|
||||
ProcessContext.server.stop()
|
||||
return
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ HARDLINK = 2
|
|||
|
||||
|
||||
@attr.s
|
||||
class TextureResult:
|
||||
class TextureResult(object):
|
||||
"""The resulting texture of a processed file for a resource"""
|
||||
# Path to the file
|
||||
path = attr.ib()
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ from openpype.client import (
|
|||
|
||||
from openpype.host import HostDirmap
|
||||
from openpype.tools.utils import host_tools
|
||||
from openpype.pipeline.workfile.workfile_template_builder import (
|
||||
TemplateProfileNotFound
|
||||
)
|
||||
from openpype.lib import (
|
||||
env_value_to_bool,
|
||||
Logger,
|
||||
|
|
@ -2684,7 +2687,10 @@ def start_workfile_template_builder():
|
|||
|
||||
# to avoid looping of the callback, remove it!
|
||||
log.info("Starting workfile template builder...")
|
||||
build_workfile_template(workfile_creation_enabled=True)
|
||||
try:
|
||||
build_workfile_template(workfile_creation_enabled=True)
|
||||
except TemplateProfileNotFound:
|
||||
log.warning("Template profile not found. Skipping...")
|
||||
|
||||
# remove callback since it would be duplicating the workfile
|
||||
nuke.removeOnCreate(start_workfile_template_builder, nodeClass="Root")
|
||||
|
|
|
|||
|
|
@ -208,6 +208,12 @@ class NukeCreator(NewCreator):
|
|||
|
||||
def collect_instances(self):
|
||||
cached_instances = _collect_and_cache_nodes(self)
|
||||
attr_def_keys = {
|
||||
attr_def.key
|
||||
for attr_def in self.get_instance_attr_defs()
|
||||
}
|
||||
attr_def_keys.discard(None)
|
||||
|
||||
for (node, data) in cached_instances[self.identifier]:
|
||||
created_instance = CreatedInstance.from_existing(
|
||||
data, self
|
||||
|
|
@ -215,6 +221,12 @@ class NukeCreator(NewCreator):
|
|||
created_instance.transient_data["node"] = node
|
||||
self._add_instance_to_context(created_instance)
|
||||
|
||||
for key in (
|
||||
set(created_instance["creator_attributes"].keys())
|
||||
- attr_def_keys
|
||||
):
|
||||
created_instance["creator_attributes"].pop(key)
|
||||
|
||||
def update_instances(self, update_list):
|
||||
for created_inst, _changes in update_list:
|
||||
instance_node = created_inst.transient_data["node"]
|
||||
|
|
@ -301,8 +313,11 @@ class NukeWriteCreator(NukeCreator):
|
|||
def get_instance_attr_defs(self):
|
||||
attr_defs = [
|
||||
self._get_render_target_enum(),
|
||||
self._get_reviewable_bool()
|
||||
]
|
||||
# add reviewable attribute
|
||||
if "reviewable" in self.instance_attributes:
|
||||
attr_defs.append(self._get_reviewable_bool())
|
||||
|
||||
return attr_defs
|
||||
|
||||
def _get_render_target_enum(self):
|
||||
|
|
@ -322,7 +337,7 @@ class NukeWriteCreator(NukeCreator):
|
|||
def _get_reviewable_bool(self):
|
||||
return BoolDef(
|
||||
"review",
|
||||
default=("reviewable" in self.instance_attributes),
|
||||
default=True,
|
||||
label="Review"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -219,14 +219,17 @@ class NukePlaceholderLoadPlugin(NukePlaceholderPlugin, PlaceholderLoadMixin):
|
|||
|
||||
# fix the problem of z_order for backdrops
|
||||
self._fix_z_order(placeholder)
|
||||
self._imprint_siblings(placeholder)
|
||||
|
||||
if placeholder.data.get("keep_placeholder"):
|
||||
self._imprint_siblings(placeholder)
|
||||
|
||||
if placeholder.data["nb_children"] == 0:
|
||||
# save initial nodes positions and dimensions, update them
|
||||
# and set inputs and outputs of loaded nodes
|
||||
if placeholder.data.get("keep_placeholder"):
|
||||
self._imprint_inits()
|
||||
self._update_nodes(placeholder, nuke.allNodes(), nodes_loaded)
|
||||
|
||||
self._imprint_inits()
|
||||
self._update_nodes(placeholder, nuke.allNodes(), nodes_loaded)
|
||||
self._set_loaded_connections(placeholder)
|
||||
|
||||
elif placeholder.data["siblings"]:
|
||||
|
|
@ -629,14 +632,18 @@ class NukePlaceholderCreatePlugin(
|
|||
|
||||
# fix the problem of z_order for backdrops
|
||||
self._fix_z_order(placeholder)
|
||||
self._imprint_siblings(placeholder)
|
||||
|
||||
if placeholder.data.get("keep_placeholder"):
|
||||
self._imprint_siblings(placeholder)
|
||||
|
||||
if placeholder.data["nb_children"] == 0:
|
||||
# save initial nodes positions and dimensions, update them
|
||||
# and set inputs and outputs of created nodes
|
||||
|
||||
self._imprint_inits()
|
||||
self._update_nodes(placeholder, nuke.allNodes(), nodes_created)
|
||||
if placeholder.data.get("keep_placeholder"):
|
||||
self._imprint_inits()
|
||||
self._update_nodes(placeholder, nuke.allNodes(), nodes_created)
|
||||
|
||||
self._set_created_connections(placeholder)
|
||||
|
||||
elif placeholder.data["siblings"]:
|
||||
|
|
|
|||
|
|
@ -63,13 +63,6 @@ class CreateWriteImage(napi.NukeWriteCreator):
|
|||
default=nuke.frame()
|
||||
)
|
||||
|
||||
def get_instance_attr_defs(self):
|
||||
attr_defs = [
|
||||
self._get_render_target_enum(),
|
||||
self._get_reviewable_bool()
|
||||
]
|
||||
return attr_defs
|
||||
|
||||
def create_instance_node(self, subset_name, instance_data):
|
||||
linked_knobs_ = []
|
||||
if "use_range_limit" in self.instance_attributes:
|
||||
|
|
|
|||
|
|
@ -41,13 +41,6 @@ class CreateWritePrerender(napi.NukeWriteCreator):
|
|||
]
|
||||
return attr_defs
|
||||
|
||||
def get_instance_attr_defs(self):
|
||||
attr_defs = [
|
||||
self._get_render_target_enum(),
|
||||
self._get_reviewable_bool()
|
||||
]
|
||||
return attr_defs
|
||||
|
||||
def create_instance_node(self, subset_name, instance_data):
|
||||
linked_knobs_ = []
|
||||
if "use_range_limit" in self.instance_attributes:
|
||||
|
|
|
|||
|
|
@ -38,13 +38,6 @@ class CreateWriteRender(napi.NukeWriteCreator):
|
|||
]
|
||||
return attr_defs
|
||||
|
||||
def get_instance_attr_defs(self):
|
||||
attr_defs = [
|
||||
self._get_render_target_enum(),
|
||||
self._get_reviewable_bool()
|
||||
]
|
||||
return attr_defs
|
||||
|
||||
def create_instance_node(self, subset_name, instance_data):
|
||||
# add fpath_template
|
||||
write_data = {
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import openpype.hosts.nuke.api.lib as nlib
|
|||
from openpype.pipeline.publish import (
|
||||
ValidateContentsOrder,
|
||||
PublishXmlValidationError,
|
||||
OptionalPyblishPluginMixin
|
||||
)
|
||||
|
||||
|
||||
class SelectInvalidInstances(pyblish.api.Action):
|
||||
"""Select invalid instances in Outliner."""
|
||||
|
||||
|
|
@ -92,7 +92,10 @@ class RepairSelectInvalidInstances(pyblish.api.Action):
|
|||
nlib.set_node_data(node, nlib.INSTANCE_DATA_KNOB, node_data)
|
||||
|
||||
|
||||
class ValidateCorrectAssetName(pyblish.api.InstancePlugin):
|
||||
class ValidateCorrectAssetName(
|
||||
pyblish.api.InstancePlugin,
|
||||
OptionalPyblishPluginMixin
|
||||
):
|
||||
"""Validator to check if instance asset match context asset.
|
||||
|
||||
When working in per-shot style you always publish data in context of
|
||||
|
|
@ -111,6 +114,9 @@ class ValidateCorrectAssetName(pyblish.api.InstancePlugin):
|
|||
optional = True
|
||||
|
||||
def process(self, instance):
|
||||
if not self.is_active(instance.data):
|
||||
return
|
||||
|
||||
asset = instance.data.get("asset")
|
||||
context_asset = instance.context.data["assetEntity"]["name"]
|
||||
node = instance.data["transientData"]["node"]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
import nuke
|
||||
import pyblish
|
||||
from openpype.hosts.nuke import api as napi
|
||||
from openpype.pipeline import PublishXmlValidationError
|
||||
|
||||
from openpype.pipeline.publish import (
|
||||
ValidateContentsOrder,
|
||||
PublishXmlValidationError,
|
||||
OptionalPyblishPluginMixin
|
||||
)
|
||||
|
||||
class SelectCenterInNodeGraph(pyblish.api.Action):
|
||||
"""
|
||||
|
|
@ -46,12 +50,15 @@ class SelectCenterInNodeGraph(pyblish.api.Action):
|
|||
nuke.zoom(2, [min(all_xC), min(all_yC)])
|
||||
|
||||
|
||||
class ValidateBackdrop(pyblish.api.InstancePlugin):
|
||||
class ValidateBackdrop(
|
||||
pyblish.api.InstancePlugin,
|
||||
OptionalPyblishPluginMixin
|
||||
):
|
||||
""" Validate amount of nodes on backdrop node in case user
|
||||
forgotten to add nodes above the publishing backdrop node.
|
||||
"""
|
||||
|
||||
order = pyblish.api.ValidatorOrder
|
||||
order = ValidateContentsOrder
|
||||
optional = True
|
||||
families = ["nukenodes"]
|
||||
label = "Validate Backdrop"
|
||||
|
|
@ -59,6 +66,9 @@ class ValidateBackdrop(pyblish.api.InstancePlugin):
|
|||
actions = [SelectCenterInNodeGraph]
|
||||
|
||||
def process(self, instance):
|
||||
if not self.is_active(instance.data):
|
||||
return
|
||||
|
||||
child_nodes = instance.data["transientData"]["childNodes"]
|
||||
connections_out = instance.data["transientData"]["nodeConnectionsOut"]
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class ValidateScriptAttributes(
|
|||
|
||||
order = pyblish.api.ValidatorOrder + 0.1
|
||||
families = ["workfile"]
|
||||
label = "Validatte script attributes"
|
||||
label = "Validate script attributes"
|
||||
hosts = ["nuke"]
|
||||
optional = True
|
||||
actions = [RepairAction]
|
||||
|
|
|
|||
|
|
@ -256,17 +256,18 @@ class TemplatesDict(object):
|
|||
elif isinstance(templates, dict):
|
||||
self._raw_templates = copy.deepcopy(templates)
|
||||
self._templates = templates
|
||||
self._objected_templates = self.create_ojected_templates(templates)
|
||||
self._objected_templates = self.create_objected_templates(
|
||||
templates)
|
||||
else:
|
||||
raise TypeError("<{}> argument must be a dict, not {}.".format(
|
||||
self.__class__.__name__, str(type(templates))
|
||||
))
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.templates[key]
|
||||
return self.objected_templates[key]
|
||||
|
||||
def get(self, key, *args, **kwargs):
|
||||
return self.templates.get(key, *args, **kwargs)
|
||||
return self.objected_templates.get(key, *args, **kwargs)
|
||||
|
||||
@property
|
||||
def raw_templates(self):
|
||||
|
|
@ -280,8 +281,21 @@ class TemplatesDict(object):
|
|||
def objected_templates(self):
|
||||
return self._objected_templates
|
||||
|
||||
@classmethod
|
||||
def create_ojected_templates(cls, templates):
|
||||
def _create_template_object(self, template):
|
||||
"""Create template object from a template string.
|
||||
|
||||
Separated into method to give option change class of templates.
|
||||
|
||||
Args:
|
||||
template (str): Template string.
|
||||
|
||||
Returns:
|
||||
StringTemplate: Object of template.
|
||||
"""
|
||||
|
||||
return StringTemplate(template)
|
||||
|
||||
def create_objected_templates(self, templates):
|
||||
if not isinstance(templates, dict):
|
||||
raise TypeError("Expected dict object, got {}".format(
|
||||
str(type(templates))
|
||||
|
|
@ -297,7 +311,7 @@ class TemplatesDict(object):
|
|||
for key in tuple(item.keys()):
|
||||
value = item[key]
|
||||
if isinstance(value, six.string_types):
|
||||
item[key] = StringTemplate(value)
|
||||
item[key] = self._create_template_object(value)
|
||||
elif isinstance(value, dict):
|
||||
inner_queue.append(value)
|
||||
return objected_templates
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ from openpype.client import get_project
|
|||
from openpype.lib.path_templates import (
|
||||
TemplateUnsolved,
|
||||
TemplateResult,
|
||||
StringTemplate,
|
||||
TemplatesDict,
|
||||
FormatObject,
|
||||
)
|
||||
|
|
@ -606,6 +607,32 @@ class AnatomyTemplateResult(TemplateResult):
|
|||
return self.__class__(tmp, self.rootless)
|
||||
|
||||
|
||||
class AnatomyStringTemplate(StringTemplate):
|
||||
"""String template which has access to anatomy."""
|
||||
|
||||
def __init__(self, anatomy_templates, template):
|
||||
self.anatomy_templates = anatomy_templates
|
||||
super(AnatomyStringTemplate, self).__init__(template)
|
||||
|
||||
def format(self, data):
|
||||
"""Format template and add 'root' key to data if not available.
|
||||
|
||||
Args:
|
||||
data (dict[str, Any]): Formatting data for template.
|
||||
|
||||
Returns:
|
||||
AnatomyTemplateResult: Formatting result.
|
||||
"""
|
||||
|
||||
anatomy_templates = self.anatomy_templates
|
||||
if not data.get("root"):
|
||||
data = copy.deepcopy(data)
|
||||
data["root"] = anatomy_templates.anatomy.roots
|
||||
result = StringTemplate.format(self, data)
|
||||
rootless_path = anatomy_templates.rootless_path_from_result(result)
|
||||
return AnatomyTemplateResult(result, rootless_path)
|
||||
|
||||
|
||||
class AnatomyTemplates(TemplatesDict):
|
||||
inner_key_pattern = re.compile(r"(\{@.*?[^{}0]*\})")
|
||||
inner_key_name_pattern = re.compile(r"\{@(.*?[^{}0]*)\}")
|
||||
|
|
@ -615,12 +642,6 @@ class AnatomyTemplates(TemplatesDict):
|
|||
self.anatomy = anatomy
|
||||
self.loaded_project = None
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.templates[key]
|
||||
|
||||
def get(self, key, default=None):
|
||||
return self.templates.get(key, default)
|
||||
|
||||
def reset(self):
|
||||
self._raw_templates = None
|
||||
self._templates = None
|
||||
|
|
@ -655,12 +676,7 @@ class AnatomyTemplates(TemplatesDict):
|
|||
def _format_value(self, value, data):
|
||||
if isinstance(value, RootItem):
|
||||
return self._solve_dict(value, data)
|
||||
|
||||
result = super(AnatomyTemplates, self)._format_value(value, data)
|
||||
if isinstance(result, TemplateResult):
|
||||
rootless_path = self._rootless_path(result, data)
|
||||
result = AnatomyTemplateResult(result, rootless_path)
|
||||
return result
|
||||
return super(AnatomyTemplates, self)._format_value(value, data)
|
||||
|
||||
def set_templates(self, templates):
|
||||
if not templates:
|
||||
|
|
@ -689,10 +705,13 @@ class AnatomyTemplates(TemplatesDict):
|
|||
|
||||
solved_templates = self.solve_template_inner_links(templates)
|
||||
self._templates = solved_templates
|
||||
self._objected_templates = self.create_ojected_templates(
|
||||
self._objected_templates = self.create_objected_templates(
|
||||
solved_templates
|
||||
)
|
||||
|
||||
def _create_template_object(self, template):
|
||||
return AnatomyStringTemplate(self, template)
|
||||
|
||||
def default_templates(self):
|
||||
"""Return default templates data with solved inner keys."""
|
||||
return self.solve_template_inner_links(
|
||||
|
|
@ -886,7 +905,8 @@ class AnatomyTemplates(TemplatesDict):
|
|||
|
||||
return keys_by_subkey
|
||||
|
||||
def _dict_to_subkeys_list(self, subdict, pre_keys=None):
|
||||
@classmethod
|
||||
def _dict_to_subkeys_list(cls, subdict, pre_keys=None):
|
||||
if pre_keys is None:
|
||||
pre_keys = []
|
||||
output = []
|
||||
|
|
@ -895,7 +915,7 @@ class AnatomyTemplates(TemplatesDict):
|
|||
result = list(pre_keys)
|
||||
result.append(key)
|
||||
if isinstance(value, dict):
|
||||
for item in self._dict_to_subkeys_list(value, result):
|
||||
for item in cls._dict_to_subkeys_list(value, result):
|
||||
output.append(item)
|
||||
else:
|
||||
output.append(result)
|
||||
|
|
@ -908,7 +928,17 @@ class AnatomyTemplates(TemplatesDict):
|
|||
return {key_list[0]: value}
|
||||
return {key_list[0]: self._keys_to_dicts(key_list[1:], value)}
|
||||
|
||||
def _rootless_path(self, result, final_data):
|
||||
@classmethod
|
||||
def rootless_path_from_result(cls, result):
|
||||
"""Calculate rootless path from formatting result.
|
||||
|
||||
Args:
|
||||
result (TemplateResult): Result of StringTemplate formatting.
|
||||
|
||||
Returns:
|
||||
str: Rootless path if result contains one of anatomy roots.
|
||||
"""
|
||||
|
||||
used_values = result.used_values
|
||||
missing_keys = result.missing_keys
|
||||
template = result.template
|
||||
|
|
@ -924,7 +954,7 @@ class AnatomyTemplates(TemplatesDict):
|
|||
if "root" in invalid_type:
|
||||
return
|
||||
|
||||
root_keys = self._dict_to_subkeys_list({"root": used_values["root"]})
|
||||
root_keys = cls._dict_to_subkeys_list({"root": used_values["root"]})
|
||||
if not root_keys:
|
||||
return
|
||||
|
||||
|
|
|
|||
|
|
@ -596,7 +596,14 @@ class AttributeValues(object):
|
|||
self[_key] = _value
|
||||
|
||||
def pop(self, key, default=None):
|
||||
return self._data.pop(key, default)
|
||||
value = self._data.pop(key, default)
|
||||
# Remove attribute definition if is 'UnknownDef'
|
||||
# - gives option to get rid of unknown values
|
||||
attr_def = self._attr_defs_by_key.get(key)
|
||||
if isinstance(attr_def, UnknownDef):
|
||||
self._attr_defs_by_key.pop(key)
|
||||
self._attr_defs.remove(attr_def)
|
||||
return value
|
||||
|
||||
def reset_values(self):
|
||||
self._data = {}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,9 @@ class CollectOtioReview(pyblish.api.InstancePlugin):
|
|||
otio_review_clips.append(otio_gap)
|
||||
|
||||
if otio_review_clips:
|
||||
instance.data["label"] += " (review)"
|
||||
# add review track to instance and change label to reflect it
|
||||
label = instance.data.get("label", instance.data["subset"])
|
||||
instance.data["label"] = label + " (review)"
|
||||
instance.data["families"] += ["review", "ftrack"]
|
||||
instance.data["otioReviewClips"] = otio_review_clips
|
||||
self.log.info(
|
||||
|
|
|
|||
|
|
@ -363,6 +363,11 @@
|
|||
"optional": true,
|
||||
"active": true
|
||||
},
|
||||
"ValidateBackdrop": {
|
||||
"enabled": true,
|
||||
"optional": true,
|
||||
"active": true
|
||||
},
|
||||
"ValidateScript": {
|
||||
"enabled": true,
|
||||
"optional": true,
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
"template_data": [
|
||||
{
|
||||
"key": "ValidateCorrectAssetName",
|
||||
"label": "Validate Correct Asset name"
|
||||
"label": "Validate Correct Asset Name"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
"template_data": [
|
||||
{
|
||||
"key": "ValidateContainers",
|
||||
"label": "ValidateContainers"
|
||||
"label": "Validate Containers"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
"collapsible": true,
|
||||
"checkbox_key": "enabled",
|
||||
"key": "ValidateKnobs",
|
||||
"label": "ValidateKnobs",
|
||||
"label": "Validate Knobs",
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
|
|
@ -104,6 +104,10 @@
|
|||
"key": "ValidateOutputResolution",
|
||||
"label": "Validate Output Resolution"
|
||||
},
|
||||
{
|
||||
"key": "ValidateBackdrop",
|
||||
"label": "Validate Backdrop"
|
||||
},
|
||||
{
|
||||
"key": "ValidateGizmo",
|
||||
"label": "Validate Gizmo (Group)"
|
||||
|
|
|
|||
|
|
@ -361,10 +361,11 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
|
|||
version_data.get("endFrame", None)
|
||||
)
|
||||
|
||||
handles_label = None
|
||||
handle_start = version_data.get("handleStart", None)
|
||||
handle_end = version_data.get("handleEnd", None)
|
||||
if handle_start is not None and handle_end is not None:
|
||||
handles = "{}-{}".format(str(handle_start), str(handle_end))
|
||||
handles_label = "{}-{}".format(str(handle_start), str(handle_end))
|
||||
|
||||
if frame_start is not None and frame_end is not None:
|
||||
# Remove superfluous zeros from numbers (3.0 -> 3) to improve
|
||||
|
|
@ -401,7 +402,7 @@ class SubsetsModel(TreeModel, BaseRepresentationModel):
|
|||
"frameStart": frame_start,
|
||||
"frameEnd": frame_end,
|
||||
"duration": duration,
|
||||
"handles": handles,
|
||||
"handles": handles_label,
|
||||
"frames": frames,
|
||||
"step": version_data.get("step", None),
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue