diff --git a/.github/workflows/nightly_merge.yml b/.github/workflows/nightly_merge.yml
new file mode 100644
index 0000000000..1776d7a464
--- /dev/null
+++ b/.github/workflows/nightly_merge.yml
@@ -0,0 +1,29 @@
+name: Dev -> Main
+
+on:
+ schedule:
+ - cron: '21 3 * * 3,6'
+ workflow_dispatch:
+
+jobs:
+ develop-to-main:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: 🚛 Checkout Code
+ uses: actions/checkout@v2
+
+ - name: 🔨 Merge develop to main
+ uses: everlytic/branch-merge@1.1.0
+ with:
+ github_token: ${{ secrets.YNPUT_BOT_TOKEN }}
+ source_ref: 'develop'
+ target_branch: 'main'
+ commit_message_template: '[Automated] Merged {source_ref} into {target_branch}'
+
+ - name: Invoke pre-release workflow
+ uses: benc-uk/workflow-dispatch@v1
+ with:
+ workflow: Nightly Prerelease
+ token: ${{ secrets.YNPUT_BOT_TOKEN }}
diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml
new file mode 100644
index 0000000000..571b0339e1
--- /dev/null
+++ b/.github/workflows/prerelease.yml
@@ -0,0 +1,67 @@
+name: Nightly Prerelease
+
+on:
+ workflow_dispatch:
+
+
+jobs:
+ create_nightly:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: 🚛 Checkout Code
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+
+ - name: Set up Python
+ uses: actions/setup-python@v2
+ with:
+ python-version: 3.9
+
+ - name: Install Python requirements
+ run: pip install gitpython semver PyGithub
+
+ - name: 🔎 Determine next version type
+ id: version_type
+ run: |
+ TYPE=$(python ./tools/ci_tools.py --bump --github_token ${{ secrets.YNPUT_BOT_TOKEN }})
+ echo "type=${TYPE}" >> $GITHUB_OUTPUT
+
+ - name: 💉 Inject new version into files
+ id: version
+ if: steps.version_type.outputs.type != 'skip'
+ run: |
+ NEW_VERSION_TAG=$(python ./tools/ci_tools.py --nightly --github_token ${{ secrets.YNPUT_BOT_TOKEN }})
+ echo "next_tag=${NEW_VERSION_TAG}" >> $GITHUB_OUTPUT
+
+ - name: 💾 Commit and Tag
+ id: git_commit
+ if: steps.version_type.outputs.type != 'skip'
+ run: |
+ git config user.email ${{ secrets.CI_EMAIL }}
+ git config user.name ${{ secrets.CI_USER }}
+ git checkout main
+ git pull
+ git add .
+ git commit -m "[Automated] Bump version"
+ tag_name="CI/${{ steps.version.outputs.next_tag }}"
+ echo $tag_name
+ git tag -a $tag_name -m "nightly build"
+
+ - name: Push to protected main branch
+ uses: CasperWA/push-protected@v2.10.0
+ with:
+ token: ${{ secrets.YNPUT_BOT_TOKEN }}
+ branch: main
+ tags: true
+ unprotect_reviews: true
+
+ - name: 🔨 Merge main back to develop
+ uses: everlytic/branch-merge@1.1.0
+ if: steps.version_type.outputs.type != 'skip'
+ with:
+ github_token: ${{ secrets.YNPUT_BOT_TOKEN }}
+ source_ref: 'main'
+ target_branch: 'develop'
+ commit_message_template: '[Automated] Merged {source_ref} into {target_branch}'
diff --git a/openpype/hosts/harmony/api/pipeline.py b/openpype/hosts/harmony/api/pipeline.py
index 4b9849c190..686770b64e 100644
--- a/openpype/hosts/harmony/api/pipeline.py
+++ b/openpype/hosts/harmony/api/pipeline.py
@@ -126,10 +126,6 @@ def check_inventory():
def application_launch(event):
"""Event that is executed after Harmony is launched."""
- # FIXME: This is breaking server <-> client communication.
- # It is now moved so it it manually called.
- # ensure_scene_settings()
- # check_inventory()
# fills OPENPYPE_HARMONY_JS
pype_harmony_path = Path(__file__).parent.parent / "js" / "PypeHarmony.js"
pype_harmony_js = pype_harmony_path.read_text()
@@ -146,6 +142,9 @@ def application_launch(event):
harmony.send({"script": script})
inject_avalon_js()
+ ensure_scene_settings()
+ check_inventory()
+
def export_template(backdrops, nodes, filepath):
"""Export Template to file.
diff --git a/openpype/hosts/maya/api/commands.py b/openpype/hosts/maya/api/commands.py
index 19ad18d824..018340d86c 100644
--- a/openpype/hosts/maya/api/commands.py
+++ b/openpype/hosts/maya/api/commands.py
@@ -4,7 +4,6 @@ from maya import cmds
from openpype.client import get_asset_by_name, get_project
from openpype.pipeline import legacy_io
-from . import lib
class ToolWindows:
@@ -58,54 +57,6 @@ def edit_shader_definitions():
window.show()
-def reset_frame_range():
- """Set frame range to current asset"""
-
- fps = lib.convert_to_maya_fps(
- float(legacy_io.Session.get("AVALON_FPS", 25))
- )
- lib.set_scene_fps(fps)
-
- # Set frame start/end
- project_name = legacy_io.active_project()
- asset_name = legacy_io.Session["AVALON_ASSET"]
- asset = get_asset_by_name(project_name, asset_name)
-
- frame_start = asset["data"].get("frameStart")
- frame_end = asset["data"].get("frameEnd")
- # Backwards compatibility
- if frame_start is None or frame_end is None:
- frame_start = asset["data"].get("edit_in")
- frame_end = asset["data"].get("edit_out")
-
- if frame_start is None or frame_end is None:
- cmds.warning("No edit information found for %s" % asset_name)
- return
-
- handles = asset["data"].get("handles") or 0
- handle_start = asset["data"].get("handleStart")
- if handle_start is None:
- handle_start = handles
-
- handle_end = asset["data"].get("handleEnd")
- if handle_end is None:
- handle_end = handles
-
- frame_start -= int(handle_start)
- frame_end += int(handle_end)
-
- cmds.playbackOptions(minTime=frame_start)
- cmds.playbackOptions(maxTime=frame_end)
- cmds.playbackOptions(animationStartTime=frame_start)
- cmds.playbackOptions(animationEndTime=frame_end)
- cmds.playbackOptions(minTime=frame_start)
- cmds.playbackOptions(maxTime=frame_end)
- cmds.currentTime(frame_start)
-
- cmds.setAttr("defaultRenderGlobals.startFrame", frame_start)
- cmds.setAttr("defaultRenderGlobals.endFrame", frame_end)
-
-
def _resolution_from_document(doc):
if not doc or "data" not in doc:
print("Entered document is not valid. \"{}\"".format(str(doc)))
diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py
index b920428b20..509168278c 100644
--- a/openpype/hosts/maya/api/lib.py
+++ b/openpype/hosts/maya/api/lib.py
@@ -34,7 +34,6 @@ from openpype.pipeline import (
registered_host,
)
from openpype.pipeline.context_tools import get_current_project_asset
-from .commands import reset_frame_range
self = sys.modules[__name__]
@@ -1998,7 +1997,7 @@ def set_scene_fps(fps, update=True):
'48000': '48000fps'
}
- unit = fps_mapping.get(str(fps), None)
+ unit = fps_mapping.get(str(convert_to_maya_fps(fps)), None)
if unit is None:
raise ValueError("Unsupported FPS value: `%s`" % fps)
@@ -2065,6 +2064,54 @@ def set_scene_resolution(width, height, pixelAspect):
cmds.setAttr("%s.pixelAspect" % control_node, pixelAspect)
+def reset_frame_range():
+ """Set frame range to current asset"""
+
+ fps = convert_to_maya_fps(
+ float(legacy_io.Session.get("AVALON_FPS", 25))
+ )
+ set_scene_fps(fps)
+
+ # Set frame start/end
+ project_name = legacy_io.active_project()
+ asset_name = legacy_io.Session["AVALON_ASSET"]
+ asset = get_asset_by_name(project_name, asset_name)
+
+ frame_start = asset["data"].get("frameStart")
+ frame_end = asset["data"].get("frameEnd")
+ # Backwards compatibility
+ if frame_start is None or frame_end is None:
+ frame_start = asset["data"].get("edit_in")
+ frame_end = asset["data"].get("edit_out")
+
+ if frame_start is None or frame_end is None:
+ cmds.warning("No edit information found for %s" % asset_name)
+ return
+
+ handles = asset["data"].get("handles") or 0
+ handle_start = asset["data"].get("handleStart")
+ if handle_start is None:
+ handle_start = handles
+
+ handle_end = asset["data"].get("handleEnd")
+ if handle_end is None:
+ handle_end = handles
+
+ frame_start -= int(handle_start)
+ frame_end += int(handle_end)
+
+ cmds.playbackOptions(minTime=frame_start)
+ cmds.playbackOptions(maxTime=frame_end)
+ cmds.playbackOptions(animationStartTime=frame_start)
+ cmds.playbackOptions(animationEndTime=frame_end)
+ cmds.playbackOptions(minTime=frame_start)
+ cmds.playbackOptions(maxTime=frame_end)
+ cmds.currentTime(frame_start)
+
+ cmds.setAttr("defaultRenderGlobals.startFrame", frame_start)
+ cmds.setAttr("defaultRenderGlobals.endFrame", frame_end)
+
+
def reset_scene_resolution():
"""Apply the scene resolution from the project definition
@@ -3407,11 +3454,11 @@ def convert_to_maya_fps(fps):
# If input fps is a whole number we'll return.
if float(fps).is_integer():
# Validate fps is part of Maya's fps selection.
- if fps not in int_framerates:
+ if int(fps) not in int_framerates:
raise ValueError(
"Framerate \"{}\" is not supported in Maya".format(fps)
)
- return fps
+ return int(fps)
else:
# Differences to supported float frame rates.
differences = []
diff --git a/openpype/hosts/maya/api/lib_renderproducts.py b/openpype/hosts/maya/api/lib_renderproducts.py
index 0eecedd231..60090e9f6d 100644
--- a/openpype/hosts/maya/api/lib_renderproducts.py
+++ b/openpype/hosts/maya/api/lib_renderproducts.py
@@ -797,6 +797,11 @@ class RenderProductsVray(ARenderProducts):
if default_ext in {"exr (multichannel)", "exr (deep)"}:
default_ext = "exr"
+ # Define multipart.
+ multipart = False
+ if image_format_str == "exr (multichannel)":
+ multipart = True
+
products = []
# add beauty as default when not disabled
@@ -804,23 +809,28 @@ class RenderProductsVray(ARenderProducts):
if not dont_save_rgb:
for camera in cameras:
products.append(
- RenderProduct(productName="",
- ext=default_ext,
- camera=camera))
+ RenderProduct(
+ productName="",
+ ext=default_ext,
+ camera=camera,
+ multipart=multipart
+ )
+ )
# separate alpha file
separate_alpha = self._get_attr("vraySettings.separateAlpha")
if separate_alpha:
for camera in cameras:
products.append(
- RenderProduct(productName="Alpha",
- ext=default_ext,
- camera=camera)
+ RenderProduct(
+ productName="Alpha",
+ ext=default_ext,
+ camera=camera,
+ multipart=multipart
+ )
)
-
- if image_format_str == "exr (multichannel)":
+ if multipart:
# AOVs are merged in m-channel file, only main layer is rendered
- self.multipart = True
return products
# handle aovs from references
diff --git a/openpype/hosts/maya/api/lib_rendersettings.py b/openpype/hosts/maya/api/lib_rendersettings.py
index 6190a49401..2a730100de 100644
--- a/openpype/hosts/maya/api/lib_rendersettings.py
+++ b/openpype/hosts/maya/api/lib_rendersettings.py
@@ -14,7 +14,7 @@ from openpype.settings import (
from openpype.pipeline import legacy_io
from openpype.pipeline import CreatorError
from openpype.pipeline.context_tools import get_current_project_asset
-from openpype.hosts.maya.api.commands import reset_frame_range
+from openpype.hosts.maya.api.lib import reset_frame_range
class RenderSettings(object):
diff --git a/openpype/hosts/maya/api/menu.py b/openpype/hosts/maya/api/menu.py
index 791475173f..0f48a133a6 100644
--- a/openpype/hosts/maya/api/menu.py
+++ b/openpype/hosts/maya/api/menu.py
@@ -12,7 +12,6 @@ from openpype.pipeline.workfile import BuildWorkfile
from openpype.tools.utils import host_tools
from openpype.hosts.maya.api import lib, lib_rendersettings
from .lib import get_main_window, IS_HEADLESS
-from .commands import reset_frame_range
from .workfile_template_builder import (
create_placeholder,
@@ -113,7 +112,7 @@ def install():
cmds.menuItem(
"Reset Frame Range",
- command=lambda *args: reset_frame_range()
+ command=lambda *args: lib.reset_frame_range()
)
cmds.menuItem(
diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py
index 1f9f9db99a..1966ad7b66 100644
--- a/openpype/hosts/maya/plugins/publish/extract_playblast.py
+++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py
@@ -1,4 +1,5 @@
import os
+import json
import clique
import capture
@@ -44,10 +45,6 @@ class ExtractPlayblast(publish.Extractor):
# get cameras
camera = instance.data['review_camera']
- override_viewport_options = (
- self.capture_preset['Viewport Options']
- ['override_viewport_options']
- )
preset = lib.load_capture_preset(data=self.capture_preset)
# Grab capture presets from the project settings
capture_presets = self.capture_preset
@@ -119,6 +116,27 @@ class ExtractPlayblast(publish.Extractor):
pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"]))
cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), False)
+ # Need to explicitly enable some viewport changes so the viewport is
+ # refreshed ahead of playblasting.
+ panel = cmds.getPanel(withFocus=True)
+ keys = [
+ "useDefaultMaterial",
+ "wireframeOnShaded",
+ "xray",
+ "jointXray",
+ "backfaceCulling"
+ ]
+ viewport_defaults = {}
+ for key in keys:
+ viewport_defaults[key] = cmds.modelEditor(
+ panel, query=True, **{key: True}
+ )
+ if preset["viewport_options"][key]:
+ cmds.modelEditor(panel, edit=True, **{key: True})
+
+ override_viewport_options = (
+ capture_presets['Viewport Options']['override_viewport_options']
+ )
with lib.maintained_time():
filename = preset.get("filename", "%TEMP%")
@@ -127,18 +145,26 @@ class ExtractPlayblast(publish.Extractor):
# playblast and viewer
preset['viewer'] = False
- self.log.info('using viewport preset: {}'.format(preset))
-
# Update preset with current panel setting
# if override_viewport_options is turned off
- if not override_viewport_options:
- panel = cmds.getPanel(withFocus=True)
+ panel = cmds.getPanel(withFocus=True) or ""
+ if not override_viewport_options and "modelPanel" in panel:
panel_preset = capture.parse_active_view()
+ panel_preset.pop("camera")
preset.update(panel_preset)
cmds.setFocus(panel)
+ self.log.info(
+ "Using preset:\n{}".format(
+ json.dumps(preset, sort_keys=True, indent=4)
+ )
+ )
+
path = capture.capture(log=self.log, **preset)
+ # Restoring viewport options.
+ cmds.modelEditor(panel, edit=True, **viewport_defaults)
+
cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom)
self.log.debug("playblast path {}".format(path))
diff --git a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py
index 1edafeb926..1d94bd58c5 100644
--- a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py
+++ b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py
@@ -134,8 +134,8 @@ class ExtractThumbnail(publish.Extractor):
# Update preset with current panel setting
# if override_viewport_options is turned off
- if not override_viewport_options:
- panel = cmds.getPanel(withFocus=True)
+ panel = cmds.getPanel(withFocus=True) or ""
+ if not override_viewport_options and "modelPanel" in panel:
panel_preset = capture.parse_active_view()
preset.update(panel_preset)
cmds.setFocus(panel)
diff --git a/openpype/hosts/maya/plugins/publish/validate_maya_units.py b/openpype/hosts/maya/plugins/publish/validate_maya_units.py
index ad256b6a72..357dde692c 100644
--- a/openpype/hosts/maya/plugins/publish/validate_maya_units.py
+++ b/openpype/hosts/maya/plugins/publish/validate_maya_units.py
@@ -4,7 +4,6 @@ import pyblish.api
import openpype.hosts.maya.api.lib as mayalib
from openpype.pipeline.context_tools import get_current_project_asset
-from math import ceil
from openpype.pipeline.publish import (
RepairContextAction,
ValidateSceneOrder,
diff --git a/openpype/modules/deadline/plugins/publish/submit_aftereffects_deadline.py b/openpype/modules/deadline/plugins/publish/submit_aftereffects_deadline.py
index f26047bb9d..83dd5b49e2 100644
--- a/openpype/modules/deadline/plugins/publish/submit_aftereffects_deadline.py
+++ b/openpype/modules/deadline/plugins/publish/submit_aftereffects_deadline.py
@@ -12,6 +12,7 @@ from openpype.pipeline import legacy_io
from openpype_modules.deadline import abstract_submit_deadline
from openpype_modules.deadline.abstract_submit_deadline import DeadlineJobInfo
from openpype.tests.lib import is_in_tests
+from openpype.lib import is_running_from_build
@attr.s
@@ -87,9 +88,13 @@ class AfterEffectsSubmitDeadline(
"AVALON_APP_NAME",
"OPENPYPE_DEV",
"OPENPYPE_LOG_NO_COLORS",
- "OPENPYPE_VERSION",
"IS_TEST"
]
+
+ # Add OpenPype version if we are running from build.
+ if is_running_from_build():
+ keys.append("OPENPYPE_VERSION")
+
# Add mongo url if it's enabled
if self._instance.context.data.get("deadlinePassMongoUrl"):
keys.append("OPENPYPE_MONGO")
diff --git a/openpype/modules/deadline/plugins/publish/submit_harmony_deadline.py b/openpype/modules/deadline/plugins/publish/submit_harmony_deadline.py
index 425883393f..84fca11d9d 100644
--- a/openpype/modules/deadline/plugins/publish/submit_harmony_deadline.py
+++ b/openpype/modules/deadline/plugins/publish/submit_harmony_deadline.py
@@ -14,6 +14,7 @@ from openpype.pipeline import legacy_io
from openpype_modules.deadline import abstract_submit_deadline
from openpype_modules.deadline.abstract_submit_deadline import DeadlineJobInfo
from openpype.tests.lib import is_in_tests
+from openpype.lib import is_running_from_build
class _ZipFile(ZipFile):
@@ -279,10 +280,14 @@ class HarmonySubmitDeadline(
"AVALON_TASK",
"AVALON_APP_NAME",
"OPENPYPE_DEV",
- "OPENPYPE_LOG_NO_COLORS",
- "OPENPYPE_VERSION",
+ "OPENPYPE_LOG_NO_COLORS"
"IS_TEST"
]
+
+ # Add OpenPype version if we are running from build.
+ if is_running_from_build():
+ keys.append("OPENPYPE_VERSION")
+
# Add mongo url if it's enabled
if self._instance.context.data.get("deadlinePassMongoUrl"):
keys.append("OPENPYPE_MONGO")
diff --git a/openpype/modules/deadline/plugins/publish/submit_houdini_remote_publish.py b/openpype/modules/deadline/plugins/publish/submit_houdini_remote_publish.py
index 6a62f83cae..68aa653804 100644
--- a/openpype/modules/deadline/plugins/publish/submit_houdini_remote_publish.py
+++ b/openpype/modules/deadline/plugins/publish/submit_houdini_remote_publish.py
@@ -9,6 +9,7 @@ import pyblish.api
from openpype.pipeline import legacy_io
from openpype.tests.lib import is_in_tests
+from openpype.lib import is_running_from_build
class HoudiniSubmitPublishDeadline(pyblish.api.ContextPlugin):
@@ -133,9 +134,13 @@ class HoudiniSubmitPublishDeadline(pyblish.api.ContextPlugin):
# Submit along the current Avalon tool setup that we launched
# this application with so the Render Slave can build its own
# similar environment using it, e.g. "houdini17.5;pluginx2.3"
- "AVALON_TOOLS",
- "OPENPYPE_VERSION"
+ "AVALON_TOOLS"
]
+
+ # Add OpenPype version if we are running from build.
+ if is_running_from_build():
+ keys.append("OPENPYPE_VERSION")
+
# Add mongo url if it's enabled
if context.data.get("deadlinePassMongoUrl"):
keys.append("OPENPYPE_MONGO")
diff --git a/openpype/modules/deadline/plugins/publish/submit_houdini_render_deadline.py b/openpype/modules/deadline/plugins/publish/submit_houdini_render_deadline.py
index 2b17b644b8..73ab689c9a 100644
--- a/openpype/modules/deadline/plugins/publish/submit_houdini_render_deadline.py
+++ b/openpype/modules/deadline/plugins/publish/submit_houdini_render_deadline.py
@@ -10,6 +10,7 @@ import pyblish.api
from openpype.pipeline import legacy_io
from openpype.tests.lib import is_in_tests
+from openpype.lib import is_running_from_build
class HoudiniSubmitRenderDeadline(pyblish.api.InstancePlugin):
@@ -105,9 +106,13 @@ class HoudiniSubmitRenderDeadline(pyblish.api.InstancePlugin):
# Submit along the current Avalon tool setup that we launched
# this application with so the Render Slave can build its own
# similar environment using it, e.g. "maya2018;vray4.x;yeti3.1.9"
- "AVALON_TOOLS",
- "OPENPYPE_VERSION"
+ "AVALON_TOOLS"
]
+
+ # Add OpenPype version if we are running from build.
+ if is_running_from_build():
+ keys.append("OPENPYPE_VERSION")
+
# Add mongo url if it's enabled
if context.data.get("deadlinePassMongoUrl"):
keys.append("OPENPYPE_MONGO")
diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py
index ed37ff1897..22b5c02296 100644
--- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py
+++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py
@@ -38,6 +38,7 @@ from openpype.hosts.maya.api.lib import get_attr_in_layer
from openpype_modules.deadline import abstract_submit_deadline
from openpype_modules.deadline.abstract_submit_deadline import DeadlineJobInfo
from openpype.tests.lib import is_in_tests
+from openpype.lib import is_running_from_build
def _validate_deadline_bool_value(instance, attribute, value):
@@ -165,10 +166,14 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline):
"AVALON_ASSET",
"AVALON_TASK",
"AVALON_APP_NAME",
- "OPENPYPE_DEV",
- "OPENPYPE_VERSION",
+ "OPENPYPE_DEV"
"IS_TEST"
]
+
+ # Add OpenPype version if we are running from build.
+ if is_running_from_build():
+ keys.append("OPENPYPE_VERSION")
+
# Add mongo url if it's enabled
if self._instance.context.data.get("deadlinePassMongoUrl"):
keys.append("OPENPYPE_MONGO")
diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_remote_publish_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_remote_publish_deadline.py
index bab6591c7f..25f859554f 100644
--- a/openpype/modules/deadline/plugins/publish/submit_maya_remote_publish_deadline.py
+++ b/openpype/modules/deadline/plugins/publish/submit_maya_remote_publish_deadline.py
@@ -7,6 +7,7 @@ from maya import cmds
from openpype.pipeline import legacy_io, PublishXmlValidationError
from openpype.settings import get_project_settings
from openpype.tests.lib import is_in_tests
+from openpype.lib import is_running_from_build
import pyblish.api
@@ -104,9 +105,13 @@ class MayaSubmitRemotePublishDeadline(pyblish.api.InstancePlugin):
keys = [
"FTRACK_API_USER",
"FTRACK_API_KEY",
- "FTRACK_SERVER",
- "OPENPYPE_VERSION"
+ "FTRACK_SERVER"
]
+
+ # Add OpenPype version if we are running from build.
+ if is_running_from_build():
+ keys.append("OPENPYPE_VERSION")
+
environment = dict({key: os.environ[key] for key in keys
if key in os.environ}, **legacy_io.Session)
diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py
index d1948d8d50..cca2a4d896 100644
--- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py
+++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py
@@ -10,6 +10,7 @@ import pyblish.api
import nuke
from openpype.pipeline import legacy_io
from openpype.tests.lib import is_in_tests
+from openpype.lib import is_running_from_build
class NukeSubmitDeadline(pyblish.api.InstancePlugin):
@@ -265,9 +266,13 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin):
"PYBLISHPLUGINPATH",
"NUKE_PATH",
"TOOL_ENV",
- "FOUNDRY_LICENSE",
- "OPENPYPE_VERSION"
+ "FOUNDRY_LICENSE"
]
+
+ # Add OpenPype version if we are running from build.
+ if is_running_from_build():
+ keys.append("OPENPYPE_VERSION")
+
# Add mongo url if it's enabled
if instance.context.data.get("deadlinePassMongoUrl"):
keys.append("OPENPYPE_MONGO")
diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py
index 7e39a644a2..e132d7323b 100644
--- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py
+++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py
@@ -20,6 +20,7 @@ from openpype.pipeline import (
)
from openpype.tests.lib import is_in_tests
from openpype.pipeline.farm.patterning import match_aov_pattern
+from openpype.lib import is_running_from_build
def get_resources(project_name, version, extension=None):
@@ -136,10 +137,13 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
"FTRACK_API_KEY",
"FTRACK_SERVER",
"AVALON_APP_NAME",
- "OPENPYPE_USERNAME",
- "OPENPYPE_VERSION"
+ "OPENPYPE_USERNAME"
]
+ # Add OpenPype version if we are running from build.
+ if is_running_from_build():
+ environ_keys.append("OPENPYPE_VERSION")
+
# custom deadline attributes
deadline_department = ""
deadline_pool = ""
@@ -514,6 +518,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
# toggle preview on if multipart is on
if instance_data.get("multipartExr"):
+ self.log.debug("Adding preview tag because its multipartExr")
preview = True
self.log.debug("preview:{}".format(preview))
new_instance = deepcopy(instance_data)
@@ -593,6 +598,9 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
if instance["useSequenceForReview"]:
# toggle preview on if multipart is on
if instance.get("multipartExr", False):
+ self.log.debug(
+ "Adding preview tag because its multipartExr"
+ )
preview = True
else:
render_file_name = list(collection)[0]
@@ -700,8 +708,14 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
if preview:
if "ftrack" not in families:
if os.environ.get("FTRACK_SERVER"):
+ self.log.debug(
+ "Adding \"ftrack\" to families because of preview tag."
+ )
families.append("ftrack")
if "review" not in families:
+ self.log.debug(
+ "Adding \"review\" to families because of preview tag."
+ )
families.append("review")
instance["families"] = families
diff --git a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py
index b0560ce1e8..e4fc64269a 100644
--- a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py
+++ b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py
@@ -201,19 +201,21 @@ def get_openpype_versions(dir_list):
print(">>> Getting OpenPype executable ...")
openpype_versions = []
- install_dir = DirectoryUtils.SearchDirectoryList(dir_list)
- if install_dir:
- print("--- Looking for OpenPype at: {}".format(install_dir))
- sub_dirs = [
- f.path for f in os.scandir(install_dir)
- if f.is_dir()
- ]
- for subdir in sub_dirs:
- version = get_openpype_version_from_path(subdir)
- if not version:
- continue
- print(" - found: {} - {}".format(version, subdir))
- openpype_versions.append((version, subdir))
+ # special case of multiple install dirs
+ for dir_list in dir_list.split(","):
+ install_dir = DirectoryUtils.SearchDirectoryList(dir_list)
+ if install_dir:
+ print("--- Looking for OpenPype at: {}".format(install_dir))
+ sub_dirs = [
+ f.path for f in os.scandir(install_dir)
+ if f.is_dir()
+ ]
+ for subdir in sub_dirs:
+ version = get_openpype_version_from_path(subdir)
+ if not version:
+ continue
+ print(" - found: {} - {}".format(version, subdir))
+ openpype_versions.append((version, subdir))
return openpype_versions
diff --git a/openpype/modules/deadline/repository/custom/plugins/OpenPype/OpenPype.py b/openpype/modules/deadline/repository/custom/plugins/OpenPype/OpenPype.py
index ab4a3d5e9b..6e1b973fb9 100644
--- a/openpype/modules/deadline/repository/custom/plugins/OpenPype/OpenPype.py
+++ b/openpype/modules/deadline/repository/custom/plugins/OpenPype/OpenPype.py
@@ -107,20 +107,23 @@ class OpenPypeDeadlinePlugin(DeadlinePlugin):
"Scanning for compatible requested "
f"version {requested_version}"))
dir_list = self.GetConfigEntry("OpenPypeInstallationDirs")
+
# clean '\ ' for MacOS pasting
if platform.system().lower() == "darwin":
dir_list = dir_list.replace("\\ ", " ")
- install_dir = DirectoryUtils.SearchDirectoryList(dir_list)
- if install_dir:
- sub_dirs = [
- f.path for f in os.scandir(install_dir)
- if f.is_dir()
- ]
- for subdir in sub_dirs:
- version = self.get_openpype_version_from_path(subdir)
- if not version:
- continue
- openpype_versions.append((version, subdir))
+
+ for dir_list in dir_list.split(","):
+ install_dir = DirectoryUtils.SearchDirectoryList(dir_list)
+ if install_dir:
+ sub_dirs = [
+ f.path for f in os.scandir(install_dir)
+ if f.is_dir()
+ ]
+ for subdir in sub_dirs:
+ version = self.get_openpype_version_from_path(subdir)
+ if not version:
+ continue
+ openpype_versions.append((version, subdir))
exe_list = self.GetConfigEntry("OpenPypeExecutable")
# clean '\ ' for MacOS pasting
diff --git a/openpype/modules/ftrack/plugins/publish/integrate_ftrack_instances.py b/openpype/modules/ftrack/plugins/publish/integrate_ftrack_instances.py
index d6cb3daf0d..75f43cb22f 100644
--- a/openpype/modules/ftrack/plugins/publish/integrate_ftrack_instances.py
+++ b/openpype/modules/ftrack/plugins/publish/integrate_ftrack_instances.py
@@ -56,6 +56,7 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
"reference": "reference"
}
keep_first_subset_name_for_review = True
+ upload_reviewable_with_origin_name = False
asset_versions_status_profiles = []
additional_metadata_keys = []
@@ -294,6 +295,13 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
)
# Add item to component list
component_list.append(review_item)
+ if self.upload_reviewable_with_origin_name:
+ origin_name_component = copy.deepcopy(review_item)
+ filename = os.path.basename(repre_path)
+ origin_name_component["component_data"]["name"] = (
+ os.path.splitext(filename)[0]
+ )
+ component_list.append(origin_name_component)
# Duplicate thumbnail component for all not first reviews
if first_thumbnail_component is not None:
diff --git a/openpype/settings/defaults/project_settings/ftrack.json b/openpype/settings/defaults/project_settings/ftrack.json
index cdf861df4a..ec48ba52ea 100644
--- a/openpype/settings/defaults/project_settings/ftrack.json
+++ b/openpype/settings/defaults/project_settings/ftrack.json
@@ -324,7 +324,8 @@
"animation",
"look",
"rig",
- "camera"
+ "camera",
+ "renderlayer"
],
"task_types": [],
"tasks": [],
@@ -488,7 +489,8 @@
},
"keep_first_subset_name_for_review": true,
"asset_versions_status_profiles": [],
- "additional_metadata_keys": []
+ "additional_metadata_keys": [],
+ "upload_reviewable_with_origin_name": false
},
"IntegrateFtrackFarmStatus": {
"farm_status_profiles": []
diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json
index 64bba7b28c..03c2d325bb 100644
--- a/openpype/settings/defaults/project_settings/maya.json
+++ b/openpype/settings/defaults/project_settings/maya.json
@@ -815,6 +815,11 @@
"twoSidedLighting": true,
"lineAAEnable": true,
"multiSample": 8,
+ "useDefaultMaterial": false,
+ "wireframeOnShaded": false,
+ "xray": false,
+ "jointXray": false,
+ "backfaceCulling": false,
"ssaoEnable": false,
"ssaoAmount": 1,
"ssaoRadius": 16,
diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json
index da414cc961..7050721742 100644
--- a/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json
+++ b/openpype/settings/entities/schemas/projects_schema/schema_project_ftrack.json
@@ -1037,6 +1037,21 @@
{"fps": "FPS"},
{"code": "Codec"}
]
+ },
+ {
+ "type": "separator"
+ },
+ {
+ "type": "boolean",
+ "key": "upload_reviewable_with_origin_name",
+ "label": "Upload reviewable with origin name"
+ },
+ {
+ "type": "label",
+ "label": "Note: Reviewable will be uploaded twice into ftrack when enabled. One with original name and second with required 'ftrackreview-mp4'. That may cause dramatic increase of ftrack storage usage."
+ },
+ {
+ "type": "separator"
}
]
},
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json
index 62c33f55fc..1f0e4eeffb 100644
--- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json
@@ -184,6 +184,10 @@
{
"type": "splitter"
},
+ {
+ "type": "label",
+ "label": "Display"
+ },
{
"type":"boolean",
"key": "renderDepthOfField",
@@ -221,6 +225,31 @@
{
"type": "splitter"
},
+ {
+ "type": "boolean",
+ "key": "useDefaultMaterial",
+ "label": "Use Default Material"
+ },
+ {
+ "type": "boolean",
+ "key": "wireframeOnShaded",
+ "label": "Wireframe On Shaded"
+ },
+ {
+ "type": "boolean",
+ "key": "xray",
+ "label": "X-Ray"
+ },
+ {
+ "type": "boolean",
+ "key": "jointXray",
+ "label": "X-Ray Joints"
+ },
+ {
+ "type": "boolean",
+ "key": "backfaceCulling",
+ "label": "Backface Culling"
+ },
{
"type": "boolean",
"key": "ssaoEnable",