mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge branch 'develop' of github.com:pypeclub/OpenPype into feature/OP-3426_Add-support-for-Deadline-for-automatic-tests
This commit is contained in:
commit
90bc39b4d4
60 changed files with 287 additions and 323 deletions
|
|
@ -1,5 +1,4 @@
|
|||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
|
||||
class AfterEffectsAddon(OpenPypeModule, IHostAddon):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
BLENDER_ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
HOST_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
FUSION_HOST_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
HARMONY_HOST_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import os
|
||||
import platform
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
HIERO_ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
HOUDINI_HOST_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
MAYA_ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import os
|
||||
import platform
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
NUKE_ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
PHOTOSHOP_HOST_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import os
|
||||
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
from .utils import RESOLVE_ROOT_DIR
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ import click
|
|||
|
||||
from openpype.lib import get_openpype_execute_args
|
||||
from openpype.lib.execute import run_detached_process
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import ITrayAction, IHostAddon
|
||||
from openpype.modules import OpenPypeModule, ITrayAction, IHostAddon
|
||||
|
||||
STANDALONEPUBLISH_ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ import click
|
|||
|
||||
from openpype.lib import get_openpype_execute_args
|
||||
from openpype.lib.execute import run_detached_process
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import ITrayAction, IHostAddon
|
||||
from openpype.modules import OpenPypeModule, ITrayAction, IHostAddon
|
||||
|
||||
TRAYPUBLISH_ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,54 +1,32 @@
|
|||
import collections
|
||||
|
||||
from openpype.lib.attribute_definitions import FileDef
|
||||
from openpype.lib.transcoding import IMAGE_EXTENSIONS, VIDEO_EXTENSIONS
|
||||
from openpype.pipeline.create import (
|
||||
Creator,
|
||||
HiddenCreator,
|
||||
CreatedInstance,
|
||||
cache_and_get_instances,
|
||||
PRE_CREATE_THUMBNAIL_KEY,
|
||||
)
|
||||
|
||||
from .pipeline import (
|
||||
list_instances,
|
||||
update_instances,
|
||||
remove_instances,
|
||||
HostContext,
|
||||
)
|
||||
from openpype.lib.transcoding import IMAGE_EXTENSIONS, VIDEO_EXTENSIONS
|
||||
|
||||
|
||||
REVIEW_EXTENSIONS = set(IMAGE_EXTENSIONS) | set(VIDEO_EXTENSIONS)
|
||||
|
||||
|
||||
def _cache_and_get_instances(creator):
|
||||
"""Cache instances in shared data.
|
||||
|
||||
Args:
|
||||
creator (Creator): Plugin which would like to get instances from host.
|
||||
|
||||
Returns:
|
||||
List[Dict[str, Any]]: Cached instances list from host implementation.
|
||||
"""
|
||||
|
||||
shared_key = "openpype.traypublisher.instances"
|
||||
if shared_key not in creator.collection_shared_data:
|
||||
instances_by_creator_id = collections.defaultdict(list)
|
||||
for instance_data in list_instances():
|
||||
creator_id = instance_data.get("creator_identifier")
|
||||
instances_by_creator_id[creator_id].append(instance_data)
|
||||
creator.collection_shared_data[shared_key] = instances_by_creator_id
|
||||
return creator.collection_shared_data[shared_key]
|
||||
SHARED_DATA_KEY = "openpype.traypublisher.instances"
|
||||
|
||||
|
||||
class HiddenTrayPublishCreator(HiddenCreator):
|
||||
host_name = "traypublisher"
|
||||
|
||||
def collect_instances(self):
|
||||
instance_data_by_identifier = _cache_and_get_instances(self)
|
||||
for instance_data in instance_data_by_identifier[self.identifier]:
|
||||
instance = CreatedInstance.from_existing(
|
||||
instance_data, self
|
||||
)
|
||||
instances_by_identifier = cache_and_get_instances(
|
||||
self, SHARED_DATA_KEY, list_instances
|
||||
)
|
||||
for instance_data in instances_by_identifier[self.identifier]:
|
||||
instance = CreatedInstance.from_existing(instance_data, self)
|
||||
self._add_instance_to_context(instance)
|
||||
|
||||
def update_instances(self, update_list):
|
||||
|
|
@ -80,11 +58,11 @@ class TrayPublishCreator(Creator):
|
|||
host_name = "traypublisher"
|
||||
|
||||
def collect_instances(self):
|
||||
instance_data_by_identifier = _cache_and_get_instances(self)
|
||||
for instance_data in instance_data_by_identifier[self.identifier]:
|
||||
instance = CreatedInstance.from_existing(
|
||||
instance_data, self
|
||||
)
|
||||
instances_by_identifier = cache_and_get_instances(
|
||||
self, SHARED_DATA_KEY, list_instances
|
||||
)
|
||||
for instance_data in instances_by_identifier[self.identifier]:
|
||||
instance = CreatedInstance.from_existing(instance_data, self)
|
||||
self._add_instance_to_context(instance)
|
||||
|
||||
def update_instances(self, update_list):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
TVPAINT_ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import qargparse
|
||||
from openpype.lib.attribute_definitions import BoolDef
|
||||
from openpype.hosts.tvpaint.api import plugin
|
||||
from openpype.hosts.tvpaint.api.lib import execute_george_through_file
|
||||
|
||||
|
|
@ -27,26 +27,28 @@ class ImportImage(plugin.Loader):
|
|||
"preload": True
|
||||
}
|
||||
|
||||
options = [
|
||||
qargparse.Boolean(
|
||||
"stretch",
|
||||
label="Stretch to project size",
|
||||
default=True,
|
||||
help="Stretch loaded image/s to project resolution?"
|
||||
),
|
||||
qargparse.Boolean(
|
||||
"timestretch",
|
||||
label="Stretch to timeline length",
|
||||
default=True,
|
||||
help="Clip loaded image/s to timeline length?"
|
||||
),
|
||||
qargparse.Boolean(
|
||||
"preload",
|
||||
label="Preload loaded image/s",
|
||||
default=True,
|
||||
help="Preload image/s?"
|
||||
)
|
||||
]
|
||||
@classmethod
|
||||
def get_options(cls, contexts):
|
||||
return [
|
||||
BoolDef(
|
||||
"stretch",
|
||||
label="Stretch to project size",
|
||||
default=cls.defaults["stretch"],
|
||||
tooltip="Stretch loaded image/s to project resolution?"
|
||||
),
|
||||
BoolDef(
|
||||
"timestretch",
|
||||
label="Stretch to timeline length",
|
||||
default=cls.defaults["timestretch"],
|
||||
tooltip="Clip loaded image/s to timeline length?"
|
||||
),
|
||||
BoolDef(
|
||||
"preload",
|
||||
label="Preload loaded image/s",
|
||||
default=cls.defaults["preload"],
|
||||
tooltip="Preload image/s?"
|
||||
)
|
||||
]
|
||||
|
||||
def load(self, context, name, namespace, options):
|
||||
stretch = options.get("stretch", self.defaults["stretch"])
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import collections
|
||||
|
||||
import qargparse
|
||||
|
||||
from openpype.lib.attribute_definitions import BoolDef
|
||||
from openpype.pipeline import (
|
||||
get_representation_context,
|
||||
register_host,
|
||||
|
|
@ -42,26 +41,28 @@ class LoadImage(plugin.Loader):
|
|||
"preload": True
|
||||
}
|
||||
|
||||
options = [
|
||||
qargparse.Boolean(
|
||||
"stretch",
|
||||
label="Stretch to project size",
|
||||
default=True,
|
||||
help="Stretch loaded image/s to project resolution?"
|
||||
),
|
||||
qargparse.Boolean(
|
||||
"timestretch",
|
||||
label="Stretch to timeline length",
|
||||
default=True,
|
||||
help="Clip loaded image/s to timeline length?"
|
||||
),
|
||||
qargparse.Boolean(
|
||||
"preload",
|
||||
label="Preload loaded image/s",
|
||||
default=True,
|
||||
help="Preload image/s?"
|
||||
)
|
||||
]
|
||||
@classmethod
|
||||
def get_options(cls, contexts):
|
||||
return [
|
||||
BoolDef(
|
||||
"stretch",
|
||||
label="Stretch to project size",
|
||||
default=cls.defaults["stretch"],
|
||||
tooltip="Stretch loaded image/s to project resolution?"
|
||||
),
|
||||
BoolDef(
|
||||
"timestretch",
|
||||
label="Stretch to timeline length",
|
||||
default=cls.defaults["timestretch"],
|
||||
tooltip="Clip loaded image/s to timeline length?"
|
||||
),
|
||||
BoolDef(
|
||||
"preload",
|
||||
label="Preload loaded image/s",
|
||||
default=cls.defaults["preload"],
|
||||
tooltip="Preload image/s?"
|
||||
)
|
||||
]
|
||||
|
||||
def load(self, context, name, namespace, options):
|
||||
stretch = options.get("stretch", self.defaults["stretch"])
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
UNREAL_ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import os
|
|||
|
||||
import click
|
||||
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IHostAddon
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
WEBPUBLISHER_ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -83,8 +83,9 @@ class CollectPublishedFiles(pyblish.api.ContextPlugin):
|
|||
self.log.info("task_data:: {}".format(task_data))
|
||||
|
||||
is_sequence = len(task_data["files"]) > 1
|
||||
first_file = task_data["files"][0]
|
||||
|
||||
_, extension = os.path.splitext(task_data["files"][0])
|
||||
_, extension = os.path.splitext(first_file)
|
||||
family, families, tags = self._get_family(
|
||||
self.task_type_to_family,
|
||||
task_type,
|
||||
|
|
@ -149,10 +150,13 @@ class CollectPublishedFiles(pyblish.api.ContextPlugin):
|
|||
self.log.warning("Unable to count frames "
|
||||
"duration {}".format(no_of_frames))
|
||||
|
||||
# raise ValueError("STOP")
|
||||
instance.data["handleStart"] = asset_doc["data"]["handleStart"]
|
||||
instance.data["handleEnd"] = asset_doc["data"]["handleEnd"]
|
||||
|
||||
if "review" in tags:
|
||||
first_file_path = os.path.join(task_dir, first_file)
|
||||
instance.data["thumbnailSource"] = first_file_path
|
||||
|
||||
instances.append(instance)
|
||||
self.log.info("instance.data:: {}".format(instance.data))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,137 +0,0 @@
|
|||
import os
|
||||
import shutil
|
||||
|
||||
import pyblish.api
|
||||
from openpype.lib import (
|
||||
get_ffmpeg_tool_path,
|
||||
|
||||
run_subprocess,
|
||||
|
||||
get_transcode_temp_directory,
|
||||
convert_input_paths_for_ffmpeg,
|
||||
should_convert_for_ffmpeg
|
||||
)
|
||||
|
||||
|
||||
class ExtractThumbnail(pyblish.api.InstancePlugin):
|
||||
"""Create jpg thumbnail from input using ffmpeg."""
|
||||
|
||||
label = "Extract Thumbnail"
|
||||
order = pyblish.api.ExtractorOrder
|
||||
families = [
|
||||
"render",
|
||||
"image"
|
||||
]
|
||||
hosts = ["webpublisher"]
|
||||
targets = ["filespublish"]
|
||||
|
||||
def process(self, instance):
|
||||
self.log.info("subset {}".format(instance.data['subset']))
|
||||
|
||||
filtered_repres = self._get_filtered_repres(instance)
|
||||
for repre in filtered_repres:
|
||||
repre_files = repre["files"]
|
||||
if not isinstance(repre_files, (list, tuple)):
|
||||
input_file = repre_files
|
||||
else:
|
||||
file_index = int(float(len(repre_files)) * 0.5)
|
||||
input_file = repre_files[file_index]
|
||||
|
||||
stagingdir = os.path.normpath(repre["stagingDir"])
|
||||
|
||||
full_input_path = os.path.join(stagingdir, input_file)
|
||||
self.log.info("Input filepath: {}".format(full_input_path))
|
||||
|
||||
do_convert = should_convert_for_ffmpeg(full_input_path)
|
||||
# If result is None the requirement of conversion can't be
|
||||
# determined
|
||||
if do_convert is None:
|
||||
self.log.info((
|
||||
"Can't determine if representation requires conversion."
|
||||
" Skipped."
|
||||
))
|
||||
continue
|
||||
|
||||
# Do conversion if needed
|
||||
# - change staging dir of source representation
|
||||
# - must be set back after output definitions processing
|
||||
convert_dir = None
|
||||
if do_convert:
|
||||
convert_dir = get_transcode_temp_directory()
|
||||
filename = os.path.basename(full_input_path)
|
||||
convert_input_paths_for_ffmpeg(
|
||||
[full_input_path],
|
||||
convert_dir,
|
||||
self.log
|
||||
)
|
||||
full_input_path = os.path.join(convert_dir, filename)
|
||||
|
||||
filename = os.path.splitext(input_file)[0]
|
||||
while filename.endswith("."):
|
||||
filename = filename[:-1]
|
||||
thumbnail_filename = filename + "_thumbnail.jpg"
|
||||
full_output_path = os.path.join(stagingdir, thumbnail_filename)
|
||||
|
||||
self.log.info("output {}".format(full_output_path))
|
||||
|
||||
ffmpeg_args = [
|
||||
get_ffmpeg_tool_path("ffmpeg"),
|
||||
"-y",
|
||||
"-i", full_input_path,
|
||||
"-vframes", "1",
|
||||
full_output_path
|
||||
]
|
||||
|
||||
# run subprocess
|
||||
self.log.debug("{}".format(" ".join(ffmpeg_args)))
|
||||
try: # temporary until oiiotool is supported cross platform
|
||||
run_subprocess(
|
||||
ffmpeg_args, logger=self.log
|
||||
)
|
||||
except RuntimeError as exp:
|
||||
if "Compression" in str(exp):
|
||||
self.log.debug(
|
||||
"Unsupported compression on input files. Skipping!!!"
|
||||
)
|
||||
return
|
||||
self.log.warning("Conversion crashed", exc_info=True)
|
||||
raise
|
||||
|
||||
new_repre = {
|
||||
"name": "thumbnail",
|
||||
"ext": "jpg",
|
||||
"files": thumbnail_filename,
|
||||
"stagingDir": stagingdir,
|
||||
"thumbnail": True,
|
||||
"tags": ["thumbnail"]
|
||||
}
|
||||
|
||||
# adding representation
|
||||
self.log.debug("Adding: {}".format(new_repre))
|
||||
instance.data["representations"].append(new_repre)
|
||||
|
||||
# Cleanup temp folder
|
||||
if convert_dir is not None and os.path.exists(convert_dir):
|
||||
shutil.rmtree(convert_dir)
|
||||
|
||||
def _get_filtered_repres(self, instance):
|
||||
filtered_repres = []
|
||||
repres = instance.data.get("representations") or []
|
||||
for repre in repres:
|
||||
self.log.debug(repre)
|
||||
tags = repre.get("tags") or []
|
||||
# Skip instance if already has thumbnail representation
|
||||
if "thumbnail" in tags:
|
||||
return []
|
||||
|
||||
if "review" not in tags:
|
||||
continue
|
||||
|
||||
if not repre.get("files"):
|
||||
self.log.info((
|
||||
"Representation \"{}\" don't have files. Skipping"
|
||||
).format(repre["name"]))
|
||||
continue
|
||||
|
||||
filtered_repres.append(repre)
|
||||
return filtered_repres
|
||||
|
|
@ -91,7 +91,7 @@ class AbstractAttrDefMeta(ABCMeta):
|
|||
|
||||
|
||||
@six.add_metaclass(AbstractAttrDefMeta)
|
||||
class AbtractAttrDef:
|
||||
class AbtractAttrDef(object):
|
||||
"""Abstraction of attribute definiton.
|
||||
|
||||
Each attribute definition must have implemented validation and
|
||||
|
|
|
|||
|
|
@ -1,4 +1,14 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from .interfaces import (
|
||||
ILaunchHookPaths,
|
||||
IPluginPaths,
|
||||
ITrayModule,
|
||||
ITrayAction,
|
||||
ITrayService,
|
||||
ISettingsChangeListener,
|
||||
IHostAddon,
|
||||
)
|
||||
|
||||
from .base import (
|
||||
OpenPypeModule,
|
||||
OpenPypeAddOn,
|
||||
|
|
@ -17,6 +27,14 @@ from .base import (
|
|||
|
||||
|
||||
__all__ = (
|
||||
"ILaunchHookPaths",
|
||||
"IPluginPaths",
|
||||
"ITrayModule",
|
||||
"ITrayAction",
|
||||
"ITrayService",
|
||||
"ISettingsChangeListener",
|
||||
"IHostAddon",
|
||||
|
||||
"OpenPypeModule",
|
||||
"OpenPypeAddOn",
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import os
|
||||
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import ITrayModule
|
||||
from openpype.modules import OpenPypeModule, ITrayModule
|
||||
|
||||
|
||||
class AvalonModule(OpenPypeModule, ITrayModule):
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import logging
|
|||
import platform
|
||||
import threading
|
||||
import collections
|
||||
import traceback
|
||||
from uuid import uuid4
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import six
|
||||
|
|
@ -139,6 +140,15 @@ class _InterfacesClass(_ModuleClass):
|
|||
"cannot import name '{}' from 'openpype_interfaces'"
|
||||
).format(attr_name))
|
||||
|
||||
if _LoadCache.interfaces_loaded and attr_name != "log":
|
||||
stack = list(traceback.extract_stack())
|
||||
stack.pop(-1)
|
||||
self.log.warning((
|
||||
"Using deprecated import of \"{}\" from 'openpype_interfaces'."
|
||||
" Please switch to use import"
|
||||
" from 'openpype.modules.interfaces'"
|
||||
" (will be removed after 3.16.x).{}"
|
||||
).format(attr_name, "".join(traceback.format_list(stack))))
|
||||
return self.__attributes__[attr_name]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,16 +2,17 @@ import os
|
|||
import threading
|
||||
import time
|
||||
|
||||
from openpype.modules import (
|
||||
OpenPypeModule,
|
||||
ITrayModule,
|
||||
IPluginPaths
|
||||
)
|
||||
|
||||
from .clockify_api import ClockifyAPI
|
||||
from .constants import (
|
||||
CLOCKIFY_FTRACK_USER_PATH,
|
||||
CLOCKIFY_FTRACK_SERVER_PATH
|
||||
)
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import (
|
||||
ITrayModule,
|
||||
IPluginPaths
|
||||
)
|
||||
|
||||
|
||||
class ClockifyModule(
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ import six
|
|||
import sys
|
||||
|
||||
from openpype.lib import requests_get, Logger
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import IPluginPaths
|
||||
from openpype.modules import OpenPypeModule, IPluginPaths
|
||||
|
||||
|
||||
class DeadlineWebserviceError(Exception):
|
||||
|
|
|
|||
|
|
@ -13,10 +13,7 @@ import click
|
|||
from openpype.modules import (
|
||||
JsonFilesSettingsDef,
|
||||
OpenPypeAddOn,
|
||||
ModulesManager
|
||||
)
|
||||
# Import interface defined by this addon to be able find other addons using it
|
||||
from openpype_interfaces import (
|
||||
ModulesManager,
|
||||
IPluginPaths,
|
||||
ITrayAction
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import platform
|
|||
|
||||
import click
|
||||
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import (
|
||||
from openpype.modules import (
|
||||
OpenPypeModule,
|
||||
ITrayModule,
|
||||
IPluginPaths,
|
||||
ISettingsChangeListener
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@
|
|||
import click
|
||||
import os
|
||||
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import IPluginPaths, ITrayAction
|
||||
from openpype.modules import (
|
||||
OpenPypeModule,
|
||||
IPluginPaths,
|
||||
ITrayAction,
|
||||
)
|
||||
|
||||
|
||||
class KitsuModule(OpenPypeModule, IPluginPaths, ITrayAction):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import ITrayAction
|
||||
from openpype.modules import (
|
||||
OpenPypeModule,
|
||||
ITrayAction,
|
||||
)
|
||||
|
||||
|
||||
class LauncherAction(OpenPypeModule, ITrayAction):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import ITrayModule
|
||||
from openpype.modules import OpenPypeModule, ITrayModule
|
||||
|
||||
|
||||
class LogViewModule(OpenPypeModule, ITrayModule):
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import os
|
|||
import json
|
||||
import appdirs
|
||||
import requests
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import ITrayModule
|
||||
from openpype.modules import OpenPypeModule, ITrayModule
|
||||
|
||||
|
||||
class MusterModule(OpenPypeModule, ITrayModule):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import ITrayAction
|
||||
from openpype.modules import OpenPypeModule, ITrayAction
|
||||
|
||||
|
||||
class ProjectManagerAction(OpenPypeModule, ITrayAction):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import ITrayAction
|
||||
from openpype.modules import OpenPypeModule, ITrayAction
|
||||
|
||||
|
||||
class PythonInterpreterAction(OpenPypeModule, ITrayAction):
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
"""Module providing support for Royal Render."""
|
||||
import os
|
||||
import openpype.modules
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import IPluginPaths
|
||||
from openpype.modules import OpenPypeModule, IPluginPaths
|
||||
|
||||
|
||||
class RoyalRenderModule(OpenPypeModule, IPluginPaths):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import ITrayAction
|
||||
from openpype.modules import OpenPypeModule, ITrayAction
|
||||
|
||||
|
||||
class SettingsAction(OpenPypeModule, ITrayAction):
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import os
|
||||
|
||||
from openpype_interfaces import (
|
||||
from openpype.modules import (
|
||||
OpenPypeModule,
|
||||
ITrayModule,
|
||||
IPluginPaths,
|
||||
)
|
||||
|
||||
from openpype.modules import OpenPypeModule
|
||||
|
||||
SHOTGRID_MODULE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype.modules.interfaces import IPluginPaths
|
||||
from openpype.modules import OpenPypeModule, IPluginPaths
|
||||
|
||||
SLACK_MODULE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,12 @@ from collections import deque, defaultdict
|
|||
import click
|
||||
from bson.objectid import ObjectId
|
||||
|
||||
from openpype.client import get_projects
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import ITrayModule
|
||||
from openpype.client import (
|
||||
get_projects,
|
||||
get_representations,
|
||||
get_representation_by_id,
|
||||
)
|
||||
from openpype.modules import OpenPypeModule, ITrayModule
|
||||
from openpype.settings import (
|
||||
get_project_settings,
|
||||
get_system_settings,
|
||||
|
|
@ -30,9 +33,6 @@ from .providers import lib
|
|||
|
||||
from .utils import time_function, SyncStatus, SiteAlreadyPresentError
|
||||
|
||||
from openpype.client import get_representations, get_representation_by_id
|
||||
|
||||
|
||||
log = Logger.get_logger("SyncServer")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import platform
|
|||
|
||||
|
||||
from openpype.client import get_asset_by_name
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import (
|
||||
from openpype.modules import (
|
||||
OpenPypeModule,
|
||||
ITrayService,
|
||||
IPluginPaths
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import logging
|
|||
from concurrent.futures import CancelledError
|
||||
from Qt import QtWidgets
|
||||
|
||||
from openpype_interfaces import ITrayService
|
||||
from openpype.modules import ITrayService
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@ import os
|
|||
import socket
|
||||
|
||||
from openpype import resources
|
||||
from openpype.modules import OpenPypeModule
|
||||
from openpype_interfaces import ITrayService
|
||||
from openpype.modules import OpenPypeModule, ITrayService
|
||||
|
||||
|
||||
class WebServerModule(OpenPypeModule, ITrayService):
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ from .creator_plugins import (
|
|||
deregister_creator_plugin,
|
||||
register_creator_plugin_path,
|
||||
deregister_creator_plugin_path,
|
||||
|
||||
cache_and_get_instances,
|
||||
)
|
||||
|
||||
from .context import (
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
import copy
|
||||
import collections
|
||||
|
||||
from abc import (
|
||||
ABCMeta,
|
||||
|
|
@ -674,3 +675,34 @@ def deregister_creator_plugin_path(path):
|
|||
deregister_plugin_path(BaseCreator, path)
|
||||
deregister_plugin_path(LegacyCreator, path)
|
||||
deregister_plugin_path(SubsetConvertorPlugin, path)
|
||||
|
||||
|
||||
def cache_and_get_instances(creator, shared_key, list_instances_func):
|
||||
"""Common approach to cache instances in shared data.
|
||||
|
||||
This is helper function which does not handle cases when a 'shared_key' is
|
||||
used for different list instances functions. The same approach of caching
|
||||
instances into 'collection_shared_data' is not required but is so common
|
||||
we've decided to unify it to some degree.
|
||||
|
||||
Function 'list_instances_func' is called only if 'shared_key' is not
|
||||
available in 'collection_shared_data' on creator.
|
||||
|
||||
Args:
|
||||
creator (Creator): Plugin which would like to get instance data.
|
||||
shared_key (str): Key under which output of function will be stored.
|
||||
list_instances_func (Function): Function that will return instance data
|
||||
if data were not yet stored under 'shared_key'.
|
||||
|
||||
Returns:
|
||||
Dict[str, Dict[str, Any]]: Cached instances by creator identifier from
|
||||
result of passed function.
|
||||
"""
|
||||
|
||||
if shared_key not in creator.collection_shared_data:
|
||||
value = collections.defaultdict(list)
|
||||
for instance in list_instances_func():
|
||||
identifier = instance.get("creator_identifier")
|
||||
value[identifier].append(instance)
|
||||
creator.collection_shared_data[shared_key] = value
|
||||
return creator.collection_shared_data[shared_key]
|
||||
|
|
|
|||
|
|
@ -21,9 +21,8 @@ class PreIntegrateThumbnails(pyblish.api.InstancePlugin):
|
|||
|
||||
label = "Override Integrate Thumbnail Representations"
|
||||
order = pyblish.api.IntegratorOrder - 0.1
|
||||
families = ["review"]
|
||||
|
||||
integrate_profiles = {}
|
||||
integrate_profiles = []
|
||||
|
||||
def process(self, instance):
|
||||
repres = instance.data.get("representations")
|
||||
|
|
|
|||
|
|
@ -138,8 +138,7 @@ def save_studio_settings(data):
|
|||
SaveWarningExc: If any module raises the exception.
|
||||
"""
|
||||
# Notify Pype modules
|
||||
from openpype.modules import ModulesManager
|
||||
from openpype_interfaces import ISettingsChangeListener
|
||||
from openpype.modules import ModulesManager, ISettingsChangeListener
|
||||
|
||||
old_data = get_system_settings()
|
||||
default_values = get_default_settings()[SYSTEM_SETTINGS_KEY]
|
||||
|
|
@ -186,8 +185,7 @@ def save_project_settings(project_name, overrides):
|
|||
SaveWarningExc: If any module raises the exception.
|
||||
"""
|
||||
# Notify Pype modules
|
||||
from openpype.modules import ModulesManager
|
||||
from openpype_interfaces import ISettingsChangeListener
|
||||
from openpype.modules import ModulesManager, ISettingsChangeListener
|
||||
|
||||
default_values = get_default_settings()[PROJECT_SETTINGS_KEY]
|
||||
if project_name:
|
||||
|
|
@ -248,8 +246,7 @@ def save_project_anatomy(project_name, anatomy_data):
|
|||
SaveWarningExc: If any module raises the exception.
|
||||
"""
|
||||
# Notify Pype modules
|
||||
from openpype.modules import ModulesManager
|
||||
from openpype_interfaces import ISettingsChangeListener
|
||||
from openpype.modules import ModulesManager, ISettingsChangeListener
|
||||
|
||||
default_values = get_default_settings()[PROJECT_ANATOMY_KEY]
|
||||
if project_name:
|
||||
|
|
|
|||
|
|
@ -3,8 +3,14 @@ from .widgets import (
|
|||
AttributeDefinitionsWidget,
|
||||
)
|
||||
|
||||
from .dialog import (
|
||||
AttributeDefinitionsDialog,
|
||||
)
|
||||
|
||||
|
||||
__all__ = (
|
||||
"create_widget_for_attr_def",
|
||||
"AttributeDefinitionsWidget",
|
||||
|
||||
"AttributeDefinitionsDialog",
|
||||
)
|
||||
33
openpype/tools/attribute_defs/dialog.py
Normal file
33
openpype/tools/attribute_defs/dialog.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
from Qt import QtWidgets
|
||||
|
||||
from .widgets import AttributeDefinitionsWidget
|
||||
|
||||
|
||||
class AttributeDefinitionsDialog(QtWidgets.QDialog):
|
||||
def __init__(self, attr_defs, parent=None):
|
||||
super(AttributeDefinitionsDialog, self).__init__(parent)
|
||||
|
||||
attrs_widget = AttributeDefinitionsWidget(attr_defs, self)
|
||||
|
||||
btns_widget = QtWidgets.QWidget(self)
|
||||
ok_btn = QtWidgets.QPushButton("OK", btns_widget)
|
||||
cancel_btn = QtWidgets.QPushButton("Cancel", btns_widget)
|
||||
|
||||
btns_layout = QtWidgets.QHBoxLayout(btns_widget)
|
||||
btns_layout.setContentsMargins(0, 0, 0, 0)
|
||||
btns_layout.addStretch(1)
|
||||
btns_layout.addWidget(ok_btn, 0)
|
||||
btns_layout.addWidget(cancel_btn, 0)
|
||||
|
||||
main_layout = QtWidgets.QVBoxLayout(self)
|
||||
main_layout.addWidget(attrs_widget, 0)
|
||||
main_layout.addStretch(1)
|
||||
main_layout.addWidget(btns_widget, 0)
|
||||
|
||||
ok_btn.clicked.connect(self.accept)
|
||||
cancel_btn.clicked.connect(self.reject)
|
||||
|
||||
self._attrs_widget = attrs_widget
|
||||
|
||||
def get_values(self):
|
||||
return self._attrs_widget.current_value()
|
||||
|
|
@ -2,6 +2,8 @@ import inspect
|
|||
from Qt import QtGui
|
||||
import qtawesome
|
||||
|
||||
from openpype.lib.attribute_definitions import AbtractAttrDef
|
||||
from openpype.tools.attribute_defs import AttributeDefinitionsDialog
|
||||
from openpype.tools.utils.widgets import (
|
||||
OptionalAction,
|
||||
OptionDialog
|
||||
|
|
@ -34,21 +36,30 @@ def get_options(action, loader, parent, repre_contexts):
|
|||
None when dialog was closed or cancelled, in all other cases {}
|
||||
if no options
|
||||
"""
|
||||
|
||||
# Pop option dialog
|
||||
options = {}
|
||||
loader_options = loader.get_options(repre_contexts)
|
||||
if getattr(action, "optioned", False) and loader_options:
|
||||
if not getattr(action, "optioned", False) or not loader_options:
|
||||
return options
|
||||
|
||||
if isinstance(loader_options[0], AbtractAttrDef):
|
||||
qargparse_options = False
|
||||
dialog = AttributeDefinitionsDialog(loader_options, parent)
|
||||
else:
|
||||
qargparse_options = True
|
||||
dialog = OptionDialog(parent)
|
||||
dialog.setWindowTitle(action.label + " Options")
|
||||
dialog.create(loader_options)
|
||||
|
||||
if not dialog.exec_():
|
||||
return None
|
||||
dialog.setWindowTitle(action.label + " Options")
|
||||
|
||||
# Get option
|
||||
options = dialog.parse()
|
||||
if not dialog.exec_():
|
||||
return None
|
||||
|
||||
return options
|
||||
# Get option
|
||||
if qargparse_options:
|
||||
return dialog.parse()
|
||||
return dialog.get_values()
|
||||
|
||||
|
||||
def add_representation_loaders_to_menu(loaders, menu, repre_contexts):
|
||||
|
|
|
|||
|
|
@ -90,9 +90,9 @@ class AssetDocsCache:
|
|||
return
|
||||
|
||||
project_name = self._controller.project_name
|
||||
asset_docs = get_assets(
|
||||
asset_docs = list(get_assets(
|
||||
project_name, fields=self.projection.keys()
|
||||
)
|
||||
))
|
||||
asset_docs_by_name = {}
|
||||
task_names_by_asset_name = {}
|
||||
for asset_doc in asset_docs:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from Qt import QtWidgets, QtCore
|
||||
|
||||
from openpype.widgets.attribute_defs import create_widget_for_attr_def
|
||||
from openpype.tools.attribute_defs import create_widget_for_attr_def
|
||||
|
||||
|
||||
class PreCreateWidget(QtWidgets.QWidget):
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import collections
|
|||
from Qt import QtWidgets, QtCore, QtGui
|
||||
import qtawesome
|
||||
|
||||
from openpype.widgets.attribute_defs import create_widget_for_attr_def
|
||||
from openpype.tools.attribute_defs import create_widget_for_attr_def
|
||||
from openpype.tools import resources
|
||||
from openpype.tools.flickcharm import FlickCharm
|
||||
from openpype.tools.utils import (
|
||||
|
|
@ -1229,7 +1229,7 @@ class CreatorAttrsWidget(QtWidgets.QWidget):
|
|||
Attributes are defined on creator so are dynamic. Their look and type is
|
||||
based on attribute definitions that are defined in
|
||||
`~/openpype/pipeline/lib/attribute_definitions.py` and their widget
|
||||
representation in `~/openpype/widgets/attribute_defs/*`.
|
||||
representation in `~/openpype/tools/attribute_defs/*`.
|
||||
|
||||
Widgets are disabled if context of instance is not valid.
|
||||
|
||||
|
|
@ -1353,7 +1353,7 @@ class PublishPluginAttrsWidget(QtWidgets.QWidget):
|
|||
|
||||
Look and type of attributes is based on attribute definitions that are
|
||||
defined in `~/openpype/pipeline/lib/attribute_definitions.py` and their
|
||||
widget representation in `~/openpype/widgets/attribute_defs/*`.
|
||||
widget representation in `~/openpype/tools/attribute_defs/*`.
|
||||
|
||||
Widgets are disabled if context of instance is not valid.
|
||||
|
||||
|
|
|
|||
|
|
@ -892,6 +892,10 @@ class ProjectWidget(SettingsCategoryWidget):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super(ProjectWidget, self).__init__(*args, **kwargs)
|
||||
|
||||
def set_edit_mode(self, enabled):
|
||||
super(ProjectWidget, self).set_edit_mode(enabled)
|
||||
self.project_list_widget.set_edit_mode(enabled)
|
||||
|
||||
def _check_last_saved_info(self):
|
||||
if self.is_modifying_defaults:
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -646,6 +646,9 @@ class UnsavedChangesDialog(QtWidgets.QDialog):
|
|||
|
||||
def __init__(self, parent=None):
|
||||
super(UnsavedChangesDialog, self).__init__(parent)
|
||||
|
||||
self.setWindowTitle("Unsaved changes")
|
||||
|
||||
message_label = QtWidgets.QLabel(self.message)
|
||||
|
||||
btns_widget = QtWidgets.QWidget(self)
|
||||
|
|
@ -1009,6 +1012,7 @@ class ProjectListWidget(QtWidgets.QWidget):
|
|||
|
||||
self._entity = None
|
||||
self.current_project = None
|
||||
self._edit_mode = True
|
||||
|
||||
super(ProjectListWidget, self).__init__(parent)
|
||||
self.setObjectName("ProjectListWidget")
|
||||
|
|
@ -1061,6 +1065,10 @@ class ProjectListWidget(QtWidgets.QWidget):
|
|||
self.project_model = project_model
|
||||
self.inactive_chk = inactive_chk
|
||||
|
||||
def set_edit_mode(self, enabled):
|
||||
if self._edit_mode is not enabled:
|
||||
self._edit_mode = enabled
|
||||
|
||||
def set_entity(self, entity):
|
||||
self._entity = entity
|
||||
|
||||
|
|
@ -1112,7 +1120,7 @@ class ProjectListWidget(QtWidgets.QWidget):
|
|||
|
||||
save_changes = False
|
||||
change_project = False
|
||||
if self.validate_context_change():
|
||||
if not self._edit_mode or self.validate_context_change():
|
||||
change_project = True
|
||||
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ class TrayManager:
|
|||
|
||||
def initialize_modules(self):
|
||||
"""Add modules to tray."""
|
||||
from openpype_interfaces import (
|
||||
from openpype.modules import (
|
||||
ITrayAction,
|
||||
ITrayService
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@ import logging
|
|||
from Qt import QtWidgets, QtCore, QtGui
|
||||
import qargparse
|
||||
import qtawesome
|
||||
|
||||
from openpype.style import (
|
||||
get_objected_colors,
|
||||
get_style_image_path
|
||||
)
|
||||
from openpype.lib.attribute_definitions import AbtractAttrDef
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -401,8 +403,26 @@ class OptionalAction(QtWidgets.QWidgetAction):
|
|||
|
||||
def set_option_tip(self, options):
|
||||
sep = "\n\n"
|
||||
mak = (lambda opt: opt["name"] + " :\n " + opt["help"])
|
||||
self.option_tip = sep.join(mak(opt) for opt in options)
|
||||
if not options or not isinstance(options[0], AbtractAttrDef):
|
||||
mak = (lambda opt: opt["name"] + " :\n " + opt["help"])
|
||||
self.option_tip = sep.join(mak(opt) for opt in options)
|
||||
return
|
||||
|
||||
option_items = []
|
||||
for option in options:
|
||||
option_lines = []
|
||||
if option.label:
|
||||
option_lines.append(
|
||||
"{} ({}) :".format(option.label, option.key)
|
||||
)
|
||||
else:
|
||||
option_lines.append("{} :".format(option.key))
|
||||
|
||||
if option.tooltip:
|
||||
option_lines.append(" - {}".format(option.tooltip))
|
||||
option_items.append("\n".join(option_lines))
|
||||
|
||||
self.option_tip = sep.join(option_items)
|
||||
|
||||
def on_option(self):
|
||||
self.optioned = True
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from Qt import QtWidgets
|
|||
from openpype import style
|
||||
from openpype.lib import Logger
|
||||
from openpype.pipeline import legacy_io
|
||||
from openpype.widgets.attribute_defs import AttributeDefinitionsWidget
|
||||
from openpype.tools.attribute_defs import AttributeDefinitionsWidget
|
||||
|
||||
|
||||
class WorkfileBuildPlaceholderDialog(QtWidgets.QDialog):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue