mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 05:14:40 +01:00
Merge branch 'chore/AY-4916_Move-Houdini-client-code' into chore/AY-4916_Move-Houdini-client-code-settings-category
This commit is contained in:
commit
78fac68206
209 changed files with 872 additions and 233 deletions
|
|
@ -52,10 +52,13 @@ IGNORED_MODULES_IN_AYON = set()
|
|||
MOVED_ADDON_MILESTONE_VERSIONS = {
|
||||
"applications": VersionInfo(0, 2, 0),
|
||||
"clockify": VersionInfo(0, 2, 0),
|
||||
"traypublisher": VersionInfo(0, 2, 0),
|
||||
"tvpaint": VersionInfo(0, 2, 0),
|
||||
"nuke": VersionInfo(0, 2, 0),
|
||||
"houdini": VersionInfo(0, 3, 0),
|
||||
}
|
||||
|
||||
|
||||
# Inherit from `object` for Python 2 hosts
|
||||
class _ModuleClass(object):
|
||||
"""Fake module class for storing AYON addons.
|
||||
|
|
|
|||
|
|
@ -26,27 +26,32 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin,
|
|||
|
||||
order = pyblish.api.CollectorOrder + 0.420
|
||||
label = "Collect Deadline Pools"
|
||||
hosts = ["aftereffects",
|
||||
"fusion",
|
||||
"harmony"
|
||||
"nuke",
|
||||
"maya",
|
||||
"max",
|
||||
"houdini"]
|
||||
hosts = [
|
||||
"aftereffects",
|
||||
"fusion",
|
||||
"harmony",
|
||||
"maya",
|
||||
"max",
|
||||
"houdini",
|
||||
"nuke",
|
||||
]
|
||||
|
||||
families = ["render",
|
||||
"rendering",
|
||||
"render.farm",
|
||||
"renderFarm",
|
||||
"renderlayer",
|
||||
"maxrender",
|
||||
"usdrender",
|
||||
"redshift_rop",
|
||||
"arnold_rop",
|
||||
"mantra_rop",
|
||||
"karma_rop",
|
||||
"vray_rop",
|
||||
"publish.hou"]
|
||||
families = [
|
||||
"render",
|
||||
"prerender",
|
||||
"rendering",
|
||||
"render.farm",
|
||||
"renderFarm",
|
||||
"renderlayer",
|
||||
"maxrender",
|
||||
"usdrender",
|
||||
"redshift_rop",
|
||||
"arnold_rop",
|
||||
"mantra_rop",
|
||||
"karma_rop",
|
||||
"vray_rop",
|
||||
"publish.hou",
|
||||
]
|
||||
|
||||
primary_pool = None
|
||||
secondary_pool = None
|
||||
|
|
|
|||
|
|
@ -681,7 +681,7 @@ class PublishAttributeValues(AttributeValues):
|
|||
|
||||
@property
|
||||
def parent(self):
|
||||
self.publish_attributes.parent
|
||||
return self.publish_attributes.parent
|
||||
|
||||
|
||||
class PublishAttributes:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import pyblish.api
|
||||
from ayon_core.pipeline.publish import PublishValidationError
|
||||
from ayon_core.pipeline.publish import (
|
||||
PublishValidationError, OptionalPyblishPluginMixin
|
||||
)
|
||||
|
||||
|
||||
class ValidateVersion(pyblish.api.InstancePlugin):
|
||||
class ValidateVersion(pyblish.api.InstancePlugin, OptionalPyblishPluginMixin):
|
||||
"""Validate instance version.
|
||||
|
||||
AYON does not allow overwriting previously published versions.
|
||||
|
|
@ -18,6 +20,9 @@ class ValidateVersion(pyblish.api.InstancePlugin):
|
|||
active = True
|
||||
|
||||
def process(self, instance):
|
||||
if not self.is_active(instance.data):
|
||||
return
|
||||
|
||||
version = instance.data.get("version")
|
||||
latest_version = instance.data.get("latestVersion")
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import ayon_api
|
|||
import six
|
||||
|
||||
from ayon_core.style import get_default_entity_icon_color
|
||||
from ayon_core.lib import CacheItem
|
||||
from ayon_core.lib import CacheItem, NestedCacheItem
|
||||
|
||||
PROJECTS_MODEL_SENDER = "projects.model"
|
||||
|
||||
|
|
@ -17,6 +17,49 @@ class AbstractHierarchyController:
|
|||
pass
|
||||
|
||||
|
||||
class StatusItem:
|
||||
"""Item representing status of project.
|
||||
|
||||
Args:
|
||||
name (str): Status name ("Not ready").
|
||||
color (str): Status color in hex ("#434a56").
|
||||
short (str): Short status name ("NRD").
|
||||
icon (str): Icon name in MaterialIcons ("fiber_new").
|
||||
state (Literal["not_started", "in_progress", "done", "blocked"]):
|
||||
Status state.
|
||||
|
||||
"""
|
||||
def __init__(self, name, color, short, icon, state):
|
||||
self.name = name
|
||||
self.color = color
|
||||
self.short = short
|
||||
self.icon = icon
|
||||
self.state = state
|
||||
|
||||
def to_data(self):
|
||||
return {
|
||||
"name": self.name,
|
||||
"color": self.color,
|
||||
"short": self.short,
|
||||
"icon": self.icon,
|
||||
"state": self.state,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_data(cls, data):
|
||||
return cls(**data)
|
||||
|
||||
@classmethod
|
||||
def from_project_item(cls, status_data):
|
||||
return cls(
|
||||
name=status_data["name"],
|
||||
color=status_data["color"],
|
||||
short=status_data["shortName"],
|
||||
icon=status_data["icon"],
|
||||
state=status_data["state"],
|
||||
)
|
||||
|
||||
|
||||
class ProjectItem:
|
||||
"""Item representing folder entity on a server.
|
||||
|
||||
|
|
@ -40,6 +83,23 @@ class ProjectItem:
|
|||
}
|
||||
self.icon = icon
|
||||
|
||||
@classmethod
|
||||
def from_entity(cls, project_entity):
|
||||
"""Creates folder item from entity.
|
||||
|
||||
Args:
|
||||
project_entity (dict[str, Any]): Project entity.
|
||||
|
||||
Returns:
|
||||
ProjectItem: Project item.
|
||||
|
||||
"""
|
||||
return cls(
|
||||
project_entity["name"],
|
||||
project_entity["active"],
|
||||
project_entity["library"],
|
||||
)
|
||||
|
||||
def to_data(self):
|
||||
"""Converts folder item to data.
|
||||
|
||||
|
|
@ -79,7 +139,7 @@ def _get_project_items_from_entitiy(projects):
|
|||
"""
|
||||
|
||||
return [
|
||||
ProjectItem(project["name"], project["active"], project["library"])
|
||||
ProjectItem.from_entity(project)
|
||||
for project in projects
|
||||
]
|
||||
|
||||
|
|
@ -87,18 +147,29 @@ def _get_project_items_from_entitiy(projects):
|
|||
class ProjectsModel(object):
|
||||
def __init__(self, controller):
|
||||
self._projects_cache = CacheItem(default_factory=list)
|
||||
self._project_items_by_name = {}
|
||||
self._projects_by_name = {}
|
||||
self._project_statuses_cache = NestedCacheItem(
|
||||
levels=1, default_factory=list
|
||||
)
|
||||
self._projects_by_name = NestedCacheItem(
|
||||
levels=1, default_factory=list
|
||||
)
|
||||
|
||||
self._is_refreshing = False
|
||||
self._controller = controller
|
||||
|
||||
def reset(self):
|
||||
self._projects_cache.reset()
|
||||
self._project_items_by_name = {}
|
||||
self._projects_by_name = {}
|
||||
self._project_statuses_cache.reset()
|
||||
self._projects_by_name.reset()
|
||||
|
||||
def refresh(self):
|
||||
"""Refresh project items.
|
||||
|
||||
This method will requery list of ProjectItem returned by
|
||||
'get_project_items'.
|
||||
|
||||
To reset all cached items use 'reset' method.
|
||||
"""
|
||||
self._refresh_projects_cache()
|
||||
|
||||
def get_project_items(self, sender):
|
||||
|
|
@ -117,12 +188,51 @@ class ProjectsModel(object):
|
|||
return self._projects_cache.get_data()
|
||||
|
||||
def get_project_entity(self, project_name):
|
||||
if project_name not in self._projects_by_name:
|
||||
"""Get project entity.
|
||||
|
||||
Args:
|
||||
project_name (str): Project name.
|
||||
|
||||
Returns:
|
||||
Union[dict[str, Any], None]: Project entity or None if project
|
||||
was not found by name.
|
||||
|
||||
"""
|
||||
project_cache = self._projects_by_name[project_name]
|
||||
if not project_cache.is_valid:
|
||||
entity = None
|
||||
if project_name:
|
||||
entity = ayon_api.get_project(project_name)
|
||||
self._projects_by_name[project_name] = entity
|
||||
return self._projects_by_name[project_name]
|
||||
project_cache.update_data(entity)
|
||||
return project_cache.get_data()
|
||||
|
||||
def get_project_status_items(self, project_name, sender):
|
||||
"""Get project status items.
|
||||
|
||||
Args:
|
||||
project_name (str): Project name.
|
||||
sender (Union[str, None]): Name of sender who asked for items.
|
||||
|
||||
Returns:
|
||||
list[StatusItem]: Status items for project.
|
||||
|
||||
"""
|
||||
statuses_cache = self._project_statuses_cache[project_name]
|
||||
if not statuses_cache.is_valid:
|
||||
with self._project_statuses_refresh_event_manager(
|
||||
sender, project_name
|
||||
):
|
||||
project_entity = None
|
||||
if project_name:
|
||||
project_entity = self.get_project_entity(project_name)
|
||||
statuses = []
|
||||
if project_entity:
|
||||
statuses = [
|
||||
StatusItem.from_project_item(status)
|
||||
for status in project_entity["statuses"]
|
||||
]
|
||||
statuses_cache.update_data(statuses)
|
||||
return statuses_cache.get_data()
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _project_refresh_event_manager(self, sender):
|
||||
|
|
@ -143,6 +253,23 @@ class ProjectsModel(object):
|
|||
)
|
||||
self._is_refreshing = False
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _project_statuses_refresh_event_manager(self, sender, project_name):
|
||||
self._controller.emit_event(
|
||||
"projects.statuses.refresh.started",
|
||||
{"sender": sender, "project_name": project_name},
|
||||
PROJECTS_MODEL_SENDER
|
||||
)
|
||||
try:
|
||||
yield
|
||||
|
||||
finally:
|
||||
self._controller.emit_event(
|
||||
"projects.statuses.refresh.finished",
|
||||
{"sender": sender, "project_name": project_name},
|
||||
PROJECTS_MODEL_SENDER
|
||||
)
|
||||
|
||||
def _refresh_projects_cache(self, sender=None):
|
||||
if self._is_refreshing:
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ class VersionItem:
|
|||
thumbnail_id (Union[str, None]): Thumbnail id.
|
||||
published_time (Union[str, None]): Published time in format
|
||||
'%Y%m%dT%H%M%SZ'.
|
||||
status (Union[str, None]): Status name.
|
||||
author (Union[str, None]): Author.
|
||||
frame_range (Union[str, None]): Frame range.
|
||||
duration (Union[int, None]): Duration.
|
||||
|
|
@ -132,6 +133,7 @@ class VersionItem:
|
|||
thumbnail_id,
|
||||
published_time,
|
||||
author,
|
||||
status,
|
||||
frame_range,
|
||||
duration,
|
||||
handles,
|
||||
|
|
@ -146,6 +148,7 @@ class VersionItem:
|
|||
self.is_hero = is_hero
|
||||
self.published_time = published_time
|
||||
self.author = author
|
||||
self.status = status
|
||||
self.frame_range = frame_range
|
||||
self.duration = duration
|
||||
self.handles = handles
|
||||
|
|
@ -185,6 +188,7 @@ class VersionItem:
|
|||
"is_hero": self.is_hero,
|
||||
"published_time": self.published_time,
|
||||
"author": self.author,
|
||||
"status": self.status,
|
||||
"frame_range": self.frame_range,
|
||||
"duration": self.duration,
|
||||
"handles": self.handles,
|
||||
|
|
@ -488,6 +492,27 @@ class FrontendLoaderController(_BaseLoaderController):
|
|||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_project_status_items(self, project_name, sender=None):
|
||||
"""Items for all projects available on server.
|
||||
|
||||
Triggers event topics "projects.statuses.refresh.started" and
|
||||
"projects.statuses.refresh.finished" with data:
|
||||
{
|
||||
"sender": sender,
|
||||
"project_name": project_name
|
||||
}
|
||||
|
||||
Args:
|
||||
project_name (Union[str, None]): Project name.
|
||||
sender (Optional[str]): Sender who requested the items.
|
||||
|
||||
Returns:
|
||||
list[StatusItem]: List of status items.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_product_items(self, project_name, folder_ids, sender=None):
|
||||
"""Product items for folder ids.
|
||||
|
|
|
|||
|
|
@ -180,6 +180,11 @@ class LoaderController(BackendLoaderController, FrontendLoaderController):
|
|||
def get_project_items(self, sender=None):
|
||||
return self._projects_model.get_project_items(sender)
|
||||
|
||||
def get_project_status_items(self, project_name, sender=None):
|
||||
return self._projects_model.get_project_status_items(
|
||||
project_name, sender
|
||||
)
|
||||
|
||||
def get_folder_items(self, project_name, sender=None):
|
||||
return self._hierarchy_model.get_folder_items(project_name, sender)
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ def version_item_from_entity(version):
|
|||
thumbnail_id=version["thumbnailId"],
|
||||
published_time=published_time,
|
||||
author=author,
|
||||
status=version["status"],
|
||||
frame_range=frame_range,
|
||||
duration=duration,
|
||||
handles=handles,
|
||||
|
|
@ -526,8 +527,11 @@ class ProductsModel:
|
|||
products = list(ayon_api.get_products(project_name, **kwargs))
|
||||
product_ids = {product["id"] for product in products}
|
||||
|
||||
# Add 'status' to fields -> fixed in ayon-python-api 1.0.4
|
||||
fields = ayon_api.get_default_fields_for_type("version")
|
||||
fields.add("status")
|
||||
versions = ayon_api.get_versions(
|
||||
project_name, product_ids=product_ids
|
||||
project_name, product_ids=product_ids, fields=fields
|
||||
)
|
||||
|
||||
return self._create_product_items(
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ from ayon_core.tools.utils.lib import format_version
|
|||
from .products_model import (
|
||||
PRODUCT_ID_ROLE,
|
||||
VERSION_NAME_EDIT_ROLE,
|
||||
VERSION_STATUS_NAME_ROLE,
|
||||
VERSION_STATUS_SHORT_ROLE,
|
||||
VERSION_STATUS_COLOR_ROLE,
|
||||
VERSION_ID_ROLE,
|
||||
PRODUCT_IN_SCENE_ROLE,
|
||||
ACTIVE_SITE_ICON_ROLE,
|
||||
|
|
@ -104,7 +107,10 @@ class VersionDelegate(QtWidgets.QStyledItemDelegate):
|
|||
style = QtWidgets.QApplication.style()
|
||||
|
||||
style.drawControl(
|
||||
style.CE_ItemViewItem, option, painter, option.widget
|
||||
QtWidgets.QCommonStyle.CE_ItemViewItem,
|
||||
option,
|
||||
painter,
|
||||
option.widget
|
||||
)
|
||||
|
||||
painter.save()
|
||||
|
|
@ -116,9 +122,14 @@ class VersionDelegate(QtWidgets.QStyledItemDelegate):
|
|||
pen.setColor(fg_color)
|
||||
painter.setPen(pen)
|
||||
|
||||
text_rect = style.subElementRect(style.SE_ItemViewItemText, option)
|
||||
text_rect = style.subElementRect(
|
||||
QtWidgets.QCommonStyle.SE_ItemViewItemText,
|
||||
option
|
||||
)
|
||||
text_margin = style.proxy().pixelMetric(
|
||||
style.PM_FocusFrameHMargin, option, option.widget
|
||||
QtWidgets.QCommonStyle.PM_FocusFrameHMargin,
|
||||
option,
|
||||
option.widget
|
||||
) + 1
|
||||
|
||||
painter.drawText(
|
||||
|
|
@ -194,6 +205,57 @@ class LoadedInSceneDelegate(QtWidgets.QStyledItemDelegate):
|
|||
option.palette.setBrush(QtGui.QPalette.Text, color)
|
||||
|
||||
|
||||
class StatusDelegate(QtWidgets.QStyledItemDelegate):
|
||||
"""Delegate showing status name and short name."""
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
if option.widget:
|
||||
style = option.widget.style()
|
||||
else:
|
||||
style = QtWidgets.QApplication.style()
|
||||
|
||||
style.drawControl(
|
||||
QtWidgets.QCommonStyle.CE_ItemViewItem,
|
||||
option,
|
||||
painter,
|
||||
option.widget
|
||||
)
|
||||
|
||||
painter.save()
|
||||
|
||||
text_rect = style.subElementRect(
|
||||
QtWidgets.QCommonStyle.SE_ItemViewItemText,
|
||||
option
|
||||
)
|
||||
text_margin = style.proxy().pixelMetric(
|
||||
QtWidgets.QCommonStyle.PM_FocusFrameHMargin,
|
||||
option,
|
||||
option.widget
|
||||
) + 1
|
||||
padded_text_rect = text_rect.adjusted(
|
||||
text_margin, 0, - text_margin, 0
|
||||
)
|
||||
|
||||
fm = QtGui.QFontMetrics(option.font)
|
||||
text = index.data(VERSION_STATUS_NAME_ROLE)
|
||||
if padded_text_rect.width() < fm.width(text):
|
||||
text = index.data(VERSION_STATUS_SHORT_ROLE)
|
||||
|
||||
status_color = index.data(VERSION_STATUS_COLOR_ROLE)
|
||||
fg_color = QtGui.QColor(status_color)
|
||||
pen = painter.pen()
|
||||
pen.setColor(fg_color)
|
||||
painter.setPen(pen)
|
||||
|
||||
painter.drawText(
|
||||
padded_text_rect,
|
||||
option.displayAlignment,
|
||||
text
|
||||
)
|
||||
|
||||
painter.restore()
|
||||
|
||||
|
||||
class SiteSyncDelegate(QtWidgets.QStyledItemDelegate):
|
||||
"""Paints icons and downloaded representation ration for both sites."""
|
||||
|
||||
|
|
|
|||
|
|
@ -22,18 +22,21 @@ VERSION_HERO_ROLE = QtCore.Qt.UserRole + 11
|
|||
VERSION_NAME_ROLE = QtCore.Qt.UserRole + 12
|
||||
VERSION_NAME_EDIT_ROLE = QtCore.Qt.UserRole + 13
|
||||
VERSION_PUBLISH_TIME_ROLE = QtCore.Qt.UserRole + 14
|
||||
VERSION_AUTHOR_ROLE = QtCore.Qt.UserRole + 15
|
||||
VERSION_FRAME_RANGE_ROLE = QtCore.Qt.UserRole + 16
|
||||
VERSION_DURATION_ROLE = QtCore.Qt.UserRole + 17
|
||||
VERSION_HANDLES_ROLE = QtCore.Qt.UserRole + 18
|
||||
VERSION_STEP_ROLE = QtCore.Qt.UserRole + 19
|
||||
VERSION_AVAILABLE_ROLE = QtCore.Qt.UserRole + 20
|
||||
VERSION_THUMBNAIL_ID_ROLE = QtCore.Qt.UserRole + 21
|
||||
ACTIVE_SITE_ICON_ROLE = QtCore.Qt.UserRole + 22
|
||||
REMOTE_SITE_ICON_ROLE = QtCore.Qt.UserRole + 23
|
||||
REPRESENTATIONS_COUNT_ROLE = QtCore.Qt.UserRole + 24
|
||||
SYNC_ACTIVE_SITE_AVAILABILITY = QtCore.Qt.UserRole + 25
|
||||
SYNC_REMOTE_SITE_AVAILABILITY = QtCore.Qt.UserRole + 26
|
||||
VERSION_STATUS_NAME_ROLE = QtCore.Qt.UserRole + 15
|
||||
VERSION_STATUS_SHORT_ROLE = QtCore.Qt.UserRole + 16
|
||||
VERSION_STATUS_COLOR_ROLE = QtCore.Qt.UserRole + 17
|
||||
VERSION_AUTHOR_ROLE = QtCore.Qt.UserRole + 18
|
||||
VERSION_FRAME_RANGE_ROLE = QtCore.Qt.UserRole + 19
|
||||
VERSION_DURATION_ROLE = QtCore.Qt.UserRole + 20
|
||||
VERSION_HANDLES_ROLE = QtCore.Qt.UserRole + 21
|
||||
VERSION_STEP_ROLE = QtCore.Qt.UserRole + 22
|
||||
VERSION_AVAILABLE_ROLE = QtCore.Qt.UserRole + 23
|
||||
VERSION_THUMBNAIL_ID_ROLE = QtCore.Qt.UserRole + 24
|
||||
ACTIVE_SITE_ICON_ROLE = QtCore.Qt.UserRole + 25
|
||||
REMOTE_SITE_ICON_ROLE = QtCore.Qt.UserRole + 26
|
||||
REPRESENTATIONS_COUNT_ROLE = QtCore.Qt.UserRole + 27
|
||||
SYNC_ACTIVE_SITE_AVAILABILITY = QtCore.Qt.UserRole + 28
|
||||
SYNC_REMOTE_SITE_AVAILABILITY = QtCore.Qt.UserRole + 29
|
||||
|
||||
|
||||
class ProductsModel(QtGui.QStandardItemModel):
|
||||
|
|
@ -44,6 +47,7 @@ class ProductsModel(QtGui.QStandardItemModel):
|
|||
"Product type",
|
||||
"Folder",
|
||||
"Version",
|
||||
"Status",
|
||||
"Time",
|
||||
"Author",
|
||||
"Frames",
|
||||
|
|
@ -69,11 +73,35 @@ class ProductsModel(QtGui.QStandardItemModel):
|
|||
]
|
||||
]
|
||||
|
||||
version_col = column_labels.index("Version")
|
||||
published_time_col = column_labels.index("Time")
|
||||
product_name_col = column_labels.index("Product name")
|
||||
product_type_col = column_labels.index("Product type")
|
||||
folders_label_col = column_labels.index("Folder")
|
||||
version_col = column_labels.index("Version")
|
||||
status_col = column_labels.index("Status")
|
||||
published_time_col = column_labels.index("Time")
|
||||
author_col = column_labels.index("Author")
|
||||
frame_range_col = column_labels.index("Frames")
|
||||
duration_col = column_labels.index("Duration")
|
||||
handles_col = column_labels.index("Handles")
|
||||
step_col = column_labels.index("Step")
|
||||
in_scene_col = column_labels.index("In scene")
|
||||
sitesync_avail_col = column_labels.index("Availability")
|
||||
_display_role_mapping = {
|
||||
product_name_col: QtCore.Qt.DisplayRole,
|
||||
product_type_col: PRODUCT_TYPE_ROLE,
|
||||
folders_label_col: FOLDER_LABEL_ROLE,
|
||||
version_col: VERSION_NAME_ROLE,
|
||||
status_col: VERSION_STATUS_NAME_ROLE,
|
||||
published_time_col: VERSION_PUBLISH_TIME_ROLE,
|
||||
author_col: VERSION_AUTHOR_ROLE,
|
||||
frame_range_col: VERSION_FRAME_RANGE_ROLE,
|
||||
duration_col: VERSION_DURATION_ROLE,
|
||||
handles_col: VERSION_HANDLES_ROLE,
|
||||
step_col: VERSION_STEP_ROLE,
|
||||
in_scene_col: PRODUCT_IN_SCENE_ROLE,
|
||||
sitesync_avail_col: VERSION_AVAILABLE_ROLE,
|
||||
|
||||
}
|
||||
|
||||
def __init__(self, controller):
|
||||
super(ProductsModel, self).__init__()
|
||||
|
|
@ -96,6 +124,7 @@ class ProductsModel(QtGui.QStandardItemModel):
|
|||
|
||||
self._last_project_name = None
|
||||
self._last_folder_ids = []
|
||||
self._last_project_statuses = {}
|
||||
|
||||
def get_product_item_indexes(self):
|
||||
return [
|
||||
|
|
@ -141,6 +170,15 @@ class ProductsModel(QtGui.QStandardItemModel):
|
|||
if not index.isValid():
|
||||
return None
|
||||
|
||||
if role in (VERSION_STATUS_SHORT_ROLE, VERSION_STATUS_COLOR_ROLE):
|
||||
status_name = self.data(index, VERSION_STATUS_NAME_ROLE)
|
||||
status_item = self._last_project_statuses.get(status_name)
|
||||
if status_item is None:
|
||||
return ""
|
||||
if role == VERSION_STATUS_SHORT_ROLE:
|
||||
return status_item.short
|
||||
return status_item.color
|
||||
|
||||
col = index.column()
|
||||
if col == 0:
|
||||
return super(ProductsModel, self).data(index, role)
|
||||
|
|
@ -168,29 +206,8 @@ class ProductsModel(QtGui.QStandardItemModel):
|
|||
if role == QtCore.Qt.DisplayRole:
|
||||
if not index.data(PRODUCT_ID_ROLE):
|
||||
return None
|
||||
if col == self.version_col:
|
||||
role = VERSION_NAME_ROLE
|
||||
elif col == 1:
|
||||
role = PRODUCT_TYPE_ROLE
|
||||
elif col == 2:
|
||||
role = FOLDER_LABEL_ROLE
|
||||
elif col == 4:
|
||||
role = VERSION_PUBLISH_TIME_ROLE
|
||||
elif col == 5:
|
||||
role = VERSION_AUTHOR_ROLE
|
||||
elif col == 6:
|
||||
role = VERSION_FRAME_RANGE_ROLE
|
||||
elif col == 7:
|
||||
role = VERSION_DURATION_ROLE
|
||||
elif col == 8:
|
||||
role = VERSION_HANDLES_ROLE
|
||||
elif col == 9:
|
||||
role = VERSION_STEP_ROLE
|
||||
elif col == 10:
|
||||
role = PRODUCT_IN_SCENE_ROLE
|
||||
elif col == 11:
|
||||
role = VERSION_AVAILABLE_ROLE
|
||||
else:
|
||||
role = self._display_role_mapping.get(col)
|
||||
if role is None:
|
||||
return None
|
||||
|
||||
index = self.index(index.row(), 0, index.parent())
|
||||
|
|
@ -312,6 +329,7 @@ class ProductsModel(QtGui.QStandardItemModel):
|
|||
version_item.published_time, VERSION_PUBLISH_TIME_ROLE
|
||||
)
|
||||
model_item.setData(version_item.author, VERSION_AUTHOR_ROLE)
|
||||
model_item.setData(version_item.status, VERSION_STATUS_NAME_ROLE)
|
||||
model_item.setData(version_item.frame_range, VERSION_FRAME_RANGE_ROLE)
|
||||
model_item.setData(version_item.duration, VERSION_DURATION_ROLE)
|
||||
model_item.setData(version_item.handles, VERSION_HANDLES_ROLE)
|
||||
|
|
@ -393,6 +411,11 @@ class ProductsModel(QtGui.QStandardItemModel):
|
|||
|
||||
self._last_project_name = project_name
|
||||
self._last_folder_ids = folder_ids
|
||||
status_items = self._controller.get_project_status_items(project_name)
|
||||
self._last_project_statuses = {
|
||||
status_item.name: status_item
|
||||
for status_item in status_items
|
||||
}
|
||||
|
||||
active_site_icon_def = self._controller.get_active_site_icon_def(
|
||||
project_name
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ from .products_model import (
|
|||
from .products_delegates import (
|
||||
VersionDelegate,
|
||||
LoadedInSceneDelegate,
|
||||
SiteSyncDelegate
|
||||
StatusDelegate,
|
||||
SiteSyncDelegate,
|
||||
)
|
||||
from .actions_utils import show_actions_menu
|
||||
|
||||
|
|
@ -89,6 +90,7 @@ class ProductsWidget(QtWidgets.QWidget):
|
|||
90, # Product type
|
||||
130, # Folder label
|
||||
60, # Version
|
||||
100, # Status
|
||||
125, # Time
|
||||
75, # Author
|
||||
75, # Frames
|
||||
|
|
@ -128,20 +130,19 @@ class ProductsWidget(QtWidgets.QWidget):
|
|||
products_view.setColumnWidth(idx, width)
|
||||
|
||||
version_delegate = VersionDelegate()
|
||||
products_view.setItemDelegateForColumn(
|
||||
products_model.version_col, version_delegate)
|
||||
|
||||
time_delegate = PrettyTimeDelegate()
|
||||
products_view.setItemDelegateForColumn(
|
||||
products_model.published_time_col, time_delegate)
|
||||
|
||||
status_delegate = StatusDelegate()
|
||||
in_scene_delegate = LoadedInSceneDelegate()
|
||||
products_view.setItemDelegateForColumn(
|
||||
products_model.in_scene_col, in_scene_delegate)
|
||||
|
||||
sitesync_delegate = SiteSyncDelegate()
|
||||
products_view.setItemDelegateForColumn(
|
||||
products_model.sitesync_avail_col, sitesync_delegate)
|
||||
|
||||
for col, delegate in (
|
||||
(products_model.version_col, version_delegate),
|
||||
(products_model.published_time_col, time_delegate),
|
||||
(products_model.status_col, status_delegate),
|
||||
(products_model.in_scene_col, in_scene_delegate),
|
||||
(products_model.sitesync_avail_col, sitesync_delegate),
|
||||
):
|
||||
products_view.setItemDelegateForColumn(col, delegate)
|
||||
|
||||
main_layout = QtWidgets.QHBoxLayout(self)
|
||||
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
|
@ -175,6 +176,7 @@ class ProductsWidget(QtWidgets.QWidget):
|
|||
|
||||
self._version_delegate = version_delegate
|
||||
self._time_delegate = time_delegate
|
||||
self._status_delegate = status_delegate
|
||||
self._in_scene_delegate = in_scene_delegate
|
||||
self._sitesync_delegate = sitesync_delegate
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ class PublishPluginsModel(BaseSettingsModel):
|
|||
)
|
||||
ValidateInstanceInContextHoudini: BasicValidateModel = SettingsField(
|
||||
default_factory=BasicValidateModel,
|
||||
title="Validate Instance is in same Context.")
|
||||
title="Validate Instance is in same Context.",
|
||||
section="Validators")
|
||||
ValidateMeshIsStatic: BasicValidateModel = SettingsField(
|
||||
default_factory=BasicValidateModel,
|
||||
title="Validate Mesh is Static.")
|
||||
|
|
|
|||
|
|
@ -354,7 +354,7 @@ def imprint(node, data, tab=None):
|
|||
Examples:
|
||||
```
|
||||
import nuke
|
||||
from ayon_core.hosts.nuke.api import lib
|
||||
from ayon_nuke.api import lib
|
||||
|
||||
node = nuke.createNode("NoOp")
|
||||
data = {
|
||||
|
|
@ -419,7 +419,7 @@ def add_publish_knob(node):
|
|||
return node
|
||||
|
||||
|
||||
@deprecated("ayon_core.hosts.nuke.api.lib.set_node_data")
|
||||
@deprecated("ayon_nuke.api.lib.set_node_data")
|
||||
def set_avalon_knob_data(node, data=None, prefix="avalon:"):
|
||||
"""[DEPRECATED] Sets data into nodes's avalon knob
|
||||
|
||||
|
|
@ -485,7 +485,7 @@ def set_avalon_knob_data(node, data=None, prefix="avalon:"):
|
|||
return node
|
||||
|
||||
|
||||
@deprecated("ayon_core.hosts.nuke.api.lib.get_node_data")
|
||||
@deprecated("ayon_nuke.api.lib.get_node_data")
|
||||
def get_avalon_knob_data(node, prefix="avalon:", create=True):
|
||||
"""[DEPRECATED] Gets a data from nodes's avalon knob
|
||||
|
||||
|
|
@ -1024,6 +1024,18 @@ def script_name():
|
|||
return nuke.root().knob("name").value()
|
||||
|
||||
|
||||
def add_button_render_on_farm(node):
|
||||
name = "renderOnFarm"
|
||||
label = "Render On Farm"
|
||||
value = (
|
||||
"from ayon_nuke.api.utils import submit_render_on_farm;"
|
||||
"submit_render_on_farm(nuke.thisNode())"
|
||||
)
|
||||
knob = nuke.PyScript_Knob(name, label, value)
|
||||
knob.clearFlag(nuke.STARTLINE)
|
||||
node.addKnob(knob)
|
||||
|
||||
|
||||
def add_button_write_to_read(node):
|
||||
name = "createReadNode"
|
||||
label = "Read From Rendered"
|
||||
|
|
@ -1146,6 +1158,17 @@ def create_write_node(
|
|||
Return:
|
||||
node (obj): group node with avalon data as Knobs
|
||||
'''
|
||||
# Ensure name does not contain any invalid characters.
|
||||
special_chars = re.escape("!@#$%^&*()=[]{}|\\;',.<>/?~+-")
|
||||
special_chars_regex = re.compile(f"[{special_chars}]")
|
||||
found_special_characters = list(special_chars_regex.findall(name))
|
||||
|
||||
msg = (
|
||||
f"Special characters found in name \"{name}\": "
|
||||
f"{' '.join(found_special_characters)}"
|
||||
)
|
||||
assert not found_special_characters, msg
|
||||
|
||||
prenodes = prenodes or []
|
||||
|
||||
# filtering variables
|
||||
|
|
@ -1270,6 +1293,10 @@ def create_write_node(
|
|||
link.setFlag(0x1000)
|
||||
GN.addKnob(link)
|
||||
|
||||
# Adding render farm submission button.
|
||||
if data.get("render_on_farm", False):
|
||||
add_button_render_on_farm(GN)
|
||||
|
||||
# adding write to read button
|
||||
add_button_write_to_read(GN)
|
||||
|
||||
|
|
@ -2442,7 +2469,7 @@ def _launch_workfile_app():
|
|||
host_tools.show_workfiles(parent=None, on_top=True)
|
||||
|
||||
|
||||
@deprecated("ayon_core.hosts.nuke.api.lib.start_workfile_template_builder")
|
||||
@deprecated("ayon_nuke.api.lib.start_workfile_template_builder")
|
||||
def process_workfile_builder():
|
||||
""" [DEPRECATED] Process workfile builder on nuke start
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ from ayon_core.pipeline import (
|
|||
)
|
||||
from ayon_core.pipeline.workfile import BuildWorkfile
|
||||
from ayon_core.tools.utils import host_tools
|
||||
from ayon_core.hosts.nuke import NUKE_ROOT_DIR
|
||||
from ayon_nuke import NUKE_ROOT_DIR
|
||||
from ayon_core.tools.workfile_template_build import open_template_ui
|
||||
|
||||
from .lib import (
|
||||
|
|
@ -188,10 +188,10 @@ def reload_config():
|
|||
"""
|
||||
|
||||
for module in (
|
||||
"ayon_core.hosts.nuke.api.actions",
|
||||
"ayon_core.hosts.nuke.api.menu",
|
||||
"ayon_core.hosts.nuke.api.plugin",
|
||||
"ayon_core.hosts.nuke.api.lib",
|
||||
"ayon_nuke.api.actions",
|
||||
"ayon_nuke.api.menu",
|
||||
"ayon_nuke.api.plugin",
|
||||
"ayon_nuke.api.lib",
|
||||
):
|
||||
log.info("Reloading module: {}...".format(module))
|
||||
|
||||
|
|
@ -572,8 +572,11 @@ class ExporterReview(object):
|
|||
self.fhead = self.fhead.replace("#", "")[:-1]
|
||||
|
||||
def get_representation_data(
|
||||
self, tags=None, range=False,
|
||||
custom_tags=None, colorspace=None
|
||||
self,
|
||||
tags=None,
|
||||
range=False,
|
||||
custom_tags=None,
|
||||
colorspace=None,
|
||||
):
|
||||
""" Add representation data to self.data
|
||||
|
||||
|
|
@ -584,6 +587,8 @@ class ExporterReview(object):
|
|||
Defaults to False.
|
||||
custom_tags (list[str], optional): user inputted custom tags.
|
||||
Defaults to None.
|
||||
colorspace (str, optional): colorspace name.
|
||||
Defaults to None.
|
||||
"""
|
||||
add_tags = tags or []
|
||||
repre = {
|
||||
|
|
@ -591,7 +596,13 @@ class ExporterReview(object):
|
|||
"ext": self.ext,
|
||||
"files": self.file,
|
||||
"stagingDir": self.staging_dir,
|
||||
"tags": [self.name.replace("_", "-")] + add_tags
|
||||
"tags": [self.name.replace("_", "-")] + add_tags,
|
||||
"data": {
|
||||
# making sure that once intermediate file is published
|
||||
# as representation, we will be able to then identify it
|
||||
# from representation.data.isIntermediate
|
||||
"isIntermediate": True
|
||||
},
|
||||
}
|
||||
|
||||
if custom_tags:
|
||||
|
|
@ -837,7 +848,8 @@ class ExporterReviewMov(ExporterReview):
|
|||
|
||||
def generate_mov(self, farm=False, delete=True, **kwargs):
|
||||
# colorspace data
|
||||
colorspace = None
|
||||
colorspace = self.write_colorspace
|
||||
|
||||
# get colorspace settings
|
||||
# get colorspace data from context
|
||||
config_data, _ = get_colorspace_settings_from_publish_context(
|
||||
|
|
@ -999,7 +1011,7 @@ class ExporterReviewMov(ExporterReview):
|
|||
tags=tags + add_tags,
|
||||
custom_tags=add_custom_tags,
|
||||
range=True,
|
||||
colorspace=colorspace
|
||||
colorspace=colorspace,
|
||||
)
|
||||
|
||||
self.log.debug("Representation... `{}`".format(self.data))
|
||||
|
|
@ -1038,7 +1050,7 @@ def convert_to_valid_instaces():
|
|||
}
|
||||
return mapping[product_type]
|
||||
|
||||
from ayon_core.hosts.nuke.api import workio
|
||||
from ayon_nuke.api import workio
|
||||
|
||||
task_name = get_current_task_name()
|
||||
|
||||
|
|
@ -3,9 +3,15 @@ import re
|
|||
|
||||
import nuke
|
||||
|
||||
from ayon_core import resources
|
||||
import pyblish.util
|
||||
import pyblish.api
|
||||
from qtpy import QtWidgets
|
||||
|
||||
from ayon_core import resources
|
||||
from ayon_core.pipeline import registered_host
|
||||
from ayon_core.tools.utils import show_message_dialog
|
||||
from ayon_core.pipeline.create import CreateContext
|
||||
|
||||
|
||||
def set_context_favorites(favorites=None):
|
||||
""" Adding favorite folders to nuke's browser
|
||||
|
|
@ -142,3 +148,77 @@ def is_headless():
|
|||
bool: headless
|
||||
"""
|
||||
return QtWidgets.QApplication.instance() is None
|
||||
|
||||
|
||||
def submit_render_on_farm(node):
|
||||
# Ensure code is executed in root context.
|
||||
if nuke.root() == nuke.thisNode():
|
||||
_submit_render_on_farm(node)
|
||||
else:
|
||||
# If not in root context, move to the root context and then execute the
|
||||
# code.
|
||||
with nuke.root():
|
||||
_submit_render_on_farm(node)
|
||||
|
||||
|
||||
def _submit_render_on_farm(node):
|
||||
"""Render on farm submission
|
||||
|
||||
This function prepares the context for farm submission, validates it,
|
||||
extracts relevant data, copies the current workfile to a timestamped copy,
|
||||
and submits the job to the farm.
|
||||
|
||||
Args:
|
||||
node (Node): The node for which the farm submission is being made.
|
||||
"""
|
||||
|
||||
host = registered_host()
|
||||
create_context = CreateContext(host)
|
||||
|
||||
# Ensure CreateInstance is enabled.
|
||||
for instance in create_context.instances:
|
||||
if node.name() != instance.transient_data["node"].name():
|
||||
continue
|
||||
|
||||
instance.data["active"] = True
|
||||
|
||||
context = pyblish.api.Context()
|
||||
context.data["create_context"] = create_context
|
||||
# Used in pyblish plugin to determine which instance to publish.
|
||||
context.data["node_name"] = node.name()
|
||||
# Used in pyblish plugins to determine whether to run or not.
|
||||
context.data["render_on_farm"] = True
|
||||
|
||||
# Since we need to bypass version validation and incrementing, we need to
|
||||
# remove the plugins from the list that are responsible for these tasks.
|
||||
plugins = pyblish.api.discover()
|
||||
blacklist = ["IncrementScriptVersion", "ValidateVersion"]
|
||||
plugins = [
|
||||
plugin
|
||||
for plugin in plugins
|
||||
if plugin.__name__ not in blacklist
|
||||
]
|
||||
|
||||
context = pyblish.util.publish(context, plugins=plugins)
|
||||
|
||||
error_message = ""
|
||||
success = True
|
||||
for result in context.data["results"]:
|
||||
if result["success"]:
|
||||
continue
|
||||
|
||||
success = False
|
||||
|
||||
err = result["error"]
|
||||
error_message += "\n"
|
||||
error_message += err.formatted_traceback
|
||||
|
||||
if not success:
|
||||
show_message_dialog(
|
||||
"Publish Errors", error_message, level="critical"
|
||||
)
|
||||
return
|
||||
|
||||
show_message_dialog(
|
||||
"Submission Successful", "Submission to the farm was successful."
|
||||
)
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
from ayon_core.pipeline import AYON_INSTANCE_ID, AVALON_INSTANCE_ID
|
||||
from ayon_core.pipeline.create.creator_plugins import ProductConvertorPlugin
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
INSTANCE_DATA_KNOB,
|
||||
get_node_data,
|
||||
get_avalon_knob_data,
|
||||
NODE_TAB_NAME,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.plugin import convert_to_valid_instaces
|
||||
from ayon_nuke.api.plugin import convert_to_valid_instaces
|
||||
|
||||
import nuke
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
from nukescripts import autoBackdrop
|
||||
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
NukeCreator,
|
||||
maintained_selection,
|
||||
select_nodes
|
||||
|
|
@ -10,6 +10,8 @@ from ayon_core.hosts.nuke.api import (
|
|||
class CreateBackdrop(NukeCreator):
|
||||
"""Add Publishable Backdrop"""
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
identifier = "create_backdrop"
|
||||
label = "Nukenodes (backdrop)"
|
||||
product_type = "nukenodes"
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import nuke
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
NukeCreator,
|
||||
NukeCreatorError,
|
||||
maintained_selection
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
create_camera_node_by_version
|
||||
)
|
||||
|
||||
|
|
@ -12,6 +12,8 @@ from ayon_core.hosts.nuke.api.lib import (
|
|||
class CreateCamera(NukeCreator):
|
||||
"""Add Publishable Camera"""
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
identifier = "create_camera"
|
||||
label = "Camera (3d)"
|
||||
product_type = "camera"
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import nuke
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
NukeCreator,
|
||||
NukeCreatorError,
|
||||
maintained_selection
|
||||
|
|
@ -9,6 +9,8 @@ from ayon_core.hosts.nuke.api import (
|
|||
class CreateGizmo(NukeCreator):
|
||||
"""Add Publishable Group as gizmo"""
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
identifier = "create_gizmo"
|
||||
label = "Gizmo (group)"
|
||||
product_type = "gizmo"
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import nuke
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
NukeCreator,
|
||||
NukeCreatorError,
|
||||
maintained_selection
|
||||
|
|
@ -9,6 +9,8 @@ from ayon_core.hosts.nuke.api import (
|
|||
class CreateModel(NukeCreator):
|
||||
"""Add Publishable Camera"""
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
identifier = "create_model"
|
||||
label = "Model (3d)"
|
||||
product_type = "model"
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import nuke
|
||||
import six
|
||||
import sys
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
INSTANCE_DATA_KNOB,
|
||||
NukeCreator,
|
||||
NukeCreatorError,
|
||||
|
|
@ -15,6 +15,8 @@ from ayon_core.pipeline import (
|
|||
class CreateSource(NukeCreator):
|
||||
"""Add Publishable Read with source"""
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
identifier = "create_source"
|
||||
label = "Source (read)"
|
||||
product_type = "source"
|
||||
|
|
@ -11,11 +11,14 @@ from ayon_core.lib import (
|
|||
UISeparatorDef,
|
||||
EnumDef
|
||||
)
|
||||
from ayon_core.hosts.nuke import api as napi
|
||||
from ayon_core.hosts.nuke.api.plugin import exposed_write_knobs
|
||||
from ayon_nuke import api as napi
|
||||
from ayon_nuke.api.plugin import exposed_write_knobs
|
||||
|
||||
|
||||
class CreateWriteImage(napi.NukeWriteCreator):
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
identifier = "create_write_image"
|
||||
label = "Image (write)"
|
||||
product_type = "image"
|
||||
|
|
@ -65,12 +68,16 @@ class CreateWriteImage(napi.NukeWriteCreator):
|
|||
)
|
||||
|
||||
def create_instance_node(self, product_name, instance_data):
|
||||
settings = self.project_settings["nuke"]["create"]["CreateWriteImage"]
|
||||
|
||||
# add fpath_template
|
||||
write_data = {
|
||||
"creator": self.__class__.__name__,
|
||||
"productName": product_name,
|
||||
"fpath_template": self.temp_rendering_path_template
|
||||
"fpath_template": self.temp_rendering_path_template,
|
||||
"render_on_farm": (
|
||||
"render_on_farm" in settings["instance_attributes"]
|
||||
)
|
||||
}
|
||||
write_data.update(instance_data)
|
||||
|
||||
|
|
@ -8,11 +8,14 @@ from ayon_core.pipeline import (
|
|||
from ayon_core.lib import (
|
||||
BoolDef
|
||||
)
|
||||
from ayon_core.hosts.nuke import api as napi
|
||||
from ayon_core.hosts.nuke.api.plugin import exposed_write_knobs
|
||||
from ayon_nuke import api as napi
|
||||
from ayon_nuke.api.plugin import exposed_write_knobs
|
||||
|
||||
|
||||
class CreateWritePrerender(napi.NukeWriteCreator):
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
identifier = "create_write_prerender"
|
||||
label = "Prerender (write)"
|
||||
product_type = "prerender"
|
||||
|
|
@ -46,11 +49,17 @@ class CreateWritePrerender(napi.NukeWriteCreator):
|
|||
return attr_defs
|
||||
|
||||
def create_instance_node(self, product_name, instance_data):
|
||||
settings = self.project_settings["nuke"]["create"]
|
||||
settings = settings["CreateWritePrerender"]
|
||||
|
||||
# add fpath_template
|
||||
write_data = {
|
||||
"creator": self.__class__.__name__,
|
||||
"productName": product_name,
|
||||
"fpath_template": self.temp_rendering_path_template
|
||||
"fpath_template": self.temp_rendering_path_template,
|
||||
"render_on_farm": (
|
||||
"render_on_farm" in settings["instance_attributes"]
|
||||
)
|
||||
}
|
||||
|
||||
write_data.update(instance_data)
|
||||
|
|
@ -8,11 +8,14 @@ from ayon_core.pipeline import (
|
|||
from ayon_core.lib import (
|
||||
BoolDef
|
||||
)
|
||||
from ayon_core.hosts.nuke import api as napi
|
||||
from ayon_core.hosts.nuke.api.plugin import exposed_write_knobs
|
||||
from ayon_nuke import api as napi
|
||||
from ayon_nuke.api.plugin import exposed_write_knobs
|
||||
|
||||
|
||||
class CreateWriteRender(napi.NukeWriteCreator):
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
identifier = "create_write_render"
|
||||
label = "Render (write)"
|
||||
product_type = "render"
|
||||
|
|
@ -40,11 +43,16 @@ class CreateWriteRender(napi.NukeWriteCreator):
|
|||
return attr_defs
|
||||
|
||||
def create_instance_node(self, product_name, instance_data):
|
||||
settings = self.project_settings["nuke"]["create"]["CreateWriteRender"]
|
||||
|
||||
# add fpath_template
|
||||
write_data = {
|
||||
"creator": self.__class__.__name__,
|
||||
"productName": product_name,
|
||||
"fpath_template": self.temp_rendering_path_template
|
||||
"fpath_template": self.temp_rendering_path_template,
|
||||
"render_on_farm": (
|
||||
"render_on_farm" in settings["instance_attributes"]
|
||||
)
|
||||
}
|
||||
|
||||
write_data.update(instance_data)
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
import ayon_api
|
||||
|
||||
import ayon_core.hosts.nuke.api as api
|
||||
import ayon_nuke.api as api
|
||||
from ayon_core.pipeline import (
|
||||
AutoCreator,
|
||||
CreatedInstance,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
INSTANCE_DATA_KNOB,
|
||||
set_node_data
|
||||
)
|
||||
|
|
@ -13,6 +13,9 @@ import nuke
|
|||
|
||||
|
||||
class WorkfileCreator(AutoCreator):
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
identifier = "workfile"
|
||||
product_type = "workfile"
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
from ayon_core.lib import Logger
|
||||
from ayon_core.pipeline import InventoryAction
|
||||
from ayon_core.hosts.nuke.api.lib import set_avalon_knob_data
|
||||
from ayon_nuke.api.lib import set_avalon_knob_data
|
||||
|
||||
|
||||
class RepairOldLoaders(InventoryAction):
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
from ayon_core.pipeline import InventoryAction
|
||||
from ayon_core.hosts.nuke.api.command import viewer_update_and_undo_stop
|
||||
from ayon_nuke.api.command import viewer_update_and_undo_stop
|
||||
|
||||
|
||||
class SelectContainers(InventoryAction):
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
from ayon_core.lib import Logger
|
||||
from ayon_core.pipeline import load
|
||||
from ayon_core.hosts.nuke.api import lib
|
||||
from ayon_nuke.api import lib
|
||||
|
||||
log = Logger.get_logger(__name__)
|
||||
|
||||
|
|
@ -6,7 +6,7 @@ from ayon_core.pipeline import (
|
|||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
find_free_space_to_paste_nodes,
|
||||
maintained_selection,
|
||||
reset_selection,
|
||||
|
|
@ -14,8 +14,8 @@ from ayon_core.hosts.nuke.api.lib import (
|
|||
get_avalon_knob_data,
|
||||
set_avalon_knob_data
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.command import viewer_update_and_undo_stop
|
||||
from ayon_core.hosts.nuke.api import containerise, update_container
|
||||
from ayon_nuke.api.command import viewer_update_and_undo_stop
|
||||
from ayon_nuke.api import containerise, update_container
|
||||
|
||||
|
||||
class LoadBackdropNodes(load.LoaderPlugin):
|
||||
|
|
@ -25,6 +25,8 @@ class LoadBackdropNodes(load.LoaderPlugin):
|
|||
representations = {"*"}
|
||||
extensions = {"nk"}
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
label = "Import Nuke Nodes"
|
||||
order = 0
|
||||
icon = "eye"
|
||||
|
|
@ -5,12 +5,12 @@ from ayon_core.pipeline import (
|
|||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
containerise,
|
||||
update_container,
|
||||
viewer_update_and_undo_stop
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
maintained_selection
|
||||
)
|
||||
|
||||
|
|
@ -24,6 +24,8 @@ class AlembicCameraLoader(load.LoaderPlugin):
|
|||
representations = {"*"}
|
||||
extensions = {"abc"}
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
label = "Load Alembic Camera"
|
||||
icon = "camera"
|
||||
color = "orange"
|
||||
|
|
@ -12,11 +12,11 @@ from ayon_core.pipeline.colorspace import (
|
|||
get_imageio_file_rules_colorspace_from_filepath,
|
||||
get_current_context_imageio_config_preset,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
get_imageio_input_colorspace,
|
||||
maintained_selection
|
||||
)
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
containerise,
|
||||
update_container,
|
||||
viewer_update_and_undo_stop,
|
||||
|
|
@ -26,7 +26,7 @@ from ayon_core.lib.transcoding import (
|
|||
VIDEO_EXTENSIONS,
|
||||
IMAGE_EXTENSIONS
|
||||
)
|
||||
from ayon_core.hosts.nuke.api import plugin
|
||||
from ayon_nuke.api import plugin
|
||||
|
||||
|
||||
class LoadClip(plugin.NukeLoader):
|
||||
|
|
@ -48,6 +48,8 @@ class LoadClip(plugin.NukeLoader):
|
|||
ext.lstrip(".") for ext in IMAGE_EXTENSIONS.union(VIDEO_EXTENSIONS)
|
||||
)
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
label = "Load Clip"
|
||||
order = -20
|
||||
icon = "file-video-o"
|
||||
|
|
@ -61,7 +63,8 @@ class LoadClip(plugin.NukeLoader):
|
|||
# option gui
|
||||
options_defaults = {
|
||||
"start_at_workfile": True,
|
||||
"add_retime": True
|
||||
"add_retime": True,
|
||||
"deep_exr": False
|
||||
}
|
||||
|
||||
node_name_template = "{class_name}_{ext}"
|
||||
|
|
@ -78,6 +81,11 @@ class LoadClip(plugin.NukeLoader):
|
|||
"add_retime",
|
||||
help="Load with retime",
|
||||
default=cls.options_defaults["add_retime"]
|
||||
),
|
||||
qargparse.Boolean(
|
||||
"deep_exr",
|
||||
help="Read with deep exr",
|
||||
default=cls.options_defaults["deep_exr"]
|
||||
)
|
||||
]
|
||||
|
||||
|
|
@ -113,6 +121,9 @@ class LoadClip(plugin.NukeLoader):
|
|||
add_retime = options.get(
|
||||
"add_retime", self.options_defaults["add_retime"])
|
||||
|
||||
deep_exr = options.get(
|
||||
"deep_exr", self.options_defaults["deep_exr"])
|
||||
|
||||
repre_id = repre_entity["id"]
|
||||
|
||||
self.log.debug(
|
||||
|
|
@ -153,13 +164,21 @@ class LoadClip(plugin.NukeLoader):
|
|||
return
|
||||
|
||||
read_name = self._get_node_name(context)
|
||||
|
||||
# Create the Loader with the filename path set
|
||||
read_node = nuke.createNode(
|
||||
"Read",
|
||||
"name {}".format(read_name),
|
||||
inpanel=False
|
||||
)
|
||||
read_node = None
|
||||
if deep_exr:
|
||||
# Create the Loader with the filename path set
|
||||
read_node = nuke.createNode(
|
||||
"DeepRead",
|
||||
"name {}".format(read_name),
|
||||
inpanel=False
|
||||
)
|
||||
else:
|
||||
# Create the Loader with the filename path set
|
||||
read_node = nuke.createNode(
|
||||
"Read",
|
||||
"name {}".format(read_name),
|
||||
inpanel=False
|
||||
)
|
||||
|
||||
# get colorspace
|
||||
colorspace = (
|
||||
|
|
@ -171,14 +190,14 @@ class LoadClip(plugin.NukeLoader):
|
|||
# we will switch off undo-ing
|
||||
with viewer_update_and_undo_stop():
|
||||
read_node["file"].setValue(filepath)
|
||||
|
||||
self.set_colorspace_to_node(
|
||||
read_node,
|
||||
filepath,
|
||||
project_name,
|
||||
version_entity,
|
||||
repre_entity
|
||||
)
|
||||
if read_node.Class() == "Read":
|
||||
self.set_colorspace_to_node(
|
||||
read_node,
|
||||
filepath,
|
||||
project_name,
|
||||
version_entity,
|
||||
repre_entity
|
||||
)
|
||||
|
||||
self._set_range_to_node(
|
||||
read_node, first, last, start_at_workfile, slate_frames
|
||||
|
|
@ -328,13 +347,14 @@ class LoadClip(plugin.NukeLoader):
|
|||
# to avoid multiple undo steps for rest of process
|
||||
# we will switch off undo-ing
|
||||
with viewer_update_and_undo_stop():
|
||||
self.set_colorspace_to_node(
|
||||
read_node,
|
||||
filepath,
|
||||
project_name,
|
||||
version_entity,
|
||||
repre_entity
|
||||
)
|
||||
if read_node.Class() == "Read":
|
||||
self.set_colorspace_to_node(
|
||||
read_node,
|
||||
filepath,
|
||||
project_name,
|
||||
version_entity,
|
||||
repre_entity
|
||||
)
|
||||
|
||||
self._set_range_to_node(read_node, first, last, start_at_workfile)
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ from ayon_core.pipeline import (
|
|||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
containerise,
|
||||
update_container,
|
||||
viewer_update_and_undo_stop
|
||||
|
|
@ -22,13 +22,14 @@ class LoadEffects(load.LoaderPlugin):
|
|||
representations = {"*"}
|
||||
extensions = {"json"}
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
label = "Load Effects - nodes"
|
||||
order = 0
|
||||
icon = "cc"
|
||||
color = "white"
|
||||
ignore_attr = ["useLifetime"]
|
||||
|
||||
|
||||
def load(self, context, name, namespace, data):
|
||||
"""
|
||||
Loading function to get the soft effects to particular read node
|
||||
|
|
@ -8,8 +8,8 @@ from ayon_core.pipeline import (
|
|||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api import lib
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import lib
|
||||
from ayon_nuke.api import (
|
||||
containerise,
|
||||
update_container,
|
||||
viewer_update_and_undo_stop
|
||||
|
|
@ -23,6 +23,8 @@ class LoadEffectsInputProcess(load.LoaderPlugin):
|
|||
representations = {"*"}
|
||||
extensions = {"json"}
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
label = "Load Effects - Input Process"
|
||||
order = 0
|
||||
icon = "eye"
|
||||
|
|
@ -5,13 +5,13 @@ from ayon_core.pipeline import (
|
|||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
maintained_selection,
|
||||
get_avalon_knob_data,
|
||||
set_avalon_knob_data,
|
||||
swap_node_with_dependency,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
containerise,
|
||||
update_container,
|
||||
viewer_update_and_undo_stop
|
||||
|
|
@ -25,6 +25,8 @@ class LoadGizmo(load.LoaderPlugin):
|
|||
representations = {"*"}
|
||||
extensions = {"nk"}
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
label = "Load Gizmo"
|
||||
order = 0
|
||||
icon = "dropbox"
|
||||
|
|
@ -6,14 +6,14 @@ from ayon_core.pipeline import (
|
|||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
maintained_selection,
|
||||
create_backdrop,
|
||||
get_avalon_knob_data,
|
||||
set_avalon_knob_data,
|
||||
swap_node_with_dependency,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
containerise,
|
||||
update_container,
|
||||
viewer_update_and_undo_stop
|
||||
|
|
@ -27,6 +27,8 @@ class LoadGizmoInputProcess(load.LoaderPlugin):
|
|||
representations = {"*"}
|
||||
extensions = {"nk"}
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
label = "Load Gizmo - Input Process"
|
||||
order = 0
|
||||
icon = "eye"
|
||||
|
|
@ -7,10 +7,10 @@ from ayon_core.pipeline import (
|
|||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
get_imageio_input_colorspace
|
||||
)
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
containerise,
|
||||
update_container,
|
||||
viewer_update_and_undo_stop
|
||||
|
|
@ -33,9 +33,9 @@ class LoadImage(load.LoaderPlugin):
|
|||
"image",
|
||||
}
|
||||
representations = {"*"}
|
||||
extensions = set(
|
||||
ext.lstrip(".") for ext in IMAGE_EXTENSIONS
|
||||
)
|
||||
extensions = set(ext.lstrip(".") for ext in IMAGE_EXTENSIONS)
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
label = "Load Image"
|
||||
order = -10
|
||||
|
|
@ -11,6 +11,8 @@ class MatchmoveLoader(load.LoaderPlugin):
|
|||
representations = {"*"}
|
||||
extensions = {"py"}
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
defaults = ["Camera", "Object"]
|
||||
|
||||
label = "Run matchmove script"
|
||||
|
|
@ -5,8 +5,8 @@ from ayon_core.pipeline import (
|
|||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.lib import maintained_selection
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api.lib import maintained_selection
|
||||
from ayon_nuke.api import (
|
||||
containerise,
|
||||
update_container,
|
||||
viewer_update_and_undo_stop
|
||||
|
|
@ -22,6 +22,8 @@ class AlembicModelLoader(load.LoaderPlugin):
|
|||
representations = {"*"}
|
||||
extensions = {"abc"}
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
label = "Load Alembic"
|
||||
icon = "cube"
|
||||
color = "orange"
|
||||
|
|
@ -10,7 +10,7 @@ from ayon_core.pipeline import (
|
|||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
containerise,
|
||||
viewer_update_and_undo_stop,
|
||||
update_container,
|
||||
|
|
@ -24,6 +24,8 @@ class LoadOcioLookNodes(load.LoaderPlugin):
|
|||
representations = {"*"}
|
||||
extensions = {"json"}
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
label = "Load OcioLook [nodes]"
|
||||
order = 0
|
||||
icon = "cc"
|
||||
|
|
@ -5,8 +5,8 @@ from ayon_core.pipeline import (
|
|||
load,
|
||||
get_representation_path,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.lib import get_avalon_knob_data
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api.lib import get_avalon_knob_data
|
||||
from ayon_nuke.api import (
|
||||
containerise,
|
||||
update_container,
|
||||
viewer_update_and_undo_stop
|
||||
|
|
@ -20,6 +20,8 @@ class LinkAsGroup(load.LoaderPlugin):
|
|||
representations = {"*"}
|
||||
extensions = {"nk"}
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
label = "Load Precomp"
|
||||
order = 0
|
||||
icon = "file"
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
from pprint import pformat
|
||||
import pyblish.api
|
||||
from ayon_core.hosts.nuke.api import lib as pnlib
|
||||
from ayon_nuke.api import lib as pnlib
|
||||
import nuke
|
||||
|
||||
|
||||
|
|
@ -13,6 +13,8 @@ class CollectBackdrops(pyblish.api.InstancePlugin):
|
|||
hosts = ["nuke"]
|
||||
families = ["nukenodes"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
self.log.debug(pformat(instance.data))
|
||||
|
||||
|
|
@ -2,7 +2,7 @@ import os
|
|||
import nuke
|
||||
import pyblish.api
|
||||
from ayon_core.lib import get_version_from_path
|
||||
import ayon_core.hosts.nuke.api as napi
|
||||
import ayon_nuke.api as napi
|
||||
from ayon_core.pipeline import KnownPublishError
|
||||
|
||||
|
||||
|
|
@ -13,6 +13,8 @@ class CollectContextData(pyblish.api.ContextPlugin):
|
|||
label = "Collect context data"
|
||||
hosts = ['nuke']
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, context): # sourcery skip: avoid-builtin-shadow
|
||||
root_node = nuke.root()
|
||||
|
||||
|
|
@ -13,5 +13,7 @@ class CollectFramerate(pyblish.api.ContextPlugin):
|
|||
"nukeassist"
|
||||
]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, context):
|
||||
context.data["fps"] = nuke.root()["fps"].getValue()
|
||||
|
|
@ -11,6 +11,8 @@ class CollectGizmo(pyblish.api.InstancePlugin):
|
|||
hosts = ["nuke"]
|
||||
families = ["gizmo"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
gizmo_node = instance.data["transientData"]["node"]
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import pyblish.api
|
||||
|
||||
from ayon_core.pipeline.publish import (
|
||||
AYONPyblishPluginMixin
|
||||
)
|
||||
|
||||
|
||||
class CollectRenderOnFarm(pyblish.api.ContextPlugin):
|
||||
"""Setup instances for render on farm submission."""
|
||||
|
||||
# Needs to be after CollectFromCreateContext
|
||||
order = pyblish.api.CollectorOrder - 0.49
|
||||
label = "Collect Render On Farm"
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, context):
|
||||
if not context.data.get("render_on_farm", False):
|
||||
return
|
||||
|
||||
for instance in context:
|
||||
if instance.data["family"] == "workfile":
|
||||
instance.data["active"] = False
|
||||
continue
|
||||
|
||||
# Filter out all other instances.
|
||||
node = instance.data["transientData"]["node"]
|
||||
if node.name() != instance.context.data["node_name"]:
|
||||
instance.data["active"] = False
|
||||
continue
|
||||
|
||||
instance.data["families"].append("render_on_farm")
|
||||
|
||||
# Enable for farm publishing.
|
||||
instance.data["farm"] = True
|
||||
|
||||
# Skip workfile version incremental save.
|
||||
instance.context.data["increment_script_version"] = False
|
||||
|
||||
|
||||
class SetupRenderOnFarm(pyblish.api.InstancePlugin, AYONPyblishPluginMixin):
|
||||
"""Setup instance for render on farm submission."""
|
||||
|
||||
order = pyblish.api.CollectorOrder + 0.4999
|
||||
label = "Setup Render On Farm"
|
||||
hosts = ["nuke"]
|
||||
families = ["render_on_farm"]
|
||||
|
||||
def process(self, instance):
|
||||
# Clear the families as we only want the main family, ei. no review
|
||||
# etc.
|
||||
instance.data["families"] = ["render_on_farm"]
|
||||
|
||||
# Use the workfile instead of published.
|
||||
publish_attributes = instance.data["publish_attributes"]
|
||||
plugin_attributes = publish_attributes["NukeSubmitDeadline"]
|
||||
plugin_attributes["use_published_workfile"] = False
|
||||
|
|
@ -11,6 +11,8 @@ class CollectModel(pyblish.api.InstancePlugin):
|
|||
hosts = ["nuke"]
|
||||
families = ["model"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
geo_node = instance.data["transientData"]["node"]
|
||||
|
|
@ -11,6 +11,8 @@ class CollectInstanceData(pyblish.api.InstancePlugin):
|
|||
label = "Collect Nuke Instance Data"
|
||||
hosts = ["nuke", "nukeassist"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
# presets
|
||||
sync_workfile_version_on_families = []
|
||||
|
||||
|
|
@ -12,6 +12,8 @@ class CollectNukeReads(pyblish.api.InstancePlugin):
|
|||
hosts = ["nuke", "nukeassist"]
|
||||
families = ["source"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
self.log.debug("checking instance: {}".format(instance))
|
||||
|
||||
|
|
@ -10,6 +10,8 @@ class CollectSlate(pyblish.api.InstancePlugin):
|
|||
hosts = ["nuke"]
|
||||
families = ["render"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
node = instance.data["transientData"]["node"]
|
||||
|
||||
|
|
@ -11,6 +11,8 @@ class CollectWorkfile(pyblish.api.InstancePlugin):
|
|||
hosts = ['nuke']
|
||||
families = ["workfile"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance): # sourcery skip: avoid-builtin-shadow
|
||||
|
||||
script_data = instance.context.data["scriptData"]
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import os
|
||||
import nuke
|
||||
import pyblish.api
|
||||
from ayon_core.hosts.nuke import api as napi
|
||||
from ayon_nuke import api as napi
|
||||
from ayon_core.pipeline import publish
|
||||
|
||||
|
||||
|
|
@ -14,6 +14,8 @@ class CollectNukeWrites(pyblish.api.InstancePlugin,
|
|||
hosts = ["nuke", "nukeassist"]
|
||||
families = ["render", "prerender", "image"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
# cache
|
||||
_write_nodes = {}
|
||||
_frame_ranges = {}
|
||||
|
|
@ -5,7 +5,7 @@ import nuke
|
|||
import pyblish.api
|
||||
|
||||
from ayon_core.pipeline import publish
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
maintained_selection,
|
||||
reset_selection,
|
||||
select_nodes
|
||||
|
|
@ -25,6 +25,8 @@ class ExtractBackdropNode(publish.Extractor):
|
|||
hosts = ["nuke"]
|
||||
families = ["nukenodes"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
tmp_nodes = []
|
||||
child_nodes = instance.data["transientData"]["childNodes"]
|
||||
|
|
@ -6,7 +6,7 @@ import nuke
|
|||
import pyblish.api
|
||||
|
||||
from ayon_core.pipeline import publish
|
||||
from ayon_core.hosts.nuke.api.lib import maintained_selection
|
||||
from ayon_nuke.api.lib import maintained_selection
|
||||
|
||||
|
||||
class ExtractCamera(publish.Extractor):
|
||||
|
|
@ -17,6 +17,8 @@ class ExtractCamera(publish.Extractor):
|
|||
families = ["camera"]
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
# presets
|
||||
write_geo_knobs = [
|
||||
("file_type", "abc"),
|
||||
|
|
@ -4,8 +4,8 @@ import nuke
|
|||
import pyblish.api
|
||||
|
||||
from ayon_core.pipeline import publish
|
||||
from ayon_core.hosts.nuke.api import utils as pnutils
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api import utils as pnutils
|
||||
from ayon_nuke.api.lib import (
|
||||
maintained_selection,
|
||||
reset_selection,
|
||||
select_nodes
|
||||
|
|
@ -23,6 +23,8 @@ class ExtractGizmo(publish.Extractor):
|
|||
hosts = ["nuke"]
|
||||
families = ["gizmo"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
tmp_nodes = []
|
||||
orig_grpn = instance.data["transientData"]["node"]
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import os
|
||||
from datetime import datetime
|
||||
import shutil
|
||||
|
||||
import pyblish.api
|
||||
|
||||
from ayon_core.pipeline import registered_host
|
||||
|
||||
|
||||
class ExtractRenderOnFarm(pyblish.api.InstancePlugin):
|
||||
"""Copy the workfile to a timestamped copy."""
|
||||
|
||||
order = pyblish.api.ExtractorOrder + 0.499
|
||||
label = "Extract Render On Farm"
|
||||
hosts = ["nuke"]
|
||||
families = ["render_on_farm"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
if not instance.context.data.get("render_on_farm", False):
|
||||
return
|
||||
|
||||
host = registered_host()
|
||||
current_datetime = datetime.now()
|
||||
formatted_timestamp = current_datetime.strftime("%Y%m%d%H%M%S")
|
||||
base, ext = os.path.splitext(host.current_file())
|
||||
|
||||
directory = os.path.join(os.path.dirname(base), "farm_submissions")
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
filename = "{}_{}{}".format(
|
||||
os.path.basename(base), formatted_timestamp, ext
|
||||
)
|
||||
path = os.path.join(directory, filename).replace("\\", "/")
|
||||
instance.context.data["currentFile"] = path
|
||||
shutil.copy(host.current_file(), path)
|
||||
|
|
@ -4,7 +4,7 @@ import nuke
|
|||
import pyblish.api
|
||||
|
||||
from ayon_core.pipeline import publish
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
maintained_selection,
|
||||
select_nodes
|
||||
)
|
||||
|
|
@ -18,6 +18,8 @@ class ExtractModel(publish.Extractor):
|
|||
families = ["model"]
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
# presets
|
||||
write_geo_knobs = [
|
||||
("file_type", "abc"),
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import nuke
|
||||
import pyblish.api
|
||||
from ayon_core.hosts.nuke.api.lib import maintained_selection
|
||||
from ayon_nuke.api.lib import maintained_selection
|
||||
|
||||
|
||||
class CreateOutputNode(pyblish.api.ContextPlugin):
|
||||
|
|
@ -11,7 +11,9 @@ class CreateOutputNode(pyblish.api.ContextPlugin):
|
|||
label = 'Output Node Create'
|
||||
order = pyblish.api.ExtractorOrder + 0.4
|
||||
families = ["workfile"]
|
||||
hosts = ['nuke']
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, context):
|
||||
# capture selection state
|
||||
|
|
@ -10,7 +10,7 @@ class ExtractOutputDirectory(pyblish.api.InstancePlugin):
|
|||
label = "Output Directory"
|
||||
optional = True
|
||||
|
||||
# targets = ["process"]
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
|
|
@ -4,7 +4,7 @@ import shutil
|
|||
import pyblish.api
|
||||
import clique
|
||||
import nuke
|
||||
from ayon_core.hosts.nuke import api as napi
|
||||
from ayon_nuke import api as napi
|
||||
from ayon_core.pipeline import publish
|
||||
from ayon_core.lib import collect_frames
|
||||
|
||||
|
|
@ -25,6 +25,8 @@ class NukeRenderLocal(publish.Extractor,
|
|||
hosts = ["nuke"]
|
||||
families = ["render.local", "prerender.local", "image.local"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
child_nodes = (
|
||||
instance.data.get("transientData", {}).get("childNodes")
|
||||
|
|
@ -16,6 +16,8 @@ class ExtractReviewData(publish.Extractor):
|
|||
families = ["review"]
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
fpath = instance.data["path"]
|
||||
ext = os.path.splitext(fpath)[-1][1:]
|
||||
|
|
@ -2,8 +2,8 @@ import os
|
|||
import pyblish.api
|
||||
|
||||
from ayon_core.pipeline import publish
|
||||
from ayon_core.hosts.nuke.api import plugin
|
||||
from ayon_core.hosts.nuke.api.lib import maintained_selection
|
||||
from ayon_nuke.api import plugin
|
||||
from ayon_nuke.api.lib import maintained_selection
|
||||
|
||||
|
||||
class ExtractReviewDataLut(publish.Extractor):
|
||||
|
|
@ -19,6 +19,8 @@ class ExtractReviewDataLut(publish.Extractor):
|
|||
families = ["review"]
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
self.log.debug("Creating staging dir...")
|
||||
if "representations" in instance.data:
|
||||
|
|
@ -4,8 +4,8 @@ from pprint import pformat
|
|||
import pyblish.api
|
||||
|
||||
from ayon_core.pipeline import publish
|
||||
from ayon_core.hosts.nuke.api import plugin
|
||||
from ayon_core.hosts.nuke.api.lib import maintained_selection
|
||||
from ayon_nuke.api import plugin
|
||||
from ayon_nuke.api.lib import maintained_selection
|
||||
|
||||
|
||||
class ExtractReviewIntermediates(publish.Extractor):
|
||||
|
|
@ -22,6 +22,8 @@ class ExtractReviewIntermediates(publish.Extractor):
|
|||
families = ["review"]
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
# presets
|
||||
viewer_lut_raw = None
|
||||
outputs = {}
|
||||
|
|
@ -136,7 +138,6 @@ class ExtractReviewIntermediates(publish.Extractor):
|
|||
self, instance, o_name, o_data["extension"],
|
||||
multiple_presets)
|
||||
|
||||
o_data["add_custom_tags"].append("intermediate")
|
||||
delete = not o_data.get("publish", False)
|
||||
|
||||
if instance.data.get("farm"):
|
||||
|
|
@ -6,7 +6,9 @@ class ExtractScriptSave(pyblish.api.InstancePlugin):
|
|||
"""Save current Nuke workfile script"""
|
||||
label = 'Script Save'
|
||||
order = pyblish.api.ExtractorOrder - 0.1
|
||||
hosts = ['nuke']
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ import pyblish.api
|
|||
import six
|
||||
|
||||
from ayon_core.pipeline import publish
|
||||
from ayon_core.hosts.nuke.api import (
|
||||
from ayon_nuke.api import (
|
||||
maintained_selection,
|
||||
duplicate_node,
|
||||
get_view_process_node
|
||||
|
|
@ -27,6 +27,8 @@ class ExtractSlateFrame(publish.Extractor):
|
|||
families = ["slate"]
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
# Settings values
|
||||
key_value_mapping = {
|
||||
"f_submission_note": {
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import nuke
|
||||
import pyblish.api
|
||||
|
||||
|
|
@ -10,9 +9,13 @@ class IncrementScriptVersion(pyblish.api.ContextPlugin):
|
|||
label = "Increment Script Version"
|
||||
optional = True
|
||||
families = ["workfile"]
|
||||
hosts = ['nuke']
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, context):
|
||||
if not context.data.get("increment_script_version", True):
|
||||
return
|
||||
|
||||
assert all(result["success"] for result in context.data["results"]), (
|
||||
"Publishing not successful so version is not increased.")
|
||||
|
|
@ -9,7 +9,9 @@ class RemoveOutputNode(pyblish.api.ContextPlugin):
|
|||
label = 'Output Node Remove'
|
||||
order = pyblish.api.IntegratorOrder + 0.4
|
||||
families = ["workfile"]
|
||||
hosts = ['nuke']
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, context):
|
||||
try:
|
||||
|
|
@ -10,7 +10,7 @@ from ayon_core.pipeline.publish import (
|
|||
PublishXmlValidationError,
|
||||
OptionalPyblishPluginMixin
|
||||
)
|
||||
from ayon_core.hosts.nuke.api import SelectInstanceNodeAction
|
||||
from ayon_nuke.api import SelectInstanceNodeAction
|
||||
|
||||
|
||||
class ValidateCorrectAssetContext(
|
||||
|
|
@ -34,6 +34,8 @@ class ValidateCorrectAssetContext(
|
|||
]
|
||||
optional = True
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
@classmethod
|
||||
def apply_settings(cls, project_settings):
|
||||
"""Apply deprecated settings from project settings.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import nuke
|
||||
import pyblish
|
||||
from ayon_core.hosts.nuke import api as napi
|
||||
from ayon_nuke import api as napi
|
||||
|
||||
from ayon_core.pipeline.publish import (
|
||||
ValidateContentsOrder,
|
||||
|
|
@ -65,6 +65,8 @@ class ValidateBackdrop(
|
|||
hosts = ["nuke"]
|
||||
actions = [SelectCenterInNodeGraph]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
if not self.is_active(instance.data):
|
||||
return
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import pyblish.api
|
||||
|
||||
from ayon_core.pipeline.publish import get_errored_instances_from_context
|
||||
from ayon_core.hosts.nuke.api.lib import link_knobs
|
||||
from ayon_nuke.api.lib import link_knobs
|
||||
from ayon_core.pipeline.publish import (
|
||||
OptionalPyblishPluginMixin,
|
||||
PublishValidationError
|
||||
|
|
@ -52,6 +52,9 @@ class ValidateExposedKnobs(
|
|||
label = "Validate Exposed Knobs"
|
||||
actions = [RepairExposedKnobs]
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
product_types_mapping = {
|
||||
"render": "CreateWriteRender",
|
||||
"prerender": "CreateWritePrerender",
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import pyblish
|
||||
from ayon_core.pipeline import PublishXmlValidationError
|
||||
from ayon_core.hosts.nuke import api as napi
|
||||
from ayon_nuke import api as napi
|
||||
import nuke
|
||||
|
||||
|
||||
|
|
@ -43,6 +43,8 @@ class ValidateGizmo(pyblish.api.InstancePlugin):
|
|||
hosts = ["nuke"]
|
||||
actions = [OpenFailedGroupNode]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
grpn = instance.data["transientData"]["node"]
|
||||
|
||||
|
|
@ -32,6 +32,8 @@ class ValidateKnobs(pyblish.api.ContextPlugin):
|
|||
actions = [RepairContextAction]
|
||||
optional = True
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
knobs = "{}"
|
||||
|
||||
def process(self, context):
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import pyblish.api
|
||||
|
||||
from ayon_core.hosts.nuke import api as napi
|
||||
from ayon_nuke import api as napi
|
||||
from ayon_core.pipeline.publish import RepairAction
|
||||
from ayon_core.pipeline import (
|
||||
PublishXmlValidationError,
|
||||
|
|
@ -27,6 +27,8 @@ class ValidateOutputResolution(
|
|||
hosts = ["nuke"]
|
||||
actions = [RepairAction]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
missing_msg = "Missing Reformat node in render group node"
|
||||
resolution_msg = "Reformat is set to wrong format"
|
||||
|
||||
|
|
@ -25,6 +25,8 @@ class ValidateProxyMode(pyblish.api.ContextPlugin):
|
|||
hosts = ["nuke"]
|
||||
actions = [FixProxyMode]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, context):
|
||||
|
||||
rootNode = nuke.root()
|
||||
|
|
@ -54,6 +54,8 @@ class ValidateRenderedFrames(pyblish.api.InstancePlugin):
|
|||
hosts = ["nuke", "nukestudio"]
|
||||
actions = [RepairCollectionActionToLocal, RepairCollectionActionToFarm]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
node = instance.data["transientData"]["node"]
|
||||
|
||||
|
|
@ -5,7 +5,7 @@ from ayon_core.pipeline import (
|
|||
OptionalPyblishPluginMixin
|
||||
)
|
||||
from ayon_core.pipeline.publish import RepairAction
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
WorkfileSettings
|
||||
)
|
||||
|
||||
|
|
@ -23,6 +23,8 @@ class ValidateScriptAttributes(
|
|||
optional = True
|
||||
actions = [RepairAction]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
if not self.is_active(instance.data):
|
||||
return
|
||||
|
|
@ -2,7 +2,7 @@ from collections import defaultdict
|
|||
|
||||
import pyblish.api
|
||||
from ayon_core.pipeline.publish import get_errored_instances_from_context
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
get_write_node_template_attr,
|
||||
set_node_knobs_from_settings,
|
||||
color_gui_to_int
|
||||
|
|
@ -59,6 +59,8 @@ class ValidateNukeWriteNode(
|
|||
actions = [RepairNukeWriteNodeAction]
|
||||
hosts = ["nuke"]
|
||||
|
||||
settings_category = "nuke"
|
||||
|
||||
def process(self, instance):
|
||||
if not self.is_active(instance.data):
|
||||
return
|
||||
|
|
@ -4,7 +4,7 @@ from ayon_core.pipeline.workfile.workfile_template_builder import (
|
|||
CreatePlaceholderItem,
|
||||
PlaceholderCreateMixin,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
find_free_space_to_paste_nodes,
|
||||
get_extreme_positions,
|
||||
get_group_io_nodes,
|
||||
|
|
@ -18,7 +18,7 @@ from ayon_core.hosts.nuke.api.lib import (
|
|||
duplicate_node,
|
||||
node_tempfile,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.workfile_template_builder import (
|
||||
from ayon_nuke.api.workfile_template_builder import (
|
||||
NukePlaceholderPlugin
|
||||
)
|
||||
|
||||
|
|
@ -4,7 +4,7 @@ from ayon_core.pipeline.workfile.workfile_template_builder import (
|
|||
LoadPlaceholderItem,
|
||||
PlaceholderLoadMixin,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.lib import (
|
||||
from ayon_nuke.api.lib import (
|
||||
find_free_space_to_paste_nodes,
|
||||
get_extreme_positions,
|
||||
get_group_io_nodes,
|
||||
|
|
@ -18,7 +18,7 @@ from ayon_core.hosts.nuke.api.lib import (
|
|||
duplicate_node,
|
||||
node_tempfile,
|
||||
)
|
||||
from ayon_core.hosts.nuke.api.workfile_template_builder import (
|
||||
from ayon_nuke.api.workfile_template_builder import (
|
||||
NukePlaceholderPlugin
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue