mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
[Automated] Merged develop into main
This commit is contained in:
commit
8e2ff09c07
34 changed files with 468 additions and 179 deletions
|
|
@ -1221,7 +1221,7 @@ def set_track_color(track_item, color):
|
|||
|
||||
def check_inventory_versions(track_items=None):
|
||||
"""
|
||||
Actual version color idetifier of Loaded containers
|
||||
Actual version color identifier of Loaded containers
|
||||
|
||||
Check all track items and filter only
|
||||
Loader nodes for its version. It will get all versions from database
|
||||
|
|
@ -1249,10 +1249,10 @@ def check_inventory_versions(track_items=None):
|
|||
project_name = legacy_io.active_project()
|
||||
filter_result = filter_containers(containers, project_name)
|
||||
for container in filter_result.latest:
|
||||
set_track_color(container["_item"], clip_color)
|
||||
set_track_color(container["_item"], clip_color_last)
|
||||
|
||||
for container in filter_result.outdated:
|
||||
set_track_color(container["_item"], clip_color_last)
|
||||
set_track_color(container["_item"], clip_color)
|
||||
|
||||
|
||||
def selection_changed_timeline(event):
|
||||
|
|
|
|||
|
|
@ -6,6 +6,11 @@ from pymxs import runtime as rt
|
|||
from typing import Union
|
||||
import contextlib
|
||||
|
||||
from openpype.pipeline.context_tools import (
|
||||
get_current_project_asset,
|
||||
get_current_project
|
||||
)
|
||||
|
||||
|
||||
JSON_PREFIX = "JSON::"
|
||||
|
||||
|
|
@ -157,6 +162,112 @@ def get_multipass_setting(project_setting=None):
|
|||
["multipass"])
|
||||
|
||||
|
||||
def set_scene_resolution(width: int, height: int):
|
||||
"""Set the render resolution
|
||||
|
||||
Args:
|
||||
width(int): value of the width
|
||||
height(int): value of the height
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
"""
|
||||
rt.renderWidth = width
|
||||
rt.renderHeight = height
|
||||
|
||||
|
||||
def reset_scene_resolution():
|
||||
"""Apply the scene resolution from the project definition
|
||||
|
||||
scene resolution can be overwritten by an asset if the asset.data contains
|
||||
any information regarding scene resolution .
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
data = ["data.resolutionWidth", "data.resolutionHeight"]
|
||||
project_resolution = get_current_project(fields=data)
|
||||
project_resolution_data = project_resolution["data"]
|
||||
asset_resolution = get_current_project_asset(fields=data)
|
||||
asset_resolution_data = asset_resolution["data"]
|
||||
# Set project resolution
|
||||
project_width = int(project_resolution_data.get("resolutionWidth", 1920))
|
||||
project_height = int(project_resolution_data.get("resolutionHeight", 1080))
|
||||
width = int(asset_resolution_data.get("resolutionWidth", project_width))
|
||||
height = int(asset_resolution_data.get("resolutionHeight", project_height))
|
||||
|
||||
set_scene_resolution(width, height)
|
||||
|
||||
|
||||
def get_frame_range() -> dict:
|
||||
"""Get the current assets frame range and handles.
|
||||
|
||||
Returns:
|
||||
dict: with frame start, frame end, handle start, handle end.
|
||||
"""
|
||||
# Set frame start/end
|
||||
asset = get_current_project_asset()
|
||||
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:
|
||||
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
|
||||
return {
|
||||
"frameStart": frame_start,
|
||||
"frameEnd": frame_end,
|
||||
"handleStart": handle_start,
|
||||
"handleEnd": handle_end
|
||||
}
|
||||
|
||||
|
||||
def reset_frame_range(fps: bool = True):
|
||||
"""Set frame range to current asset.
|
||||
This is part of 3dsmax documentation:
|
||||
|
||||
animationRange: A System Global variable which lets you get and
|
||||
set an Interval value that defines the start and end frames
|
||||
of the Active Time Segment.
|
||||
frameRate: A System Global variable which lets you get
|
||||
and set an Integer value that defines the current
|
||||
scene frame rate in frames-per-second.
|
||||
"""
|
||||
if fps:
|
||||
data_fps = get_current_project(fields=["data.fps"])
|
||||
fps_number = float(data_fps["data"]["fps"])
|
||||
rt.frameRate = fps_number
|
||||
frame_range = get_frame_range()
|
||||
frame_start = frame_range["frameStart"] - int(frame_range["handleStart"])
|
||||
frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"])
|
||||
frange_cmd = f"animationRange = interval {frame_start} {frame_end}"
|
||||
rt.execute(frange_cmd)
|
||||
|
||||
|
||||
def set_context_setting():
|
||||
"""Apply the project settings from the project definition
|
||||
|
||||
Settings can be overwritten by an asset if the asset.data contains
|
||||
any information regarding those settings.
|
||||
|
||||
Examples of settings:
|
||||
frame range
|
||||
resolution
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
reset_scene_resolution()
|
||||
|
||||
|
||||
def get_max_version():
|
||||
"""
|
||||
Args:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from qtpy import QtWidgets, QtCore
|
|||
from pymxs import runtime as rt
|
||||
|
||||
from openpype.tools.utils import host_tools
|
||||
from openpype.hosts.max.api import lib
|
||||
|
||||
|
||||
class OpenPypeMenu(object):
|
||||
|
|
@ -107,6 +108,17 @@ class OpenPypeMenu(object):
|
|||
workfiles_action = QtWidgets.QAction("Work Files...", openpype_menu)
|
||||
workfiles_action.triggered.connect(self.workfiles_callback)
|
||||
openpype_menu.addAction(workfiles_action)
|
||||
|
||||
openpype_menu.addSeparator()
|
||||
|
||||
res_action = QtWidgets.QAction("Set Resolution", openpype_menu)
|
||||
res_action.triggered.connect(self.resolution_callback)
|
||||
openpype_menu.addAction(res_action)
|
||||
|
||||
frame_action = QtWidgets.QAction("Set Frame Range", openpype_menu)
|
||||
frame_action.triggered.connect(self.frame_range_callback)
|
||||
openpype_menu.addAction(frame_action)
|
||||
|
||||
return openpype_menu
|
||||
|
||||
def load_callback(self):
|
||||
|
|
@ -128,3 +140,11 @@ class OpenPypeMenu(object):
|
|||
def workfiles_callback(self):
|
||||
"""Callback to show Workfiles tool."""
|
||||
host_tools.show_workfiles(parent=self.main_widget)
|
||||
|
||||
def resolution_callback(self):
|
||||
"""Callback to reset scene resolution"""
|
||||
return lib.reset_scene_resolution()
|
||||
|
||||
def frame_range_callback(self):
|
||||
"""Callback to reset frame range"""
|
||||
return lib.reset_frame_range()
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@ class MaxHost(HostBase, IWorkfileHost, ILoadHost, INewPublisher):
|
|||
|
||||
self._has_been_setup = True
|
||||
|
||||
def context_setting():
|
||||
return lib.set_context_setting()
|
||||
rt.callbacks.addScript(rt.Name('systemPostNew'),
|
||||
context_setting)
|
||||
|
||||
def has_unsaved_changes(self):
|
||||
# TODO: how to get it from 3dsmax?
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class CollectRender(pyblish.api.InstancePlugin):
|
|||
"plugin": "3dsmax",
|
||||
"frameStart": context.data['frameStart'],
|
||||
"frameEnd": context.data['frameEnd'],
|
||||
"version": version_int
|
||||
"version": version_int,
|
||||
}
|
||||
self.log.info("data: {0}".format(data))
|
||||
instance.data.update(data)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class CreateReview(plugin.Creator):
|
|||
"alpha cut"
|
||||
]
|
||||
useMayaTimeline = True
|
||||
panZoom = False
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CreateReview, self).__init__(*args, **kwargs)
|
||||
|
|
@ -45,5 +46,6 @@ class CreateReview(plugin.Creator):
|
|||
data["keepImages"] = self.keepImages
|
||||
data["imagePlane"] = self.imagePlane
|
||||
data["transparency"] = self.transparency
|
||||
data["panZoom"] = self.panZoom
|
||||
|
||||
self.data = data
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ class CollectReview(pyblish.api.InstancePlugin):
|
|||
data['review_width'] = instance.data['review_width']
|
||||
data['review_height'] = instance.data['review_height']
|
||||
data["isolate"] = instance.data["isolate"]
|
||||
data["panZoom"] = instance.data.get("panZoom", False)
|
||||
data["panel"] = instance.data["panel"]
|
||||
cmds.setAttr(str(instance) + '.active', 1)
|
||||
self.log.debug('data {}'.format(instance.context[i].data))
|
||||
instance.context[i].data.update(data)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
import json
|
||||
import contextlib
|
||||
|
||||
import clique
|
||||
import capture
|
||||
|
|
@ -11,6 +12,16 @@ from maya import cmds
|
|||
import pymel.core as pm
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def panel_camera(panel, camera):
|
||||
original_camera = cmds.modelPanel(panel, query=True, camera=True)
|
||||
try:
|
||||
cmds.modelPanel(panel, edit=True, camera=camera)
|
||||
yield
|
||||
finally:
|
||||
cmds.modelPanel(panel, edit=True, camera=original_camera)
|
||||
|
||||
|
||||
class ExtractPlayblast(publish.Extractor):
|
||||
"""Extract viewport playblast.
|
||||
|
||||
|
|
@ -25,6 +36,16 @@ class ExtractPlayblast(publish.Extractor):
|
|||
optional = True
|
||||
capture_preset = {}
|
||||
|
||||
def _capture(self, preset):
|
||||
self.log.info(
|
||||
"Using preset:\n{}".format(
|
||||
json.dumps(preset, sort_keys=True, indent=4)
|
||||
)
|
||||
)
|
||||
|
||||
path = capture.capture(log=self.log, **preset)
|
||||
self.log.debug("playblast path {}".format(path))
|
||||
|
||||
def process(self, instance):
|
||||
self.log.info("Extracting capture..")
|
||||
|
||||
|
|
@ -43,7 +64,7 @@ class ExtractPlayblast(publish.Extractor):
|
|||
self.log.info("start: {}, end: {}".format(start, end))
|
||||
|
||||
# get cameras
|
||||
camera = instance.data['review_camera']
|
||||
camera = instance.data["review_camera"]
|
||||
|
||||
preset = lib.load_capture_preset(data=self.capture_preset)
|
||||
# Grab capture presets from the project settings
|
||||
|
|
@ -57,23 +78,23 @@ class ExtractPlayblast(publish.Extractor):
|
|||
asset_height = asset_data.get("resolutionHeight")
|
||||
review_instance_width = instance.data.get("review_width")
|
||||
review_instance_height = instance.data.get("review_height")
|
||||
preset['camera'] = camera
|
||||
preset["camera"] = camera
|
||||
|
||||
# Tests if project resolution is set,
|
||||
# if it is a value other than zero, that value is
|
||||
# used, if not then the asset resolution is
|
||||
# used
|
||||
if review_instance_width and review_instance_height:
|
||||
preset['width'] = review_instance_width
|
||||
preset['height'] = review_instance_height
|
||||
preset["width"] = review_instance_width
|
||||
preset["height"] = review_instance_height
|
||||
elif width_preset and height_preset:
|
||||
preset['width'] = width_preset
|
||||
preset['height'] = height_preset
|
||||
preset["width"] = width_preset
|
||||
preset["height"] = height_preset
|
||||
elif asset_width and asset_height:
|
||||
preset['width'] = asset_width
|
||||
preset['height'] = asset_height
|
||||
preset['start_frame'] = start
|
||||
preset['end_frame'] = end
|
||||
preset["width"] = asset_width
|
||||
preset["height"] = asset_height
|
||||
preset["start_frame"] = start
|
||||
preset["end_frame"] = end
|
||||
|
||||
# Enforce persisting camera depth of field
|
||||
camera_options = preset.setdefault("camera_options", {})
|
||||
|
|
@ -86,8 +107,8 @@ class ExtractPlayblast(publish.Extractor):
|
|||
|
||||
self.log.info("Outputting images to %s" % path)
|
||||
|
||||
preset['filename'] = path
|
||||
preset['overwrite'] = True
|
||||
preset["filename"] = path
|
||||
preset["overwrite"] = True
|
||||
|
||||
pm.refresh(f=True)
|
||||
|
||||
|
|
@ -114,7 +135,8 @@ class ExtractPlayblast(publish.Extractor):
|
|||
|
||||
# Disable Pan/Zoom.
|
||||
pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"]))
|
||||
cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), False)
|
||||
preset.pop("pan_zoom", None)
|
||||
preset["camera_options"]["panZoomEnabled"] = instance.data["panZoom"]
|
||||
|
||||
# Need to explicitly enable some viewport changes so the viewport is
|
||||
# refreshed ahead of playblasting.
|
||||
|
|
@ -136,30 +158,39 @@ class ExtractPlayblast(publish.Extractor):
|
|||
)
|
||||
|
||||
override_viewport_options = (
|
||||
capture_presets['Viewport Options']['override_viewport_options']
|
||||
capture_presets["Viewport Options"]["override_viewport_options"]
|
||||
)
|
||||
with lib.maintained_time():
|
||||
filename = preset.get("filename", "%TEMP%")
|
||||
|
||||
# Force viewer to False in call to capture because we have our own
|
||||
# viewer opening call to allow a signal to trigger between
|
||||
# playblast and viewer
|
||||
preset['viewer'] = False
|
||||
# Force viewer to False in call to capture because we have our own
|
||||
# viewer opening call to allow a signal to trigger between
|
||||
# playblast and viewer
|
||||
preset["viewer"] = False
|
||||
|
||||
# Update preset with current panel setting
|
||||
# if override_viewport_options is turned off
|
||||
if not override_viewport_options:
|
||||
panel_preset = capture.parse_view(instance.data["panel"])
|
||||
panel_preset.pop("camera")
|
||||
preset.update(panel_preset)
|
||||
# Update preset with current panel setting
|
||||
# if override_viewport_options is turned off
|
||||
if not override_viewport_options:
|
||||
panel_preset = capture.parse_view(instance.data["panel"])
|
||||
panel_preset.pop("camera")
|
||||
preset.update(panel_preset)
|
||||
|
||||
self.log.info(
|
||||
"Using preset:\n{}".format(
|
||||
json.dumps(preset, sort_keys=True, indent=4)
|
||||
# Need to ensure Python 2 compatibility.
|
||||
# TODO: Remove once dropping Python 2.
|
||||
if getattr(contextlib, "nested", None):
|
||||
# Python 3 compatibility.
|
||||
with contextlib.nested(
|
||||
lib.maintained_time(),
|
||||
panel_camera(instance.data["panel"], preset["camera"])
|
||||
):
|
||||
self._capture(preset)
|
||||
else:
|
||||
# Python 2 compatibility.
|
||||
with contextlib.ExitStack() as stack:
|
||||
stack.enter_context(lib.maintained_time())
|
||||
stack.enter_context(
|
||||
panel_camera(instance.data["panel"], preset["camera"])
|
||||
)
|
||||
)
|
||||
|
||||
path = capture.capture(log=self.log, **preset)
|
||||
self._capture(preset)
|
||||
|
||||
# Restoring viewport options.
|
||||
if viewport_defaults:
|
||||
|
|
@ -169,18 +200,17 @@ class ExtractPlayblast(publish.Extractor):
|
|||
|
||||
cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom)
|
||||
|
||||
self.log.debug("playblast path {}".format(path))
|
||||
|
||||
collected_files = os.listdir(stagingdir)
|
||||
patterns = [clique.PATTERNS["frames"]]
|
||||
collections, remainder = clique.assemble(collected_files,
|
||||
minimum_items=1,
|
||||
patterns=patterns)
|
||||
|
||||
filename = preset.get("filename", "%TEMP%")
|
||||
self.log.debug("filename {}".format(filename))
|
||||
frame_collection = None
|
||||
for collection in collections:
|
||||
filebase = collection.format('{head}').rstrip(".")
|
||||
filebase = collection.format("{head}").rstrip(".")
|
||||
self.log.debug("collection head {}".format(filebase))
|
||||
if filebase in filename:
|
||||
frame_collection = collection
|
||||
|
|
@ -204,15 +234,15 @@ class ExtractPlayblast(publish.Extractor):
|
|||
collected_files = collected_files[0]
|
||||
|
||||
representation = {
|
||||
'name': 'png',
|
||||
'ext': 'png',
|
||||
'files': collected_files,
|
||||
"name": self.capture_preset["Codec"]["compression"],
|
||||
"ext": self.capture_preset["Codec"]["compression"],
|
||||
"files": collected_files,
|
||||
"stagingDir": stagingdir,
|
||||
"frameStart": start,
|
||||
"frameEnd": end,
|
||||
'fps': fps,
|
||||
'preview': True,
|
||||
'tags': tags,
|
||||
'camera_name': camera_node_name
|
||||
"fps": fps,
|
||||
"preview": True,
|
||||
"tags": tags,
|
||||
"camera_name": camera_node_name
|
||||
}
|
||||
instance.data["representations"].append(representation)
|
||||
|
|
|
|||
|
|
@ -26,28 +26,28 @@ class ExtractThumbnail(publish.Extractor):
|
|||
def process(self, instance):
|
||||
self.log.info("Extracting capture..")
|
||||
|
||||
camera = instance.data['review_camera']
|
||||
camera = instance.data["review_camera"]
|
||||
|
||||
capture_preset = (
|
||||
instance.context.data["project_settings"]['maya']['publish']['ExtractPlayblast']['capture_preset']
|
||||
)
|
||||
maya_setting = instance.context.data["project_settings"]["maya"]
|
||||
plugin_setting = maya_setting["publish"]["ExtractPlayblast"]
|
||||
capture_preset = plugin_setting["capture_preset"]
|
||||
override_viewport_options = (
|
||||
capture_preset['Viewport Options']['override_viewport_options']
|
||||
capture_preset["Viewport Options"]["override_viewport_options"]
|
||||
)
|
||||
|
||||
try:
|
||||
preset = lib.load_capture_preset(data=capture_preset)
|
||||
except KeyError as ke:
|
||||
self.log.error('Error loading capture presets: {}'.format(str(ke)))
|
||||
self.log.error("Error loading capture presets: {}".format(str(ke)))
|
||||
preset = {}
|
||||
self.log.info('Using viewport preset: {}'.format(preset))
|
||||
self.log.info("Using viewport preset: {}".format(preset))
|
||||
|
||||
# preset["off_screen"] = False
|
||||
|
||||
preset['camera'] = camera
|
||||
preset['start_frame'] = instance.data["frameStart"]
|
||||
preset['end_frame'] = instance.data["frameStart"]
|
||||
preset['camera_options'] = {
|
||||
preset["camera"] = camera
|
||||
preset["start_frame"] = instance.data["frameStart"]
|
||||
preset["end_frame"] = instance.data["frameStart"]
|
||||
preset["camera_options"] = {
|
||||
"displayGateMask": False,
|
||||
"displayResolution": False,
|
||||
"displayFilmGate": False,
|
||||
|
|
@ -74,14 +74,14 @@ class ExtractThumbnail(publish.Extractor):
|
|||
# used, if not then the asset resolution is
|
||||
# used
|
||||
if review_instance_width and review_instance_height:
|
||||
preset['width'] = review_instance_width
|
||||
preset['height'] = review_instance_height
|
||||
preset["width"] = review_instance_width
|
||||
preset["height"] = review_instance_height
|
||||
elif width_preset and height_preset:
|
||||
preset['width'] = width_preset
|
||||
preset['height'] = height_preset
|
||||
preset["width"] = width_preset
|
||||
preset["height"] = height_preset
|
||||
elif asset_width and asset_height:
|
||||
preset['width'] = asset_width
|
||||
preset['height'] = asset_height
|
||||
preset["width"] = asset_width
|
||||
preset["height"] = asset_height
|
||||
|
||||
# Create temp directory for thumbnail
|
||||
# - this is to avoid "override" of source file
|
||||
|
|
@ -96,8 +96,8 @@ class ExtractThumbnail(publish.Extractor):
|
|||
|
||||
self.log.info("Outputting images to %s" % path)
|
||||
|
||||
preset['filename'] = path
|
||||
preset['overwrite'] = True
|
||||
preset["filename"] = path
|
||||
preset["overwrite"] = True
|
||||
|
||||
pm.refresh(f=True)
|
||||
|
||||
|
|
@ -123,14 +123,14 @@ class ExtractThumbnail(publish.Extractor):
|
|||
preset["viewport_options"] = {"imagePlane": image_plane}
|
||||
|
||||
# Disable Pan/Zoom.
|
||||
pan_zoom = cmds.getAttr("{}.panZoomEnabled".format(preset["camera"]))
|
||||
cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), False)
|
||||
preset.pop("pan_zoom", None)
|
||||
preset["camera_options"]["panZoomEnabled"] = instance.data["panZoom"]
|
||||
|
||||
with lib.maintained_time():
|
||||
# Force viewer to False in call to capture because we have our own
|
||||
# viewer opening call to allow a signal to trigger between
|
||||
# playblast and viewer
|
||||
preset['viewer'] = False
|
||||
preset["viewer"] = False
|
||||
|
||||
# Update preset with current panel setting
|
||||
# if override_viewport_options is turned off
|
||||
|
|
@ -145,17 +145,15 @@ class ExtractThumbnail(publish.Extractor):
|
|||
|
||||
_, thumbnail = os.path.split(playblast)
|
||||
|
||||
cmds.setAttr("{}.panZoomEnabled".format(preset["camera"]), pan_zoom)
|
||||
|
||||
self.log.info("file list {}".format(thumbnail))
|
||||
|
||||
if "representations" not in instance.data:
|
||||
instance.data["representations"] = []
|
||||
|
||||
representation = {
|
||||
'name': 'thumbnail',
|
||||
'ext': 'jpg',
|
||||
'files': thumbnail,
|
||||
"name": "thumbnail",
|
||||
"ext": "jpg",
|
||||
"files": thumbnail,
|
||||
"stagingDir": dst_staging,
|
||||
"thumbnail": True
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,22 +54,19 @@ class LoadBackdropNodes(load.LoaderPlugin):
|
|||
version = context['version']
|
||||
version_data = version.get("data", {})
|
||||
vname = version.get("name", None)
|
||||
first = version_data.get("frameStart", None)
|
||||
last = version_data.get("frameEnd", None)
|
||||
namespace = namespace or context['asset']['name']
|
||||
colorspace = version_data.get("colorspace", None)
|
||||
object_name = "{}_{}".format(name, namespace)
|
||||
|
||||
# prepare data for imprinting
|
||||
# add additional metadata from the version to imprint to Avalon knob
|
||||
add_keys = ["frameStart", "frameEnd", "handleStart", "handleEnd",
|
||||
"source", "author", "fps"]
|
||||
add_keys = ["source", "author", "fps"]
|
||||
|
||||
data_imprint = {"frameStart": first,
|
||||
"frameEnd": last,
|
||||
"version": vname,
|
||||
"colorspaceInput": colorspace,
|
||||
"objectName": object_name}
|
||||
data_imprint = {
|
||||
"version": vname,
|
||||
"colorspaceInput": colorspace,
|
||||
"objectName": object_name
|
||||
}
|
||||
|
||||
for k in add_keys:
|
||||
data_imprint.update({k: version_data[k]})
|
||||
|
|
@ -204,18 +201,13 @@ class LoadBackdropNodes(load.LoaderPlugin):
|
|||
name = container['name']
|
||||
version_data = version_doc.get("data", {})
|
||||
vname = version_doc.get("name", None)
|
||||
first = version_data.get("frameStart", None)
|
||||
last = version_data.get("frameEnd", None)
|
||||
namespace = container['namespace']
|
||||
colorspace = version_data.get("colorspace", None)
|
||||
object_name = "{}_{}".format(name, namespace)
|
||||
|
||||
add_keys = ["frameStart", "frameEnd", "handleStart", "handleEnd",
|
||||
"source", "author", "fps"]
|
||||
add_keys = ["source", "author", "fps"]
|
||||
|
||||
data_imprint = {"representation": str(representation["_id"]),
|
||||
"frameStart": first,
|
||||
"frameEnd": last,
|
||||
"version": vname,
|
||||
"colorspaceInput": colorspace,
|
||||
"objectName": object_name}
|
||||
|
|
|
|||
|
|
@ -51,38 +51,10 @@ class CollectBackdrops(pyblish.api.InstancePlugin):
|
|||
instance.data["label"] = "{0} ({1} nodes)".format(
|
||||
bckn.name(), len(instance.data["transientData"]["childNodes"]))
|
||||
|
||||
instance.data["families"].append(instance.data["family"])
|
||||
|
||||
# Get frame range
|
||||
handle_start = instance.context.data["handleStart"]
|
||||
handle_end = instance.context.data["handleEnd"]
|
||||
first_frame = int(nuke.root()["first_frame"].getValue())
|
||||
last_frame = int(nuke.root()["last_frame"].getValue())
|
||||
|
||||
# get version
|
||||
version = instance.context.data.get('version')
|
||||
|
||||
if not version:
|
||||
raise RuntimeError("Script name has no version in the name.")
|
||||
if version:
|
||||
instance.data['version'] = version
|
||||
|
||||
instance.data['version'] = version
|
||||
|
||||
# Add version data to instance
|
||||
version_data = {
|
||||
"handles": handle_start,
|
||||
"handleStart": handle_start,
|
||||
"handleEnd": handle_end,
|
||||
"frameStart": first_frame + handle_start,
|
||||
"frameEnd": last_frame - handle_end,
|
||||
"version": int(version),
|
||||
"families": [instance.data["family"]] + instance.data["families"],
|
||||
"subset": instance.data["subset"],
|
||||
"fps": instance.context.data["fps"]
|
||||
}
|
||||
|
||||
instance.data.update({
|
||||
"versionData": version_data,
|
||||
"frameStart": first_frame,
|
||||
"frameEnd": last_frame
|
||||
})
|
||||
self.log.info("Backdrop instance collected: `{}`".format(instance))
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class TVPaintLegacyConverted(SubsetConvertorPlugin):
|
|||
self._convert_render_layers(
|
||||
to_convert["renderLayer"], current_instances)
|
||||
self._convert_render_passes(
|
||||
to_convert["renderpass"], current_instances)
|
||||
to_convert["renderPass"], current_instances)
|
||||
self._convert_render_scenes(
|
||||
to_convert["renderScene"], current_instances)
|
||||
self._convert_workfiles(
|
||||
|
|
@ -116,7 +116,7 @@ class TVPaintLegacyConverted(SubsetConvertorPlugin):
|
|||
render_layers_by_group_id = {}
|
||||
for instance in current_instances:
|
||||
if instance.get("creator_identifier") == "render.layer":
|
||||
group_id = instance["creator_identifier"]["group_id"]
|
||||
group_id = instance["creator_attributes"]["group_id"]
|
||||
render_layers_by_group_id[group_id] = instance
|
||||
|
||||
for render_pass in render_passes:
|
||||
|
|
|
|||
|
|
@ -415,11 +415,11 @@ class CreateRenderPass(TVPaintCreator):
|
|||
.get("creator_attributes", {})
|
||||
.get("render_layer_instance_id")
|
||||
)
|
||||
render_layer_info = render_layers.get(render_layer_instance_id)
|
||||
render_layer_info = render_layers.get(render_layer_instance_id, {})
|
||||
self.update_instance_labels(
|
||||
instance_data,
|
||||
render_layer_info["variant"],
|
||||
render_layer_info["template_data"]
|
||||
render_layer_info.get("variant"),
|
||||
render_layer_info.get("template_data")
|
||||
)
|
||||
instance = CreatedInstance.from_existing(instance_data, self)
|
||||
self._add_instance_to_context(instance)
|
||||
|
|
@ -607,11 +607,11 @@ class CreateRenderPass(TVPaintCreator):
|
|||
current_instances = self.host.list_instances()
|
||||
render_layers = [
|
||||
{
|
||||
"value": instance["instance_id"],
|
||||
"label": instance["subset"]
|
||||
"value": inst["instance_id"],
|
||||
"label": inst["subset"]
|
||||
}
|
||||
for instance in current_instances
|
||||
if instance["creator_identifier"] == CreateRenderlayer.identifier
|
||||
for inst in current_instances
|
||||
if inst.get("creator_identifier") == CreateRenderlayer.identifier
|
||||
]
|
||||
if not render_layers:
|
||||
render_layers.append({"value": None, "label": "N/A"})
|
||||
|
|
@ -697,6 +697,7 @@ class TVPaintAutoDetectRenderCreator(TVPaintCreator):
|
|||
["create"]
|
||||
["auto_detect_render"]
|
||||
)
|
||||
self.enabled = plugin_settings.get("enabled", False)
|
||||
self.allow_group_rename = plugin_settings["allow_group_rename"]
|
||||
self.group_name_template = plugin_settings["group_name_template"]
|
||||
self.group_idx_offset = plugin_settings["group_idx_offset"]
|
||||
|
|
|
|||
|
|
@ -22,9 +22,11 @@ class CollectOutputFrameRange(pyblish.api.InstancePlugin):
|
|||
context = instance.context
|
||||
|
||||
frame_start = asset_doc["data"]["frameStart"]
|
||||
fps = asset_doc["data"]["fps"]
|
||||
frame_end = frame_start + (
|
||||
context.data["sceneMarkOut"] - context.data["sceneMarkIn"]
|
||||
)
|
||||
instance.data["fps"] = fps
|
||||
instance.data["frameStart"] = frame_start
|
||||
instance.data["frameEnd"] = frame_end
|
||||
self.log.info(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import pyblish.api
|
||||
from openpype.pipeline import PublishXmlValidationError
|
||||
from openpype.pipeline import (
|
||||
PublishXmlValidationError,
|
||||
OptionalPyblishPluginMixin,
|
||||
)
|
||||
from openpype.hosts.tvpaint.api.pipeline import (
|
||||
list_instances,
|
||||
write_instances,
|
||||
|
|
@ -31,7 +34,10 @@ class FixAssetNames(pyblish.api.Action):
|
|||
write_instances(new_instance_items)
|
||||
|
||||
|
||||
class ValidateAssetNames(pyblish.api.ContextPlugin):
|
||||
class ValidateAssetName(
|
||||
OptionalPyblishPluginMixin,
|
||||
pyblish.api.ContextPlugin
|
||||
):
|
||||
"""Validate assset name present on instance.
|
||||
|
||||
Asset name on instance should be the same as context's.
|
||||
|
|
@ -43,6 +49,8 @@ class ValidateAssetNames(pyblish.api.ContextPlugin):
|
|||
actions = [FixAssetNames]
|
||||
|
||||
def process(self, context):
|
||||
if not self.is_active(context.data):
|
||||
return
|
||||
context_asset_name = context.data["asset"]
|
||||
for instance in context:
|
||||
asset_name = instance.data.get("asset")
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ class ValidateLayersVisiblity(pyblish.api.InstancePlugin):
|
|||
families = ["review", "render"]
|
||||
|
||||
def process(self, instance):
|
||||
layers = instance.data["layers"]
|
||||
layers = instance.data.get("layers")
|
||||
# Instance have empty layers
|
||||
# - it is not job of this validator to check that
|
||||
if not layers:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import json
|
||||
|
||||
import pyblish.api
|
||||
from openpype.pipeline import PublishXmlValidationError
|
||||
from openpype.pipeline import (
|
||||
PublishXmlValidationError,
|
||||
OptionalPyblishPluginMixin,
|
||||
)
|
||||
from openpype.hosts.tvpaint.api.lib import execute_george
|
||||
|
||||
|
||||
|
|
@ -23,7 +26,10 @@ class ValidateMarksRepair(pyblish.api.Action):
|
|||
)
|
||||
|
||||
|
||||
class ValidateMarks(pyblish.api.ContextPlugin):
|
||||
class ValidateMarks(
|
||||
OptionalPyblishPluginMixin,
|
||||
pyblish.api.ContextPlugin
|
||||
):
|
||||
"""Validate mark in and out are enabled and it's duration.
|
||||
|
||||
Mark In/Out does not have to match frameStart and frameEnd but duration is
|
||||
|
|
@ -59,6 +65,9 @@ class ValidateMarks(pyblish.api.ContextPlugin):
|
|||
}
|
||||
|
||||
def process(self, context):
|
||||
if not self.is_active(context.data):
|
||||
return
|
||||
|
||||
current_data = {
|
||||
"markIn": context.data["sceneMarkIn"],
|
||||
"markInState": context.data["sceneMarkInState"],
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
import json
|
||||
|
||||
import pyblish.api
|
||||
from openpype.pipeline import PublishXmlValidationError
|
||||
from openpype.pipeline import (
|
||||
PublishXmlValidationError,
|
||||
OptionalPyblishPluginMixin,
|
||||
)
|
||||
|
||||
|
||||
# TODO @iLliCiTiT add fix action for fps
|
||||
class ValidateProjectSettings(pyblish.api.ContextPlugin):
|
||||
class ValidateProjectSettings(
|
||||
OptionalPyblishPluginMixin,
|
||||
pyblish.api.ContextPlugin
|
||||
):
|
||||
"""Validate scene settings against database."""
|
||||
|
||||
label = "Validate Scene Settings"
|
||||
|
|
@ -13,6 +19,9 @@ class ValidateProjectSettings(pyblish.api.ContextPlugin):
|
|||
optional = True
|
||||
|
||||
def process(self, context):
|
||||
if not self.is_active(context.data):
|
||||
return
|
||||
|
||||
expected_data = context.data["assetEntity"]["data"]
|
||||
scene_data = {
|
||||
"fps": context.data.get("sceneFps"),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import pyblish.api
|
||||
from openpype.pipeline import PublishXmlValidationError
|
||||
from openpype.pipeline import (
|
||||
PublishXmlValidationError,
|
||||
OptionalPyblishPluginMixin,
|
||||
)
|
||||
from openpype.hosts.tvpaint.api.lib import execute_george
|
||||
|
||||
|
||||
|
|
@ -14,7 +17,10 @@ class RepairStartFrame(pyblish.api.Action):
|
|||
execute_george("tv_startframe 0")
|
||||
|
||||
|
||||
class ValidateStartFrame(pyblish.api.ContextPlugin):
|
||||
class ValidateStartFrame(
|
||||
OptionalPyblishPluginMixin,
|
||||
pyblish.api.ContextPlugin
|
||||
):
|
||||
"""Validate start frame being at frame 0."""
|
||||
|
||||
label = "Validate Start Frame"
|
||||
|
|
@ -24,6 +30,9 @@ class ValidateStartFrame(pyblish.api.ContextPlugin):
|
|||
optional = True
|
||||
|
||||
def process(self, context):
|
||||
if not self.is_active(context.data):
|
||||
return
|
||||
|
||||
start_frame = execute_george("tv_startframe")
|
||||
if start_frame == 0:
|
||||
return
|
||||
|
|
|
|||
|
|
@ -3,21 +3,60 @@
|
|||
|
||||
"""
|
||||
import pyblish.api
|
||||
from openpype.lib import TextDef
|
||||
from openpype.pipeline.publish import OpenPypePyblishPluginMixin
|
||||
|
||||
|
||||
class CollectDeadlinePools(pyblish.api.InstancePlugin):
|
||||
class CollectDeadlinePools(pyblish.api.InstancePlugin,
|
||||
OpenPypePyblishPluginMixin):
|
||||
"""Collect pools from instance if present, from Setting otherwise."""
|
||||
|
||||
order = pyblish.api.CollectorOrder + 0.420
|
||||
label = "Collect Deadline Pools"
|
||||
families = ["rendering", "render.farm", "renderFarm", "renderlayer"]
|
||||
families = ["rendering",
|
||||
"render.farm",
|
||||
"renderFarm",
|
||||
"renderlayer",
|
||||
"maxrender"]
|
||||
|
||||
primary_pool = None
|
||||
secondary_pool = None
|
||||
|
||||
@classmethod
|
||||
def apply_settings(cls, project_settings, system_settings):
|
||||
# deadline.publish.CollectDeadlinePools
|
||||
settings = project_settings["deadline"]["publish"]["CollectDeadlinePools"] # noqa
|
||||
cls.primary_pool = settings.get("primary_pool", None)
|
||||
cls.secondary_pool = settings.get("secondary_pool", None)
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
attr_values = self.get_attr_values_from_data(instance.data)
|
||||
if not instance.data.get("primaryPool"):
|
||||
instance.data["primaryPool"] = self.primary_pool or "none"
|
||||
instance.data["primaryPool"] = (
|
||||
attr_values.get("primaryPool") or self.primary_pool or "none"
|
||||
)
|
||||
|
||||
if not instance.data.get("secondaryPool"):
|
||||
instance.data["secondaryPool"] = self.secondary_pool or "none"
|
||||
instance.data["secondaryPool"] = (
|
||||
attr_values.get("secondaryPool") or self.secondary_pool or "none" # noqa
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_attribute_defs(cls):
|
||||
# TODO: Preferably this would be an enum for the user
|
||||
# but the Deadline server URL can be dynamic and
|
||||
# can be set per render instance. Since get_attribute_defs
|
||||
# can't be dynamic unfortunately EnumDef isn't possible (yet?)
|
||||
# pool_names = self.deadline_module.get_deadline_pools(deadline_url,
|
||||
# self.log)
|
||||
# secondary_pool_names = ["-"] + pool_names
|
||||
|
||||
return [
|
||||
TextDef("primaryPool",
|
||||
label="Primary Pool",
|
||||
default=cls.primary_pool),
|
||||
TextDef("secondaryPool",
|
||||
label="Secondary Pool",
|
||||
default=cls.secondary_pool)
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,7 +3,15 @@ import getpass
|
|||
import copy
|
||||
|
||||
import attr
|
||||
from openpype.pipeline import legacy_io
|
||||
from openpype.lib import (
|
||||
TextDef,
|
||||
BoolDef,
|
||||
NumberDef,
|
||||
)
|
||||
from openpype.pipeline import (
|
||||
legacy_io,
|
||||
OpenPypePyblishPluginMixin
|
||||
)
|
||||
from openpype.settings import get_project_settings
|
||||
from openpype.hosts.max.api.lib import (
|
||||
get_current_renderer,
|
||||
|
|
@ -22,7 +30,8 @@ class MaxPluginInfo(object):
|
|||
IgnoreInputs = attr.ib(default=True)
|
||||
|
||||
|
||||
class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline):
|
||||
class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline,
|
||||
OpenPypePyblishPluginMixin):
|
||||
|
||||
label = "Submit Render to Deadline"
|
||||
hosts = ["max"]
|
||||
|
|
@ -31,14 +40,22 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline):
|
|||
|
||||
use_published = True
|
||||
priority = 50
|
||||
tile_priority = 50
|
||||
chunk_size = 1
|
||||
jobInfo = {}
|
||||
pluginInfo = {}
|
||||
group = None
|
||||
deadline_pool = None
|
||||
deadline_pool_secondary = None
|
||||
framePerTask = 1
|
||||
|
||||
@classmethod
|
||||
def apply_settings(cls, project_settings, system_settings):
|
||||
settings = project_settings["deadline"]["publish"]["MaxSubmitDeadline"] # noqa
|
||||
|
||||
# Take some defaults from settings
|
||||
cls.use_published = settings.get("use_published",
|
||||
cls.use_published)
|
||||
cls.priority = settings.get("priority",
|
||||
cls.priority)
|
||||
cls.chuck_size = settings.get("chunk_size", cls.chunk_size)
|
||||
cls.group = settings.get("group", cls.group)
|
||||
|
||||
def get_job_info(self):
|
||||
job_info = DeadlineJobInfo(Plugin="3dsmax")
|
||||
|
|
@ -49,11 +66,11 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline):
|
|||
|
||||
instance = self._instance
|
||||
context = instance.context
|
||||
|
||||
# Always use the original work file name for the Job name even when
|
||||
# rendering is done from the published Work File. The original work
|
||||
# file name is clearer because it can also have subversion strings,
|
||||
# etc. which are stripped for the published file.
|
||||
|
||||
src_filepath = context.data["currentFile"]
|
||||
src_filename = os.path.basename(src_filepath)
|
||||
|
||||
|
|
@ -71,13 +88,13 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline):
|
|||
|
||||
job_info.Pool = instance.data.get("primaryPool")
|
||||
job_info.SecondaryPool = instance.data.get("secondaryPool")
|
||||
job_info.ChunkSize = instance.data.get("chunkSize", 1)
|
||||
job_info.Comment = context.data.get("comment")
|
||||
job_info.Priority = instance.data.get("priority", self.priority)
|
||||
job_info.FramesPerTask = instance.data.get("framesPerTask", 1)
|
||||
|
||||
if self.group:
|
||||
job_info.Group = self.group
|
||||
attr_values = self.get_attr_values_from_data(instance.data)
|
||||
|
||||
job_info.ChunkSize = attr_values.get("chunkSize", 1)
|
||||
job_info.Comment = context.data.get("comment")
|
||||
job_info.Priority = attr_values.get("priority", self.priority)
|
||||
job_info.Group = attr_values.get("group", self.group)
|
||||
|
||||
# Add options from RenderGlobals
|
||||
render_globals = instance.data.get("renderGlobals", {})
|
||||
|
|
@ -216,3 +233,32 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline):
|
|||
plugin_info.update(plugin_data)
|
||||
|
||||
return job_info, plugin_info
|
||||
|
||||
@classmethod
|
||||
def get_attribute_defs(cls):
|
||||
defs = super(MaxSubmitDeadline, cls).get_attribute_defs()
|
||||
defs.extend([
|
||||
BoolDef("use_published",
|
||||
default=cls.use_published,
|
||||
label="Use Published Scene"),
|
||||
|
||||
NumberDef("priority",
|
||||
minimum=1,
|
||||
maximum=250,
|
||||
decimals=0,
|
||||
default=cls.priority,
|
||||
label="Priority"),
|
||||
|
||||
NumberDef("chunkSize",
|
||||
minimum=1,
|
||||
maximum=50,
|
||||
decimals=0,
|
||||
default=cls.chunk_size,
|
||||
label="Frame Per Task"),
|
||||
|
||||
TextDef("group",
|
||||
default=cls.group,
|
||||
label="Group Name"),
|
||||
])
|
||||
|
||||
return defs
|
||||
|
|
|
|||
|
|
@ -17,7 +17,11 @@ class ValidateDeadlinePools(OptionalPyblishPluginMixin,
|
|||
|
||||
label = "Validate Deadline Pools"
|
||||
order = pyblish.api.ValidatorOrder
|
||||
families = ["rendering", "render.farm", "renderFarm", "renderlayer"]
|
||||
families = ["rendering",
|
||||
"render.farm",
|
||||
"renderFarm",
|
||||
"renderlayer",
|
||||
"maxrender"]
|
||||
optional = True
|
||||
|
||||
def process(self, instance):
|
||||
|
|
|
|||
|
|
@ -43,10 +43,7 @@
|
|||
"use_published": true,
|
||||
"priority": 50,
|
||||
"chunk_size": 10,
|
||||
"group": "none",
|
||||
"deadline_pool": "",
|
||||
"deadline_pool_secondary": "",
|
||||
"framePerTask": 1
|
||||
"group": "none"
|
||||
},
|
||||
"NukeSubmitDeadline": {
|
||||
"enabled": true,
|
||||
|
|
|
|||
|
|
@ -790,7 +790,7 @@
|
|||
"ExtractPlayblast": {
|
||||
"capture_preset": {
|
||||
"Codec": {
|
||||
"compression": "jpg",
|
||||
"compression": "png",
|
||||
"format": "image",
|
||||
"quality": 95
|
||||
},
|
||||
|
|
@ -817,7 +817,8 @@
|
|||
},
|
||||
"Generic": {
|
||||
"isolate_view": true,
|
||||
"off_screen": true
|
||||
"off_screen": true,
|
||||
"pan_zoom": false
|
||||
},
|
||||
"Renderer": {
|
||||
"rendererName": "vp2Renderer"
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
"default_variants": []
|
||||
},
|
||||
"auto_detect_render": {
|
||||
"enabled": false,
|
||||
"allow_group_rename": true,
|
||||
"group_name_template": "L{group_index}",
|
||||
"group_idx_offset": 10,
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@
|
|||
"linux": []
|
||||
},
|
||||
"arguments": {
|
||||
"windows": [],
|
||||
"windows": ["-U MAXScript {OPENPYPE_ROOT}\\openpype\\hosts\\max\\startup\\startup.ms"],
|
||||
"darwin": [],
|
||||
"linux": []
|
||||
},
|
||||
|
|
|
|||
|
|
@ -239,27 +239,12 @@
|
|||
{
|
||||
"type": "number",
|
||||
"key": "chunk_size",
|
||||
"label": "Chunk Size"
|
||||
"label": "Frame per Task"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "group",
|
||||
"label": "Group Name"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_pool",
|
||||
"label": "Deadline pool"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_pool_secondary",
|
||||
"label": "Deadline pool (secondary)"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "framePerTask",
|
||||
"label": "Frame Per Task"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -202,7 +202,13 @@
|
|||
"key": "auto_detect_render",
|
||||
"label": "Auto-Detect Create Render",
|
||||
"is_group": true,
|
||||
"checkbox_key": "enabled",
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"label": "The creator tries to auto-detect Render Layers and Render Passes in scene. For Render Layers is used group name as a variant and for Render Passes is used TVPaint layer name.<br/><br/>Group names can be renamed by their used order in scene. The renaming template where can be used <b>{group_index}</b> formatting key which is filled by \"used position index of group\".<br/>- Template: <b>L{group_index}</b><br/>- Group offset: <b>10</b><br/>- Group padding: <b>3</b><br/>Would create group names \"<b>L010</b>\", \"<b>L020</b>\", ..."
|
||||
|
|
|
|||
|
|
@ -91,6 +91,11 @@
|
|||
"type": "boolean",
|
||||
"key": "off_screen",
|
||||
"label": " Off Screen"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "pan_zoom",
|
||||
"label": " 2D Pan/Zoom"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -156,7 +161,7 @@
|
|||
{
|
||||
"type": "boolean",
|
||||
"key": "override_viewport_options",
|
||||
"label": "override_viewport_options"
|
||||
"label": "Override Viewport Options"
|
||||
},
|
||||
{
|
||||
"type": "enum",
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ class HierarchyView(QtWidgets.QTreeView):
|
|||
column_delegate_defs = {
|
||||
"name": NameDef(),
|
||||
"type": TypeDef(),
|
||||
"frameStart": NumberDef(1),
|
||||
"frameEnd": NumberDef(1),
|
||||
"frameStart": NumberDef(0),
|
||||
"frameEnd": NumberDef(0),
|
||||
"fps": NumberDef(1, decimals=3, step=1),
|
||||
"resolutionWidth": NumberDef(0),
|
||||
"resolutionHeight": NumberDef(0),
|
||||
|
|
|
|||
|
|
@ -110,6 +110,41 @@ or Deadlines **Draft Tile Assembler**.
|
|||
This is useful to fix some specific renderer glitches and advanced hacking of Maya Scene files. `Patch name` is label for patch for easier orientation.
|
||||
`Patch regex` is regex used to find line in file, after `Patch line` string is inserted. Note that you need to add line ending.
|
||||
|
||||
### Extract Playblast Settings (review)
|
||||
These settings provide granular control over how the playblasts or reviews are produced in Maya.
|
||||
|
||||
Some of these settings are also available on the instance itself, in which case these settings will become the default value when creating the review instance.
|
||||
|
||||

|
||||
|
||||
- **Compression type** which file encoding to use.
|
||||
- **Data format** what format is the file encoding.
|
||||
- **Quality** lets you control the compression value for the output. Results can vary depending on the compression you selected. Quality values can range from 0 to 100, with a default value of 95.
|
||||
- **Background Color** the viewports background color.
|
||||
- **Background Bottom** the viewports background bottom color.
|
||||
- **Background Top** the viewports background top color.
|
||||
- **Override display options** override the viewports display options to use what is set in the settings.
|
||||
- **Isolate view** isolates the view to what is in the review instance. If only a camera is present in the review instance, all nodes are displayed in view.
|
||||
- **Off Screen** records the playblast hidden from the user.
|
||||
- **2D Pan/Zoom** enables the 2D Pan/Zoom functionality of the camera.
|
||||
- **Renderer name** which renderer to use for playblasting.
|
||||
- **Width** width of the output resolution. If this value is `0`, the asset's width is used.
|
||||
- **Height** height of the output resolution. If this value is `0`, the asset's height is used.
|
||||
|
||||
#### Viewport Options
|
||||
|
||||
Most settings to override in the viewport are self explanatory and can be found in Maya.
|
||||
|
||||

|
||||
|
||||
- **Override Viewport Options** enable to use the settings below for the viewport when publishing the review.
|
||||
|
||||
#### Camera Options
|
||||
|
||||
These options are set on the camera shape when publishing the review. They correspond to attributes on the Maya camera shape node.
|
||||
|
||||

|
||||
|
||||
## Custom Menu
|
||||
You can add your custom tools menu into Maya by extending definitions in **Maya -> Scripts Menu Definition**.
|
||||

|
||||
|
|
|
|||
BIN
website/docs/assets/maya-admin_extract_playblast_settings.png
Normal file
BIN
website/docs/assets/maya-admin_extract_playblast_settings.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1 MiB |
Loading…
Add table
Add a link
Reference in a new issue