mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-02 08:54:53 +01:00
Merge branch 'develop' into enhancement/OP-5751_render-multiple-cameras
This commit is contained in:
commit
b5e48bfb47
87 changed files with 2176 additions and 801 deletions
8
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
8
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -35,6 +35,10 @@ body:
|
|||
label: Version
|
||||
description: What version are you running? Look to OpenPype Tray
|
||||
options:
|
||||
- 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
|
||||
- 3.15.9
|
||||
|
|
@ -131,10 +135,6 @@ body:
|
|||
- 3.14.3-nightly.7
|
||||
- 3.14.3-nightly.6
|
||||
- 3.14.3-nightly.5
|
||||
- 3.14.3-nightly.4
|
||||
- 3.14.3-nightly.3
|
||||
- 3.14.3-nightly.2
|
||||
- 3.14.3-nightly.1
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
|
|
|||
393
CHANGELOG.md
393
CHANGELOG.md
|
|
@ -1,6 +1,399 @@
|
|||
# Changelog
|
||||
|
||||
|
||||
## [3.15.10](https://github.com/ynput/OpenPype/tree/3.15.10)
|
||||
|
||||
|
||||
[Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.9...3.15.10)
|
||||
|
||||
### **🆕 New features**
|
||||
|
||||
|
||||
<details>
|
||||
<summary>ImageIO: Adding ImageIO activation toggle to all hosts <a href="https://github.com/ynput/OpenPype/pull/4700">#4700</a></summary>
|
||||
|
||||
Colorspace management can now be enabled at the project level, although it is disabled by default. Once enabled, all hosts will use the OCIO config file defined in the settings. If settings are disabled, the system switches to DCC's native color space management, and we do not store colorspace information at the representative level.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Redshift Proxy Support in 3dsMax <a href="https://github.com/ynput/OpenPype/pull/4625">#4625</a></summary>
|
||||
|
||||
Redshift Proxy Support for 3dsMax.
|
||||
- [x] Creator
|
||||
- [x] Loader
|
||||
- [x] Extractor
|
||||
- [x] Validator
|
||||
- [x] Add documentation
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Houdini farm publishing and rendering <a href="https://github.com/ynput/OpenPype/pull/4825">#4825</a></summary>
|
||||
|
||||
Deadline Farm publishing and Rendering for Houdini
|
||||
- [x] Mantra
|
||||
- [x] Karma(including usd renders)
|
||||
- [x] Arnold
|
||||
- [x] Elaborate Redshift ROP for deadline submission
|
||||
- [x] fix the existing bug in Redshift ROP
|
||||
- [x] Vray
|
||||
- [x] add docs
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Feature: Blender hook to execute python scripts at launch <a href="https://github.com/ynput/OpenPype/pull/4905">#4905</a></summary>
|
||||
|
||||
Hook to allow hooks to add path to a python script that will be executed when Blender starts.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Feature: Resolve: Open last workfile on launch through .scriptlib <a href="https://github.com/ynput/OpenPype/pull/5047">#5047</a></summary>
|
||||
|
||||
Added implementation to Resolve integration to open last workfile on launch.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>General: Remove default windowFlags from publisher <a href="https://github.com/ynput/OpenPype/pull/5089">#5089</a></summary>
|
||||
|
||||
The default windowFlags is making the publisher window (in Linux at least) only show the close button and it's frustrating as many times you just want to minimize the window and get back to the validation after. Removing that line I get what I'd expect.**Before:****After:**
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>General: Show user who created the workfile on the details pane of workfile manager <a href="https://github.com/ynput/OpenPype/pull/5093">#5093</a></summary>
|
||||
|
||||
New PR for https://github.com/ynput/OpenPype/pull/5087, which was closed after merging `next-minor` branch and then realizing we don't need to target it as it was decided it's not required to support windows. More info on that PR discussion.Small addition to add name of the `user` who created the workfile on the details pane of the workfile manager:
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Loader: Hide inactive versions in UI <a href="https://github.com/ynput/OpenPype/pull/5100">#5100</a></summary>
|
||||
|
||||
Hide versions with `active` set to `False` in Loader UI.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
### **🚀 Enhancements**
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Repair RenderPass token when merging AOVs. <a href="https://github.com/ynput/OpenPype/pull/5055">#5055</a></summary>
|
||||
|
||||
Validator was flagging that `<RenderPass>` was in the image prefix, but did not repair the issue.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Improve error feedback when no renderable cameras exist for ASS family. <a href="https://github.com/ynput/OpenPype/pull/5092">#5092</a></summary>
|
||||
|
||||
When collecting cameras for `ass` family, this improves the error message when no cameras are renderable.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Nuke: Custom script to set frame range of read nodes <a href="https://github.com/ynput/OpenPype/pull/5039">#5039</a></summary>
|
||||
|
||||
Adding option to set frame range specifically for the read nodes in Openpype Panel. User can set up their preferred frame range with the frame range dialog, which can be showed after clicking `Set Frame Range (Read Node)` in Openpype Tools
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Update extract review letterbox docs <a href="https://github.com/ynput/OpenPype/pull/5074">#5074</a></summary>
|
||||
|
||||
Update Extract Review - Letter Box section in Docs. Letterbox type description is removed.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Project pack: Documents only skips roots validation <a href="https://github.com/ynput/OpenPype/pull/5082">#5082</a></summary>
|
||||
|
||||
Single roots validation is skipped if only documents are extracted.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Nuke: custom settings for write node without publish <a href="https://github.com/ynput/OpenPype/pull/5084">#5084</a></summary>
|
||||
|
||||
Set Render Output and other settings to write nodes for non-publish purposes.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
### **🐛 Bug fixes**
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Deadline servers <a href="https://github.com/ynput/OpenPype/pull/5052">#5052</a></summary>
|
||||
|
||||
Fix working with multiple Deadline servers in Maya.
|
||||
- Pools (primary and secondary) attributes were not recreated correctly.
|
||||
- Order of collector plugins were wrong, so collected data was not injected into render instances.
|
||||
- Server attribute was not converted to string so comparing with settings was incorrect.
|
||||
- Improve debug logging for where the webservice url is getting fetched from.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Fix Load Reference. <a href="https://github.com/ynput/OpenPype/pull/5091">#5091</a></summary>
|
||||
|
||||
Fix bug introduced with https://github.com/ynput/OpenPype/pull/4751 where `cmds.ls` returns a list.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>3dsmax: Publishing Deadline jobs from RedShift <a href="https://github.com/ynput/OpenPype/pull/4960">#4960</a></summary>
|
||||
|
||||
Fix the bug of being uable to publish deadline jobs from RedshiftUse Current File instead of Published Scene for just Redshift.
|
||||
- add save scene before rendering to ensure the scene is saved after the modification.
|
||||
- add separated aov files option to allow users to choose to have aovs in render output
|
||||
- add validator for render publish to aovid overriding the previous renders
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Houdini: Fix missing frame range for pointcache and camera exports <a href="https://github.com/ynput/OpenPype/pull/5026">#5026</a></summary>
|
||||
|
||||
Fix missing frame range for pointcache and camera exports on published version.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Global: collect_frame_fix plugin fix and cleanup <a href="https://github.com/ynput/OpenPype/pull/5064">#5064</a></summary>
|
||||
|
||||
Previous implementation https://github.com/ynput/OpenPype/pull/5036 was broken this is fixing the issue where attribute is found in instance data although the settings were disabled for the plugin.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Hiero: Fix apply settings Clip Load <a href="https://github.com/ynput/OpenPype/pull/5073">#5073</a></summary>
|
||||
|
||||
Changed `apply_settings` to classmethod which fixes the issue with settings.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Resolve: Make sure scripts dir exists <a href="https://github.com/ynput/OpenPype/pull/5078">#5078</a></summary>
|
||||
|
||||
Make sure the scripts directory exists before looping over it's content.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>removing info knob from nuke creators <a href="https://github.com/ynput/OpenPype/pull/5083">#5083</a></summary>
|
||||
|
||||
- removing instance node if removed via publisher
|
||||
- removing info knob since it is not needed any more (was there only for the transition phase)
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Tray: Fix restart arguments on update <a href="https://github.com/ynput/OpenPype/pull/5085">#5085</a></summary>
|
||||
|
||||
Fix arguments on restart.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: bug fix on repair action in Arnold Scene Source CBID Validator <a href="https://github.com/ynput/OpenPype/pull/5096">#5096</a></summary>
|
||||
|
||||
Fix the bug of not being able to use repair action in Arnold Scene Source CBID Validator
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Nuke: batch of small fixes <a href="https://github.com/ynput/OpenPype/pull/5103">#5103</a></summary>
|
||||
|
||||
- default settings for `imageio.requiredNodes` **CreateWriteImage**
|
||||
- default settings for **LoadImage** representations
|
||||
- **Create** and **Publish** menu items with `parent=main_window` (version > 14)
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Deadline: make prerender check safer <a href="https://github.com/ynput/OpenPype/pull/5104">#5104</a></summary>
|
||||
|
||||
Prerender wasn't correctly recognized and was replaced with just 'render' family.In Nuke it is correctly `prerender.farm` in families, which wasn't handled here. It resulted into using `render` in templates even if `render` and `prerender` templates were split.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>General: Sort launcher actions alphabetically <a href="https://github.com/ynput/OpenPype/pull/5106">#5106</a></summary>
|
||||
|
||||
The launcher actions weren't being sorted by its label but its name (which on the case of the apps it's the version number) and thus the order wasn't consistent and we kept getting a different order on every launch. From my debugging session, this was the result of what the `actions` variable held after the `filter_compatible_actions` function before these changes:
|
||||
```
|
||||
(Pdb) for p in actions: print(p.order, p.name)
|
||||
0 14-02
|
||||
0 14-02
|
||||
0 14-02
|
||||
0 14-02
|
||||
0 14-02
|
||||
0 19-5-493
|
||||
0 2023
|
||||
0 3-41
|
||||
0 6-01
|
||||
```This caused already a couple bugs from our artists thinking they had launched Nuke X and instead launched Nuke and telling us their Nuke was missing nodes**Before:****After:**
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>TrayPublisher: Editorial video stream discovery <a href="https://github.com/ynput/OpenPype/pull/5120">#5120</a></summary>
|
||||
|
||||
Editorial create plugin in traypublisher does not expect that first stream in input is video.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
### **🔀 Refactored code**
|
||||
|
||||
|
||||
<details>
|
||||
<summary>3dsmax: Move from deprecated interface <a href="https://github.com/ynput/OpenPype/pull/5117">#5117</a></summary>
|
||||
|
||||
`INewPublisher` interface is deprecated, this PR is changing the use to `IPublishHost` instead.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
### **Merged pull requests**
|
||||
|
||||
|
||||
<details>
|
||||
<summary>add movalex as a contributor for code <a href="https://github.com/ynput/OpenPype/pull/5076">#5076</a></summary>
|
||||
|
||||
Adds @movalex as a contributor for code.
|
||||
|
||||
This was requested by mkolar [in this comment](https://github.com/ynput/OpenPype/pull/4916#issuecomment-1571498425)
|
||||
|
||||
[skip ci]
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>3dsmax: refactor load plugins <a href="https://github.com/ynput/OpenPype/pull/5079">#5079</a></summary>
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
|
||||
|
||||
## [3.15.9](https://github.com/ynput/OpenPype/tree/3.15.9)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
from openpype.lib import PreLaunchHook
|
||||
|
||||
from openpype.pipeline.colorspace import get_imageio_config
|
||||
from openpype.pipeline.template_data import get_template_data
|
||||
|
||||
|
||||
class PreLaunchHostSetOCIO(PreLaunchHook):
|
||||
"""Set OCIO environment for the host"""
|
||||
|
||||
order = 0
|
||||
app_groups = ["substancepainter"]
|
||||
|
||||
def execute(self):
|
||||
"""Hook entry method."""
|
||||
|
||||
anatomy_data = get_template_data(
|
||||
project_doc=self.data["project_doc"],
|
||||
asset_doc=self.data["asset_doc"],
|
||||
task_name=self.data["task_name"],
|
||||
host_name=self.host_name,
|
||||
system_settings=self.data["system_settings"]
|
||||
)
|
||||
|
||||
ocio_config = get_imageio_config(
|
||||
project_name=self.data["project_doc"]["name"],
|
||||
host_name=self.host_name,
|
||||
project_settings=self.data["project_settings"],
|
||||
anatomy_data=anatomy_data,
|
||||
anatomy=self.data["anatomy"]
|
||||
)
|
||||
|
||||
if ocio_config:
|
||||
ocio_path = ocio_config["path"]
|
||||
self.log.info(f"Setting OCIO config path: {ocio_path}")
|
||||
self.launch_context.env["OCIO"] = ocio_path
|
||||
else:
|
||||
self.log.debug("OCIO not set or enabled")
|
||||
|
|
@ -1,12 +1,27 @@
|
|||
from openpype.lib import PreLaunchHook
|
||||
|
||||
from openpype.pipeline.colorspace import get_imageio_config
|
||||
from openpype.pipeline.colorspace import (
|
||||
get_imageio_config
|
||||
)
|
||||
from openpype.pipeline.template_data import get_template_data_with_names
|
||||
|
||||
|
||||
class FusionPreLaunchOCIO(PreLaunchHook):
|
||||
"""Set OCIO environment variable for Fusion"""
|
||||
app_groups = ["fusion"]
|
||||
class OCIOEnvHook(PreLaunchHook):
|
||||
"""Set OCIO environment variable for hosts that use OpenColorIO."""
|
||||
|
||||
order = 0
|
||||
hosts = [
|
||||
"substancepainter",
|
||||
"fusion",
|
||||
"blender",
|
||||
"aftereffects",
|
||||
"max",
|
||||
"houdini",
|
||||
"maya",
|
||||
"nuke",
|
||||
"hiero",
|
||||
"resolve"
|
||||
]
|
||||
|
||||
def execute(self):
|
||||
"""Hook entry method."""
|
||||
|
|
@ -26,7 +41,13 @@ class FusionPreLaunchOCIO(PreLaunchHook):
|
|||
anatomy_data=template_data,
|
||||
anatomy=self.data["anatomy"]
|
||||
)
|
||||
ocio_path = config_data["path"]
|
||||
|
||||
self.log.info(f"Setting OCIO config path: {ocio_path}")
|
||||
self.launch_context.env["OCIO"] = ocio_path
|
||||
if config_data:
|
||||
ocio_path = config_data["path"]
|
||||
|
||||
self.log.info(
|
||||
f"Setting OCIO environment to config path: {ocio_path}")
|
||||
|
||||
self.launch_context.env["OCIO"] = ocio_path
|
||||
else:
|
||||
self.log.debug("OCIO not set or enabled")
|
||||
|
|
@ -10,6 +10,7 @@ from qtpy import QtCore, QtWidgets
|
|||
from openpype import style
|
||||
from openpype.lib import Logger, StringTemplate
|
||||
from openpype.pipeline import LegacyCreator, LoaderPlugin
|
||||
from openpype.pipeline.colorspace import get_remapped_colorspace_to_native
|
||||
from openpype.settings import get_current_project_settings
|
||||
|
||||
from . import constants
|
||||
|
|
@ -701,6 +702,7 @@ class ClipLoader(LoaderPlugin):
|
|||
]
|
||||
|
||||
_mapping = None
|
||||
_host_settings = None
|
||||
|
||||
def apply_settings(cls, project_settings, system_settings):
|
||||
|
||||
|
|
@ -769,15 +771,26 @@ class ClipLoader(LoaderPlugin):
|
|||
Returns:
|
||||
str: native colorspace name defined in mapping or None
|
||||
"""
|
||||
# TODO: rewrite to support only pipeline's remapping
|
||||
if not cls._host_settings:
|
||||
cls._host_settings = get_current_project_settings()["flame"]
|
||||
|
||||
# [Deprecated] way of remapping
|
||||
if not cls._mapping:
|
||||
settings = get_current_project_settings()["flame"]
|
||||
mapping = settings["imageio"]["profilesMapping"]["inputs"]
|
||||
mapping = (
|
||||
cls._host_settings["imageio"]["profilesMapping"]["inputs"])
|
||||
cls._mapping = {
|
||||
input["ocioName"]: input["flameName"]
|
||||
for input in mapping
|
||||
}
|
||||
|
||||
return cls._mapping.get(input_colorspace)
|
||||
native_name = cls._mapping.get(input_colorspace)
|
||||
|
||||
if not native_name:
|
||||
native_name = get_remapped_colorspace_to_native(
|
||||
input_colorspace, "flame", cls._host_settings["imageio"])
|
||||
|
||||
return native_name
|
||||
|
||||
|
||||
class OpenClipSolver(flib.MediaInfoFile):
|
||||
|
|
|
|||
|
|
@ -47,6 +47,17 @@ class FlamePrelaunch(PreLaunchHook):
|
|||
|
||||
imageio_flame = project_settings["flame"]["imageio"]
|
||||
|
||||
# Check whether 'enabled' key from host imageio settings exists
|
||||
# so we can tell if host is using the new colormanagement framework.
|
||||
# If the 'enabled' isn't found we want 'colormanaged' set to True
|
||||
# because prior to the key existing we always did colormanagement for
|
||||
# Flame
|
||||
colormanaged = imageio_flame.get("enabled")
|
||||
# if key was not found, set to True
|
||||
# ensuring backward compatibility
|
||||
if colormanaged is None:
|
||||
colormanaged = True
|
||||
|
||||
# get user name and host name
|
||||
user_name = get_openpype_username()
|
||||
user_name = user_name.replace(".", "_")
|
||||
|
|
@ -68,9 +79,7 @@ class FlamePrelaunch(PreLaunchHook):
|
|||
"FrameWidth": int(width),
|
||||
"FrameHeight": int(height),
|
||||
"AspectRatio": float((width / height) * _db_p_data["pixelAspect"]),
|
||||
"FrameRate": self._get_flame_fps(fps),
|
||||
"FrameDepth": str(imageio_flame["project"]["frameDepth"]),
|
||||
"FieldDominance": str(imageio_flame["project"]["fieldDominance"])
|
||||
"FrameRate": self._get_flame_fps(fps)
|
||||
}
|
||||
|
||||
data_to_script = {
|
||||
|
|
@ -78,7 +87,6 @@ class FlamePrelaunch(PreLaunchHook):
|
|||
"host_name": _env.get("FLAME_WIRETAP_HOSTNAME") or hostname,
|
||||
"volume_name": volume_name,
|
||||
"group_name": _env.get("FLAME_WIRETAP_GROUP"),
|
||||
"color_policy": str(imageio_flame["project"]["colourPolicy"]),
|
||||
|
||||
# from project
|
||||
"project_name": project_name,
|
||||
|
|
@ -86,6 +94,16 @@ class FlamePrelaunch(PreLaunchHook):
|
|||
"project_data": project_data
|
||||
}
|
||||
|
||||
# add color management data
|
||||
if colormanaged:
|
||||
project_data.update({
|
||||
"FrameDepth": str(imageio_flame["project"]["frameDepth"]),
|
||||
"FieldDominance": str(
|
||||
imageio_flame["project"]["fieldDominance"])
|
||||
})
|
||||
data_to_script["color_policy"] = str(
|
||||
imageio_flame["project"]["colourPolicy"])
|
||||
|
||||
self.log.info(pformat(dict(_env)))
|
||||
self.log.info(pformat(data_to_script))
|
||||
|
||||
|
|
|
|||
|
|
@ -23,11 +23,17 @@ except ImportError:
|
|||
|
||||
from openpype.client import get_project
|
||||
from openpype.settings import get_project_settings
|
||||
from openpype.pipeline import legacy_io, Anatomy
|
||||
from openpype.pipeline import (
|
||||
get_current_project_name, legacy_io, Anatomy
|
||||
)
|
||||
from openpype.pipeline.load import filter_containers
|
||||
from openpype.lib import Logger
|
||||
from . import tags
|
||||
|
||||
from openpype.pipeline.colorspace import (
|
||||
get_imageio_config
|
||||
)
|
||||
|
||||
|
||||
class DeprecatedWarning(DeprecationWarning):
|
||||
pass
|
||||
|
|
@ -1047,6 +1053,18 @@ def apply_colorspace_project():
|
|||
imageio = get_project_settings(project_name)["hiero"]["imageio"]
|
||||
presets = imageio.get("workfile")
|
||||
|
||||
# backward compatibility layer
|
||||
# TODO: remove this after some time
|
||||
config_data = get_imageio_config(
|
||||
project_name=get_current_project_name(),
|
||||
host_name="hiero"
|
||||
)
|
||||
|
||||
if config_data:
|
||||
presets.update({
|
||||
"ocioConfigName": "custom"
|
||||
})
|
||||
|
||||
# save the workfile as subversion "comment:_colorspaceChange"
|
||||
split_current_file = os.path.splitext(current_file)
|
||||
copy_current_file = current_file
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"""Standalone helper functions"""
|
||||
|
||||
import os
|
||||
from pprint import pformat
|
||||
import sys
|
||||
import platform
|
||||
import uuid
|
||||
|
|
@ -3239,75 +3240,6 @@ def iter_shader_edits(relationships, shader_nodes, nodes_by_id, label=None):
|
|||
def set_colorspace():
|
||||
"""Set Colorspace from project configuration
|
||||
"""
|
||||
project_name = os.getenv("AVALON_PROJECT")
|
||||
imageio = get_project_settings(project_name)["maya"]["imageio"]
|
||||
|
||||
# Maya 2022+ introduces new OCIO v2 color management settings that
|
||||
# can override the old color managenement preferences. OpenPype has
|
||||
# separate settings for both so we fall back when necessary.
|
||||
use_ocio_v2 = imageio["colorManagementPreference_v2"]["enabled"]
|
||||
required_maya_version = 2022
|
||||
maya_version = int(cmds.about(version=True))
|
||||
maya_supports_ocio_v2 = maya_version >= required_maya_version
|
||||
if use_ocio_v2 and not maya_supports_ocio_v2:
|
||||
# Fallback to legacy behavior with a warning
|
||||
log.warning("Color Management Preference v2 is enabled but not "
|
||||
"supported by current Maya version: {} (< {}). Falling "
|
||||
"back to legacy settings.".format(
|
||||
maya_version, required_maya_version)
|
||||
)
|
||||
use_ocio_v2 = False
|
||||
|
||||
if use_ocio_v2:
|
||||
root_dict = imageio["colorManagementPreference_v2"]
|
||||
else:
|
||||
root_dict = imageio["colorManagementPreference"]
|
||||
|
||||
if not isinstance(root_dict, dict):
|
||||
msg = "set_colorspace(): argument should be dictionary"
|
||||
log.error(msg)
|
||||
|
||||
log.debug(">> root_dict: {}".format(root_dict))
|
||||
|
||||
# enable color management
|
||||
cmds.colorManagementPrefs(e=True, cmEnabled=True)
|
||||
cmds.colorManagementPrefs(e=True, ocioRulesEnabled=True)
|
||||
|
||||
# set config path
|
||||
custom_ocio_config = False
|
||||
if root_dict.get("configFilePath"):
|
||||
unresolved_path = root_dict["configFilePath"]
|
||||
ocio_paths = unresolved_path[platform.system().lower()]
|
||||
|
||||
resolved_path = None
|
||||
for ocio_p in ocio_paths:
|
||||
resolved_path = str(ocio_p).format(**os.environ)
|
||||
if not os.path.exists(resolved_path):
|
||||
continue
|
||||
|
||||
if resolved_path:
|
||||
filepath = str(resolved_path).replace("\\", "/")
|
||||
cmds.colorManagementPrefs(e=True, configFilePath=filepath)
|
||||
cmds.colorManagementPrefs(e=True, cmConfigFileEnabled=True)
|
||||
log.debug("maya '{}' changed to: {}".format(
|
||||
"configFilePath", resolved_path))
|
||||
custom_ocio_config = True
|
||||
else:
|
||||
cmds.colorManagementPrefs(e=True, cmConfigFileEnabled=False)
|
||||
cmds.colorManagementPrefs(e=True, configFilePath="")
|
||||
|
||||
# If no custom OCIO config file was set we make sure that Maya 2022+
|
||||
# either chooses between Maya's newer default v2 or legacy config based
|
||||
# on OpenPype setting to use ocio v2 or not.
|
||||
if maya_supports_ocio_v2 and not custom_ocio_config:
|
||||
if use_ocio_v2:
|
||||
# Use Maya 2022+ default OCIO v2 config
|
||||
log.info("Setting default Maya OCIO v2 config")
|
||||
cmds.colorManagementPrefs(edit=True, configFilePath="")
|
||||
else:
|
||||
# Set the Maya default config file path
|
||||
log.info("Setting default Maya OCIO v1 legacy config")
|
||||
cmds.colorManagementPrefs(edit=True, configFilePath="legacy")
|
||||
|
||||
# set color spaces for rendering space and view transforms
|
||||
def _colormanage(**kwargs):
|
||||
|
|
@ -3324,17 +3256,74 @@ def set_colorspace():
|
|||
except RuntimeError as exc:
|
||||
log.error(exc)
|
||||
|
||||
if use_ocio_v2:
|
||||
_colormanage(renderingSpaceName=root_dict["renderSpace"])
|
||||
_colormanage(displayName=root_dict["displayName"])
|
||||
_colormanage(viewName=root_dict["viewName"])
|
||||
else:
|
||||
_colormanage(renderingSpaceName=root_dict["renderSpace"])
|
||||
if maya_supports_ocio_v2:
|
||||
_colormanage(viewName=root_dict["viewTransform"])
|
||||
_colormanage(displayName="legacy")
|
||||
project_name = os.getenv("AVALON_PROJECT")
|
||||
imageio = get_project_settings(project_name)["maya"]["imageio"]
|
||||
|
||||
# ocio compatibility variables
|
||||
ocio_v2_maya_version = 2022
|
||||
maya_version = int(cmds.about(version=True))
|
||||
ocio_v2_support = use_ocio_v2 = maya_version >= ocio_v2_maya_version
|
||||
|
||||
root_dict = {}
|
||||
use_workfile_settings = imageio.get("workfile", {}).get("enabled")
|
||||
|
||||
if use_workfile_settings:
|
||||
# TODO: deprecated code from 3.15.5 - remove
|
||||
# Maya 2022+ introduces new OCIO v2 color management settings that
|
||||
# can override the old color management preferences. OpenPype has
|
||||
# separate settings for both so we fall back when necessary.
|
||||
use_ocio_v2 = imageio["colorManagementPreference_v2"]["enabled"]
|
||||
if use_ocio_v2 and not ocio_v2_support:
|
||||
# Fallback to legacy behavior with a warning
|
||||
log.warning(
|
||||
"Color Management Preference v2 is enabled but not "
|
||||
"supported by current Maya version: {} (< {}). Falling "
|
||||
"back to legacy settings.".format(
|
||||
maya_version, ocio_v2_maya_version)
|
||||
)
|
||||
|
||||
if use_ocio_v2:
|
||||
root_dict = imageio["colorManagementPreference_v2"]
|
||||
else:
|
||||
_colormanage(viewTransformName=root_dict["viewTransform"])
|
||||
root_dict = imageio["colorManagementPreference"]
|
||||
|
||||
if not isinstance(root_dict, dict):
|
||||
msg = "set_colorspace(): argument should be dictionary"
|
||||
log.error(msg)
|
||||
|
||||
else:
|
||||
root_dict = imageio["workfile"]
|
||||
|
||||
log.debug(">> root_dict: {}".format(pformat(root_dict)))
|
||||
|
||||
if root_dict:
|
||||
# enable color management
|
||||
cmds.colorManagementPrefs(e=True, cmEnabled=True)
|
||||
cmds.colorManagementPrefs(e=True, ocioRulesEnabled=True)
|
||||
|
||||
# backward compatibility
|
||||
# TODO: deprecated code from 3.15.5 - refactor to use new settings
|
||||
view_name = root_dict.get("viewTransform")
|
||||
if view_name is None:
|
||||
view_name = root_dict.get("viewName")
|
||||
|
||||
if use_ocio_v2:
|
||||
# Use Maya 2022+ default OCIO v2 config
|
||||
log.info("Setting default Maya OCIO v2 config")
|
||||
cmds.colorManagementPrefs(edit=True, configFilePath="")
|
||||
|
||||
# set rendering space and view transform
|
||||
_colormanage(renderingSpaceName=root_dict["renderSpace"])
|
||||
_colormanage(viewName=view_name)
|
||||
_colormanage(displayName=root_dict["displayName"])
|
||||
else:
|
||||
# Set the Maya default config file path
|
||||
log.info("Setting default Maya OCIO v1 legacy config")
|
||||
cmds.colorManagementPrefs(edit=True, configFilePath="legacy")
|
||||
|
||||
# set rendering space and view transform
|
||||
_colormanage(renderingSpaceName=root_dict["renderSpace"])
|
||||
_colormanage(viewTransformName=view_name)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
|
|
|
|||
|
|
@ -273,6 +273,11 @@ class FileNodeLoader(load.LoaderPlugin):
|
|||
project_name, host_name,
|
||||
project_settings=project_settings
|
||||
)
|
||||
|
||||
# ignore if host imageio is not enabled
|
||||
if not config_data:
|
||||
return
|
||||
|
||||
file_rules = get_imageio_file_rules(
|
||||
project_name, host_name,
|
||||
project_settings=project_settings
|
||||
|
|
|
|||
|
|
@ -274,16 +274,18 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin):
|
|||
|
||||
# go through definitions and test if such node.attribute exists.
|
||||
# if so, compare its value from the one required.
|
||||
for attribute, data in cls.get_nodes(instance, renderer).items():
|
||||
for data in cls.get_nodes(instance, renderer):
|
||||
for node in data["nodes"]:
|
||||
try:
|
||||
render_value = cmds.getAttr(
|
||||
"{}.{}".format(node, attribute)
|
||||
"{}.{}".format(node, data["attribute"])
|
||||
)
|
||||
except RuntimeError:
|
||||
invalid = True
|
||||
cls.log.error(
|
||||
"Cannot get value of {}.{}".format(node, attribute)
|
||||
"Cannot get value of {}.{}".format(
|
||||
node, data["attribute"]
|
||||
)
|
||||
)
|
||||
else:
|
||||
if render_value not in data["values"]:
|
||||
|
|
@ -291,7 +293,10 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin):
|
|||
cls.log.error(
|
||||
"Invalid value {} set on {}.{}. Expecting "
|
||||
"{}".format(
|
||||
render_value, node, attribute, data["values"]
|
||||
render_value,
|
||||
node,
|
||||
data["attribute"],
|
||||
data["values"]
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -305,7 +310,7 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin):
|
|||
"{}_render_attributes".format(renderer)
|
||||
) or []
|
||||
)
|
||||
result = {}
|
||||
result = []
|
||||
for attr, values in OrderedDict(validation_settings).items():
|
||||
values = [convert_to_int_or_float(v) for v in values if v]
|
||||
|
||||
|
|
@ -335,7 +340,13 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin):
|
|||
)
|
||||
continue
|
||||
|
||||
result[attribute_name] = {"nodes": nodes, "values": values}
|
||||
result.append(
|
||||
{
|
||||
"attribute": attribute_name,
|
||||
"nodes": nodes,
|
||||
"values": values
|
||||
}
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
|
|
@ -350,11 +361,11 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin):
|
|||
"{aov_separator}", instance.data.get("aovSeparator", "_")
|
||||
)
|
||||
|
||||
for attribute, data in cls.get_nodes(instance, renderer).items():
|
||||
for data in cls.get_nodes(instance, renderer):
|
||||
if not data["values"]:
|
||||
continue
|
||||
for node in data["nodes"]:
|
||||
lib.set_attribute(attribute, data["values"][0], node)
|
||||
lib.set_attribute(data["attribute"], data["values"][0], node)
|
||||
|
||||
with lib.renderlayer(layer_node):
|
||||
default = lib.RENDER_ATTRS['default']
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ from openpype.settings import (
|
|||
from openpype.modules import ModulesManager
|
||||
from openpype.pipeline.template_data import get_template_data_with_names
|
||||
from openpype.pipeline import (
|
||||
get_current_project_name,
|
||||
discover_legacy_creator_plugins,
|
||||
legacy_io,
|
||||
Anatomy,
|
||||
|
|
@ -2001,63 +2002,72 @@ class WorkfileSettings(object):
|
|||
"Attention! Viewer nodes {} were erased."
|
||||
"It had wrong color profile".format(erased_viewers))
|
||||
|
||||
def set_root_colorspace(self, nuke_colorspace):
|
||||
def set_root_colorspace(self, imageio_host):
|
||||
''' Adds correct colorspace to root
|
||||
|
||||
Arguments:
|
||||
nuke_colorspace (dict): adjustmensts from presets
|
||||
imageio_host (dict): host colorspace configurations
|
||||
|
||||
'''
|
||||
workfile_settings = nuke_colorspace["workfile"]
|
||||
config_data = get_imageio_config(
|
||||
project_name=get_current_project_name(),
|
||||
host_name="nuke"
|
||||
)
|
||||
|
||||
# resolve config data if they are enabled in host
|
||||
config_data = None
|
||||
if nuke_colorspace.get("ocio_config", {}).get("enabled"):
|
||||
# switch ocio config to custom config
|
||||
workfile_settings["OCIO_config"] = "custom"
|
||||
workfile_settings["colorManagement"] = "OCIO"
|
||||
workfile_settings = imageio_host["workfile"]
|
||||
|
||||
# get resolved ocio config path
|
||||
config_data = get_imageio_config(
|
||||
legacy_io.active_project(), "nuke"
|
||||
)
|
||||
if not config_data:
|
||||
# TODO: backward compatibility for old projects - remove later
|
||||
# perhaps old project overrides is having it set to older version
|
||||
# with use of `customOCIOConfigPath`
|
||||
resolved_path = None
|
||||
if workfile_settings.get("customOCIOConfigPath"):
|
||||
unresolved_path = workfile_settings["customOCIOConfigPath"]
|
||||
ocio_paths = unresolved_path[platform.system().lower()]
|
||||
|
||||
# first set OCIO
|
||||
if self._root_node["colorManagement"].value() \
|
||||
not in str(workfile_settings["colorManagement"]):
|
||||
self._root_node["colorManagement"].setValue(
|
||||
str(workfile_settings["colorManagement"]))
|
||||
for ocio_p in ocio_paths:
|
||||
resolved_path = str(ocio_p).format(**os.environ)
|
||||
if not os.path.exists(resolved_path):
|
||||
continue
|
||||
|
||||
# we dont need the key anymore
|
||||
workfile_settings.pop("colorManagement")
|
||||
if resolved_path:
|
||||
# set values to root
|
||||
self._root_node["colorManagement"].setValue("OCIO")
|
||||
self._root_node["OCIO_config"].setValue("custom")
|
||||
self._root_node["customOCIOConfigPath"].setValue(
|
||||
resolved_path)
|
||||
else:
|
||||
# no ocio config found and no custom path used
|
||||
if self._root_node["colorManagement"].value() \
|
||||
not in str(workfile_settings["colorManagement"]):
|
||||
self._root_node["colorManagement"].setValue(
|
||||
str(workfile_settings["colorManagement"]))
|
||||
|
||||
# second set ocio version
|
||||
if self._root_node["OCIO_config"].value() \
|
||||
not in str(workfile_settings["OCIO_config"]):
|
||||
self._root_node["OCIO_config"].setValue(
|
||||
str(workfile_settings["OCIO_config"]))
|
||||
# second set ocio version
|
||||
if self._root_node["OCIO_config"].value() \
|
||||
not in str(workfile_settings["OCIO_config"]):
|
||||
self._root_node["OCIO_config"].setValue(
|
||||
str(workfile_settings["OCIO_config"]))
|
||||
|
||||
# we dont need the key anymore
|
||||
workfile_settings.pop("OCIO_config")
|
||||
else:
|
||||
# set values to root
|
||||
self._root_node["colorManagement"].setValue("OCIO")
|
||||
|
||||
# third set ocio custom path
|
||||
if config_data:
|
||||
self._root_node["customOCIOConfigPath"].setValue(
|
||||
str(config_data["path"]).replace("\\", "/")
|
||||
)
|
||||
# backward compatibility, remove in case it exists
|
||||
workfile_settings.pop("customOCIOConfigPath")
|
||||
# we dont need the key anymore
|
||||
workfile_settings.pop("customOCIOConfigPath", None)
|
||||
workfile_settings.pop("colorManagement", None)
|
||||
workfile_settings.pop("OCIO_config", None)
|
||||
|
||||
# then set the rest
|
||||
for knob, value in workfile_settings.items():
|
||||
for knob, value_ in workfile_settings.items():
|
||||
# skip unfilled ocio config path
|
||||
# it will be dict in value
|
||||
if isinstance(value, dict):
|
||||
if isinstance(value_, dict):
|
||||
continue
|
||||
if self._root_node[knob].value() not in value:
|
||||
self._root_node[knob].setValue(str(value))
|
||||
if self._root_node[knob].value() not in value_:
|
||||
self._root_node[knob].setValue(str(value_))
|
||||
log.debug("nuke.root()['{}'] changed to: {}".format(
|
||||
knob, value))
|
||||
knob, value_))
|
||||
|
||||
def set_writes_colorspace(self):
|
||||
''' Adds correct colorspace to write node dict
|
||||
|
|
|
|||
|
|
@ -237,15 +237,25 @@ def _install_menu():
|
|||
|
||||
menu.addSeparator()
|
||||
if not ASSIST:
|
||||
# only add parent if nuke version is 14 or higher
|
||||
# known issue with no solution yet
|
||||
menu.addCommand(
|
||||
"Create...",
|
||||
lambda: host_tools.show_publisher(
|
||||
parent=(
|
||||
main_window if nuke.NUKE_VERSION_RELEASE >= 14 else None
|
||||
),
|
||||
tab="create"
|
||||
)
|
||||
)
|
||||
# only add parent if nuke version is 14 or higher
|
||||
# known issue with no solution yet
|
||||
menu.addCommand(
|
||||
"Publish...",
|
||||
lambda: host_tools.show_publisher(
|
||||
parent=(
|
||||
main_window if nuke.NUKE_VERSION_RELEASE >= 14 else None
|
||||
),
|
||||
tab="publish"
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class NukeRenderLocal(publish.Extractor,
|
|||
order = pyblish.api.ExtractorOrder
|
||||
label = "Render Local"
|
||||
hosts = ["nuke"]
|
||||
families = ["render.local", "prerender.local", "still.local"]
|
||||
families = ["render.local", "prerender.local", "image.local"]
|
||||
|
||||
def process(self, instance):
|
||||
child_nodes = (
|
||||
|
|
@ -136,9 +136,9 @@ class NukeRenderLocal(publish.Extractor,
|
|||
families.remove('prerender.local')
|
||||
families.insert(0, "prerender")
|
||||
instance.data["anatomyData"]["family"] = "prerender"
|
||||
elif "still.local" in families:
|
||||
elif "image.local" in families:
|
||||
instance.data['family'] = 'image'
|
||||
families.remove('still.local')
|
||||
families.remove('image.local')
|
||||
instance.data["anatomyData"]["family"] = "image"
|
||||
instance.data["families"] = families
|
||||
|
||||
|
|
|
|||
|
|
@ -222,7 +222,6 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin):
|
|||
"label": subset,
|
||||
"name": subset,
|
||||
"family": in_data["family"],
|
||||
# "version": in_data.get("version", 1),
|
||||
"frameStart": in_data.get("representations", [None])[0].get(
|
||||
"frameStart", None
|
||||
),
|
||||
|
|
@ -232,6 +231,14 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin):
|
|||
"families": instance_families
|
||||
}
|
||||
)
|
||||
# Fill version only if 'use_next_available_version' is disabled
|
||||
# and version is filled in instance data
|
||||
version = in_data.get("version")
|
||||
use_next_available_version = in_data.get(
|
||||
"use_next_available_version", True)
|
||||
if not use_next_available_version and version is not None:
|
||||
instance.data["version"] = version
|
||||
|
||||
self.log.info("collected instance: {}".format(pformat(instance.data)))
|
||||
self.log.info("parsing data: {}".format(pformat(in_data)))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,14 @@
|
|||
from openpype.lib.attribute_definitions import FileDef
|
||||
from openpype.client import (
|
||||
get_assets,
|
||||
get_subsets,
|
||||
get_last_versions,
|
||||
)
|
||||
from openpype.lib.attribute_definitions import (
|
||||
FileDef,
|
||||
BoolDef,
|
||||
NumberDef,
|
||||
UISeparatorDef,
|
||||
)
|
||||
from openpype.lib.transcoding import IMAGE_EXTENSIONS, VIDEO_EXTENSIONS
|
||||
from openpype.pipeline.create import (
|
||||
Creator,
|
||||
|
|
@ -94,6 +104,7 @@ class TrayPublishCreator(Creator):
|
|||
class SettingsCreator(TrayPublishCreator):
|
||||
create_allow_context_change = True
|
||||
create_allow_thumbnail = True
|
||||
allow_version_control = False
|
||||
|
||||
extensions = []
|
||||
|
||||
|
|
@ -101,8 +112,18 @@ class SettingsCreator(TrayPublishCreator):
|
|||
# Pass precreate data to creator attributes
|
||||
thumbnail_path = pre_create_data.pop(PRE_CREATE_THUMBNAIL_KEY, None)
|
||||
|
||||
# Fill 'version_to_use' if version control is enabled
|
||||
if self.allow_version_control:
|
||||
asset_name = data["asset"]
|
||||
subset_docs_by_asset_id = self._prepare_next_versions(
|
||||
[asset_name], [subset_name])
|
||||
version = subset_docs_by_asset_id[asset_name].get(subset_name)
|
||||
pre_create_data["version_to_use"] = version
|
||||
data["_previous_last_version"] = version
|
||||
|
||||
data["creator_attributes"] = pre_create_data
|
||||
data["settings_creator"] = True
|
||||
|
||||
# Create new instance
|
||||
new_instance = CreatedInstance(self.family, subset_name, data, self)
|
||||
|
||||
|
|
@ -111,7 +132,158 @@ class SettingsCreator(TrayPublishCreator):
|
|||
if thumbnail_path:
|
||||
self.set_instance_thumbnail_path(new_instance.id, thumbnail_path)
|
||||
|
||||
def _prepare_next_versions(self, asset_names, subset_names):
|
||||
"""Prepare next versions for given asset and subset names.
|
||||
|
||||
Todos:
|
||||
Expect combination of subset names by asset name to avoid
|
||||
unnecessary server calls for unused subsets.
|
||||
|
||||
Args:
|
||||
asset_names (Iterable[str]): Asset names.
|
||||
subset_names (Iterable[str]): Subset names.
|
||||
|
||||
Returns:
|
||||
dict[str, dict[str, int]]: Last versions by asset
|
||||
and subset names.
|
||||
"""
|
||||
|
||||
# Prepare all versions for all combinations to '1'
|
||||
subset_docs_by_asset_id = {
|
||||
asset_name: {
|
||||
subset_name: 1
|
||||
for subset_name in subset_names
|
||||
}
|
||||
for asset_name in asset_names
|
||||
}
|
||||
if not asset_names or not subset_names:
|
||||
return subset_docs_by_asset_id
|
||||
|
||||
asset_docs = get_assets(
|
||||
self.project_name,
|
||||
asset_names=asset_names,
|
||||
fields=["_id", "name"]
|
||||
)
|
||||
asset_names_by_id = {
|
||||
asset_doc["_id"]: asset_doc["name"]
|
||||
for asset_doc in asset_docs
|
||||
}
|
||||
subset_docs = list(get_subsets(
|
||||
self.project_name,
|
||||
asset_ids=asset_names_by_id.keys(),
|
||||
subset_names=subset_names,
|
||||
fields=["_id", "name", "parent"]
|
||||
))
|
||||
|
||||
subset_ids = {subset_doc["_id"] for subset_doc in subset_docs}
|
||||
last_versions = get_last_versions(
|
||||
self.project_name,
|
||||
subset_ids,
|
||||
fields=["name", "parent"])
|
||||
|
||||
for subset_doc in subset_docs:
|
||||
asset_id = subset_doc["parent"]
|
||||
asset_name = asset_names_by_id[asset_id]
|
||||
subset_name = subset_doc["name"]
|
||||
subset_id = subset_doc["_id"]
|
||||
last_version = last_versions.get(subset_id)
|
||||
version = 0
|
||||
if last_version is not None:
|
||||
version = last_version["name"]
|
||||
subset_docs_by_asset_id[asset_name][subset_name] += version
|
||||
return subset_docs_by_asset_id
|
||||
|
||||
def _fill_next_versions(self, instances_data):
|
||||
"""Fill next version for instances.
|
||||
|
||||
Instances have also stored previous next version to be able to
|
||||
recognize if user did enter different version. If version was
|
||||
not changed by user, or user set it to '0' the next version will be
|
||||
updated by current database state.
|
||||
"""
|
||||
|
||||
filtered_instance_data = []
|
||||
for instance in instances_data:
|
||||
previous_last_version = instance.get("_previous_last_version")
|
||||
creator_attributes = instance["creator_attributes"]
|
||||
use_next_version = creator_attributes.get(
|
||||
"use_next_version", True)
|
||||
version = creator_attributes.get("version_to_use", 0)
|
||||
if (
|
||||
use_next_version
|
||||
or version == 0
|
||||
or version == previous_last_version
|
||||
):
|
||||
filtered_instance_data.append(instance)
|
||||
|
||||
asset_names = {
|
||||
instance["asset"]
|
||||
for instance in filtered_instance_data}
|
||||
subset_names = {
|
||||
instance["subset"]
|
||||
for instance in filtered_instance_data}
|
||||
subset_docs_by_asset_id = self._prepare_next_versions(
|
||||
asset_names, subset_names
|
||||
)
|
||||
for instance in filtered_instance_data:
|
||||
asset_name = instance["asset"]
|
||||
subset_name = instance["subset"]
|
||||
version = subset_docs_by_asset_id[asset_name][subset_name]
|
||||
instance["creator_attributes"]["version_to_use"] = version
|
||||
instance["_previous_last_version"] = version
|
||||
|
||||
def collect_instances(self):
|
||||
"""Collect instances from host.
|
||||
|
||||
Overriden to be able to manage version control attributes. If version
|
||||
control is disabled, the attributes will be removed from instances,
|
||||
and next versions are filled if is version control enabled.
|
||||
"""
|
||||
|
||||
instances_by_identifier = cache_and_get_instances(
|
||||
self, SHARED_DATA_KEY, list_instances
|
||||
)
|
||||
instances = instances_by_identifier[self.identifier]
|
||||
if not instances:
|
||||
return
|
||||
|
||||
if self.allow_version_control:
|
||||
self._fill_next_versions(instances)
|
||||
|
||||
for instance_data in instances:
|
||||
# Make sure that there are not data related to version control
|
||||
# if plugin does not support it
|
||||
if not self.allow_version_control:
|
||||
instance_data.pop("_previous_last_version", None)
|
||||
creator_attributes = instance_data["creator_attributes"]
|
||||
creator_attributes.pop("version_to_use", None)
|
||||
creator_attributes.pop("use_next_version", None)
|
||||
|
||||
instance = CreatedInstance.from_existing(instance_data, self)
|
||||
self._add_instance_to_context(instance)
|
||||
|
||||
def get_instance_attr_defs(self):
|
||||
defs = self.get_pre_create_attr_defs()
|
||||
if self.allow_version_control:
|
||||
defs += [
|
||||
UISeparatorDef(),
|
||||
BoolDef(
|
||||
"use_next_version",
|
||||
default=True,
|
||||
label="Use next version",
|
||||
),
|
||||
NumberDef(
|
||||
"version_to_use",
|
||||
default=1,
|
||||
minimum=0,
|
||||
maximum=999,
|
||||
label="Version to use",
|
||||
)
|
||||
]
|
||||
return defs
|
||||
|
||||
def get_pre_create_attr_defs(self):
|
||||
# Use same attributes as for instance attributes
|
||||
return [
|
||||
FileDef(
|
||||
"representation_files",
|
||||
|
|
@ -132,10 +304,6 @@ class SettingsCreator(TrayPublishCreator):
|
|||
)
|
||||
]
|
||||
|
||||
def get_pre_create_attr_defs(self):
|
||||
# Use same attributes as for instance attrobites
|
||||
return self.get_instance_attr_defs()
|
||||
|
||||
@classmethod
|
||||
def from_settings(cls, item_data):
|
||||
identifier = item_data["identifier"]
|
||||
|
|
@ -155,6 +323,8 @@ class SettingsCreator(TrayPublishCreator):
|
|||
"extensions": item_data["extensions"],
|
||||
"allow_sequences": item_data["allow_sequences"],
|
||||
"allow_multiple_items": item_data["allow_multiple_items"],
|
||||
"default_variants": item_data["default_variants"]
|
||||
"allow_version_control": item_data.get(
|
||||
"allow_version_control", False),
|
||||
"default_variants": item_data["default_variants"],
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ class CollectSettingsSimpleInstances(pyblish.api.InstancePlugin):
|
|||
"Created temp staging directory for instance {}. {}"
|
||||
).format(instance_label, tmp_folder))
|
||||
|
||||
self._fill_version(instance, instance_label)
|
||||
|
||||
# Store filepaths for validation of their existence
|
||||
source_filepaths = []
|
||||
# Make sure there are no representations with same name
|
||||
|
|
@ -93,6 +95,28 @@ class CollectSettingsSimpleInstances(pyblish.api.InstancePlugin):
|
|||
)
|
||||
)
|
||||
|
||||
def _fill_version(self, instance, instance_label):
|
||||
"""Fill instance version under which will be instance integrated.
|
||||
|
||||
Instance must have set 'use_next_version' to 'False'
|
||||
and 'version_to_use' to version to use.
|
||||
|
||||
Args:
|
||||
instance (pyblish.api.Instance): Instance to fill version for.
|
||||
instance_label (str): Label of instance to fill version for.
|
||||
"""
|
||||
|
||||
creator_attributes = instance.data["creator_attributes"]
|
||||
use_next_version = creator_attributes.get("use_next_version", True)
|
||||
# If 'version_to_use' is '0' it means that next version should be used
|
||||
version_to_use = creator_attributes.get("version_to_use", 0)
|
||||
if use_next_version or not version_to_use:
|
||||
return
|
||||
instance.data["version"] = version_to_use
|
||||
self.log.debug(
|
||||
"Version for instance \"{}\" was set to \"{}\"".format(
|
||||
instance_label, version_to_use))
|
||||
|
||||
def _create_main_representations(
|
||||
self,
|
||||
instance,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<root>
|
||||
<error id="main">
|
||||
<title>Version already exists</title>
|
||||
<description>
|
||||
## Version already exists
|
||||
|
||||
Version {version} you have set on instance '{subset_name}' under '{asset_name}' already exists. This validation is enabled by default to prevent accidental override of existing versions.
|
||||
|
||||
### How to repair?
|
||||
- Click on 'Repair' action -> this will change version to next available.
|
||||
- Disable validation on the instance if you are sure you want to override the version.
|
||||
- Reset publishing and manually change the version number.
|
||||
</description>
|
||||
</error>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import pyblish.api
|
||||
|
||||
from openpype.pipeline.publish import (
|
||||
ValidateContentsOrder,
|
||||
PublishXmlValidationError,
|
||||
OptionalPyblishPluginMixin,
|
||||
RepairAction,
|
||||
)
|
||||
|
||||
|
||||
class ValidateExistingVersion(
|
||||
OptionalPyblishPluginMixin,
|
||||
pyblish.api.InstancePlugin
|
||||
):
|
||||
label = "Validate Existing Version"
|
||||
order = ValidateContentsOrder
|
||||
|
||||
hosts = ["traypublisher"]
|
||||
|
||||
actions = [RepairAction]
|
||||
|
||||
settings_category = "traypublisher"
|
||||
optional = True
|
||||
|
||||
def process(self, instance):
|
||||
if not self.is_active(instance.data):
|
||||
return
|
||||
|
||||
version = instance.data.get("version")
|
||||
if version is None:
|
||||
return
|
||||
|
||||
last_version = instance.data.get("latestVersion")
|
||||
if last_version is None or last_version < version:
|
||||
return
|
||||
|
||||
subset_name = instance.data["subset"]
|
||||
msg = "Version {} already exists for subset {}.".format(
|
||||
version, subset_name)
|
||||
|
||||
formatting_data = {
|
||||
"subset_name": subset_name,
|
||||
"asset_name": instance.data["asset"],
|
||||
"version": version
|
||||
}
|
||||
raise PublishXmlValidationError(
|
||||
self, msg, formatting_data=formatting_data)
|
||||
|
||||
@classmethod
|
||||
def repair(cls, instance):
|
||||
create_context = instance.context.data["create_context"]
|
||||
created_instance = create_context.get_instance_by_id(
|
||||
instance.data["instance_id"])
|
||||
creator_attributes = created_instance["creator_attributes"]
|
||||
# Disable version override
|
||||
creator_attributes["use_next_version"] = True
|
||||
create_context.save_changes()
|
||||
|
|
@ -113,6 +113,12 @@ def pack_project(
|
|||
project_name
|
||||
))
|
||||
|
||||
if only_documents and not destination_dir:
|
||||
raise ValueError((
|
||||
"Destination directory must be defined"
|
||||
" when only documents should be packed."
|
||||
))
|
||||
|
||||
root_path = None
|
||||
source_root = {}
|
||||
project_source_path = None
|
||||
|
|
@ -141,6 +147,11 @@ def pack_project(
|
|||
if not destination_dir:
|
||||
destination_dir = root_path
|
||||
|
||||
if not destination_dir:
|
||||
raise ValueError(
|
||||
"Project {} does not have any roots.".format(project_name)
|
||||
)
|
||||
|
||||
destination_dir = os.path.normpath(destination_dir)
|
||||
if not os.path.exists(destination_dir):
|
||||
os.makedirs(destination_dir)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ IMAGE_EXTENSIONS = {
|
|||
".jng", ".jpeg", ".jpeg-ls", ".jpeg", ".2000", ".jpg", ".xr",
|
||||
".jpeg", ".xt", ".jpeg-hdr", ".kra", ".mng", ".miff", ".nrrd",
|
||||
".ora", ".pam", ".pbm", ".pgm", ".ppm", ".pnm", ".pcx", ".pgf",
|
||||
".pictor", ".png", ".psb", ".psp", ".qtvr", ".ras",
|
||||
".pictor", ".png", ".psd", ".psb", ".psp", ".qtvr", ".ras",
|
||||
".rgbe", ".logluv", ".tiff", ".sgi", ".tga", ".tiff", ".tiff/ep",
|
||||
".tiff/it", ".ufo", ".ufp", ".wbmp", ".webp", ".xbm", ".xcf",
|
||||
".xpm", ".xwd"
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ class CelactionSubmitDeadline(pyblish.api.InstancePlugin):
|
|||
render_path).replace("\\", "/")
|
||||
|
||||
instance.data["publishJobState"] = "Suspended"
|
||||
instance.context.data['ftrackStatus'] = "Render"
|
||||
|
||||
# adding 2d render specific family for version identification in Loader
|
||||
instance.data["families"] = ["render2d"]
|
||||
|
|
|
|||
|
|
@ -109,8 +109,6 @@ class IntegrateFtrackApi(pyblish.api.InstancePlugin):
|
|||
for status in asset_version_statuses
|
||||
}
|
||||
|
||||
self._set_task_status(instance, project_entity, task_entity, session)
|
||||
|
||||
# Prepare AssetTypes
|
||||
asset_types_by_short = self._ensure_asset_types_exists(
|
||||
session, component_list
|
||||
|
|
@ -180,45 +178,6 @@ class IntegrateFtrackApi(pyblish.api.InstancePlugin):
|
|||
if asset_version not in instance.data[asset_versions_key]:
|
||||
instance.data[asset_versions_key].append(asset_version)
|
||||
|
||||
def _set_task_status(self, instance, project_entity, task_entity, session):
|
||||
if not project_entity:
|
||||
self.log.info("Task status won't be set, project is not known.")
|
||||
return
|
||||
|
||||
if not task_entity:
|
||||
self.log.info("Task status won't be set, task is not known.")
|
||||
return
|
||||
|
||||
status_name = instance.context.data.get("ftrackStatus")
|
||||
if not status_name:
|
||||
self.log.info("Ftrack status name is not set.")
|
||||
return
|
||||
|
||||
self.log.debug(
|
||||
"Ftrack status name will be (maybe) set to \"{}\"".format(
|
||||
status_name
|
||||
)
|
||||
)
|
||||
|
||||
project_schema = project_entity["project_schema"]
|
||||
task_statuses = project_schema.get_statuses(
|
||||
"Task", task_entity["type_id"]
|
||||
)
|
||||
task_statuses_by_low_name = {
|
||||
status["name"].lower(): status for status in task_statuses
|
||||
}
|
||||
status = task_statuses_by_low_name.get(status_name.lower())
|
||||
if not status:
|
||||
self.log.warning((
|
||||
"Task status \"{}\" won't be set,"
|
||||
" status is now allowed on task type \"{}\"."
|
||||
).format(status_name, task_entity["type"]["name"]))
|
||||
return
|
||||
|
||||
self.log.info("Setting task status to \"{}\"".format(status_name))
|
||||
task_entity["status"] = status
|
||||
session.commit()
|
||||
|
||||
def _fill_component_locations(self, session, component_list):
|
||||
components_by_location_name = collections.defaultdict(list)
|
||||
components_by_location_id = collections.defaultdict(list)
|
||||
|
|
|
|||
|
|
@ -1,150 +0,0 @@
|
|||
import pyblish.api
|
||||
from openpype.lib import filter_profiles
|
||||
|
||||
|
||||
class IntegrateFtrackFarmStatus(pyblish.api.ContextPlugin):
|
||||
"""Change task status when should be published on farm.
|
||||
|
||||
Instance which has set "farm" key in data to 'True' is considered as will
|
||||
be rendered on farm thus it's status should be changed.
|
||||
"""
|
||||
|
||||
order = pyblish.api.IntegratorOrder + 0.48
|
||||
label = "Integrate Ftrack Farm Status"
|
||||
|
||||
farm_status_profiles = []
|
||||
|
||||
def process(self, context):
|
||||
# Quick end
|
||||
if not self.farm_status_profiles:
|
||||
project_name = context.data["projectName"]
|
||||
self.log.info((
|
||||
"Status profiles are not filled for project \"{}\". Skipping"
|
||||
).format(project_name))
|
||||
return
|
||||
|
||||
filtered_instances = self.filter_instances(context)
|
||||
instances_with_status_names = self.get_instances_with_statuse_names(
|
||||
context, filtered_instances
|
||||
)
|
||||
if instances_with_status_names:
|
||||
self.fill_statuses(context, instances_with_status_names)
|
||||
|
||||
def filter_instances(self, context):
|
||||
filtered_instances = []
|
||||
for instance in context:
|
||||
# Skip disabled instances
|
||||
if instance.data.get("publish") is False:
|
||||
continue
|
||||
subset_name = instance.data["subset"]
|
||||
msg_start = "Skipping instance {}.".format(subset_name)
|
||||
if not instance.data.get("farm"):
|
||||
self.log.debug(
|
||||
"{} Won't be rendered on farm.".format(msg_start)
|
||||
)
|
||||
continue
|
||||
|
||||
task_entity = instance.data.get("ftrackTask")
|
||||
if not task_entity:
|
||||
self.log.debug(
|
||||
"{} Does not have filled task".format(msg_start)
|
||||
)
|
||||
continue
|
||||
|
||||
filtered_instances.append(instance)
|
||||
return filtered_instances
|
||||
|
||||
def get_instances_with_statuse_names(self, context, instances):
|
||||
instances_with_status_names = []
|
||||
for instance in instances:
|
||||
family = instance.data["family"]
|
||||
subset_name = instance.data["subset"]
|
||||
task_entity = instance.data["ftrackTask"]
|
||||
host_name = context.data["hostName"]
|
||||
task_name = task_entity["name"]
|
||||
task_type = task_entity["type"]["name"]
|
||||
status_profile = filter_profiles(
|
||||
self.farm_status_profiles,
|
||||
{
|
||||
"hosts": host_name,
|
||||
"task_types": task_type,
|
||||
"task_names": task_name,
|
||||
"families": family,
|
||||
"subsets": subset_name,
|
||||
},
|
||||
logger=self.log
|
||||
)
|
||||
if not status_profile:
|
||||
# There already is log in 'filter_profiles'
|
||||
continue
|
||||
|
||||
status_name = status_profile["status_name"]
|
||||
if status_name:
|
||||
instances_with_status_names.append((instance, status_name))
|
||||
return instances_with_status_names
|
||||
|
||||
def fill_statuses(self, context, instances_with_status_names):
|
||||
# Prepare available task statuses on the project
|
||||
project_name = context.data["projectName"]
|
||||
session = context.data["ftrackSession"]
|
||||
project_entity = session.query((
|
||||
"select project_schema from Project where full_name is \"{}\""
|
||||
).format(project_name)).one()
|
||||
project_schema = project_entity["project_schema"]
|
||||
|
||||
task_type_ids = set()
|
||||
for item in instances_with_status_names:
|
||||
instance, _ = item
|
||||
task_entity = instance.data["ftrackTask"]
|
||||
task_type_ids.add(task_entity["type"]["id"])
|
||||
|
||||
task_statuses_by_type_id = {
|
||||
task_type_id: project_schema.get_statuses("Task", task_type_id)
|
||||
for task_type_id in task_type_ids
|
||||
}
|
||||
|
||||
# Keep track if anything has changed
|
||||
skipped_status_names = set()
|
||||
status_changed = False
|
||||
for item in instances_with_status_names:
|
||||
instance, status_name = item
|
||||
task_entity = instance.data["ftrackTask"]
|
||||
task_statuses = task_statuses_by_type_id[task_entity["type"]["id"]]
|
||||
status_name_low = status_name.lower()
|
||||
|
||||
status_id = None
|
||||
status_name = None
|
||||
# Skip if status name was already tried to be found
|
||||
for status in task_statuses:
|
||||
if status["name"].lower() == status_name_low:
|
||||
status_id = status["id"]
|
||||
status_name = status["name"]
|
||||
break
|
||||
|
||||
if status_id is None:
|
||||
if status_name_low not in skipped_status_names:
|
||||
skipped_status_names.add(status_name_low)
|
||||
joined_status_names = ", ".join({
|
||||
'"{}"'.format(status["name"])
|
||||
for status in task_statuses
|
||||
})
|
||||
self.log.warning((
|
||||
"Status \"{}\" is not available on project \"{}\"."
|
||||
" Available statuses are {}"
|
||||
).format(status_name, project_name, joined_status_names))
|
||||
continue
|
||||
|
||||
# Change task status id
|
||||
if status_id != task_entity["status_id"]:
|
||||
task_entity["status_id"] = status_id
|
||||
status_changed = True
|
||||
path = "/".join([
|
||||
item["name"]
|
||||
for item in task_entity["link"]
|
||||
])
|
||||
self.log.debug("Set status \"{}\" to \"{}\"".format(
|
||||
status_name, path
|
||||
))
|
||||
|
||||
if status_changed:
|
||||
session.commit()
|
||||
|
|
@ -0,0 +1,433 @@
|
|||
import copy
|
||||
|
||||
import pyblish.api
|
||||
from openpype.lib import filter_profiles
|
||||
|
||||
|
||||
def create_chunks(iterable, chunk_size=None):
|
||||
"""Separate iterable into multiple chunks by size.
|
||||
|
||||
Args:
|
||||
iterable(list|tuple|set): Object that will be separated into chunks.
|
||||
chunk_size(int): Size of one chunk. Default value is 200.
|
||||
|
||||
Returns:
|
||||
list<list>: Chunked items.
|
||||
"""
|
||||
chunks = []
|
||||
|
||||
tupled_iterable = tuple(iterable)
|
||||
if not tupled_iterable:
|
||||
return chunks
|
||||
iterable_size = len(tupled_iterable)
|
||||
if chunk_size is None:
|
||||
chunk_size = 200
|
||||
|
||||
if chunk_size < 1:
|
||||
chunk_size = 1
|
||||
|
||||
for idx in range(0, iterable_size, chunk_size):
|
||||
chunks.append(tupled_iterable[idx:idx + chunk_size])
|
||||
return chunks
|
||||
|
||||
|
||||
class CollectFtrackTaskStatuses(pyblish.api.ContextPlugin):
|
||||
"""Collect available task statuses on the project.
|
||||
|
||||
This is preparation for integration of task statuses.
|
||||
|
||||
Requirements:
|
||||
ftrackSession (ftrack_api.Session): Prepared ftrack session.
|
||||
|
||||
Provides:
|
||||
ftrackTaskStatuses (dict[str, list[Any]]): Dictionary of available
|
||||
task statuses on project by task type id.
|
||||
ftrackStatusByTaskId (dict[str, str]): Empty dictionary of task
|
||||
statuses by task id. Status on task can be set only once.
|
||||
Value should be a name of status.
|
||||
"""
|
||||
|
||||
# After 'CollectFtrackApi'
|
||||
order = pyblish.api.CollectorOrder + 0.4992
|
||||
label = "Collect Ftrack Task Statuses"
|
||||
settings_category = "ftrack"
|
||||
|
||||
def process(self, context):
|
||||
ftrack_session = context.data("ftrackSession")
|
||||
if ftrack_session is None:
|
||||
self.log.info("Ftrack session is not created.")
|
||||
return
|
||||
|
||||
# Prepare available task statuses on the project
|
||||
project_name = context.data["projectName"]
|
||||
project_entity = ftrack_session.query((
|
||||
"select project_schema from Project where full_name is \"{}\""
|
||||
).format(project_name)).one()
|
||||
project_schema = project_entity["project_schema"]
|
||||
|
||||
task_type_ids = {
|
||||
task_type["id"]
|
||||
for task_type in ftrack_session.query("select id from Type").all()
|
||||
}
|
||||
task_statuses_by_type_id = {
|
||||
task_type_id: project_schema.get_statuses("Task", task_type_id)
|
||||
for task_type_id in task_type_ids
|
||||
}
|
||||
context.data["ftrackTaskStatuses"] = task_statuses_by_type_id
|
||||
context.data["ftrackStatusByTaskId"] = {}
|
||||
self.log.info("Collected ftrack task statuses.")
|
||||
|
||||
|
||||
class IntegrateFtrackStatusBase(pyblish.api.InstancePlugin):
|
||||
"""Base plugin for status collection.
|
||||
|
||||
Requirements:
|
||||
projectName (str): Name of the project.
|
||||
hostName (str): Name of the host.
|
||||
ftrackSession (ftrack_api.Session): Prepared ftrack session.
|
||||
ftrackTaskStatuses (dict[str, list[Any]]): Dictionary of available
|
||||
task statuses on project by task type id.
|
||||
ftrackStatusByTaskId (dict[str, str]): Empty dictionary of task
|
||||
statuses by task id. Status on task can be set only once.
|
||||
Value should be a name of status.
|
||||
"""
|
||||
|
||||
active = False
|
||||
settings_key = None
|
||||
status_profiles = []
|
||||
|
||||
@classmethod
|
||||
def apply_settings(cls, project_settings):
|
||||
settings_key = cls.settings_key
|
||||
if settings_key is None:
|
||||
settings_key = cls.__name__
|
||||
|
||||
try:
|
||||
settings = project_settings["ftrack"]["publish"][settings_key]
|
||||
except KeyError:
|
||||
return
|
||||
|
||||
for key, value in settings.items():
|
||||
setattr(cls, key, value)
|
||||
|
||||
def process(self, instance):
|
||||
context = instance.context
|
||||
# No profiles -> skip
|
||||
profiles = self.get_status_profiles()
|
||||
if not profiles:
|
||||
project_name = context.data["projectName"]
|
||||
self.log.info((
|
||||
"Status profiles are not filled for project \"{}\". Skipping"
|
||||
).format(project_name))
|
||||
return
|
||||
|
||||
# Task statuses were not collected -> skip
|
||||
task_statuses_by_type_id = context.data.get("ftrackTaskStatuses")
|
||||
if not task_statuses_by_type_id:
|
||||
self.log.info(
|
||||
"Ftrack task statuses are not collected. Skipping.")
|
||||
return
|
||||
|
||||
self.prepare_status_names(context, instance, profiles)
|
||||
|
||||
def get_status_profiles(self):
|
||||
"""List of profiles to determine status name.
|
||||
|
||||
Example profile item:
|
||||
{
|
||||
"host_names": ["nuke"],
|
||||
"task_types": ["Compositing"],
|
||||
"task_names": ["Comp"],
|
||||
"families": ["render"],
|
||||
"subset_names": ["renderComp"],
|
||||
"status_name": "Rendering",
|
||||
}
|
||||
|
||||
Returns:
|
||||
list[dict[str, Any]]: List of profiles.
|
||||
"""
|
||||
|
||||
return self.status_profiles
|
||||
|
||||
def prepare_status_names(self, context, instance, profiles):
|
||||
if not self.is_valid_instance(context, instance):
|
||||
return
|
||||
|
||||
filter_data = self.get_profile_filter_data(context, instance)
|
||||
status_profile = filter_profiles(
|
||||
profiles,
|
||||
filter_data,
|
||||
logger=self.log
|
||||
)
|
||||
if not status_profile:
|
||||
return
|
||||
|
||||
status_name = status_profile["status_name"]
|
||||
if status_name:
|
||||
self.fill_status(context, instance, status_name)
|
||||
|
||||
def get_profile_filter_data(self, context, instance):
|
||||
task_entity = instance.data["ftrackTask"]
|
||||
return {
|
||||
"host_names": context.data["hostName"],
|
||||
"task_types": task_entity["type"]["name"],
|
||||
"task_names": task_entity["name"],
|
||||
"families": instance.data["family"],
|
||||
"subset_names": instance.data["subset"],
|
||||
}
|
||||
|
||||
def is_valid_instance(self, context, instance):
|
||||
"""Filter instances that should be processed.
|
||||
|
||||
Ignore instances that are not enabled for publishing or don't have
|
||||
filled task. Also skip instances with tasks that already have defined
|
||||
status.
|
||||
|
||||
Plugin should do more filtering which is custom for plugin logic.
|
||||
|
||||
Args:
|
||||
context (pyblish.api.Context): Pyblish context.
|
||||
instance (pyblish.api.Instance): Instance to process.
|
||||
|
||||
Returns:
|
||||
list[pyblish.api.Instance]: List of instances that should be
|
||||
processed.
|
||||
"""
|
||||
|
||||
ftrack_status_by_task_id = context.data["ftrackStatusByTaskId"]
|
||||
# Skip disabled instances
|
||||
if instance.data.get("publish") is False:
|
||||
return False
|
||||
|
||||
task_entity = instance.data.get("ftrackTask")
|
||||
if not task_entity:
|
||||
self.log.debug(
|
||||
"Skipping instance Does not have filled task".format(
|
||||
instance.data["subset"]))
|
||||
return False
|
||||
|
||||
task_id = task_entity["id"]
|
||||
if task_id in ftrack_status_by_task_id:
|
||||
self.log.debug("Status for task {} was already defined".format(
|
||||
task_entity["name"]
|
||||
))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def fill_status(self, context, instance, status_name):
|
||||
"""Fill status for instance task.
|
||||
|
||||
If task already had set status, it will be skipped.
|
||||
|
||||
Args:
|
||||
context (pyblish.api.Context): Pyblish context.
|
||||
instance (pyblish.api.Instance): Pyblish instance.
|
||||
status_name (str): Name of status to set.
|
||||
"""
|
||||
|
||||
task_entity = instance.data["ftrackTask"]
|
||||
task_id = task_entity["id"]
|
||||
ftrack_status_by_task_id = context.data["ftrackStatusByTaskId"]
|
||||
if task_id in ftrack_status_by_task_id:
|
||||
self.log.debug("Status for task {} was already defined".format(
|
||||
task_entity["name"]
|
||||
))
|
||||
return
|
||||
|
||||
ftrack_status_by_task_id[task_id] = status_name
|
||||
self.log.info((
|
||||
"Task {} will be set to \"{}\" status."
|
||||
).format(task_entity["name"], status_name))
|
||||
|
||||
|
||||
class IntegrateFtrackFarmStatus(IntegrateFtrackStatusBase):
|
||||
"""Collect task status names for instances that are sent to farm.
|
||||
|
||||
Instance which has set "farm" key in data to 'True' is considered as will
|
||||
be rendered on farm thus it's status should be changed.
|
||||
|
||||
Requirements:
|
||||
projectName (str): Name of the project.
|
||||
hostName (str): Name of the host.
|
||||
ftrackSession (ftrack_api.Session): Prepared ftrack session.
|
||||
ftrackTaskStatuses (dict[str, list[Any]]): Dictionary of available
|
||||
task statuses on project by task type id.
|
||||
ftrackStatusByTaskId (dict[str, str]): Empty dictionary of task
|
||||
statuses by task id. Status on task can be set only once.
|
||||
Value should be a name of status.
|
||||
"""
|
||||
|
||||
order = pyblish.api.IntegratorOrder + 0.48
|
||||
label = "Ftrack Task Status To Farm Status"
|
||||
active = True
|
||||
|
||||
farm_status_profiles = []
|
||||
status_profiles = None
|
||||
|
||||
def is_valid_instance(self, context, instance):
|
||||
if not instance.data.get("farm"):
|
||||
self.log.debug("{} Won't be rendered on farm.".format(
|
||||
instance.data["subset"]
|
||||
))
|
||||
return False
|
||||
return super(IntegrateFtrackFarmStatus, self).is_valid_instance(
|
||||
context, instance)
|
||||
|
||||
def get_status_profiles(self):
|
||||
if self.status_profiles is None:
|
||||
profiles = copy.deepcopy(self.farm_status_profiles)
|
||||
for profile in profiles:
|
||||
profile["host_names"] = profile.pop("hosts")
|
||||
profile["subset_names"] = profile.pop("subsets")
|
||||
self.status_profiles = profiles
|
||||
return self.status_profiles
|
||||
|
||||
|
||||
class IntegrateFtrackLocalStatus(IntegrateFtrackStatusBase):
|
||||
"""Collect task status names for instances that are published locally.
|
||||
|
||||
Instance which has set "farm" key in data to 'True' is considered as will
|
||||
be rendered on farm thus it's status should be changed.
|
||||
|
||||
Requirements:
|
||||
projectName (str): Name of the project.
|
||||
hostName (str): Name of the host.
|
||||
ftrackSession (ftrack_api.Session): Prepared ftrack session.
|
||||
ftrackTaskStatuses (dict[str, list[Any]]): Dictionary of available
|
||||
task statuses on project by task type id.
|
||||
ftrackStatusByTaskId (dict[str, str]): Empty dictionary of task
|
||||
statuses by task id. Status on task can be set only once.
|
||||
Value should be a name of status.
|
||||
"""
|
||||
|
||||
order = IntegrateFtrackFarmStatus.order + 0.001
|
||||
label = "Ftrack Task Status Local Publish"
|
||||
active = True
|
||||
targets = ["local"]
|
||||
settings_key = "ftrack_task_status_local_publish"
|
||||
|
||||
def is_valid_instance(self, context, instance):
|
||||
if instance.data.get("farm"):
|
||||
self.log.debug("{} Will be rendered on farm.".format(
|
||||
instance.data["subset"]
|
||||
))
|
||||
return False
|
||||
return super(IntegrateFtrackLocalStatus, self).is_valid_instance(
|
||||
context, instance)
|
||||
|
||||
|
||||
class IntegrateFtrackOnFarmStatus(IntegrateFtrackStatusBase):
|
||||
"""Collect task status names for instances that are published on farm.
|
||||
|
||||
Requirements:
|
||||
projectName (str): Name of the project.
|
||||
hostName (str): Name of the host.
|
||||
ftrackSession (ftrack_api.Session): Prepared ftrack session.
|
||||
ftrackTaskStatuses (dict[str, list[Any]]): Dictionary of available
|
||||
task statuses on project by task type id.
|
||||
ftrackStatusByTaskId (dict[str, str]): Empty dictionary of task
|
||||
statuses by task id. Status on task can be set only once.
|
||||
Value should be a name of status.
|
||||
"""
|
||||
|
||||
order = IntegrateFtrackLocalStatus.order + 0.001
|
||||
label = "Ftrack Task Status On Farm Status"
|
||||
active = True
|
||||
targets = ["farm"]
|
||||
settings_key = "ftrack_task_status_on_farm_publish"
|
||||
|
||||
|
||||
class IntegrateFtrackTaskStatus(pyblish.api.ContextPlugin):
|
||||
# Use order of Integrate Ftrack Api plugin and offset it before or after
|
||||
base_order = pyblish.api.IntegratorOrder + 0.499
|
||||
# By default is after Integrate Ftrack Api
|
||||
order = base_order + 0.0001
|
||||
label = "Integrate Ftrack Task Status"
|
||||
|
||||
@classmethod
|
||||
def apply_settings(cls, project_settings):
|
||||
"""Apply project settings to plugin.
|
||||
|
||||
Args:
|
||||
project_settings (dict[str, Any]): Project settings.
|
||||
"""
|
||||
|
||||
settings = (
|
||||
project_settings["ftrack"]["publish"]["IntegrateFtrackTaskStatus"]
|
||||
)
|
||||
diff = 0.001
|
||||
if not settings["after_version_statuses"]:
|
||||
diff = -diff
|
||||
cls.order = cls.base_order + diff
|
||||
|
||||
def process(self, context):
|
||||
task_statuses_by_type_id = context.data.get("ftrackTaskStatuses")
|
||||
if not task_statuses_by_type_id:
|
||||
self.log.info("Ftrack task statuses are not collected. Skipping.")
|
||||
return
|
||||
|
||||
status_by_task_id = self._get_status_by_task_id(context)
|
||||
if not status_by_task_id:
|
||||
self.log.info("No statuses to set. Skipping.")
|
||||
return
|
||||
|
||||
ftrack_session = context.data["ftrackSession"]
|
||||
|
||||
task_entities = self._get_task_entities(
|
||||
ftrack_session, status_by_task_id)
|
||||
|
||||
for task_entity in task_entities:
|
||||
task_path = "/".join([
|
||||
item["name"] for item in task_entity["link"]
|
||||
])
|
||||
task_id = task_entity["id"]
|
||||
type_id = task_entity["type_id"]
|
||||
new_status = None
|
||||
status_name = status_by_task_id[task_id]
|
||||
self.log.debug(
|
||||
"Status to set {} on task {}.".format(status_name, task_path))
|
||||
status_name_low = status_name.lower()
|
||||
available_statuses = task_statuses_by_type_id[type_id]
|
||||
for status in available_statuses:
|
||||
if status["name"].lower() == status_name_low:
|
||||
new_status = status
|
||||
break
|
||||
|
||||
if new_status is None:
|
||||
joined_statuses = ", ".join([
|
||||
"'{}'".format(status["name"])
|
||||
for status in available_statuses
|
||||
])
|
||||
self.log.debug((
|
||||
"Status '{}' was not found in available statuses: {}."
|
||||
).format(status_name, joined_statuses))
|
||||
continue
|
||||
|
||||
if task_entity["status_id"] != new_status["id"]:
|
||||
task_entity["status_id"] = new_status["id"]
|
||||
|
||||
self.log.debug("Changing status of task '{}' to '{}'".format(
|
||||
task_path, status_name
|
||||
))
|
||||
ftrack_session.commit()
|
||||
|
||||
def _get_status_by_task_id(self, context):
|
||||
status_by_task_id = context.data["ftrackStatusByTaskId"]
|
||||
return {
|
||||
task_id: status_name
|
||||
for task_id, status_name in status_by_task_id.items()
|
||||
if status_name
|
||||
}
|
||||
|
||||
def _get_task_entities(self, ftrack_session, status_by_task_id):
|
||||
task_entities = []
|
||||
for chunk_ids in create_chunks(status_by_task_id.keys()):
|
||||
joined_ids = ",".join(
|
||||
['"{}"'.format(task_id) for task_id in chunk_ids]
|
||||
)
|
||||
task_entities.extend(ftrack_session.query((
|
||||
"select id, type_id, status_id, link from Task"
|
||||
" where id in ({})"
|
||||
).format(joined_ids)).all())
|
||||
return task_entities
|
||||
|
|
@ -63,7 +63,7 @@ class IntegrateHierarchyToFtrack(pyblish.api.ContextPlugin):
|
|||
"""
|
||||
|
||||
order = pyblish.api.IntegratorOrder - 0.04
|
||||
label = 'Integrate Hierarchy To Ftrack'
|
||||
label = "Integrate Hierarchy To Ftrack"
|
||||
families = ["shot"]
|
||||
hosts = [
|
||||
"hiero",
|
||||
|
|
@ -94,14 +94,13 @@ class IntegrateHierarchyToFtrack(pyblish.api.ContextPlugin):
|
|||
"Project \"{}\" was not found on ftrack.".format(project_name)
|
||||
)
|
||||
|
||||
self.context = context
|
||||
self.session = session
|
||||
self.ft_project = project
|
||||
self.task_types = self.get_all_task_types(project)
|
||||
self.task_statuses = self.get_task_statuses(project)
|
||||
|
||||
# import ftrack hierarchy
|
||||
self.import_to_ftrack(project_name, hierarchy_context)
|
||||
self.import_to_ftrack(context, project_name, hierarchy_context)
|
||||
|
||||
def query_ftrack_entitites(self, session, ft_project):
|
||||
project_id = ft_project["id"]
|
||||
|
|
@ -227,7 +226,7 @@ class IntegrateHierarchyToFtrack(pyblish.api.ContextPlugin):
|
|||
|
||||
return output
|
||||
|
||||
def import_to_ftrack(self, project_name, hierarchy_context):
|
||||
def import_to_ftrack(self, context, project_name, hierarchy_context):
|
||||
# Prequery hiearchical custom attributes
|
||||
hier_attrs = get_pype_attr(self.session)[1]
|
||||
hier_attr_by_key = {
|
||||
|
|
@ -258,7 +257,7 @@ class IntegrateHierarchyToFtrack(pyblish.api.ContextPlugin):
|
|||
self.session, matching_entities, hier_attrs)
|
||||
|
||||
# Get ftrack api module (as they are different per python version)
|
||||
ftrack_api = self.context.data["ftrackPythonModule"]
|
||||
ftrack_api = context.data["ftrackPythonModule"]
|
||||
|
||||
# Use queue of hierarchy items to process
|
||||
import_queue = collections.deque()
|
||||
|
|
@ -292,7 +291,7 @@ class IntegrateHierarchyToFtrack(pyblish.api.ContextPlugin):
|
|||
# CUSTOM ATTRIBUTES
|
||||
custom_attributes = entity_data.get('custom_attributes', {})
|
||||
instances = []
|
||||
for instance in self.context:
|
||||
for instance in context:
|
||||
instance_asset_name = instance.data.get("asset")
|
||||
if (
|
||||
instance_asset_name
|
||||
|
|
@ -369,6 +368,7 @@ class IntegrateHierarchyToFtrack(pyblish.api.ContextPlugin):
|
|||
if task_name:
|
||||
instances_by_task_name[task_name.lower()].append(instance)
|
||||
|
||||
ftrack_status_by_task_id = context.data["ftrackStatusByTaskId"]
|
||||
tasks = entity_data.get('tasks', [])
|
||||
existing_tasks = []
|
||||
tasks_to_create = []
|
||||
|
|
@ -389,11 +389,11 @@ class IntegrateHierarchyToFtrack(pyblish.api.ContextPlugin):
|
|||
|
||||
for task_name, task_type in tasks_to_create:
|
||||
task_entity = self.create_task(
|
||||
name=task_name,
|
||||
task_type=task_type,
|
||||
parent=entity
|
||||
task_name,
|
||||
task_type,
|
||||
entity,
|
||||
ftrack_status_by_task_id
|
||||
)
|
||||
|
||||
for instance in instances_by_task_name[task_name.lower()]:
|
||||
instance.data["ftrackTask"] = task_entity
|
||||
|
||||
|
|
@ -481,7 +481,7 @@ class IntegrateHierarchyToFtrack(pyblish.api.ContextPlugin):
|
|||
for status in task_workflow_statuses
|
||||
}
|
||||
|
||||
def create_task(self, name, task_type, parent):
|
||||
def create_task(self, name, task_type, parent, ftrack_status_by_task_id):
|
||||
filter_data = {
|
||||
"task_names": name,
|
||||
"task_types": task_type
|
||||
|
|
@ -491,12 +491,14 @@ class IntegrateHierarchyToFtrack(pyblish.api.ContextPlugin):
|
|||
filter_data
|
||||
)
|
||||
status_id = None
|
||||
status_name = None
|
||||
if profile:
|
||||
status_name = profile["status_name"]
|
||||
status_name_low = status_name.lower()
|
||||
for _status_id, status in self.task_statuses.items():
|
||||
if status["name"].lower() == status_name_low:
|
||||
status_id = _status_id
|
||||
status_name = status["name"]
|
||||
break
|
||||
|
||||
if status_id is None:
|
||||
|
|
@ -523,6 +525,8 @@ class IntegrateHierarchyToFtrack(pyblish.api.ContextPlugin):
|
|||
self.session._configure_locations()
|
||||
six.reraise(tp, value, tb)
|
||||
|
||||
if status_id is not None:
|
||||
ftrack_status_by_task_id[task["id"]] = None
|
||||
return task
|
||||
|
||||
def _get_active_assets(self, context):
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ from openpype.pipeline import Anatomy
|
|||
log = Logger.get_logger(__name__)
|
||||
|
||||
|
||||
class CashedData:
|
||||
remapping = None
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _make_temp_json_file():
|
||||
"""Wrapping function for json temp file
|
||||
|
|
@ -92,6 +96,11 @@ def get_imageio_colorspace_from_filepath(
|
|||
)
|
||||
config_data = get_imageio_config(
|
||||
project_name, host_name, project_settings)
|
||||
|
||||
# in case host color management is not enabled
|
||||
if not config_data:
|
||||
return None
|
||||
|
||||
file_rules = get_imageio_file_rules(
|
||||
project_name, host_name, project_settings)
|
||||
|
||||
|
|
@ -303,7 +312,8 @@ def get_views_data_subprocess(config_path):
|
|||
|
||||
|
||||
def get_imageio_config(
|
||||
project_name, host_name,
|
||||
project_name,
|
||||
host_name,
|
||||
project_settings=None,
|
||||
anatomy_data=None,
|
||||
anatomy=None
|
||||
|
|
@ -316,15 +326,12 @@ def get_imageio_config(
|
|||
Args:
|
||||
project_name (str): project name
|
||||
host_name (str): host name
|
||||
project_settings (dict, optional): project settings.
|
||||
Defaults to None.
|
||||
anatomy_data (dict, optional): anatomy formatting data.
|
||||
Defaults to None.
|
||||
anatomy (lib.Anatomy, optional): Anatomy object.
|
||||
Defaults to None.
|
||||
project_settings (Optional[dict]): Project settings.
|
||||
anatomy_data (Optional[dict]): anatomy formatting data.
|
||||
anatomy (Optional[Anatomy]): Anatomy object.
|
||||
|
||||
Returns:
|
||||
dict or bool: config path data or None
|
||||
dict: config path data or empty dict
|
||||
"""
|
||||
project_settings = project_settings or get_project_settings(project_name)
|
||||
anatomy = anatomy or Anatomy(project_name)
|
||||
|
|
@ -335,25 +342,65 @@ def get_imageio_config(
|
|||
anatomy_data = get_template_data_from_session()
|
||||
|
||||
formatting_data = deepcopy(anatomy_data)
|
||||
# add project roots to anatomy data
|
||||
|
||||
# Add project roots to anatomy data
|
||||
formatting_data["root"] = anatomy.roots
|
||||
formatting_data["platform"] = platform.system().lower()
|
||||
|
||||
# get colorspace settings
|
||||
# Get colorspace settings
|
||||
imageio_global, imageio_host = _get_imageio_settings(
|
||||
project_settings, host_name)
|
||||
|
||||
config_host = imageio_host.get("ocio_config", {})
|
||||
# Host 'ocio_config' is optional
|
||||
host_ocio_config = imageio_host.get("ocio_config") or {}
|
||||
|
||||
if config_host.get("enabled"):
|
||||
# Global color management must be enabled to be able to use host settings
|
||||
activate_color_management = imageio_global.get(
|
||||
"activate_global_color_management")
|
||||
# TODO: remove this in future - backward compatibility
|
||||
# For already saved overrides from previous version look for 'enabled'
|
||||
# on host settings.
|
||||
if activate_color_management is None:
|
||||
activate_color_management = host_ocio_config.get("enabled", False)
|
||||
|
||||
if not activate_color_management:
|
||||
# if global settings are disabled return empty dict because
|
||||
# it is expected that no colorspace management is needed
|
||||
log.info("Colorspace management is disabled globally.")
|
||||
return {}
|
||||
|
||||
# Check if host settings group is having 'activate_host_color_management'
|
||||
# - if it does not have activation key then default it to True so it uses
|
||||
# global settings
|
||||
# This is for backward compatibility.
|
||||
# TODO: in future rewrite this to be more explicit
|
||||
activate_host_color_management = imageio_host.get(
|
||||
"activate_host_color_management", True)
|
||||
|
||||
if not activate_host_color_management:
|
||||
# if host settings are disabled return False because
|
||||
# it is expected that no colorspace management is needed
|
||||
log.info(
|
||||
"Colorspace management for host '{}' is disabled.".format(
|
||||
host_name)
|
||||
)
|
||||
return {}
|
||||
|
||||
# get config path from either global or host settings
|
||||
# depending on override flag
|
||||
# TODO: in future rewrite this to be more explicit
|
||||
override_global_config = host_ocio_config.get("override_global_config")
|
||||
if override_global_config is None:
|
||||
# for already saved overrides from previous version
|
||||
# TODO: remove this in future - backward compatibility
|
||||
override_global_config = host_ocio_config.get("enabled")
|
||||
|
||||
if override_global_config:
|
||||
config_data = _get_config_data(
|
||||
config_host["filepath"], formatting_data
|
||||
host_ocio_config["filepath"], formatting_data
|
||||
)
|
||||
else:
|
||||
config_data = None
|
||||
|
||||
if not config_data:
|
||||
# get config path from either global or host_name
|
||||
# get config path from global
|
||||
config_global = imageio_global["ocio_config"]
|
||||
config_data = _get_config_data(
|
||||
config_global["filepath"], formatting_data
|
||||
|
|
@ -437,17 +484,82 @@ def get_imageio_file_rules(project_name, host_name, project_settings=None):
|
|||
|
||||
# get file rules from global and host_name
|
||||
frules_global = imageio_global["file_rules"]
|
||||
activate_global_rules = (
|
||||
frules_global.get("activate_global_file_rules", False)
|
||||
# TODO: remove this in future - backward compatibility
|
||||
or frules_global.get("enabled")
|
||||
)
|
||||
global_rules = frules_global["rules"]
|
||||
|
||||
if not activate_global_rules:
|
||||
log.info(
|
||||
"Colorspace global file rules are disabled."
|
||||
)
|
||||
global_rules = {}
|
||||
|
||||
# host is optional, some might not have any settings
|
||||
frules_host = imageio_host.get("file_rules", {})
|
||||
|
||||
# compile file rules dictionary
|
||||
file_rules = {}
|
||||
if frules_global["enabled"]:
|
||||
file_rules.update(frules_global["rules"])
|
||||
if frules_host and frules_host["enabled"]:
|
||||
file_rules.update(frules_host["rules"])
|
||||
activate_host_rules = frules_host.get("activate_host_rules")
|
||||
if activate_host_rules is None:
|
||||
# TODO: remove this in future - backward compatibility
|
||||
activate_host_rules = frules_host.get("enabled", False)
|
||||
|
||||
return file_rules
|
||||
# return host rules if activated or global rules
|
||||
return frules_host["rules"] if activate_host_rules else global_rules
|
||||
|
||||
|
||||
def get_remapped_colorspace_to_native(
|
||||
ocio_colorspace_name, host_name, imageio_host_settings
|
||||
):
|
||||
"""Return native colorspace name.
|
||||
|
||||
Args:
|
||||
ocio_colorspace_name (str | None): ocio colorspace name
|
||||
host_name (str): Host name.
|
||||
imageio_host_settings (dict[str, Any]): ImageIO host settings.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: native colorspace name defined in remapping or None
|
||||
"""
|
||||
|
||||
CashedData.remapping.setdefault(host_name, {})
|
||||
if CashedData.remapping[host_name].get("to_native") is None:
|
||||
remapping_rules = imageio_host_settings["remapping"]["rules"]
|
||||
CashedData.remapping[host_name]["to_native"] = {
|
||||
rule["ocio_name"]: rule["host_native_name"]
|
||||
for rule in remapping_rules
|
||||
}
|
||||
|
||||
return CashedData.remapping[host_name]["to_native"].get(
|
||||
ocio_colorspace_name)
|
||||
|
||||
|
||||
def get_remapped_colorspace_from_native(
|
||||
host_native_colorspace_name, host_name, imageio_host_settings
|
||||
):
|
||||
"""Return ocio colorspace name remapped from host native used name.
|
||||
|
||||
Args:
|
||||
host_native_colorspace_name (str): host native colorspace name
|
||||
host_name (str): Host name.
|
||||
imageio_host_settings (dict[str, Any]): ImageIO host settings.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: Ocio colorspace name defined in remapping or None.
|
||||
"""
|
||||
|
||||
CashedData.remapping.setdefault(host_name, {})
|
||||
if CashedData.remapping[host_name].get("from_native") is None:
|
||||
remapping_rules = imageio_host_settings["remapping"]["rules"]
|
||||
CashedData.remapping[host_name]["from_native"] = {
|
||||
rule["host_native_name"]: rule["ocio_name"]
|
||||
for rule in remapping_rules
|
||||
}
|
||||
|
||||
return CashedData.remapping[host_name]["from_native"].get(
|
||||
host_native_colorspace_name)
|
||||
|
||||
|
||||
def _get_imageio_settings(project_settings, host_name):
|
||||
|
|
|
|||
|
|
@ -1441,6 +1441,19 @@ class CreateContext:
|
|||
"""Access to global publish attributes."""
|
||||
return self._publish_attributes
|
||||
|
||||
def get_instance_by_id(self, instance_id):
|
||||
"""Receive instance by id.
|
||||
|
||||
Args:
|
||||
instance_id (str): Instance id.
|
||||
|
||||
Returns:
|
||||
Union[CreatedInstance, None]: Instance or None if instance with
|
||||
given id is not available.
|
||||
"""
|
||||
|
||||
return self._instances_by_id.get(instance_id)
|
||||
|
||||
def get_sorted_creators(self, identifiers=None):
|
||||
"""Sorted creators by 'order' attribute.
|
||||
|
||||
|
|
|
|||
|
|
@ -331,6 +331,11 @@ class ColormanagedPyblishPluginMixin(object):
|
|||
project_settings=project_settings_,
|
||||
anatomy_data=anatomy_data
|
||||
)
|
||||
|
||||
# in case host color management is not enabled
|
||||
if not config_data:
|
||||
return None
|
||||
|
||||
file_rules = get_imageio_file_rules(
|
||||
project_name, host_name,
|
||||
project_settings=project_settings_
|
||||
|
|
@ -387,6 +392,11 @@ class ColormanagedPyblishPluginMixin(object):
|
|||
if colorspace_settings is None:
|
||||
colorspace_settings = self.get_colorspace_settings(context)
|
||||
|
||||
# in case host color management is not enabled
|
||||
if not colorspace_settings:
|
||||
self.log.warning("Host's colorspace management is disabled.")
|
||||
return
|
||||
|
||||
# unpack colorspace settings
|
||||
config_data, file_rules = colorspace_settings
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class CollectFromCreateContext(pyblish.api.ContextPlugin):
|
|||
order = pyblish.api.CollectorOrder - 0.5
|
||||
|
||||
def process(self, context):
|
||||
create_context = context.data.pop("create_context", None)
|
||||
create_context = context.data.get("create_context")
|
||||
if not create_context:
|
||||
host = registered_host()
|
||||
if isinstance(host, IPublishHost):
|
||||
|
|
|
|||
|
|
@ -356,6 +356,13 @@ class PypeCommands:
|
|||
def pack_project(self, project_name, dirpath, database_only):
|
||||
from openpype.lib.project_backpack import pack_project
|
||||
|
||||
if database_only and not dirpath:
|
||||
raise ValueError((
|
||||
"Destination dir must be defined when using --dbonly."
|
||||
" Use '--dirpath {output dir path}' flag"
|
||||
" to specify directory."
|
||||
))
|
||||
|
||||
pack_project(project_name, dirpath, database_only)
|
||||
|
||||
def unpack_project(self, zip_filepath, new_root, database_only):
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@
|
|||
"base_file_unit_scale": 0.01
|
||||
},
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"remapping": {
|
||||
"rules": []
|
||||
},
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
},
|
||||
"project": {
|
||||
|
|
|
|||
|
|
@ -493,7 +493,29 @@
|
|||
"upload_reviewable_with_origin_name": false
|
||||
},
|
||||
"IntegrateFtrackFarmStatus": {
|
||||
"farm_status_profiles": []
|
||||
"farm_status_profiles": [
|
||||
{
|
||||
"hosts": [
|
||||
"celaction"
|
||||
],
|
||||
"task_types": [],
|
||||
"task_names": [],
|
||||
"families": [
|
||||
"render"
|
||||
],
|
||||
"subsets": [],
|
||||
"status_name": "Render"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ftrack_task_status_local_publish": {
|
||||
"status_profiles": []
|
||||
},
|
||||
"ftrack_task_status_on_farm_publish": {
|
||||
"status_profiles": []
|
||||
},
|
||||
"IntegrateFtrackTaskStatus": {
|
||||
"after_version_statuses": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,13 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
},
|
||||
"ocio": {
|
||||
"enabled": false,
|
||||
"configFilePath": {
|
||||
"windows": [],
|
||||
"darwin": [],
|
||||
"linux": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"copy_fusion_settings": {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_global_color_management": false,
|
||||
"ocio_config": {
|
||||
"filepath": [
|
||||
"{OPENPYPE_ROOT}/vendor/bin/ocioconfig/OpenColorIOConfigs/aces_1.2/config.ocio",
|
||||
|
|
@ -7,7 +8,7 @@
|
|||
]
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_global_file_rules": false,
|
||||
"rules": {
|
||||
"example": {
|
||||
"pattern": ".*(beauty).*",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,20 +1,16 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
},
|
||||
"workfile": {
|
||||
"ocioConfigName": "nuke-default",
|
||||
"ocioconfigpath": {
|
||||
"windows": [],
|
||||
"darwin": [],
|
||||
"linux": []
|
||||
},
|
||||
"workingSpace": "linear",
|
||||
"sixteenBitLut": "sRGB",
|
||||
"eightBitLut": "sRGB",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,12 +1,23 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
"RenderSettings": {
|
||||
"default_render_image_folder": "renders/3dsmax",
|
||||
"aov_separator": "underscore",
|
||||
"image_format": "exr",
|
||||
"multipass": true
|
||||
},
|
||||
"PointCloud":{
|
||||
"attribute":{
|
||||
"PointCloud": {
|
||||
"attribute": {
|
||||
"Age": "age",
|
||||
"Radius": "radius",
|
||||
"Position": "position",
|
||||
|
|
|
|||
|
|
@ -410,31 +410,28 @@
|
|||
]
|
||||
},
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
},
|
||||
"workfile": {
|
||||
"enabled": false,
|
||||
"renderSpace": "ACEScg",
|
||||
"displayName": "sRGB",
|
||||
"viewName": "ACES 1.0 SDR-video"
|
||||
},
|
||||
"colorManagementPreference_v2": {
|
||||
"enabled": true,
|
||||
"configFilePath": {
|
||||
"windows": [],
|
||||
"darwin": [],
|
||||
"linux": []
|
||||
},
|
||||
"renderSpace": "ACEScg",
|
||||
"displayName": "sRGB",
|
||||
"viewName": "ACES 1.0 SDR-video"
|
||||
},
|
||||
"colorManagementPreference": {
|
||||
"configFilePath": {
|
||||
"windows": [],
|
||||
"darwin": [],
|
||||
"linux": []
|
||||
},
|
||||
"renderSpace": "scene-linear Rec 709/sRGB",
|
||||
"viewTransform": "sRGB gamma"
|
||||
}
|
||||
|
|
@ -456,6 +453,10 @@
|
|||
"destination-path": []
|
||||
}
|
||||
},
|
||||
"include_handles": {
|
||||
"include_handles_default": false,
|
||||
"per_task_type": []
|
||||
},
|
||||
"scriptsmenu": {
|
||||
"name": "OpenPype Tools",
|
||||
"definition": [
|
||||
|
|
@ -1556,10 +1557,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"include_handles": {
|
||||
"include_handles_default": false,
|
||||
"per_task_type": []
|
||||
},
|
||||
"templated_workfile_build": {
|
||||
"profiles": []
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@
|
|||
}
|
||||
},
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
},
|
||||
"viewer": {
|
||||
|
|
@ -26,11 +27,6 @@
|
|||
"workfile": {
|
||||
"colorManagement": "Nuke",
|
||||
"OCIO_config": "nuke-default",
|
||||
"customOCIOConfigPath": {
|
||||
"windows": [],
|
||||
"darwin": [],
|
||||
"linux": []
|
||||
},
|
||||
"workingSpaceLUT": "linear",
|
||||
"monitorLut": "sRGB",
|
||||
"int8Lut": "sRGB",
|
||||
|
|
@ -148,7 +144,7 @@
|
|||
},
|
||||
{
|
||||
"plugins": [
|
||||
"CreateWriteStill"
|
||||
"CreateWriteImage"
|
||||
],
|
||||
"nukeNodeClass": "Write",
|
||||
"knobs": [
|
||||
|
|
@ -563,15 +559,7 @@
|
|||
"load": {
|
||||
"LoadImage": {
|
||||
"enabled": true,
|
||||
"_representations": [
|
||||
"exr",
|
||||
"dpx",
|
||||
"jpg",
|
||||
"jpeg",
|
||||
"png",
|
||||
"psd",
|
||||
"tiff"
|
||||
],
|
||||
"_representations": [],
|
||||
"node_name_template": "{class_name}_{ext}"
|
||||
},
|
||||
"LoadClip": {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"remapping": {
|
||||
"rules": []
|
||||
},
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
{
|
||||
"launch_openpype_menu_on_start": false,
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"remapping": {
|
||||
"rules": []
|
||||
},
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": true,
|
||||
"override_global_config": true,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": true,
|
||||
"activate_host_rules": true,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
|
|
@ -22,6 +23,7 @@
|
|||
"detailed_description": "Workfiles are full scenes from any application that are directly edited by artists. They represent a state of work on a task at a given point and are usually not directly referenced into other scenes.",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": false,
|
||||
"allow_version_control": false,
|
||||
"extensions": [
|
||||
".ma",
|
||||
".mb",
|
||||
|
|
@ -56,6 +58,7 @@
|
|||
"detailed_description": "Models should only contain geometry data, without any extras like cameras, locators or bones.\n\nKeep in mind that models published from tray publisher are not validated for correctness. ",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": true,
|
||||
"allow_version_control": false,
|
||||
"extensions": [
|
||||
".ma",
|
||||
".mb",
|
||||
|
|
@ -81,6 +84,7 @@
|
|||
"detailed_description": "Alembic or bgeo cache of animated data",
|
||||
"allow_sequences": true,
|
||||
"allow_multiple_items": true,
|
||||
"allow_version_control": false,
|
||||
"extensions": [
|
||||
".abc",
|
||||
".bgeo",
|
||||
|
|
@ -104,6 +108,7 @@
|
|||
"detailed_description": "Any type of image seqeuence coming from outside of the studio. Usually camera footage, but could also be animatics used for reference.",
|
||||
"allow_sequences": true,
|
||||
"allow_multiple_items": true,
|
||||
"allow_version_control": false,
|
||||
"extensions": [
|
||||
".exr",
|
||||
".png",
|
||||
|
|
@ -126,6 +131,7 @@
|
|||
"detailed_description": "Sequence or single file renders",
|
||||
"allow_sequences": true,
|
||||
"allow_multiple_items": true,
|
||||
"allow_version_control": false,
|
||||
"extensions": [
|
||||
".exr",
|
||||
".png",
|
||||
|
|
@ -149,6 +155,7 @@
|
|||
"detailed_description": "Ideally this should be only camera itself with baked animation, however, it can technically also include helper geometry.",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": true,
|
||||
"allow_version_control": false,
|
||||
"extensions": [
|
||||
".abc",
|
||||
".ma",
|
||||
|
|
@ -173,6 +180,7 @@
|
|||
"detailed_description": "Any image data can be published as image family. References, textures, concept art, matte paints. This is a fallback 2d family for everything that doesn't fit more specific family.",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": true,
|
||||
"allow_version_control": false,
|
||||
"extensions": [
|
||||
".exr",
|
||||
".jpg",
|
||||
|
|
@ -196,6 +204,7 @@
|
|||
"detailed_description": "Hierarchical data structure for the efficient storage and manipulation of sparse volumetric data discretized on three-dimensional grids",
|
||||
"allow_sequences": true,
|
||||
"allow_multiple_items": true,
|
||||
"allow_version_control": false,
|
||||
"extensions": [
|
||||
".vdb"
|
||||
]
|
||||
|
|
@ -214,6 +223,7 @@
|
|||
"detailed_description": "Script exported from matchmoving application to be later processed into a tracked camera with additional data",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": true,
|
||||
"allow_version_control": false,
|
||||
"extensions": []
|
||||
},
|
||||
{
|
||||
|
|
@ -226,6 +236,7 @@
|
|||
"detailed_description": "CG rigged character or prop. Rig should be clean of any extra data and directly loadable into it's respective application\t",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": false,
|
||||
"allow_version_control": false,
|
||||
"extensions": [
|
||||
".ma",
|
||||
".blend",
|
||||
|
|
@ -243,6 +254,7 @@
|
|||
"detailed_description": "Texture files with Unreal Engine naming conventions",
|
||||
"allow_sequences": false,
|
||||
"allow_multiple_items": true,
|
||||
"allow_version_control": false,
|
||||
"extensions": []
|
||||
}
|
||||
],
|
||||
|
|
@ -321,6 +333,11 @@
|
|||
"enabled": true,
|
||||
"optional": true,
|
||||
"active": true
|
||||
},
|
||||
"ValidateExistingVersion": {
|
||||
"enabled": true,
|
||||
"optional": true,
|
||||
"active": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"imageio": {
|
||||
"activate_host_color_management": true,
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
"override_global_config": false,
|
||||
"filepath": []
|
||||
},
|
||||
"file_rules": {
|
||||
"enabled": false,
|
||||
"activate_host_rules": false,
|
||||
"rules": {}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (OCIO managed)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_ocio"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -34,18 +34,14 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (OCIO managed)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_ocio"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (derived to OCIO)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_derived"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,16 +8,13 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (remapped to OCIO)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_remapped"
|
||||
},
|
||||
{
|
||||
"key": "project",
|
||||
|
|
@ -47,10 +44,14 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"label": "Profile names mapping settings is deprecated use <a href=\"settings://project_settings/flame/imageio/remapping\"><b>./imagio/remapping</b></a> instead"
|
||||
},
|
||||
{
|
||||
"key": "profilesMapping",
|
||||
"type": "dict",
|
||||
"label": "Profile names mapping",
|
||||
"label": "Profile names mapping [deprecated]",
|
||||
"collapsible": true,
|
||||
"children": [
|
||||
{
|
||||
|
|
@ -362,7 +363,7 @@
|
|||
},
|
||||
{
|
||||
"key": "colorspace_out",
|
||||
"label": "Output color (imageio)",
|
||||
"label": "Output color",
|
||||
"type": "text",
|
||||
"default": "linear"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1058,7 +1058,7 @@
|
|||
{
|
||||
"type": "dict",
|
||||
"key": "IntegrateFtrackFarmStatus",
|
||||
"label": "Integrate Ftrack Farm Status",
|
||||
"label": "Ftrack Status To Farm",
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
|
|
@ -1068,7 +1068,7 @@
|
|||
"type": "list",
|
||||
"collapsible": true,
|
||||
"key": "farm_status_profiles",
|
||||
"label": "Farm status profiles",
|
||||
"label": "Profiles",
|
||||
"use_label_wrap": true,
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
|
|
@ -1114,6 +1114,142 @@
|
|||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"key": "ftrack_task_status_local_publish",
|
||||
"label": "Ftrack Status Local Integration",
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
"label": "Change status of task when is integrated locally"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"collapsible": true,
|
||||
"key": "status_profiles",
|
||||
"label": "Profiles",
|
||||
"use_label_wrap": true,
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"key": "host_names",
|
||||
"label": "Host names",
|
||||
"type": "hosts-enum",
|
||||
"multiselection": true
|
||||
},
|
||||
{
|
||||
"key": "task_types",
|
||||
"label": "Task types",
|
||||
"type": "task-types-enum"
|
||||
},
|
||||
{
|
||||
"key": "task_names",
|
||||
"label": "Task names",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"key": "families",
|
||||
"label": "Families",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"key": "subset_names",
|
||||
"label": "Subset names",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"type": "separator"
|
||||
},
|
||||
{
|
||||
"key": "status_name",
|
||||
"label": "Status name",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"key": "ftrack_task_status_on_farm_publish",
|
||||
"label": "Ftrack Status On Farm",
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
"label": "Change status of task when it's subset is integrated on farm"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"collapsible": true,
|
||||
"key": "status_profiles",
|
||||
"label": "Profiles",
|
||||
"use_label_wrap": true,
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"key": "host_names",
|
||||
"label": "Host names",
|
||||
"type": "hosts-enum",
|
||||
"multiselection": true
|
||||
},
|
||||
{
|
||||
"key": "task_types",
|
||||
"label": "Task types",
|
||||
"type": "task-types-enum"
|
||||
},
|
||||
{
|
||||
"key": "task_names",
|
||||
"label": "Task names",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"key": "families",
|
||||
"label": "Families",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"key": "subset_names",
|
||||
"label": "Subset names",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"type": "separator"
|
||||
},
|
||||
{
|
||||
"key": "status_name",
|
||||
"label": "Status name",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"key": "IntegrateFtrackTaskStatus",
|
||||
"label": "Integrate Ftrack Task Status",
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
"label": "Apply collected task statuses. This plugin can run before or after version integration. Some status automations may conflict with status changes on versions because of wrong order."
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "after_version_statuses",
|
||||
"label": "After version integration"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,41 +8,13 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (OCIO managed)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
},
|
||||
{
|
||||
"key": "ocio",
|
||||
"type": "dict",
|
||||
"label": "OpenColorIO (OCIO)",
|
||||
"collapsible": true,
|
||||
"checkbox_key": "enabled",
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Set OCIO variable for Fusion"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"label": "<b style='color:red'>'configFilePath'</b> will be deprecated. <br>Please move values to : <i>project_settings/{app}/imageio/ocio_config/filepath</i>."
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"key": "configFilePath",
|
||||
"label": "OCIO Config File Path",
|
||||
"multiplatform": true,
|
||||
"multipath": true
|
||||
}
|
||||
]
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_ocio"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,9 +8,18 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management",
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
"label": "It's important to note that once color management is activated on a project, all hosts will be color managed by default. <br>The OpenColorIO (OCIO) config file is used either from the global settings or from the host's overrides. It's worth <br>noting that the order of the defined configuration paths matters, with higher priority given to paths listed earlier in <br>the configuration list.<br><br>To avoid potential issues, ensure that the OCIO configuration path is not an absolute path and includes at least <br>the root token (Anatomy). This helps ensure that the configuration path remains valid across different environments and <br>avoids any hard-coding of paths that may be specific to one particular system.<br><br><b><a href='https://ayon.ynput.io/docs/admin_colorspace' style=\"color:#00d6a1\";>Related documentation.</a></b>"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "activate_global_color_management",
|
||||
"label": "Enable Color Management"
|
||||
},
|
||||
{
|
||||
"key": "ocio_config",
|
||||
"type": "dict",
|
||||
|
|
@ -27,8 +36,44 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"key": "file_rules",
|
||||
"type": "dict",
|
||||
"label": "File Rules (OCIO v1 only)",
|
||||
"collapsible": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "activate_global_file_rules",
|
||||
"label": "Enable File Rules"
|
||||
},
|
||||
{
|
||||
"key": "rules",
|
||||
"label": "Rules",
|
||||
"type": "dict-modifiable",
|
||||
"highlight_content": true,
|
||||
"collapsible": false,
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"key": "pattern",
|
||||
"label": "Regex pattern",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "colorspace",
|
||||
"label": "Colorspace name",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "ext",
|
||||
"label": "File extension",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (OCIO managed)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_ocio"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,17 +8,13 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"is_group": true,
|
||||
"label": "Color Management (OCIO managed)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_ocio"
|
||||
},
|
||||
{
|
||||
"key": "workfile",
|
||||
|
|
@ -26,10 +22,6 @@
|
|||
"label": "Workfile",
|
||||
"collapsible": false,
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
"label": "<b style='color:red'>'ocioconfigpath'</b> will be deprecated. <br>Please move values to : <i>project_settings/{app}/imageio/ocio_config/filepath</i>."
|
||||
},
|
||||
{
|
||||
"type": "form",
|
||||
"children": [
|
||||
|
|
@ -55,19 +47,9 @@
|
|||
},
|
||||
{
|
||||
"cg-config-v1.0.0_aces-v1.3_ocio-v2.1": "cg-config-v1.0.0_aces-v1.3_ocio-v2.1 (14)"
|
||||
},
|
||||
{
|
||||
"custom": "custom"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"key": "ocioconfigpath",
|
||||
"label": "Custom OCIO path",
|
||||
"multiplatform": true,
|
||||
"multipath": true
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "workingSpace",
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (OCIO managed)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_ocio"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -35,4 +31,4 @@
|
|||
"name": "schema_houdini_publish"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,19 @@
|
|||
"label": "Max",
|
||||
"is_file": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (OCIO managed)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_ocio"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
|
|
|
|||
|
|
@ -48,40 +48,25 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (OCIO managed)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_ocio"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
},
|
||||
{
|
||||
"key": "colorManagementPreference_v2",
|
||||
"key": "workfile",
|
||||
"type": "dict",
|
||||
"label": "Color Management Preference v2 (Maya 2022+)",
|
||||
"label": "Workfile",
|
||||
"collapsible": true,
|
||||
"checkbox_key": "enabled",
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Use Color Management Preference v2"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"label": "<b style='color:red'>'configFilePath'</b> will be deprecated. <br>Please move values to : <i>project_settings/{app}/imageio/ocio_config/filepath</i>."
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"key": "configFilePath",
|
||||
"label": "OCIO Config File Path",
|
||||
"multiplatform": true,
|
||||
"multipath": true
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
|
|
@ -101,31 +86,57 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"key": "colorManagementPreference",
|
||||
"type": "dict",
|
||||
"label": "Color Management Preference (legacy)",
|
||||
"type": "collapsible-wrap",
|
||||
"label": "<b>[Deprecated] please migrate all to 'Workfile' and enable it.</b>",
|
||||
"collapsible": true,
|
||||
"collapsed": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
"label": "<b style='color:red'>'configFilePath'</b> will be deprecated. <br>Please move values to : <i>project_settings/{app}/imageio/ocio_config/filepath</i>."
|
||||
"key": "colorManagementPreference_v2",
|
||||
"type": "dict",
|
||||
"label": "[DEPRECATED] Color Management Preference v2 (Maya 2022+)",
|
||||
"collapsible": true,
|
||||
"checkbox_key": "enabled",
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Use Color Management Preference v2"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "renderSpace",
|
||||
"label": "Rendering Space"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "displayName",
|
||||
"label": "Display"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "viewName",
|
||||
"label": "View"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"key": "configFilePath",
|
||||
"label": "OCIO Config File Path",
|
||||
"multiplatform": true,
|
||||
"multipath": true
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "renderSpace",
|
||||
"label": "Rendering Space"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "viewTransform",
|
||||
"label": "Viewer Transform"
|
||||
"key": "colorManagementPreference",
|
||||
"type": "dict",
|
||||
"label": "[DEPRECATED] Color Management Preference (legacy)",
|
||||
"collapsible": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"key": "renderSpace",
|
||||
"label": "Rendering Space"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "viewTransform",
|
||||
"label": "Viewer Transform (workfile/viewName)"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (remapped to OCIO)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_remapped"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,18 +13,14 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (remapped to OCIO)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_remapped"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,18 +8,13 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (OCIO managed)",
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_ocio"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (derived to OCIO)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_derived"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -89,6 +85,12 @@
|
|||
"label": "Allow multiple items",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "allow_version_control",
|
||||
"label": "Allow version control",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"key": "extensions",
|
||||
|
|
@ -350,6 +352,10 @@
|
|||
{
|
||||
"key": "ValidateFrameRange",
|
||||
"label": "Validate frame range"
|
||||
},
|
||||
{
|
||||
"key": "ValidateExistingVersion",
|
||||
"label": "Validate Existing Version"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (derived to OCIO)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_derived"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (OCIO managed)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_ocio"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (derived to OCIO)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_derived"
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"key": "ocio_config",
|
||||
"type": "dict",
|
||||
"label": "OCIO config",
|
||||
"collapsible": true,
|
||||
"checkbox_key": "enabled",
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"key": "filepath",
|
||||
"label": "Config path",
|
||||
"multiplatform": false,
|
||||
"multipath": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
"key": "file_rules",
|
||||
"type": "dict",
|
||||
"label": "File Rules",
|
||||
"collapsible": true,
|
||||
"checkbox_key": "enabled",
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"key": "rules",
|
||||
"label": "Rules",
|
||||
"type": "dict-modifiable",
|
||||
"highlight_content": true,
|
||||
"collapsible": false,
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"key": "pattern",
|
||||
"label": "Regex pattern",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "colorspace",
|
||||
"label": "Colorspace name",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "ext",
|
||||
"label": "File extension",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,21 +1,13 @@
|
|||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
"label": "Color Management (ImageIO)",
|
||||
"label": "Color Management (OCIO managed)",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
"label": "<b style='color:red'>'Custom OCIO config path'</b> has deprecated. <br> If you need to set custom config, just enable and add path into 'OCIO config'. <br>Anatomy keys are supported.</i>."
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "schema",
|
||||
"name": "schema_imageio_file_rules"
|
||||
"type": "template",
|
||||
"name": "template_host_color_management_ocio"
|
||||
},
|
||||
{
|
||||
"key": "viewer",
|
||||
|
|
@ -102,19 +94,9 @@
|
|||
},
|
||||
{
|
||||
"cg-config-v1.0.0_aces-v1.3_ocio-v2.1": "cg-config-v1.0.0_aces-v1.3_ocio-v2.1 (14)"
|
||||
},
|
||||
{
|
||||
"custom": "custom"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"key": "customOCIOConfigPath",
|
||||
"label": "Custom OCIO config path",
|
||||
"multiplatform": true,
|
||||
"multipath": true
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "workingSpaceLUT",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
[
|
||||
{
|
||||
"key": "remapping",
|
||||
"type": "dict",
|
||||
"label": "Remapping colorspace names",
|
||||
"collapsible": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "list",
|
||||
"key": "rules",
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"key": "host_native_name",
|
||||
"label": "Application native colorspace name"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "ocio_name",
|
||||
"label": "OCIO colorspace name"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
[
|
||||
{
|
||||
"type": "label",
|
||||
"label": "The application does not include any built-in color management capabilities, OpenPype offers a solution <br>to this limitation by deriving valid colorspace names for the OpenColorIO (OCIO) color management <br>system from file paths, using File Rules feature only during Publishing.<br><br><b><a href='https://ayon.ynput.io/docs/admin_colorspace#derived-colorspace' style=\"color:#00d6a1\";>Related documentation.</a></b>"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "activate_host_color_management",
|
||||
"label": "Enable Color Management"
|
||||
},
|
||||
{
|
||||
"type": "template",
|
||||
"name": "template_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "template",
|
||||
"name": "template_imageio_file_rules"
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
[
|
||||
{
|
||||
"type": "label",
|
||||
"label": "Colorspace management for the application can be controlled through OpenPype settings. <br>Specifically, the configured OpenColorIO (OCIO) config path is utilized in the application's workfile. <br>Additionally, the File Rules feature can be leveraged for both publishing and loading procedures.<br><br><b><a href='https://ayon.ynput.io/docs/admin_colorspace#remapped-internal-colorspace' style=\"color:#00d6a1\";>Related documentation.</a></b>"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "activate_host_color_management",
|
||||
"label": "Enable Color Management"
|
||||
},
|
||||
{
|
||||
"type": "template",
|
||||
"name": "template_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "template",
|
||||
"name": "template_imageio_file_rules"
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
[
|
||||
{
|
||||
"type": "label",
|
||||
"label": "The application includes internal color management functionality, but it does not offer external control <br>over this feature. To address this limitation, OpenPype uses mapping rules to remap the native <br>colorspace names used in the internal color management system to the OpenColorIO (OCIO) <br>color management system. Remapping feature is used in Publishing and Loading procedures.<br><br><b><a href='https://ayon.ynput.io/docs/admin_colorspace#remapped-internal-colorspace' style=\"color:#00d6a1\";>Related documentation.</a></b>."
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "activate_host_color_management",
|
||||
"label": "Enable Color Management"
|
||||
},
|
||||
{
|
||||
"type": "template",
|
||||
"name": "template_colorspace_remapping"
|
||||
},
|
||||
{
|
||||
"type": "template",
|
||||
"name": "template_imageio_config"
|
||||
},
|
||||
{
|
||||
"type": "template",
|
||||
"name": "template_imageio_file_rules"
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
[
|
||||
{
|
||||
"key": "ocio_config",
|
||||
"type": "dict",
|
||||
"label": "OCIO config",
|
||||
"collapsible": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "override_global_config",
|
||||
"label": "Override global OCIO config"
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"key": "filepath",
|
||||
"label": "Config path",
|
||||
"multiplatform": false,
|
||||
"multipath": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
[
|
||||
{
|
||||
"key": "file_rules",
|
||||
"type": "dict",
|
||||
"label": "File Rules (OCIO v1 only)",
|
||||
"collapsible": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "activate_host_rules",
|
||||
"label": "Activate Host File Rules"
|
||||
},
|
||||
{
|
||||
"key": "rules",
|
||||
"label": "Rules",
|
||||
"type": "dict-modifiable",
|
||||
"highlight_content": true,
|
||||
"collapsible": false,
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"key": "pattern",
|
||||
"label": "Regex pattern",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "colorspace",
|
||||
"label": "Colorspace name",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "ext",
|
||||
"label": "File extension",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
@ -53,6 +53,9 @@ class CreatorsModel(QtGui.QStandardItemModel):
|
|||
index = self.index(row, 0)
|
||||
item_id = index.data(ITEM_ID_ROLE)
|
||||
creator_plugin = self._creators_by_id.get(item_id)
|
||||
if creator_plugin and creator_plugin.family == family:
|
||||
if creator_plugin and (
|
||||
creator_plugin.label.lower() == family.lower()
|
||||
or creator_plugin.family.lower() == family.lower()
|
||||
):
|
||||
indexes.append(index)
|
||||
return indexes
|
||||
|
|
|
|||
|
|
@ -828,6 +828,7 @@ class CreateWidget(QtWidgets.QWidget):
|
|||
|
||||
if success:
|
||||
self._set_creator(self._selected_creator)
|
||||
self.variant_input.setText(variant)
|
||||
self._controller.emit_card_message("Creation finished...")
|
||||
self._last_thumbnail_path = None
|
||||
self._thumbnail_widget.set_current_thumbnails()
|
||||
|
|
|
|||
|
|
@ -453,7 +453,11 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
return
|
||||
|
||||
save_match = event.matches(QtGui.QKeySequence.Save)
|
||||
if save_match == QtGui.QKeySequence.ExactMatch:
|
||||
# PySide2 and PySide6 support
|
||||
if not isinstance(save_match, bool):
|
||||
save_match = save_match == QtGui.QKeySequence.ExactMatch
|
||||
|
||||
if save_match:
|
||||
if not self._controller.publish_has_started:
|
||||
self._save_changes(True)
|
||||
event.accept()
|
||||
|
|
|
|||
|
|
@ -128,7 +128,8 @@ class FamilyWidget(QtWidgets.QWidget):
|
|||
'family_preset_key': key,
|
||||
'family': family,
|
||||
'subset': self.input_result.text(),
|
||||
'version': self.version_spinbox.value()
|
||||
'version': self.version_spinbox.value(),
|
||||
'use_next_available_version': self.version_checkbox.isChecked(),
|
||||
}
|
||||
return data
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Package declaring Pype version."""
|
||||
__version__ = "3.15.10-nightly.2"
|
||||
__version__ = "3.15.11-nightly.3"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "OpenPype"
|
||||
version = "3.15.9" # OpenPype
|
||||
version = "3.15.10" # OpenPype
|
||||
description = "Open VFX and Animation pipeline with support."
|
||||
authors = ["OpenPype Team <info@openpype.io>"]
|
||||
license = "MIT License"
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ log = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class TestPipelinePublishPlugins(TestPipeline):
|
||||
""" Testing Pipeline pubish_plugins.py
|
||||
""" Testing Pipeline publish_plugins.py
|
||||
|
||||
Example:
|
||||
cd to OpenPype repo root dir
|
||||
|
|
@ -37,7 +37,7 @@ class TestPipelinePublishPlugins(TestPipeline):
|
|||
# files are the same as those used in `test_pipeline_colorspace`
|
||||
TEST_FILES = [
|
||||
(
|
||||
"1d7t9_cVKeZRVF0ppCHiE5MJTTtTlJgBe",
|
||||
"1Lf-mFxev7xiwZCWfImlRcw7Fj8XgNQMh",
|
||||
"test_pipeline_colorspace.zip",
|
||||
""
|
||||
)
|
||||
|
|
@ -140,7 +140,7 @@ class TestPipelinePublishPlugins(TestPipeline):
|
|||
config_data, file_rules = plugin.get_colorspace_settings(context)
|
||||
|
||||
assert config_data["template"] == expected_config_template, (
|
||||
"Returned config tempate is not "
|
||||
"Returned config template is not "
|
||||
f"matching {expected_config_template}"
|
||||
)
|
||||
assert file_rules == expected_file_rules, (
|
||||
|
|
@ -193,11 +193,11 @@ class TestPipelinePublishPlugins(TestPipeline):
|
|||
colorspace_data_hiero = representation_hiero.get("colorspaceData")
|
||||
|
||||
assert colorspace_data_nuke, (
|
||||
"Colorspace data were not created in prepresentation"
|
||||
"Colorspace data were not created in representation"
|
||||
f"matching {representation_nuke}"
|
||||
)
|
||||
assert colorspace_data_hiero, (
|
||||
"Colorspace data were not created in prepresentation"
|
||||
"Colorspace data were not created in representation"
|
||||
f"matching {representation_hiero}"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class TestPipelineColorspace(TestPipeline):
|
|||
|
||||
TEST_FILES = [
|
||||
(
|
||||
"1d7t9_cVKeZRVF0ppCHiE5MJTTtTlJgBe",
|
||||
"1Lf-mFxev7xiwZCWfImlRcw7Fj8XgNQMh",
|
||||
"test_pipeline_colorspace.zip",
|
||||
""
|
||||
)
|
||||
|
|
@ -120,7 +120,7 @@ class TestPipelineColorspace(TestPipeline):
|
|||
)
|
||||
assert config_data["template"] == expected_template, (
|
||||
f"Config template \'{config_data['template']}\' doesn't match "
|
||||
f"expected tempalte \'{expected_template}\'"
|
||||
f"expected template \'{expected_template}\'"
|
||||
)
|
||||
|
||||
def test_parse_colorspace_from_filepath(
|
||||
|
|
|
|||
|
|
@ -196,6 +196,8 @@ if [ "$disable_submodule_update" == 1 ]; then
|
|||
echo -e "${BIGreen}>>>${RST} Fixing libs ..."
|
||||
mv "$openpype_root/build/OpenPype $openpype_version.app/Contents/MacOS/dependencies/cx_Freeze" "$openpype_root/build/OpenPype $openpype_version.app/Contents/MacOS/lib/" || { echo -e "${BIRed}!!!>${RST} ${BIYellow}Can't move cx_Freeze libs${RST}"; return 1; }
|
||||
|
||||
# force hide icon from Dock
|
||||
defaults write "$openpype_root/build/OpenPype $openpype_version.app/Contents/Info" LSUIElement 1
|
||||
|
||||
# fix code signing issue
|
||||
echo -e "${BIGreen}>>>${RST} Fixing code signatures ...\c"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue