Merge remote-tracking branch 'upstream/feature/new_publisher_proposals' into fusion_new_publish_transient_data

This commit is contained in:
Roy Nieterau 2022-09-23 17:20:19 +02:00
commit 735a7cc76a
14 changed files with 154 additions and 70 deletions

View file

@ -1,13 +1,18 @@
# Changelog
## [3.14.3-nightly.2](https://github.com/pypeclub/OpenPype/tree/HEAD)
## [3.14.3-nightly.3](https://github.com/pypeclub/OpenPype/tree/HEAD)
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.2...HEAD)
**🚀 Enhancements**
- Maya: better logging in Maketx [\#3886](https://github.com/pypeclub/OpenPype/pull/3886)
- TrayPublisher: added persisting of last selected project [\#3871](https://github.com/pypeclub/OpenPype/pull/3871)
- TrayPublisher: added text filter on project name to Tray Publisher [\#3867](https://github.com/pypeclub/OpenPype/pull/3867)
- Github issues adding `running version` section [\#3864](https://github.com/pypeclub/OpenPype/pull/3864)
- Publisher: Increase size of main window [\#3862](https://github.com/pypeclub/OpenPype/pull/3862)
- Photoshop: synchronize image version with workfile [\#3854](https://github.com/pypeclub/OpenPype/pull/3854)
- 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: lock task workfiles when they are working on [\#3810](https://github.com/pypeclub/OpenPype/pull/3810)
@ -28,11 +33,10 @@
- Hiero: Use new Extractor location [\#3851](https://github.com/pypeclub/OpenPype/pull/3851)
- Maya: Remove old legacy \(ftrack\) plug-ins that are of no use anymore [\#3819](https://github.com/pypeclub/OpenPype/pull/3819)
- Nuke: Use new Extractor location [\#3799](https://github.com/pypeclub/OpenPype/pull/3799)
- Maya: Use new Extractor location [\#3775](https://github.com/pypeclub/OpenPype/pull/3775)
- General: Change publish template settings location [\#3755](https://github.com/pypeclub/OpenPype/pull/3755)
**Merged pull requests:**
- 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)
## [3.14.2](https://github.com/pypeclub/OpenPype/tree/3.14.2) (2022-09-12)
@ -51,7 +55,6 @@
- Photoshop: attempt to speed up ExtractImage [\#3793](https://github.com/pypeclub/OpenPype/pull/3793)
- SyncServer: Added cli commands for sync server [\#3765](https://github.com/pypeclub/OpenPype/pull/3765)
- Kitsu: Drop 'entities root' setting. [\#3739](https://github.com/pypeclub/OpenPype/pull/3739)
- git: update gitignore [\#3722](https://github.com/pypeclub/OpenPype/pull/3722)
**🐛 Bug fixes**
@ -71,16 +74,18 @@
- Photoshop: Use new Extractor location [\#3789](https://github.com/pypeclub/OpenPype/pull/3789)
- Blender: Use new Extractor location [\#3787](https://github.com/pypeclub/OpenPype/pull/3787)
- AfterEffects: Use new Extractor location [\#3784](https://github.com/pypeclub/OpenPype/pull/3784)
- Maya: Use new Extractor location [\#3775](https://github.com/pypeclub/OpenPype/pull/3775)
- General: Remove unused teshost [\#3773](https://github.com/pypeclub/OpenPype/pull/3773)
- General: Copied 'Extractor' plugin to publish pipeline [\#3771](https://github.com/pypeclub/OpenPype/pull/3771)
- General: Move queries of asset and representation links [\#3770](https://github.com/pypeclub/OpenPype/pull/3770)
- General: Move create project folders to pipeline [\#3768](https://github.com/pypeclub/OpenPype/pull/3768)
- 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)
- Houdini: Define houdini as addon [\#3735](https://github.com/pypeclub/OpenPype/pull/3735)
- Fusion: Defined fusion as addon [\#3733](https://github.com/pypeclub/OpenPype/pull/3733)
- Flame: Defined flame as addon [\#3732](https://github.com/pypeclub/OpenPype/pull/3732)
- Resolve: Define resolve as addon [\#3727](https://github.com/pypeclub/OpenPype/pull/3727)
**Merged pull requests:**
@ -95,7 +100,6 @@
**🚀 Enhancements**
- General: Thumbnail can use project roots [\#3750](https://github.com/pypeclub/OpenPype/pull/3750)
- Settings: Remove settings lock on tray exit [\#3720](https://github.com/pypeclub/OpenPype/pull/3720)
**🐛 Bug fixes**
@ -103,29 +107,21 @@
- General: Smaller fixes of imports [\#3748](https://github.com/pypeclub/OpenPype/pull/3748)
- General: Logger tweaks [\#3741](https://github.com/pypeclub/OpenPype/pull/3741)
- Nuke: missing job dependency if multiple bake streams [\#3737](https://github.com/pypeclub/OpenPype/pull/3737)
- Nuke: color-space settings from anatomy is working [\#3721](https://github.com/pypeclub/OpenPype/pull/3721)
- Settings: Fix studio default anatomy save [\#3716](https://github.com/pypeclub/OpenPype/pull/3716)
**🔀 Refactored code**
- General: Move delivery logic to pipeline [\#3751](https://github.com/pypeclub/OpenPype/pull/3751)
- General: Move publish utils to pipeline [\#3745](https://github.com/pypeclub/OpenPype/pull/3745)
- 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)
- Photoshop: Defined photoshop as addon [\#3736](https://github.com/pypeclub/OpenPype/pull/3736)
- Harmony: Defined harmony as addon [\#3734](https://github.com/pypeclub/OpenPype/pull/3734)
- Flame: Defined flame as addon [\#3732](https://github.com/pypeclub/OpenPype/pull/3732)
- General: Module interfaces cleanup [\#3731](https://github.com/pypeclub/OpenPype/pull/3731)
- AfterEffects: Move AE functions from general lib [\#3730](https://github.com/pypeclub/OpenPype/pull/3730)
- Blender: Define blender as module [\#3729](https://github.com/pypeclub/OpenPype/pull/3729)
- AfterEffects: Define AfterEffects as module [\#3728](https://github.com/pypeclub/OpenPype/pull/3728)
- General: Replace PypeLogger with Logger [\#3725](https://github.com/pypeclub/OpenPype/pull/3725)
- Nuke: Define nuke as module [\#3724](https://github.com/pypeclub/OpenPype/pull/3724)
- General: Move subset name functionality [\#3723](https://github.com/pypeclub/OpenPype/pull/3723)
- General: Move creators plugin getter [\#3714](https://github.com/pypeclub/OpenPype/pull/3714)
**Merged pull requests:**
- Hiero: Define hiero as module [\#3717](https://github.com/pypeclub/OpenPype/pull/3717)
## [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

@ -22,6 +22,7 @@ class FlamePrelaunch(PreLaunchHook):
in environment var FLAME_SCRIPT_DIR.
"""
app_groups = ["flame"]
permissions = 0o777
wtc_script_path = os.path.join(
opflame.HOST_DIR, "api", "scripts", "wiretap_com.py")
@ -38,6 +39,7 @@ class FlamePrelaunch(PreLaunchHook):
"""Hook entry method."""
project_doc = self.data["project_doc"]
project_name = project_doc["name"]
volume_name = _env.get("FLAME_WIRETAP_VOLUME")
# get image io
project_anatomy = self.data["anatomy"]
@ -81,7 +83,7 @@ class FlamePrelaunch(PreLaunchHook):
data_to_script = {
# from settings
"host_name": _env.get("FLAME_WIRETAP_HOSTNAME") or hostname,
"volume_name": _env.get("FLAME_WIRETAP_VOLUME"),
"volume_name": volume_name,
"group_name": _env.get("FLAME_WIRETAP_GROUP"),
"color_policy": str(imageio_flame["project"]["colourPolicy"]),
@ -99,8 +101,41 @@ class FlamePrelaunch(PreLaunchHook):
app_arguments = self._get_launch_arguments(data_to_script)
# fix project data permission issue
self._fix_permissions(project_name, volume_name)
self.launch_context.launch_args.extend(app_arguments)
def _fix_permissions(self, project_name, volume_name):
"""Work around for project data permissions
Reported issue: when project is created locally on one machine,
it is impossible to migrate it to other machine. Autodesk Flame
is crating some unmanagable files which needs to be opened to 0o777.
Args:
project_name (str): project name
volume_name (str): studio volume
"""
dirs_to_modify = [
"/usr/discreet/project/{}".format(project_name),
"/opt/Autodesk/clip/{}/{}.prj".format(volume_name, project_name),
"/usr/discreet/clip/{}/{}.prj".format(volume_name, project_name)
]
for dirtm in dirs_to_modify:
for root, dirs, files in os.walk(dirtm):
try:
for name in set(dirs) | set(files):
path = os.path.join(root, name)
st = os.stat(path)
if oct(st.st_mode) != self.permissions:
os.chmod(path, self.permissions)
except OSError as exc:
self.log.warning("Not able to open files: {}".format(exc))
def _get_flame_fps(self, fps_num):
fps_table = {
float(23.976): "23.976 fps",

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

@ -646,9 +646,6 @@ def rename_filepaths_by_frame_start(
filepaths_by_frame, range_start, range_end, new_frame_start
):
"""Change frames in filenames of finished images to new frame start."""
# Skip if source first frame is same as destination first frame
if range_start == new_frame_start:
return
# Calculate frame end
new_frame_end = range_end + (new_frame_start - range_start)
@ -669,14 +666,17 @@ def rename_filepaths_by_frame_start(
source_range = range(range_start, range_end + 1)
output_range = range(new_frame_start, new_frame_end + 1)
# Skip if source first frame is same as destination first frame
new_dst_filepaths = {}
for src_frame, dst_frame in zip(source_range, output_range):
src_filepath = filepaths_by_frame[src_frame]
src_dirpath = os.path.dirname(src_filepath)
src_filepath = os.path.normpath(filepaths_by_frame[src_frame])
dirpath, src_filename = os.path.split(src_filepath)
dst_filename = filename_template.format(frame=dst_frame)
dst_filepath = os.path.join(src_dirpath, dst_filename)
dst_filepath = os.path.join(dirpath, dst_filename)
os.rename(src_filepath, dst_filepath)
if src_filename != dst_filename:
os.rename(src_filepath, dst_filepath)
new_dst_filepaths[dst_frame] = dst_filepath
return new_dst_filepaths

View file

@ -139,7 +139,7 @@ def convert_value_by_type_name(value_type, value, logger=None):
return float(value)
# Vectors will probably have more types
if value_type == "vec2f":
if value_type in ("vec2f", "float2"):
return [float(item) for item in value.split(",")]
# Matrix should be always have square size of element 3x3, 4x4
@ -204,8 +204,8 @@ def convert_value_by_type_name(value_type, value, logger=None):
)
return output
logger.info((
"MISSING IMPLEMENTATION:"
logger.debug((
"Dev note (missing implementation):"
" Unknown attrib type \"{}\". Value: {}"
).format(value_type, value))
return value
@ -263,8 +263,8 @@ def parse_oiio_xml_output(xml_string, logger=None):
# - feel free to add more tags
else:
value = child.text
logger.info((
"MISSING IMPLEMENTATION:"
logger.debug((
"Dev note (missing implementation):"
" Unknown tag \"{}\". Value \"{}\""
).format(tag_name, value))

View file

@ -56,7 +56,7 @@ def convert_value_by_type_name(value_type, value):
return float(value)
# Vectors will probably have more types
if value_type == "vec2f":
if value_type in ("vec2f", "float2"):
return [float(item) for item in value.split(",")]
# Matrix should be always have square size of element 3x3, 4x4
@ -127,7 +127,7 @@ def convert_value_by_type_name(value_type, value):
return output
print((
"MISSING IMPLEMENTATION:"
"Dev note (missing implementation):"
" Unknown attrib type \"{}\". Value: {}"
).format(value_type, value))
return value
@ -183,7 +183,7 @@ def parse_oiio_xml_output(xml_string):
else:
value = child.text
print((
"MISSING IMPLEMENTATION:"
"Dev note (missing implementation):"
" Unknown tag \"{}\". Value \"{}\""
).format(tag_name, value))

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._lifetime_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 lifetime_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._lifetime_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.lifetime_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, lifetime_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["lifetimeData"] = lifetime_data
self.log.info("collected instance: {}".format(instance.data))
self.log.info("parsing data: {}".format(in_data))

View file

@ -218,7 +218,7 @@ class PypeCommands:
RuntimeError: When there is no path to process.
"""
from openpype.hosts.webpublisher.cli_functions import (
from openpype.hosts.webpublisher.publish_functions import (
cli_publish
)

View file

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

View file

@ -111,14 +111,14 @@ class NiceCheckbox(QtWidgets.QFrame):
return QtCore.QSize(width, height)
def get_width_hint_by_height(self, height):
return (
height / self._base_size.height()
) * self._base_size.width()
return int((
float(height) / self._base_size.height()
) * self._base_size.width())
def get_height_hint_by_width(self, width):
return (
width / self._base_size.width()
) * self._base_size.height()
return int((
float(width) / self._base_size.width()
) * self._base_size.height())
def setFixedHeight(self, *args, **kwargs):
self._fixed_height_set = True
@ -321,7 +321,7 @@ class NiceCheckbox(QtWidgets.QFrame):
bg_color = self.unchecked_bg_color
else:
offset_ratio = self._current_step / self._steps
offset_ratio = float(self._current_step) / self._steps
# Animation bg
bg_color = self.steped_color(
self.checked_bg_color,
@ -332,7 +332,8 @@ class NiceCheckbox(QtWidgets.QFrame):
margins_ratio = self._checker_margins_divider
if margins_ratio > 0:
size_without_margins = int(
(frame_rect.height() / margins_ratio) * (margins_ratio - 2)
(float(frame_rect.height()) / margins_ratio)
* (margins_ratio - 2)
)
size_without_margins -= size_without_margins % 2
margin_size_c = ceil(
@ -434,21 +435,21 @@ class NiceCheckbox(QtWidgets.QFrame):
def _get_enabled_icon_path(
self, painter, checker_rect, step=None, half_steps=None
):
fifteenth = checker_rect.height() / 15
fifteenth = float(checker_rect.height()) / 15
# Left point
p1 = QtCore.QPoint(
checker_rect.x() + (5 * fifteenth),
checker_rect.y() + (9 * fifteenth)
int(checker_rect.x() + (5 * fifteenth)),
int(checker_rect.y() + (9 * fifteenth))
)
# Middle bottom point
p2 = QtCore.QPoint(
checker_rect.center().x(),
checker_rect.y() + (11 * fifteenth)
int(checker_rect.y() + (11 * fifteenth))
)
# Top right point
p3 = QtCore.QPoint(
checker_rect.x() + (10 * fifteenth),
checker_rect.y() + (5 * fifteenth)
int(checker_rect.x() + (10 * fifteenth)),
int(checker_rect.y() + (5 * fifteenth))
)
if step is not None:
multiplier = (half_steps - step)
@ -458,16 +459,16 @@ class NiceCheckbox(QtWidgets.QFrame):
p3c = p3 - checker_rect.center()
p1o = QtCore.QPoint(
(p1c.x() / half_steps) * multiplier,
(p1c.y() / half_steps) * multiplier
int((float(p1c.x()) / half_steps) * multiplier),
int((float(p1c.y()) / half_steps) * multiplier)
)
p2o = QtCore.QPoint(
(p2c.x() / half_steps) * multiplier,
(p2c.y() / half_steps) * multiplier
int((float(p2c.x()) / half_steps) * multiplier),
int((float(p2c.y()) / half_steps) * multiplier)
)
p3o = QtCore.QPoint(
(p3c.x() / half_steps) * multiplier,
(p3c.y() / half_steps) * multiplier
int((float(p3c.x()) / half_steps) * multiplier),
int((float(p3c.y()) / half_steps) * multiplier)
)
p1 -= p1o
@ -484,11 +485,12 @@ class NiceCheckbox(QtWidgets.QFrame):
self, painter, checker_rect, step=None, half_steps=None
):
center_point = QtCore.QPointF(
checker_rect.width() / 2, checker_rect.height() / 2
float(checker_rect.width()) / 2,
float(checker_rect.height()) / 2
)
offset = (
offset = float((
(center_point + QtCore.QPointF(0, 0)) / 2
).x() / 4 * 5
).x()) / 4 * 5
if step is not None:
diff = center_point.x() - offset
diff_offset = (diff / half_steps) * (half_steps - step)