From e14b0b284227db0acb3a8e89a540676ee1e39d39 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 31 Oct 2022 11:14:35 +0100 Subject: [PATCH 01/30] OP-3908 - whitelist all DCC but Adobe Going further Adobe DCC should switch to new publisher by default, eg. Publisher is not experimental for them anymore. --- openpype/tools/experimental_tools/tools_def.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/tools/experimental_tools/tools_def.py b/openpype/tools/experimental_tools/tools_def.py index d3a1caa60e..3275e7b87d 100644 --- a/openpype/tools/experimental_tools/tools_def.py +++ b/openpype/tools/experimental_tools/tools_def.py @@ -88,7 +88,10 @@ class ExperimentalTools: "publisher", "New publisher", "Combined creation and publishing into one tool.", - self._show_publisher + self._show_publisher, + hosts_filter=["blender", "maya", "nuke", "celaction", "flame", + "fusion", "harmony", "hiero", "resolve", + "tvpaint", "unreal"] ), ExperimentalTool( "traypublisher", From c43180aeca8c8a62c4f558e2ec4000dd364997a8 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 31 Oct 2022 11:16:14 +0100 Subject: [PATCH 02/30] OP-3908 - switch Photoshop to New Publisher --- openpype/hosts/photoshop/api/extension.zxp | Bin 54111 -> 54103 bytes .../hosts/photoshop/api/extension/index.html | 11 ----------- openpype/hosts/photoshop/api/launch_logic.py | 5 +---- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/openpype/hosts/photoshop/api/extension.zxp b/openpype/hosts/photoshop/api/extension.zxp index a25ec96e7df2348e558277faedf4f74561a7f316..b6bdb9f85d6857bde552c39eaf46f580284eefba 100644 GIT binary patch delta 3436 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 delta 3461 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 diff --git a/openpype/hosts/photoshop/api/extension/index.html b/openpype/hosts/photoshop/api/extension/index.html index 501e753c0b..f2cb30e313 100644 --- a/openpype/hosts/photoshop/api/extension/index.html +++ b/openpype/hosts/photoshop/api/extension/index.html @@ -32,17 +32,6 @@ }); - - - From bc945e9c41dee9946e94c276c2517d0e0b72af48 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 31 Oct 2022 12:01:38 +0100 Subject: [PATCH 04/30] OP-3908 - fix - wrong regex --- .../photoshop/plugins/publish/collect_extension_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/photoshop/plugins/publish/collect_extension_version.py b/openpype/hosts/photoshop/plugins/publish/collect_extension_version.py index 64c99b4fc1..dc0678c9af 100644 --- a/openpype/hosts/photoshop/plugins/publish/collect_extension_version.py +++ b/openpype/hosts/photoshop/plugins/publish/collect_extension_version.py @@ -43,7 +43,7 @@ class CollectExtensionVersion(pyblish.api.ContextPlugin): with open(manifest_url) as fp: content = fp.read() - found = re.findall(r'(ExtensionBundleVersion=")([0-10\.]+)(")', + found = re.findall(r'(ExtensionBundleVersion=")([0-9\.]+)(")', content) if found: expected_version = found[0][1] From 7809f833c38146cc081e223557fc962e5c81fccd Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 31 Oct 2022 18:31:17 +0100 Subject: [PATCH 05/30] OP-3908 - remove SubsetManager rout Functionality already in Publisher. Moved list_instances and remove_instances directly into PhotoshopHost (needed for Creators). --- openpype/hosts/photoshop/api/__init__.py | 35 +-- openpype/hosts/photoshop/api/launch_logic.py | 3 - openpype/hosts/photoshop/api/pipeline.py | 256 ++++++++++-------- .../photoshop/plugins/create/create_image.py | 5 +- .../plugins/create/workfile_creator.py | 3 +- .../plugins/publish/collect_instances.py | 2 +- .../publish/validate_unique_subsets.py | 2 +- 7 files changed, 159 insertions(+), 147 deletions(-) diff --git a/openpype/hosts/photoshop/api/__init__.py b/openpype/hosts/photoshop/api/__init__.py index 94152b5706..c5a12cba06 100644 --- a/openpype/hosts/photoshop/api/__init__.py +++ b/openpype/hosts/photoshop/api/__init__.py @@ -7,28 +7,15 @@ Anything that isn't defined here is INTERNAL and unreliable for external use. from .launch_logic import stub from .pipeline import ( + PhotoshopHost, ls, - list_instances, - remove_instance, - install, - uninstall, - containerise, - get_context_data, - update_context_data, - get_context_title + containerise ) from .plugin import ( PhotoshopLoader, get_unique_layer_name ) -from .workio import ( - file_extensions, - has_unsaved_changes, - save_file, - open_file, - current_file, - work_root, -) + from .lib import ( maintained_selection, @@ -40,28 +27,14 @@ __all__ = [ "stub", # pipeline + "PhotoshopHost", "ls", - "list_instances", - "remove_instance", - "install", - "uninstall", "containerise", - "get_context_data", - "update_context_data", - "get_context_title", # Plugin "PhotoshopLoader", "get_unique_layer_name", - # workfiles - "file_extensions", - "has_unsaved_changes", - "save_file", - "open_file", - "current_file", - "work_root", - # lib "maintained_selection", "maintained_visibility", diff --git a/openpype/hosts/photoshop/api/launch_logic.py b/openpype/hosts/photoshop/api/launch_logic.py index 669d31c804..97a2dd94f6 100644 --- a/openpype/hosts/photoshop/api/launch_logic.py +++ b/openpype/hosts/photoshop/api/launch_logic.py @@ -346,9 +346,6 @@ class PhotoshopRoute(WebSocketRoute): async def sceneinventory_route(self): self._tool_route("sceneinventory") - async def subsetmanager_route(self): - self._tool_route("subsetmanager") - async def experimental_tools_route(self): self._tool_route("experimental_tools") diff --git a/openpype/hosts/photoshop/api/pipeline.py b/openpype/hosts/photoshop/api/pipeline.py index 9f6fc0983c..dbf7426e95 100644 --- a/openpype/hosts/photoshop/api/pipeline.py +++ b/openpype/hosts/photoshop/api/pipeline.py @@ -12,6 +12,13 @@ from openpype.pipeline import ( deregister_creator_plugin_path, AVALON_CONTAINER_ID, ) + +from openpype.host import ( + HostBase, + IWorkfileHost, + ILoadHost, +) + from openpype.pipeline.load import any_outdated_containers from openpype.hosts.photoshop import PHOTOSHOP_HOST_DIR @@ -26,6 +33,147 @@ CREATE_PATH = os.path.join(PLUGINS_DIR, "create") INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory") +class PhotoshopHost(HostBase, IWorkfileHost, ILoadHost): + name = "photoshop" + + def __init__(self): + super(PhotoshopHost, self).__init__() + + def install(self): + """Install Photoshop-specific functionality of avalon-core. + + This function is called automatically on calling `api.install(photoshop)`. + """ + log.info("Installing OpenPype Photoshop...") + pyblish.api.register_host("photoshop") + + pyblish.api.register_plugin_path(PUBLISH_PATH) + register_loader_plugin_path(LOAD_PATH) + register_creator_plugin_path(CREATE_PATH) + log.info(PUBLISH_PATH) + + pyblish.api.register_callback( + "instanceToggled", on_pyblish_instance_toggled + ) + + register_event_callback("application.launched", on_application_launch) + + def current_file(self): + try: + full_name = lib.stub().get_active_document_full_name() + if full_name and full_name != "null": + return os.path.normpath(full_name).replace("\\", "/") + except Exception: + pass + + return None + + def work_root(self, session): + return os.path.normpath(session["AVALON_WORKDIR"]).replace("\\", "/") + + def open_workfile(self, filepath): + lib.stub().open(filepath) + + return True + + def save_workfile(self, filepath=None): + _, ext = os.path.splitext(filepath) + lib.stub().saveAs(filepath, ext[1:], True) + + def get_current_workfile(self): + return self.current_file() + + def workfile_has_unsaved_changes(self): + if self.current_file(): + return not lib.stub().is_saved() + + return False + + def get_workfile_extensions(self): + return [".psd", ".psb"] + + def get_containers(self): + return ls() + + def get_context_data(self): + """Get stored values for context (validation enable/disable etc)""" + meta = _get_stub().get_layers_metadata() + for item in meta: + if item.get("id") == "publish_context": + item.pop("id") + return item + + return {} + + def update_context_data(self, data, changes): + """Store value needed for context""" + item = data + item["id"] = "publish_context" + _get_stub().imprint(item["id"], item) + + def get_context_title(self): + """Returns title for Creator window""" + + project_name = legacy_io.Session["AVALON_PROJECT"] + asset_name = legacy_io.Session["AVALON_ASSET"] + task_name = legacy_io.Session["AVALON_TASK"] + return "{}/{}/{}".format(project_name, asset_name, task_name) + + def list_instances(self): + """List all created instances to publish from current workfile. + + Pulls from File > File Info + + Returns: + (list) of dictionaries matching instances format + """ + stub = _get_stub() + + if not stub: + return [] + + instances = [] + layers_meta = stub.get_layers_metadata() + if layers_meta: + for instance in layers_meta: + if instance.get("id") == "pyblish.avalon.instance": + instances.append(instance) + + return instances + + def remove_instance(self, instance): + """Remove instance from current workfile metadata. + + Updates metadata of current file in File > File Info and removes + icon highlight on group layer. + + Args: + instance (dict): instance representation from subsetmanager model + """ + stub = _get_stub() + + if not stub: + return + + inst_id = instance.get("instance_id") or instance.get("uuid") # legacy + if not inst_id: + log.warning("No instance identifier for {}".format(instance)) + return + + stub.remove_instance(inst_id) + + if instance.get("members"): + item = stub.get_layer(instance["members"][0]) + if item: + stub.rename_layer(item.id, + item.name.replace(stub.PUBLISH_ICON, '')) + + def uninstall(self): + pyblish.api.deregister_plugin_path(PUBLISH_PATH) + deregister_loader_plugin_path(LOAD_PATH) + deregister_creator_plugin_path(CREATE_PATH) + + def check_inventory(): if not any_outdated_containers(): return @@ -52,32 +200,6 @@ def on_pyblish_instance_toggled(instance, old_value, new_value): instance[0].Visible = new_value -def install(): - """Install Photoshop-specific functionality of avalon-core. - - This function is called automatically on calling `api.install(photoshop)`. - """ - log.info("Installing OpenPype Photoshop...") - pyblish.api.register_host("photoshop") - - pyblish.api.register_plugin_path(PUBLISH_PATH) - register_loader_plugin_path(LOAD_PATH) - register_creator_plugin_path(CREATE_PATH) - log.info(PUBLISH_PATH) - - pyblish.api.register_callback( - "instanceToggled", on_pyblish_instance_toggled - ) - - register_event_callback("application.launched", on_application_launch) - - -def uninstall(): - pyblish.api.deregister_plugin_path(PUBLISH_PATH) - deregister_loader_plugin_path(LOAD_PATH) - deregister_creator_plugin_path(CREATE_PATH) - - def ls(): """Yields containers from active Photoshop document @@ -117,61 +239,6 @@ def ls(): yield data -def list_instances(): - """List all created instances to publish from current workfile. - - Pulls from File > File Info - - For SubsetManager - - Returns: - (list) of dictionaries matching instances format - """ - stub = _get_stub() - - if not stub: - return [] - - instances = [] - layers_meta = stub.get_layers_metadata() - if layers_meta: - for instance in layers_meta: - if instance.get("id") == "pyblish.avalon.instance": - instances.append(instance) - - return instances - - -def remove_instance(instance): - """Remove instance from current workfile metadata. - - Updates metadata of current file in File > File Info and removes - icon highlight on group layer. - - For SubsetManager - - Args: - instance (dict): instance representation from subsetmanager model - """ - stub = _get_stub() - - if not stub: - return - - inst_id = instance.get("instance_id") or instance.get("uuid") # legacy - if not inst_id: - log.warning("No instance identifier for {}".format(instance)) - return - - stub.remove_instance(inst_id) - - if instance.get("members"): - item = stub.get_layer(instance["members"][0]) - if item: - stub.rename_layer(item.id, - item.name.replace(stub.PUBLISH_ICON, '')) - - def _get_stub(): """Handle pulling stub from PS to run operations on host @@ -224,30 +291,3 @@ def containerise( stub.imprint(layer.id, data) return layer - - -def get_context_data(): - """Get stored values for context (validation enable/disable etc)""" - meta = _get_stub().get_layers_metadata() - for item in meta: - if item.get("id") == "publish_context": - item.pop("id") - return item - - return {} - - -def update_context_data(data, changes): - """Store value needed for context""" - item = data - item["id"] = "publish_context" - _get_stub().imprint(item["id"], item) - - -def get_context_title(): - """Returns title for Creator window""" - - project_name = legacy_io.Session["AVALON_PROJECT"] - asset_name = legacy_io.Session["AVALON_ASSET"] - task_name = legacy_io.Session["AVALON_TASK"] - return "{}/{}/{}".format(project_name, asset_name, task_name) diff --git a/openpype/hosts/photoshop/plugins/create/create_image.py b/openpype/hosts/photoshop/plugins/create/create_image.py index 2cfbfa8778..ad6c657d9c 100644 --- a/openpype/hosts/photoshop/plugins/create/create_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_image.py @@ -9,6 +9,7 @@ from openpype.pipeline import ( ) from openpype.lib import prepare_template_data from openpype.pipeline.create import SUBSET_NAME_ALLOWED_SYMBOLS +from openpype.hosts.photoshop.api import PhotoshopHost class ImageCreator(Creator): @@ -19,7 +20,7 @@ class ImageCreator(Creator): description = "Image creator" def collect_instances(self): - for instance_data in api.list_instances(): + for instance_data in PhotoshopHost().list_instances(): # legacy instances have family=='image' creator_id = (instance_data.get("creator_identifier") or instance_data.get("family")) @@ -121,7 +122,7 @@ class ImageCreator(Creator): def remove_instances(self, instances): for instance in instances: - api.remove_instance(instance) + PhotoshopHost().remove_instance(instance) self._remove_instance_from_context(instance) def get_default_variants(self): diff --git a/openpype/hosts/photoshop/plugins/create/workfile_creator.py b/openpype/hosts/photoshop/plugins/create/workfile_creator.py index e79d16d154..829aff3aea 100644 --- a/openpype/hosts/photoshop/plugins/create/workfile_creator.py +++ b/openpype/hosts/photoshop/plugins/create/workfile_creator.py @@ -5,6 +5,7 @@ from openpype.pipeline import ( CreatedInstance, legacy_io ) +from openpype.hosts.photoshop.api import PhotoshopHost class PSWorkfileCreator(AutoCreator): @@ -17,7 +18,7 @@ class PSWorkfileCreator(AutoCreator): return [] def collect_instances(self): - for instance_data in api.list_instances(): + for instance_data in PhotoshopHost().list_instances(): creator_id = instance_data.get("creator_identifier") if creator_id == self.identifier: subset_name = instance_data["subset"] diff --git a/openpype/hosts/photoshop/plugins/publish/collect_instances.py b/openpype/hosts/photoshop/plugins/publish/collect_instances.py index b466ec8687..5bf12379b1 100644 --- a/openpype/hosts/photoshop/plugins/publish/collect_instances.py +++ b/openpype/hosts/photoshop/plugins/publish/collect_instances.py @@ -82,7 +82,7 @@ class CollectInstances(pyblish.api.ContextPlugin): if len(instance_names) != len(set(instance_names)): self.log.warning("Duplicate instances found. " + - "Remove unwanted via SubsetManager") + "Remove unwanted via Publisher") if len(instance_names) == 0 and self.flatten_subset_template: project_name = context.data["projectEntity"]["name"] diff --git a/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py b/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py index 78e84729ce..09859ca7c6 100644 --- a/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py +++ b/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py @@ -29,7 +29,7 @@ class ValidateSubsetUniqueness(pyblish.api.ContextPlugin): for item, count in collections.Counter(subset_names).items() if count > 1] msg = ("Instance subset names {} are not unique. ".format(non_unique) + - "Remove duplicates via SubsetManager.") + "Remove duplicates via Publisher.") formatting_data = { "non_unique": ",".join(non_unique) } From e500cae3997f8b8d5dd716ac052c0f51d304f2a1 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 31 Oct 2022 18:31:55 +0100 Subject: [PATCH 06/30] OP-3908 - modified host registration Use PhotoshopHost class instead to standardize. --- openpype/hosts/photoshop/api/lib.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/photoshop/api/lib.py b/openpype/hosts/photoshop/api/lib.py index 221b4314e6..a16e2c43ca 100644 --- a/openpype/hosts/photoshop/api/lib.py +++ b/openpype/hosts/photoshop/api/lib.py @@ -20,9 +20,11 @@ def safe_excepthook(*args): def main(*subprocess_args): - from openpype.hosts.photoshop import api + from openpype.hosts.photoshop.api import PhotoshopHost + + host = PhotoshopHost() + install_host(host) - install_host(api) sys.excepthook = safe_excepthook # coloring in StdOutBroker From d9b33889b7ed8e09fbf9c384b35eb2f87336f007 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 31 Oct 2022 18:32:47 +0100 Subject: [PATCH 07/30] OP-3908 - remove SubsetManager menu item --- openpype/hosts/photoshop/api/extension.zxp | Bin 54088 -> 54077 bytes .../hosts/photoshop/api/extension/index.html | 1 - 2 files changed, 1 deletion(-) diff --git a/openpype/hosts/photoshop/api/extension.zxp b/openpype/hosts/photoshop/api/extension.zxp index bcbd694a00363233b5d0ee0985f3058d3de225af..f34d958ae19fae8c592ee565a82a025bf77b733b 100644 GIT binary patch delta 2862 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 I`Eb1Y7Yc$Y6aWAK delta 2851 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 diff --git a/openpype/hosts/photoshop/api/extension/index.html b/openpype/hosts/photoshop/api/extension/index.html index 80018afb78..0b6cc2e182 100644 --- a/openpype/hosts/photoshop/api/extension/index.html +++ b/openpype/hosts/photoshop/api/extension/index.html @@ -101,7 +101,6 @@ - From 54828e5d7d1d8ab35b6393e5e9ffca74060aa085 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 1 Nov 2022 11:44:38 +0100 Subject: [PATCH 08/30] OP-3908 - fix renaming, keep layer name If subset was created with layer name, keep it when renaming. --- .../hosts/photoshop/plugins/create/create_image.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/create/create_image.py b/openpype/hosts/photoshop/plugins/create/create_image.py index ad6c657d9c..67f08a311b 100644 --- a/openpype/hosts/photoshop/plugins/create/create_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_image.py @@ -98,6 +98,7 @@ class ImageCreator(Creator): data.update({"subset": subset_name}) data.update({"members": [str(group.id)]}) + data.update({"layer_name": layer_name}) data.update({"long_name": "_".join(layer_names_in_hierarchy)}) new_instance = CreatedInstance(self.family, subset_name, data, @@ -164,6 +165,12 @@ class ImageCreator(Creator): def _clean_highlights(self, stub, item): return item.replace(stub.PUBLISH_ICON, '').replace(stub.LOADED_ICON, '') - @classmethod - def get_dynamic_data(cls, *args, **kwargs): - return {"layer": "{layer}"} + + def get_dynamic_data(self, variant, task_name, asset_doc, + project_name, host_name, instance): + if not instance: + return {"layer": "{layer}"} + else: + layer_name = instance.get("layer_name") + if layer_name: + return {"layer": layer_name} From 352d5c80b47b57b75625969d6722649a0990f4da Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 1 Nov 2022 12:13:41 +0100 Subject: [PATCH 09/30] OP-3908 - fix - pass None as instance argument get_dynamic_data requires instance as positional argument --- openpype/hosts/photoshop/plugins/create/workfile_creator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/photoshop/plugins/create/workfile_creator.py b/openpype/hosts/photoshop/plugins/create/workfile_creator.py index 829aff3aea..5ad9fbaa88 100644 --- a/openpype/hosts/photoshop/plugins/create/workfile_creator.py +++ b/openpype/hosts/photoshop/plugins/create/workfile_creator.py @@ -55,7 +55,7 @@ class PSWorkfileCreator(AutoCreator): } data.update(self.get_dynamic_data( self.default_variant, task_name, asset_doc, - project_name, host_name + project_name, host_name, None )) new_instance = CreatedInstance( From 0af6d3f205461a99fc7f6e9fb144e03efd61a9b6 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 1 Nov 2022 12:18:48 +0100 Subject: [PATCH 10/30] OP-3908 - remove workio file Ingested into PhotoshopHost --- openpype/hosts/photoshop/api/workio.py | 49 -------------------------- 1 file changed, 49 deletions(-) delete mode 100644 openpype/hosts/photoshop/api/workio.py diff --git a/openpype/hosts/photoshop/api/workio.py b/openpype/hosts/photoshop/api/workio.py deleted file mode 100644 index 35b44d6070..0000000000 --- a/openpype/hosts/photoshop/api/workio.py +++ /dev/null @@ -1,49 +0,0 @@ -"""Host API required Work Files tool""" -import os - -from . import lib - - -def _active_document(): - document_name = lib.stub().get_active_document_name() - if not document_name: - return None - - return document_name - - -def file_extensions(): - return [".psd", ".psb"] - - -def has_unsaved_changes(): - if _active_document(): - return not lib.stub().is_saved() - - return False - - -def save_file(filepath): - _, ext = os.path.splitext(filepath) - lib.stub().saveAs(filepath, ext[1:], True) - - -def open_file(filepath): - lib.stub().open(filepath) - - return True - - -def current_file(): - try: - full_name = lib.stub().get_active_document_full_name() - if full_name and full_name != "null": - return os.path.normpath(full_name).replace("\\", "/") - except Exception: - pass - - return None - - -def work_root(session): - return os.path.normpath(session["AVALON_WORKDIR"]).replace("\\", "/") From c2aa33cf2bf9eb75c69f4c6fb1aa1bf3777d8493 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 1 Nov 2022 12:20:59 +0100 Subject: [PATCH 11/30] OP-3908 - remove subset manager menu item Obsolete, replaced by Publisher --- openpype/hosts/photoshop/api/extension.zxp | Bin 54077 -> 54041 bytes .../hosts/photoshop/api/extension/index.html | 12 ------------ 2 files changed, 12 deletions(-) diff --git a/openpype/hosts/photoshop/api/extension.zxp b/openpype/hosts/photoshop/api/extension.zxp index f34d958ae19fae8c592ee565a82a025bf77b733b..c2fba57495f90fbd234ca29be8c5e67e09171a79 100644 GIT binary patch delta 2752 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 gy&i-OxNZgezl6Ulupc}dAn1a+9Q)Vfri8~lo z)G4UK1;9^%NLr`h>5=XF7pIA54bEUFO^Tz1;(}rY2?PMNGA9Gud~s3lfP8*vmCdgvbjuGHJ#`X<)wl@wJ24nLSgUHQ`{PtlJ_B2I@K zq%X9{Kfsqbx5G4!vreLQCT|1#Y&_=GGWWuKC6OgkRl@ShOV^6dS@4Ff=C~U@ihVv_ z)5BFHh2K@{Krxw)N=2dh1!Y)*3Kxe#3A4?1zlzlMGBWsNv>B|&+EH0e_<{P&8}_kt z$k!LFXf3f@jf}c_oYE|%zC0t%<&5;j@{TfWj+jm}8rvb<0~k;8chv;L?zVVhoZ_<- zPkfKSo6t<~WX4gCiFl*`USzm~+FN?q22uZYgeG*F;JuxrvKu-t>+i(X?^n#I5#1`}`R$kpq7f)`;>FrQ<*xHN{|RaAtyaRz#ogQ+3@$dboe7 z8G%DCUPUeTcId7ir=1OJ>@VGUip#C&h9VMo!TI1(>ZEPr)aZlK5jIl;P6IHIn+Fud z>6Rpph!lxWD<6NPceTpVJ4A-Yng@N|eT1g6Im?3B;l+4Be($U!hktX?oOC9DgM(_8Llu zdwp^Xx+552OR*`oYL>lMo?PIUQNys-wY_rqgB%ySr=b**CL4jc71%BNN$g{_v6>@wJMQogem;UpVObP~Yc9 zIl#rU$@eb^Z?korTYq!mr^uD?$^(~fwCaSga>ChobCBRcXp;?*{JFg@FJ+`)nmwxB4Br8hTYl8kEk{u9 zD9I9o45v4~$9VF7j2kS~Az;I7lmVWY@zP-I}{MmSbzehxj7-IOS# z+J3*Z^)iIgzuy1tc@Xy7wcOY1Y&RZX3lwIKBb-5f5Z0cSdiRvftofJHV?;uY$Q!e3 zmjJigrJOiBdKmGb$fxERklZ#!*;V?CAcaP!`V>1c*^n2Eb?BY63Z8`TH>FikRIOL^ zG2{-k^Xp<4pxLU7AsN^E%D7e-{>gJap{YM)Ay6g9^~;3h2+eAzuPjqhnM*9<%nMH} zyhXy#<89B_EXEl7^Q`ozP=qWPUOuo`eEjmjZ;Jht_l13Msd}ZMfp;)dU@}wZAa`!qWwm=ACvoZd;5s`FLIvap~FpNs6U*f$sO_mH!@Nj*OdBaF!v8k`pZCh8pwmL>b5R%Tm3+q0K6=acX+4@p1o zZusEbaWdG#m~h9ZQQk3H5?Q9xh6GwP($NV#>FrMUrQ|20kGnWD74xu+<1W3*LwU;$ zVCx2mRRV^1VL5hBdkhOjw>)TqWR(aSV`flSp=W#Pp!E!!yTpCgFlN1dQ2usYbrP(Q z@;%6TLPtiTJWFiAB6Xa2PyHqv

;MWu=4LG^hw}^$X0L!_0SYyyw3`GdB8#L3XTm zHd6Z4>Z2|TbAD>KOpl_HcrUMktQ(Zgw( zJttRd@8AM=?*aDjZjoru5G?!4HvkNtQ)*Bg*(Me?AeRHZlj zY}CY-p4AhK9Y8(>f2q!Vd$B|gD*Ru!*-inuAcf8-G2F+1^L9=*$*0D#dS=IY{lXl+T17A=7ITiU`L z3^;S5`tOSWF+d0aAaD)<-~h0kz5)o~`yD%ylZJ(0|J3|*OYbm`%)34Sz}wRs8xZP; X{Xdt0e@g-Yu-`Ku3;^8!aI*Us%-kC* diff --git a/openpype/hosts/photoshop/api/extension/index.html b/openpype/hosts/photoshop/api/extension/index.html index 0b6cc2e182..0c0db3a223 100644 --- a/openpype/hosts/photoshop/api/extension/index.html +++ b/openpype/hosts/photoshop/api/extension/index.html @@ -64,17 +64,6 @@ }); }); - -