mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge branch 'develop' into feature/909-define-basic-trait-type-using-dataclasses
This commit is contained in:
commit
085aa74976
11 changed files with 106 additions and 72 deletions
|
|
@ -30,7 +30,8 @@ class AddLastWorkfileToLaunchArgs(PreLaunchHook):
|
|||
"aftereffects",
|
||||
"wrap",
|
||||
"openrv",
|
||||
"cinema4d"
|
||||
"cinema4d",
|
||||
"silhouette",
|
||||
}
|
||||
launch_types = {LaunchTypes.local}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ class OCIOEnvHook(PreLaunchHook):
|
|||
"hiero",
|
||||
"resolve",
|
||||
"openrv",
|
||||
"cinema4d"
|
||||
"cinema4d",
|
||||
"silhouette",
|
||||
}
|
||||
launch_types = set()
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import os
|
|||
import logging
|
||||
import collections
|
||||
|
||||
from ayon_core.pipeline.constants import AVALON_INSTANCE_ID
|
||||
from ayon_core.pipeline.constants import AYON_INSTANCE_ID
|
||||
|
||||
from .product_name import get_product_name
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ class LegacyCreator:
|
|||
# Default data
|
||||
self.data = collections.OrderedDict()
|
||||
# TODO use 'AYON_INSTANCE_ID' when all hosts support it
|
||||
self.data["id"] = AVALON_INSTANCE_ID
|
||||
self.data["id"] = AYON_INSTANCE_ID
|
||||
self.data["productType"] = self.product_type
|
||||
self.data["folderPath"] = folder_path
|
||||
self.data["productName"] = name
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import copy
|
||||
import collections
|
||||
from uuid import uuid4
|
||||
import typing
|
||||
from typing import Optional, Dict, List, Any
|
||||
|
||||
from ayon_core.lib.attribute_definitions import (
|
||||
|
|
@ -17,6 +18,9 @@ from ayon_core.pipeline import (
|
|||
from .exceptions import ImmutableKeyError
|
||||
from .changes import TrackChangesItem
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from .creator_plugins import BaseCreator
|
||||
|
||||
|
||||
class ConvertorItem:
|
||||
"""Item representing convertor plugin.
|
||||
|
|
@ -444,10 +448,11 @@ class CreatedInstance:
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
product_type,
|
||||
product_name,
|
||||
data,
|
||||
creator,
|
||||
product_type: str,
|
||||
product_name: str,
|
||||
data: Dict[str, Any],
|
||||
creator: "BaseCreator",
|
||||
transient_data: Optional[Dict[str, Any]] = None,
|
||||
):
|
||||
self._creator = creator
|
||||
creator_identifier = creator.identifier
|
||||
|
|
@ -462,7 +467,9 @@ class CreatedInstance:
|
|||
self._members = []
|
||||
|
||||
# Data that can be used for lifetime of object
|
||||
self._transient_data = {}
|
||||
if transient_data is None:
|
||||
transient_data = {}
|
||||
self._transient_data = transient_data
|
||||
|
||||
# Create a copy of passed data to avoid changing them on the fly
|
||||
data = copy.deepcopy(data or {})
|
||||
|
|
@ -492,7 +499,7 @@ class CreatedInstance:
|
|||
item_id = data.get("id")
|
||||
# TODO use only 'AYON_INSTANCE_ID' when all hosts support it
|
||||
if item_id not in {AYON_INSTANCE_ID, AVALON_INSTANCE_ID}:
|
||||
item_id = AVALON_INSTANCE_ID
|
||||
item_id = AYON_INSTANCE_ID
|
||||
self._data["id"] = item_id
|
||||
self._data["productType"] = product_type
|
||||
self._data["productName"] = product_name
|
||||
|
|
@ -787,16 +794,26 @@ class CreatedInstance:
|
|||
self._create_context.instance_create_attr_defs_changed(self.id)
|
||||
|
||||
@classmethod
|
||||
def from_existing(cls, instance_data, creator):
|
||||
def from_existing(
|
||||
cls,
|
||||
instance_data: Dict[str, Any],
|
||||
creator: "BaseCreator",
|
||||
transient_data: Optional[Dict[str, Any]] = None,
|
||||
) -> "CreatedInstance":
|
||||
"""Convert instance data from workfile to CreatedInstance.
|
||||
|
||||
Args:
|
||||
instance_data (Dict[str, Any]): Data in a structure ready for
|
||||
'CreatedInstance' object.
|
||||
creator (BaseCreator): Creator plugin which is creating the
|
||||
instance of for which the instance belong.
|
||||
"""
|
||||
instance of for which the instance belongs.
|
||||
transient_data (Optional[dict[str, Any]]): Instance transient
|
||||
data.
|
||||
|
||||
Returns:
|
||||
CreatedInstance: Instance object.
|
||||
|
||||
"""
|
||||
instance_data = copy.deepcopy(instance_data)
|
||||
|
||||
product_type = instance_data.get("productType")
|
||||
|
|
@ -809,7 +826,11 @@ class CreatedInstance:
|
|||
product_name = instance_data.get("subset")
|
||||
|
||||
return cls(
|
||||
product_type, product_name, instance_data, creator
|
||||
product_type,
|
||||
product_name,
|
||||
instance_data,
|
||||
creator,
|
||||
transient_data=transient_data,
|
||||
)
|
||||
|
||||
def attribute_value_changed(self, key, changes):
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class ValidateCurrentSaveFile(pyblish.api.ContextPlugin):
|
|||
label = "Validate File Saved"
|
||||
order = pyblish.api.ValidatorOrder - 0.1
|
||||
hosts = ["fusion", "houdini", "max", "maya", "nuke", "substancepainter",
|
||||
"cinema4d"]
|
||||
"cinema4d", "silhouette"]
|
||||
actions = [SaveByVersionUpAction, ShowWorkfilesAction]
|
||||
|
||||
def process(self, context):
|
||||
|
|
|
|||
|
|
@ -1171,6 +1171,8 @@ ValidationArtistMessage QLabel {
|
|||
|
||||
#PublishLogMessage {
|
||||
font-family: "Noto Sans Mono";
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#PublishInstanceLogsLabel {
|
||||
|
|
|
|||
|
|
@ -1117,6 +1117,57 @@ class LogIconFrame(QtWidgets.QFrame):
|
|||
painter.end()
|
||||
|
||||
|
||||
class LogItemMessage(QtWidgets.QTextEdit):
|
||||
def __init__(self, msg, parent):
|
||||
super().__init__(parent)
|
||||
|
||||
# Set as plain text to propagate new line characters
|
||||
self.setPlainText(msg)
|
||||
|
||||
self.setObjectName("PublishLogMessage")
|
||||
self.setReadOnly(True)
|
||||
self.setFrameStyle(QtWidgets.QFrame.NoFrame)
|
||||
self.setLineWidth(0)
|
||||
self.setMidLineWidth(0)
|
||||
pal = self.palette()
|
||||
pal.setColor(QtGui.QPalette.Base, QtCore.Qt.transparent)
|
||||
self.setPalette(pal)
|
||||
self.setContentsMargins(0, 0, 0, 0)
|
||||
viewport = self.viewport()
|
||||
viewport.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
self.setTextInteractionFlags(
|
||||
QtCore.Qt.TextBrowserInteraction)
|
||||
self.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
|
||||
self.setLineWrapMode(QtWidgets.QTextEdit.WidgetWidth)
|
||||
self.setWordWrapMode(
|
||||
QtGui.QTextOption.WrapMode.WrapAtWordBoundaryOrAnywhere
|
||||
)
|
||||
self.setSizePolicy(
|
||||
QtWidgets.QSizePolicy.Preferred,
|
||||
QtWidgets.QSizePolicy.Maximum
|
||||
)
|
||||
document = self.document()
|
||||
document.documentLayout().documentSizeChanged.connect(
|
||||
self._adjust_minimum_size
|
||||
)
|
||||
document.setDocumentMargin(0.0)
|
||||
self._height = None
|
||||
|
||||
def _adjust_minimum_size(self, size):
|
||||
self._height = size.height() + (2 * self.frameWidth())
|
||||
self.updateGeometry()
|
||||
|
||||
def sizeHint(self):
|
||||
size = super().sizeHint()
|
||||
if self._height is not None:
|
||||
size.setHeight(self._height)
|
||||
return size
|
||||
|
||||
def minimumSizeHint(self):
|
||||
return self.sizeHint()
|
||||
|
||||
|
||||
class LogItemWidget(QtWidgets.QWidget):
|
||||
log_level_to_flag = {
|
||||
10: LOG_DEBUG_VISIBLE,
|
||||
|
|
@ -1132,12 +1183,7 @@ class LogItemWidget(QtWidgets.QWidget):
|
|||
type_flag, level_n = self._get_log_info(log)
|
||||
icon_label = LogIconFrame(
|
||||
self, log["type"], level_n, log.get("is_validation_error"))
|
||||
message_label = QtWidgets.QLabel(log["msg"].rstrip(), self)
|
||||
message_label.setObjectName("PublishLogMessage")
|
||||
message_label.setTextInteractionFlags(
|
||||
QtCore.Qt.TextBrowserInteraction)
|
||||
message_label.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
|
||||
message_label.setWordWrap(True)
|
||||
message_label = LogItemMessage(log["msg"].rstrip(), self)
|
||||
|
||||
main_layout = QtWidgets.QHBoxLayout(self)
|
||||
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
|
@ -1290,6 +1336,7 @@ class InstanceLogsWidget(QtWidgets.QWidget):
|
|||
|
||||
label_widget = QtWidgets.QLabel(instance.label, self)
|
||||
label_widget.setObjectName("PublishInstanceLogsLabel")
|
||||
label_widget.setWordWrap(True)
|
||||
logs_grid = LogsWithIconsView(instance.logs, self)
|
||||
|
||||
layout = QtWidgets.QVBoxLayout(self)
|
||||
|
|
@ -1329,9 +1376,11 @@ class InstancesLogsView(QtWidgets.QFrame):
|
|||
|
||||
content_wrap_widget = QtWidgets.QWidget(scroll_area)
|
||||
content_wrap_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground)
|
||||
content_wrap_widget.setMinimumWidth(80)
|
||||
|
||||
content_widget = QtWidgets.QWidget(content_wrap_widget)
|
||||
content_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground)
|
||||
|
||||
content_layout = QtWidgets.QVBoxLayout(content_widget)
|
||||
content_layout.setContentsMargins(8, 8, 8, 8)
|
||||
content_layout.setSpacing(15)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ def find_free_port(
|
|||
exclude_ports (list, tuple, set): List of ports that won't be
|
||||
checked form entered range.
|
||||
host (str): Host where will check for free ports. Set to
|
||||
"localhost" by default.
|
||||
"127.0.0.1" by default.
|
||||
"""
|
||||
if port_from is None:
|
||||
port_from = 8079
|
||||
|
|
@ -42,7 +42,7 @@ def find_free_port(
|
|||
|
||||
# Default host is localhost but it is possible to look for other hosts
|
||||
if host is None:
|
||||
host = "localhost"
|
||||
host = "127.0.0.1"
|
||||
|
||||
found_port = None
|
||||
while True:
|
||||
|
|
@ -78,7 +78,7 @@ class WebServerManager:
|
|||
self._log = None
|
||||
|
||||
self.port = port or 8079
|
||||
self.host = host or "localhost"
|
||||
self.host = host or "127.0.0.1"
|
||||
|
||||
self.on_stop_callbacks = []
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from ayon_core.resources import get_image_path
|
||||
from ayon_core.tools.flickcharm import FlickCharm
|
||||
|
||||
from qtpy import QtWidgets, QtCore, QtGui, QtSvg
|
||||
from qtpy import QtWidgets, QtCore, QtGui
|
||||
|
||||
|
||||
class DeselectableTreeView(QtWidgets.QTreeView):
|
||||
|
|
@ -19,48 +18,6 @@ class DeselectableTreeView(QtWidgets.QTreeView):
|
|||
QtWidgets.QTreeView.mousePressEvent(self, event)
|
||||
|
||||
|
||||
class TreeViewSpinner(QtWidgets.QTreeView):
|
||||
size = 160
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(TreeViewSpinner, self).__init__(parent=parent)
|
||||
|
||||
loading_image_path = get_image_path("spinner-200.svg")
|
||||
|
||||
self.spinner = QtSvg.QSvgRenderer(loading_image_path)
|
||||
|
||||
self.is_loading = False
|
||||
self.is_empty = True
|
||||
|
||||
def paint_loading(self, event):
|
||||
rect = event.rect()
|
||||
rect = QtCore.QRectF(rect.topLeft(), rect.bottomRight())
|
||||
rect.moveTo(
|
||||
rect.x() + rect.width() / 2 - self.size / 2,
|
||||
rect.y() + rect.height() / 2 - self.size / 2
|
||||
)
|
||||
rect.setSize(QtCore.QSizeF(self.size, self.size))
|
||||
painter = QtGui.QPainter(self.viewport())
|
||||
self.spinner.render(painter, rect)
|
||||
|
||||
def paint_empty(self, event):
|
||||
painter = QtGui.QPainter(self.viewport())
|
||||
rect = event.rect()
|
||||
rect = QtCore.QRectF(rect.topLeft(), rect.bottomRight())
|
||||
qtext_opt = QtGui.QTextOption(
|
||||
QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter
|
||||
)
|
||||
painter.drawText(rect, "No Data", qtext_opt)
|
||||
|
||||
def paintEvent(self, event):
|
||||
if self.is_loading:
|
||||
self.paint_loading(event)
|
||||
elif self.is_empty:
|
||||
self.paint_empty(event)
|
||||
else:
|
||||
super(TreeViewSpinner, self).paintEvent(event)
|
||||
|
||||
|
||||
class TreeView(QtWidgets.QTreeView):
|
||||
"""Ultimate TreeView with flick charm and double click signals.
|
||||
|
||||
|
|
|
|||
|
|
@ -184,9 +184,10 @@ class WorkareaModel:
|
|||
return items
|
||||
|
||||
for filename in os.listdir(workdir):
|
||||
# We want to support both files and folders. e.g. Silhoutte uses
|
||||
# folders as its project files. So we do not check whether it is
|
||||
# a file or not.
|
||||
filepath = os.path.join(workdir, filename)
|
||||
if not os.path.isfile(filepath):
|
||||
continue
|
||||
|
||||
ext = os.path.splitext(filename)[1].lower()
|
||||
if ext not in self._extensions:
|
||||
|
|
|
|||
|
|
@ -1033,7 +1033,8 @@ DEFAULT_PUBLISH_VALUES = {
|
|||
"maya",
|
||||
"nuke",
|
||||
"photoshop",
|
||||
"substancepainter"
|
||||
"substancepainter",
|
||||
"silhouette",
|
||||
],
|
||||
"enabled": True,
|
||||
"optional": False,
|
||||
|
|
@ -1053,7 +1054,8 @@ DEFAULT_PUBLISH_VALUES = {
|
|||
"harmony",
|
||||
"photoshop",
|
||||
"aftereffects",
|
||||
"fusion"
|
||||
"fusion",
|
||||
"silhouette",
|
||||
],
|
||||
"enabled": True,
|
||||
"optional": True,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue