Merge remote-tracking branch 'upstream/develop' into style_cache_objected_colors

This commit is contained in:
Roy Nieterau 2022-09-28 20:30:16 +02:00
commit fbfe26b3f9
20 changed files with 122 additions and 83 deletions

View file

@ -1,11 +1,12 @@
# Changelog
## [3.14.3-nightly.4](https://github.com/pypeclub/OpenPype/tree/HEAD)
## [3.14.3-nightly.5](https://github.com/pypeclub/OpenPype/tree/HEAD)
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.2...HEAD)
**🚀 Enhancements**
- Publisher: Enhancement proposals [\#3897](https://github.com/pypeclub/OpenPype/pull/3897)
- Maya: better logging in Maketx [\#3886](https://github.com/pypeclub/OpenPype/pull/3886)
- Photoshop: review can be turned off [\#3885](https://github.com/pypeclub/OpenPype/pull/3885)
- TrayPublisher: added persisting of last selected project [\#3871](https://github.com/pypeclub/OpenPype/pull/3871)
@ -17,9 +18,8 @@
- General: Transcoding handle float2 attr type [\#3849](https://github.com/pypeclub/OpenPype/pull/3849)
- General: Simple script for getting license information about used packages [\#3843](https://github.com/pypeclub/OpenPype/pull/3843)
- Houdini: Increment current file on workfile publish [\#3840](https://github.com/pypeclub/OpenPype/pull/3840)
- Publisher: Add new publisher to host tools [\#3833](https://github.com/pypeclub/OpenPype/pull/3833)
- General: Workfile template build enhancements [\#3838](https://github.com/pypeclub/OpenPype/pull/3838)
- General: lock task workfiles when they are working on [\#3810](https://github.com/pypeclub/OpenPype/pull/3810)
- Maya: Workspace mel loaded from settings [\#3790](https://github.com/pypeclub/OpenPype/pull/3790)
**🐛 Bug fixes**
@ -33,12 +33,13 @@
- Tray Publisher: skip plugin if otioTimeline is missing [\#3856](https://github.com/pypeclub/OpenPype/pull/3856)
- Flame: retimed attributes are integrated with settings [\#3855](https://github.com/pypeclub/OpenPype/pull/3855)
- Maya: Extract Playblast fix textures + labelize viewport show settings [\#3852](https://github.com/pypeclub/OpenPype/pull/3852)
- Ftrack: Url validation does not require ftrackapp [\#3834](https://github.com/pypeclub/OpenPype/pull/3834)
- Maya+Ftrack: Change typo in family name `mayaascii` -\> `mayaAscii` [\#3820](https://github.com/pypeclub/OpenPype/pull/3820)
- Maya Deadline: Fix Tile Rendering by forcing integer pixel values [\#3758](https://github.com/pypeclub/OpenPype/pull/3758)
**🔀 Refactored code**
- Resolve: Use new Extractor location [\#3918](https://github.com/pypeclub/OpenPype/pull/3918)
- Unreal: Use new Extractor location [\#3917](https://github.com/pypeclub/OpenPype/pull/3917)
- Flame: Use new Extractor location [\#3916](https://github.com/pypeclub/OpenPype/pull/3916)
- Houdini: Use new Extractor location [\#3894](https://github.com/pypeclub/OpenPype/pull/3894)
- Harmony: Use new Extractor location [\#3893](https://github.com/pypeclub/OpenPype/pull/3893)
- Hiero: Use new Extractor location [\#3851](https://github.com/pypeclub/OpenPype/pull/3851)
@ -48,6 +49,7 @@
**Merged pull requests:**
- Maya: Fix Scene Inventory possibly starting off-screen due to maya preferences [\#3923](https://github.com/pypeclub/OpenPype/pull/3923)
- Maya: RenderSettings set default image format for V-Ray+Redshift to exr [\#3879](https://github.com/pypeclub/OpenPype/pull/3879)
- Remove lockfile during publish [\#3874](https://github.com/pypeclub/OpenPype/pull/3874)
@ -92,8 +94,6 @@
- General: Create project function moved to client code [\#3766](https://github.com/pypeclub/OpenPype/pull/3766)
- Maya: Refactor submit deadline to use AbstractSubmitDeadline [\#3759](https://github.com/pypeclub/OpenPype/pull/3759)
- General: Change publish template settings location [\#3755](https://github.com/pypeclub/OpenPype/pull/3755)
- General: Move hostdirname functionality into host [\#3749](https://github.com/pypeclub/OpenPype/pull/3749)
- General: Move publish utils to pipeline [\#3745](https://github.com/pypeclub/OpenPype/pull/3745)
**Merged pull requests:**
@ -111,14 +111,10 @@
**🐛 Bug fixes**
- Maya: Fix typo in getPanel argument `with\_focus` -\> `withFocus` [\#3753](https://github.com/pypeclub/OpenPype/pull/3753)
- General: Smaller fixes of imports [\#3748](https://github.com/pypeclub/OpenPype/pull/3748)
- General: Logger tweaks [\#3741](https://github.com/pypeclub/OpenPype/pull/3741)
**🔀 Refactored code**
- General: Move delivery logic to pipeline [\#3751](https://github.com/pypeclub/OpenPype/pull/3751)
- General: Host addons cleanup [\#3744](https://github.com/pypeclub/OpenPype/pull/3744)
- Webpublisher: Webpublisher is used as addon [\#3740](https://github.com/pypeclub/OpenPype/pull/3740)
## [3.14.0](https://github.com/pypeclub/OpenPype/tree/3.14.0) (2022-08-18)

View file

@ -5,6 +5,7 @@ from .host import (
from .interfaces import (
IWorkfileHost,
ILoadHost,
IPublishHost,
INewPublisher,
)
@ -16,6 +17,7 @@ __all__ = (
"IWorkfileHost",
"ILoadHost",
"IPublishHost",
"INewPublisher",
"HostDirmap",

View file

@ -282,7 +282,7 @@ class IWorkfileHost:
return self.workfile_has_unsaved_changes()
class INewPublisher:
class IPublishHost:
"""Functions related to new creation system in new publisher.
New publisher is not storing information only about each created instance
@ -306,7 +306,7 @@ class INewPublisher:
workflow.
"""
if isinstance(host, INewPublisher):
if isinstance(host, IPublishHost):
return []
required = [
@ -330,7 +330,7 @@ class INewPublisher:
MissingMethodsError: If there are missing methods on host
implementation.
"""
missing = INewPublisher.get_missing_publish_methods(host)
missing = IPublishHost.get_missing_publish_methods(host)
if missing:
raise MissingMethodsError(host, missing)
@ -368,3 +368,17 @@ class INewPublisher:
"""
pass
class INewPublisher(IPublishHost):
"""Legacy interface replaced by 'IPublishHost'.
Deprecated:
'INewPublisher' is replaced by 'IPublishHost' please change your
imports.
There is no "reasonable" way hot mark these classes as deprecated
to show warning of wrong import. Deprecated since 3.14.* will be
removed in 3.15.*
"""
pass

View file

@ -1,10 +1,10 @@
import os
import pyblish.api
import openpype.api
import opentimelineio as otio
from openpype.pipeline import publish
class ExtractOTIOFile(openpype.api.Extractor):
class ExtractOTIOFile(publish.Extractor):
"""
Extractor export OTIO file
"""

View file

@ -4,7 +4,8 @@ import tempfile
from copy import deepcopy
import pyblish.api
import openpype.api
from openpype.pipeline import publish
from openpype.hosts.flame import api as opfapi
from openpype.hosts.flame.api import MediaInfoFile
from openpype.pipeline.editorial import (
@ -14,7 +15,7 @@ from openpype.pipeline.editorial import (
import flame
class ExtractSubsetResources(openpype.api.Extractor):
class ExtractSubsetResources(publish.Extractor):
"""
Extractor for transcoding files from Flame clip
"""

View file

@ -1,10 +1,11 @@
import os
import pyblish.api
import openpype.api
from openpype.pipeline import publish
from openpype.hosts.resolve.api.lib import get_project_manager
class ExtractWorkfile(openpype.api.Extractor):
class ExtractWorkfile(publish.Extractor):
"""
Extractor export DRP workfile file representation
"""

View file

@ -9,7 +9,7 @@ from openpype.pipeline import (
register_creator_plugin_path,
legacy_io,
)
from openpype.host import HostBase, INewPublisher
from openpype.host import HostBase, IPublishHost
ROOT_DIR = os.path.dirname(os.path.dirname(
@ -19,7 +19,7 @@ PUBLISH_PATH = os.path.join(ROOT_DIR, "plugins", "publish")
CREATE_PATH = os.path.join(ROOT_DIR, "plugins", "create")
class TrayPublisherHost(HostBase, INewPublisher):
class TrayPublisherHost(HostBase, IPublishHost):
name = "traypublisher"
def install(self):

View file

@ -6,10 +6,10 @@ import unreal
from unreal import EditorAssetLibrary as eal
from unreal import EditorLevelLibrary as ell
import openpype.api
from openpype.pipeline import publish
class ExtractCamera(openpype.api.Extractor):
class ExtractCamera(publish.Extractor):
"""Extract a camera."""
label = "Extract Camera"

View file

@ -3,18 +3,15 @@ import os
import json
import math
from bson.objectid import ObjectId
import unreal
from unreal import EditorLevelLibrary as ell
from unreal import EditorAssetLibrary as eal
from openpype.client import get_representation_by_name
import openpype.api
from openpype.pipeline import legacy_io
from openpype.pipeline import legacy_io, publish
class ExtractLayout(openpype.api.Extractor):
class ExtractLayout(publish.Extractor):
"""Extract a layout."""
label = "Extract Layout"

View file

@ -5,10 +5,10 @@ import os
import unreal
from unreal import MaterialEditingLibrary as mat_lib
import openpype.api
from openpype.pipeline import publish
class ExtractLook(openpype.api.Extractor):
class ExtractLook(publish.Extractor):
"""Extract look."""
label = "Extract Look"

View file

@ -2,10 +2,10 @@ from pathlib import Path
import unreal
import openpype.api
from openpype.pipeline import publish
class ExtractRender(openpype.api.Extractor):
class ExtractRender(publish.Extractor):
"""Extract render."""
label = "Extract Render"

View file

@ -21,6 +21,9 @@ from openpype.pipeline import AvalonMongoDB
from openpype.settings import get_project_settings
from openpype.modules.kitsu.utils.credentials import validate_credentials
from openpype.lib import Logger
log = Logger.get_logger(__name__)
# Accepted namin pattern for OP
naming_pattern = re.compile("^[a-zA-Z0-9_.]*$")
@ -230,7 +233,6 @@ def update_op_assets(
},
)
)
return assets_with_update
@ -248,7 +250,7 @@ def write_project_to_op(project: dict, dbcon: AvalonMongoDB) -> UpdateOne:
project_name = project["name"]
project_doc = get_project(project_name)
if not project_doc:
print(f"Creating project '{project_name}'")
log.info(f"Creating project '{project_name}'")
project_doc = create_project(project_name, project_name)
# Project data and tasks
@ -268,12 +270,18 @@ def write_project_to_op(project: dict, dbcon: AvalonMongoDB) -> UpdateOne:
{
"code": project_code,
"fps": float(project["fps"]),
"resolutionWidth": int(project["resolution"].split("x")[0]),
"resolutionHeight": int(project["resolution"].split("x")[1]),
"zou_id": project["id"],
}
)
match_res = re.match(r"(\d+)x(\d+)", project["resolution"])
if match_res:
project_data['resolutionWidth'] = int(match_res.group(1))
project_data['resolutionHeight'] = int(match_res.group(2))
else:
log.warning(f"\'{project['resolution']}\' does not match the expected"
" format for the resolution, for example: 1920x1080")
return UpdateOne(
{"_id": project_doc["_id"]},
{
@ -334,7 +342,7 @@ def sync_project_from_kitsu(dbcon: AvalonMongoDB, project: dict):
if not project:
project = gazu.project.get_project_by_name(project["name"])
print(f"Synchronizing {project['name']}...")
log.info(f"Synchronizing {project['name']}...")
# Get all assets from zou
all_assets = gazu.asset.all_assets_for_project(project)

View file

@ -7,7 +7,11 @@ from uuid import uuid4
from contextlib import contextmanager
from openpype.client import get_assets
from openpype.host import INewPublisher
from openpype.settings import (
get_system_settings,
get_project_settings
)
from openpype.host import IPublishHost
from openpype.pipeline import legacy_io
from openpype.pipeline.mongodb import (
AvalonMongoDB,
@ -20,11 +24,6 @@ from .creator_plugins import (
discover_creator_plugins,
)
from openpype.api import (
get_system_settings,
get_project_settings
)
UpdateData = collections.namedtuple("UpdateData", ["instance", "changes"])
@ -402,8 +401,12 @@ class CreatedInstance:
self.creator = creator
# Instance members may have actions on them
# TODO implement members logic
self._members = []
# Data that can be used for lifetime of object
self._transient_data = {}
# Create a copy of passed data to avoid changing them on the fly
data = copy.deepcopy(data or {})
# Store original value of passed data
@ -596,6 +599,26 @@ class CreatedInstance:
return self
@property
def transient_data(self):
"""Data stored for lifetime of instance object.
These data are not stored to scene and will be lost on object
deletion.
Can be used to store objects. In some host implementations is not
possible to reference to object in scene with some unique identifier
(e.g. node in Fusion.). In that case it is handy to store the object
here. Should be used that way only if instance data are stored on the
node itself.
Returns:
Dict[str, Any]: Dictionary object where you can store data related
to instance for lifetime of instance object.
"""
return self._transient_data
def changes(self):
"""Calculate and return changes."""
@ -771,7 +794,7 @@ class CreateContext:
"""
missing = set(
INewPublisher.get_missing_publish_methods(host)
IPublishHost.get_missing_publish_methods(host)
)
return missing

View file

@ -81,6 +81,13 @@ class BaseCreator:
# - we may use UI inside processing this attribute should be checked
self.headless = headless
self.apply_settings(project_settings, system_settings)
def apply_settings(self, project_settings, system_settings):
"""Method called on initialization of plugin to apply settings."""
pass
@property
def identifier(self):
"""Identifier of creator (must be unique).

View file

@ -25,7 +25,9 @@ class CollectFromCreateContext(pyblish.api.ContextPlugin):
for created_instance in create_context.instances:
instance_data = created_instance.data_to_store()
if instance_data["active"]:
self.create_instance(context, instance_data)
self.create_instance(
context, instance_data, created_instance.transient_data
)
# Update global data to context
context.data.update(create_context.context_data_to_store())
@ -37,7 +39,7 @@ class CollectFromCreateContext(pyblish.api.ContextPlugin):
legacy_io.Session[key] = value
os.environ[key] = value
def create_instance(self, context, in_data):
def create_instance(self, context, in_data, transient_data):
subset = in_data["subset"]
# If instance data already contain families then use it
instance_families = in_data.get("families") or []
@ -56,5 +58,8 @@ class CollectFromCreateContext(pyblish.api.ContextPlugin):
for key, value in in_data.items():
if key not in instance.data:
instance.data[key] = value
instance.data["transientData"] = transient_data
self.log.info("collected instance: {}".format(instance.data))
self.log.info("parsing data: {}".format(in_data))

View file

@ -296,7 +296,7 @@ class HSLColor:
if "%" in sat_str:
sat = float(sat_str.rstrip("%")) / 100
else:
sat = float(sat)
sat = float(sat_str)
if "%" in light_str:
light = float(light_str.rstrip("%")) / 100
@ -337,8 +337,8 @@ class HSLAColor:
as float (0-1 range).
Examples:
"hsl(27, 0.7, 0.3)"
"hsl(27, 70%, 30%)"
"hsla(27, 0.7, 0.3, 0.5)"
"hsla(27, 70%, 30%, 0.5)"
"""
def __init__(self, value):
modified_color = value.lower().strip()
@ -350,7 +350,7 @@ class HSLAColor:
if "%" in sat_str:
sat = float(sat_str.rstrip("%")) / 100
else:
sat = float(sat)
sat = float(sat_str)
if "%" in light_str:
light = float(light_str.rstrip("%")) / 100

View file

@ -20,7 +20,7 @@
"color": {
"font": "#D3D8DE",
"font-hover": "#F0F2F5",
"font-disabled": "#99A3B2",
"font-disabled": "#5b6779",
"font-view-selection": "#ffffff",
"font-view-hover": "#F0F2F5",

View file

@ -16,6 +16,7 @@ from openpype.tools.utils import (
BaseClickableFrame,
set_style_property,
)
from openpype.style import get_objected_colors
from openpype.pipeline.create import (
SUBSET_NAME_ALLOWED_SYMBOLS,
TaskNotSetError,
@ -125,28 +126,21 @@ class PublishIconBtn(IconButton):
def __init__(self, pixmap_path, *args, **kwargs):
super(PublishIconBtn, self).__init__(*args, **kwargs)
loaded_image = QtGui.QImage(pixmap_path)
colors = get_objected_colors()
icon = self.generate_icon(
pixmap_path,
enabled_color=colors["font"].get_qcolor(),
disabled_color=colors["font-disabled"].get_qcolor())
self.setIcon(icon)
pixmap = self.paint_image_with_color(loaded_image, QtCore.Qt.white)
self._base_image = loaded_image
self._enabled_icon = QtGui.QIcon(pixmap)
self._disabled_icon = None
self.setIcon(self._enabled_icon)
def get_enabled_icon(self):
"""Enabled icon."""
return self._enabled_icon
def get_disabled_icon(self):
"""Disabled icon."""
if self._disabled_icon is None:
pixmap = self.paint_image_with_color(
self._base_image, QtCore.Qt.gray
)
self._disabled_icon = QtGui.QIcon(pixmap)
return self._disabled_icon
def generate_icon(self, pixmap_path, enabled_color, disabled_color):
icon = QtGui.QIcon()
image = QtGui.QImage(pixmap_path)
enabled_pixmap = self.paint_image_with_color(image, enabled_color)
icon.addPixmap(enabled_pixmap, icon.Normal)
disabled_pixmap = self.paint_image_with_color(image, disabled_color)
icon.addPixmap(disabled_pixmap, icon.Disabled)
return icon
@staticmethod
def paint_image_with_color(image, color):
@ -187,13 +181,6 @@ class PublishIconBtn(IconButton):
return pixmap
def setEnabled(self, enabled):
super(PublishIconBtn, self).setEnabled(enabled)
if self.isEnabled():
self.setIcon(self.get_enabled_icon())
else:
self.setIcon(self.get_disabled_icon())
class ResetBtn(PublishIconBtn):
"""Publish reset button."""

View file

@ -40,8 +40,6 @@ class SceneInventoryWindow(QtWidgets.QDialog):
project_name = os.getenv("AVALON_PROJECT") or "<Project not set>"
self.setWindowTitle("Scene Inventory 1.0 - {}".format(project_name))
self.setObjectName("SceneInventory")
# Maya only property
self.setProperty("saveWindowPref", True)
self.resize(1100, 480)

View file

@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
"""Package declaring Pype version."""
__version__ = "3.14.3-nightly.4"
__version__ = "3.14.3-nightly.5"