Skip to content

Commit

Permalink
fix: Add OCIO configuration to Job Environments
Browse files Browse the repository at this point in the history
Signed-off-by: Haejung Choi <chaejung@amazon.com>
  • Loading branch information
Haejung Choi committed Sep 17, 2024
1 parent 82b7eb2 commit c3fd74d
Show file tree
Hide file tree
Showing 10 changed files with 321 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ parameterValues:
value: 1-100
- name: NukeScriptFile
value: /normalized/job/bundle/dir/ocio.nk
- name: OCIOConfigPath
value: /normalized/job/bundle/dir/config.ocio
- name: ProxyMode
value: 'false'
- name: deadline:targetTaskRunStatus
Expand Down
17 changes: 17 additions & 0 deletions job_bundle_output_tests/ocio/expected_job_bundle/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ parameterDefinitions:
patterns:
- '*'
description: The Nuke script file to render.
- name: OCIOConfigPath
type: PATH
objectType: FILE
dataFlow: IN
description: The directory containing OCIO config files used by this job.
- name: Frames
type: STRING
description: The frames to render. E.g. 1-3,8,11-15
Expand Down Expand Up @@ -126,3 +131,15 @@ steps:
cancelation:
mode: NOTIFY_THEN_TERMINATE
timeout: 518400
jobEnvironments:
- name: Add OCIO Path to Environment Variable
script:
actions:
onEnter:
command: '{{Env.File.Enter}}'
embeddedFiles:
- name: Enter
type: TEXT
runnable: true
data: "#!/bin/bash\n echo 'openjd_env: OCIO={{Param.OCIOConfigPath}}'\n \
\ "
4 changes: 2 additions & 2 deletions src/deadline/nuke_adaptor/NukeClient/nuke_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ def ensure_output_dir():
os.makedirs(output_dir)

def verify_ocio_config():
"""If using a custom OCIO config, update the internal search paths if necessary"""
if nuke_ocio.is_custom_config_enabled():
"""If using an OCIO config, update the internal search paths if necessary"""
if nuke_ocio.is_OCIO_enabled():
self._map_ocio_config()

nuke.addBeforeRender(verify_ocio_config)
Expand Down
42 changes: 33 additions & 9 deletions src/deadline/nuke_submitter/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from collections.abc import Generator
from os.path import commonpath, dirname, join, normpath, samefile
from sys import platform

from typing import Optional
import nuke

from deadline.client.job_bundle.submission import AssetReferences
Expand Down Expand Up @@ -81,17 +81,41 @@ def get_scene_asset_references() -> AssetReferences:
for filename in get_node_filenames(node):
asset_references.output_directories.add(dirname(filename))

# if using a custom OCIO config, add the config file and associated search directories
if nuke_ocio.is_custom_config_enabled():
ocio_config_path = nuke_ocio.get_custom_config_path()
ocio_config_search_paths = nuke_ocio.get_config_absolute_search_paths(ocio_config_path)
if nuke_ocio.is_OCIO_enabled():
# Determine and add the config file and associated search directories
ocio_config_path = get_ocio_config_path()
# Add the references
if ocio_config_path is not None:
if os.path.isfile(ocio_config_path):
asset_references.input_filenames.add(ocio_config_path)

ocio_config_search_paths = nuke_ocio.get_config_absolute_search_paths(
ocio_config_path
)
for search_path in ocio_config_search_paths:
asset_references.input_directories.add(search_path)
else:
nuke.alert(
"OCIO config file specified(%s) is not an existing file." % ocio_config_path
)

asset_references.input_filenames.add(ocio_config_path)
return asset_references

for search_path in ocio_config_search_paths:
asset_references.input_directories.add(search_path)

return asset_references
def get_ocio_config_path() -> Optional[str]:
ocio_config_path = None

# if using a custom OCIO environment variable
if nuke_ocio.is_env_config_enabled():
ocio_config_path = nuke_ocio.get_env_config_path()
else:
print("here?")
# if using a custom OCIO config file
if nuke_ocio.is_custom_config_enabled():
ocio_config_path = nuke_ocio.get_custom_config_path()
elif nuke_ocio.is_stock_config_enabled():
ocio_config_path = nuke_ocio.get_stock_config_path()
return ocio_config_path


def find_all_write_nodes() -> set:
Expand Down
54 changes: 53 additions & 1 deletion src/deadline/nuke_submitter/deadline_submitter_for_nuke.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
SubmitJobToDeadlineDialog,
JobBundlePurpose,
)
from deadline.nuke_util import ocio as nuke_ocio
from nuke import Node
from PySide2.QtCore import Qt # pylint: disable=import-error
from PySide2.QtWidgets import ( # pylint: disable=import-error; type: ignore
Expand All @@ -25,7 +26,12 @@
)

from ._version import version, version_tuple as adaptor_version_tuple
from .assets import get_nuke_script_file, get_scene_asset_references, find_all_write_nodes
from .assets import (
get_nuke_script_file,
get_scene_asset_references,
find_all_write_nodes,
get_ocio_config_path,
)
from .data_classes import RenderSubmitterUISettings
from .ui.components.scene_settings_tab import SceneSettingsWidget
from deadline.client.job_bundle.submission import AssetReferences
Expand Down Expand Up @@ -112,6 +118,40 @@ def _add_gizmo_dir_to_job_template(job_template: dict[str, Any]) -> None:
)


def _add_ocio_path_to_job_template(job_template: dict[str, Any]) -> None:
if "jobEnvironments" not in job_template:
job_template["jobEnvironments"] = []

# This needs to be prepended rather than appended
# as it must run before the "Nuke" environment.
job_template["jobEnvironments"].insert(
0,
{
"name": "Add OCIO Path to Environment Variable",
"script": {
"actions": {"onEnter": {"command": "{{Env.File.Enter}}"}},
"embeddedFiles": [
{
"name": "Enter",
"type": "TEXT",
"runnable": True,
"data": """#!/bin/bash
echo 'openjd_env: OCIO={{Param.OCIOConfigPath}}'
""",
}
],
},
},
)


def _remove_ocio_path_from_job_template(job_template: dict[str, Any]) -> None:
for index, param in enumerate(job_template["parameterDefinitions"]):
if param["name"] == "OCIOConfigPath":
job_template["parameterDefinitions"].pop(index)
break


def _get_job_template(settings: RenderSubmitterUISettings) -> dict[str, Any]:
# Load the default Nuke job template, and then fill in scene-specific
# values it needs.
Expand Down Expand Up @@ -144,6 +184,12 @@ def _get_job_template(settings: RenderSubmitterUISettings) -> dict[str, Any]:
# Set the View parameter allowed values
parameter_def_map["View"]["allowedValues"] = ["All Views"] + sorted(nuke.views())

# if OCIO is disabled, remove OCIO path from the template
if nuke_ocio.is_OCIO_enabled():
_add_ocio_path_to_job_template(job_template)
else:
_remove_ocio_path_from_job_template(job_template)

# If this developer option is enabled, merge the adaptor_override_environment
if settings.include_adaptor_wheels:
with open(Path(__file__).parent / "adaptor_override_environment.yaml") as f:
Expand Down Expand Up @@ -239,6 +285,12 @@ def _get_parameter_values(
parameter_values.append(
{"name": "ProxyMode", "value": "true" if settings.is_proxy_mode else "false"}
)

# Set the OCIO config path value
if nuke_ocio.is_OCIO_enabled():
ocio_config_path = get_ocio_config_path()
parameter_values.append({"name": "OCIOConfigPath", "value": ocio_config_path})

if settings.include_adaptor_wheels:
wheels_path = str(Path(__file__).parent.parent.parent.parent / "wheels")
parameter_values.append({"name": "AdaptorWheels", "value": wheels_path})
Expand Down
5 changes: 5 additions & 0 deletions src/deadline/nuke_submitter/default_nuke_job_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ parameterDefinitions:
label: Gizmo Directory
description: The directory containing Nuke Gizmo files used by this job.
default: './gizmos'
- name: OCIOConfigPath
type: PATH
objectType: FILE
dataFlow: IN
description: The directory containing OCIO config files used by this job.
- name: Frames
type: STRING
description: The frames to render. E.g. 1-3,8,11-15
Expand Down
31 changes: 30 additions & 1 deletion src/deadline/nuke_util/ocio.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,40 @@

import os
from pathlib import PurePath
from typing import Optional

import nuke
import PyOpenColorIO as OCIO


def is_env_config_enabled() -> bool:
"""True if the OCIO environment variable is specified"""
return "OCIO" in os.environ


def get_env_config_path() -> Optional[str]:
"""This is the path to the custom OCIO config used by the OCIO env var."""
return os.environ.get("OCIO")


def is_stock_config_enabled() -> bool:
"""True if the script is using a custom OCIO config"""
return (
nuke.root().knob("colorManagement").value() == "OCIO"
and nuke.root().knob("OCIO_config").value() != "custom"
)


def get_stock_config_path() -> str:
"""This is the path to the UI defined OCIO config file."""
return os.path.abspath(nuke.root().knob("OCIOConfigPath").getEvaluatedValue())


def is_OCIO_enabled() -> bool:
"""Nuke is set to use OCIO."""
return nuke.root().knob("colorManagement").value() == "OCIO"


def is_custom_config_enabled() -> bool:
"""True if the script is using a custom OCIO config"""
return (
Expand All @@ -19,7 +48,7 @@ def is_custom_config_enabled() -> bool:

def get_custom_config_path() -> str:
"""This is the path to the custom OCIO config used by the script"""
return nuke.root().knob("customOCIOConfigPath").getEvaluatedValue()
return os.path.abspath(nuke.root().knob("customOCIOConfigPath").getEvaluatedValue())


def create_config_from_file(ocio_config_path: str) -> OCIO.Config:
Expand Down
46 changes: 45 additions & 1 deletion test/unit/deadline_submitter_for_nuke/test_assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
get_node_file_knob_paths,
get_node_filenames,
get_scene_asset_references,
get_ocio_config_path,
)


Expand All @@ -37,6 +38,8 @@ def _activated_reading_write_node_knobs(knob_name: str):
return_value=["/one/asset.png", "/two/asset.png"],
)
@patch("deadline.nuke_util.ocio.is_custom_config_enabled", return_value=False)
@patch("deadline.nuke_util.ocio.is_stock_config_enabled", return_value=False)
@patch("deadline.nuke_util.ocio.is_OCIO_enabled", return_value=False)
@patch(
"deadline.nuke_util.ocio.get_custom_config_path",
return_value="/this/ocio_configs/config.ocio",
Expand All @@ -48,6 +51,8 @@ def _activated_reading_write_node_knobs(knob_name: str):
def test_get_scene_asset_references(
mock_get_config_absolute_search_paths: Mock,
mock_get_custom_config_path: Mock,
mock_is_OCIO_enabled: Mock,
mock_is_stock_config_enabled: Mock,
mock_is_custom_config_enabled: Mock,
mock_get_node_filenames: Mock,
mock_get_nuke_script_file: Mock,
Expand Down Expand Up @@ -95,10 +100,11 @@ def test_get_scene_asset_references(

nuke.allNodes.return_value = []
mock_is_custom_config_enabled.return_value = True
mock_is_OCIO_enabled.return_value = True
mock_is_stock_config_enabled.return_value = False

# WHEN
results = get_scene_asset_references()

# THEN
assert expected_script_file in results.input_filenames
assert expected_ocio_config_path in results.input_filenames
Expand All @@ -108,6 +114,44 @@ def test_get_scene_asset_references(
)


@patch("deadline.nuke_util.ocio.is_env_config_enabled", return_value=True)
@patch("deadline.nuke_util.ocio.is_custom_config_enabled", return_value=False)
@patch("deadline.nuke_util.ocio.is_stock_config_enabled", return_value=False)
@patch(
"deadline.nuke_util.ocio.get_env_config_path",
return_value="/this/ocio_configs/env_variable_config.ocio",
)
@patch(
"deadline.nuke_util.ocio.get_custom_config_path",
return_value="/this/ocio_configs/custom_config.ocio",
)
@patch(
"deadline.nuke_util.ocio.get_stock_config_path",
return_value="/this/ocio_configs/stock_config.ocio",
)
def test_get_ocio_config_path(
mock_get_stock_config_path,
mock_get_custom_config_path,
mock_get_env_config_path,
mock_is_stock_config_enabled,
mock_is_custom_enabled,
mock_is_env_config_enabled,
):
env_variable_ocio_path = get_ocio_config_path()
assert env_variable_ocio_path == "/this/ocio_configs/env_variable_config.ocio"

mock_is_env_config_enabled.return_value = False
mock_is_custom_enabled.return_value = True
custom_ocio_path = get_ocio_config_path()
assert custom_ocio_path == "/this/ocio_configs/custom_config.ocio"

mock_is_env_config_enabled.return_value = False
mock_is_custom_enabled.return_value = False
mock_is_stock_config_enabled.return_value = True
stock_ocio_path = get_ocio_config_path()
assert stock_ocio_path == "/this/ocio_configs/stock_config.ocio"


@patch("os.path.isfile", return_value=False)
@patch("deadline.nuke_submitter.assets.get_nuke_script_file", return_value="/this/scriptfile.nk")
def test_get_scene_asset_references_script_not_saved(
Expand Down
55 changes: 55 additions & 0 deletions test/unit/deadline_submitter_for_nuke/test_ocio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.


from deadline.nuke_submitter.deadline_submitter_for_nuke import (
_add_ocio_path_to_job_template,
_remove_ocio_path_from_job_template,
)


def test_add__dir_to_job_template():
job_template = {
"parameterDefinitions": [],
"steps": [
{
"name": "Render",
"stepEnvironments": [
{
"name": "OtherEnv",
},
],
}
],
}

_add_ocio_path_to_job_template(job_template)

expected_environment = {
"name": "Add OCIO Path to Environment Variable",
"script": {
"actions": {"onEnter": {"command": "{{Env.File.Enter}}"}},
"embeddedFiles": [
{
"name": "Enter",
"type": "TEXT",
"runnable": True,
"data": """#!/bin/bash
echo 'openjd_env: OCIO={{Param.OCIOConfigPath}}'
""",
}
],
},
}

assert len(job_template["jobEnvironments"]) == 1
assert job_template["jobEnvironments"][0] == expected_environment


def test_remove_ocio_path_from_job_template():
job_template = {"parameterDefinitions": [{"name": "OCIOConfigPath", "type": "PATH"}]}

_remove_ocio_path_from_job_template(job_template)
expected_job_template: dict = {"parameterDefinitions": []}

assert len(job_template["parameterDefinitions"]) == 0
assert job_template == expected_job_template
Loading

0 comments on commit c3fd74d

Please sign in to comment.