From a756be0d4c695d72bdc635606337a4cf074f773e Mon Sep 17 00:00:00 2001 From: "qi.shiyuan.ani" Date: Fri, 10 Jul 2026 11:30:29 +0200 Subject: [PATCH 1/6] first commit with code --- client/ayon_harmony/api/base_loaders.py | 6 ++- .../ayon_harmony/js/loaders/TemplateLoader.js | 43 ++++++++++--------- .../plugins/load/load_template.py | 22 +++++++--- .../plugins/load/load_template_workfile.py | 2 +- client/ayon_harmony/vendor/OpenHarmony | 2 +- 5 files changed, 45 insertions(+), 30 deletions(-) diff --git a/client/ayon_harmony/api/base_loaders.py b/client/ayon_harmony/api/base_loaders.py index 7accab7d..3f67f258 100644 --- a/client/ayon_harmony/api/base_loaders.py +++ b/client/ayon_harmony/api/base_loaders.py @@ -3,8 +3,10 @@ from pathlib import Path from ayon_core.pipeline import load +import traceback import ayon_harmony.api as harmony +log_path = r"C:\Users\normaal\Documents\YuanDev\AYON-Development-Workbench\ayon-harmony\LOG.txt" class BackdropBaseLoader(load.LoaderPlugin): @@ -96,6 +98,7 @@ def load(self, context, name=None, namespace=None, data=None): self_name ) + def remove(self, container): """Remove container. @@ -121,7 +124,8 @@ def update(self, container, context): """ return self.switch(container, context) - + + def switch(self, container, context): """Switch representation containers.""" backdrop_name = container["name"] diff --git a/client/ayon_harmony/js/loaders/TemplateLoader.js b/client/ayon_harmony/js/loaders/TemplateLoader.js index e0f2ab89..95701e13 100644 --- a/client/ayon_harmony/js/loaders/TemplateLoader.js +++ b/client/ayon_harmony/js/loaders/TemplateLoader.js @@ -37,6 +37,7 @@ TemplateLoader.prototype.loadContainer = function(args) { var templatePath = args[0]; var overrideName = args[1] || ""; var parentBackdropName = args[2] || null; + var existingNames = args[3] || []; // Copy from template file MessageLog.trace("loadContainer:: "); @@ -51,7 +52,7 @@ TemplateLoader.prototype.loadContainer = function(args) { function parseBackdropName(name) { var lastIndex = name.lastIndexOf('_'); if (lastIndex === -1) { - return { baseName: name, count: 1 }; + return { baseName: name, count: 0 }; } var base = name.substring(0, lastIndex); var suffix = name.substring(lastIndex + 1); @@ -60,7 +61,7 @@ TemplateLoader.prototype.loadContainer = function(args) { if (isNumericSuffix) { return { baseName: base, count: increment }; } - return { baseName: name, count: 1 }; + return { baseName: name, count: 0 }; } var _copyOptions = copyPaste.getCurrentCreateOptions(); @@ -72,6 +73,7 @@ TemplateLoader.prototype.loadContainer = function(args) { $.beginUndo('AYON: Load Template'); try { copyPaste.pasteNewNodes(_tpl, "Top", pasteOptions); + var pastedBackdrops = selection.selectedBackdrops(); var _allSelected = selection.selectedNodes(); var topPastedNodes = _allSelected.filter( @@ -134,27 +136,28 @@ TemplateLoader.prototype.loadContainer = function(args) { mainBackdrop.title.text = overrideName; } - // Count existing backdrops by base name - var backdropCounts = {}; - for (var i = 0; i < allBackdrops.length; i++) { - var parsed = parseBackdropName(allBackdrops[i].title.text); - var baseName = parsed.baseName; - var count = parsed.count; - - if (backdropCounts[baseName]) { - backdropCounts[baseName]++; - } else { - backdropCounts[baseName] = count; + var mainBackdropBaseName = parseBackdropName(mainBackdrop.title.text).baseName; + + // Collect used suffix slots for this baseName, based on the + // Python-provided list of already-registered container names + var usedNumbers = []; + for (var n = 0; n < existingNames.length; n++) { + var parsed = parseBackdropName(existingNames[n]); + if (parsed.baseName !== mainBackdropBaseName) { + continue; } + usedNumbers.push(parsed.count); } - // Increment count of backdrop with the same base name - var mainBackdropName = mainBackdrop.title.text; - var mainBackdropParsed = parseBackdropName(mainBackdropName); - var count = backdropCounts[mainBackdropParsed.baseName] !== undefined ? backdropCounts[mainBackdropParsed.baseName] : 1; - if (count > 1){ - // count -1 to match imported nodes which start from _1 - mainBackdropName = mainBackdropName + "_" + (count - 1); + var mainBackdropName; + if (usedNumbers.indexOf(0) === -1) { + mainBackdropName = mainBackdropBaseName; + } else { + var nextSuffix = 1; + while (usedNumbers.indexOf(nextSuffix) !== -1) { + nextSuffix++; + } + mainBackdropName = mainBackdropBaseName + "_" + nextSuffix; } // Set name of main backdrop (always at index 0) diff --git a/client/ayon_harmony/plugins/load/load_template.py b/client/ayon_harmony/plugins/load/load_template.py index 1aa4f942..1f62ad93 100644 --- a/client/ayon_harmony/plugins/load/load_template.py +++ b/client/ayon_harmony/plugins/load/load_template.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- """Load template.""" + from pathlib import Path import tempfile import zipfile @@ -7,7 +8,6 @@ import ayon_harmony.api as harmony - class TemplateLoader(harmony.BackdropBaseLoader): """Load Harmony template as Backdrop container.""" @@ -28,7 +28,6 @@ def load(self, context, name=None, namespace=None, data=None): data (dict, optional): Additional data passed into loader. """ - # Load template. self_name = self.__class__.__name__ temp_dir = tempfile.mkdtemp() zip_file = self.filepath_from_context(context) @@ -42,6 +41,14 @@ def load(self, context, name=None, namespace=None, data=None): if self.parent_backdrop_matching: parent_backdrop_name = self._resolve_parent_backdrop_name(context) + scene_data = harmony.get_scene_data() or {} + + existing_names = [ + entity_name + for entity_name, entity_data in scene_data.items() + if isinstance(entity_data, dict) and entity_data.get("loader") + ] + with zipfile.ZipFile(zip_file, "r") as zip_ref: zip_ref.extractall(temp_dir) @@ -53,7 +60,8 @@ def load(self, context, name=None, namespace=None, data=None): "args": [ next(Path(temp_dir).glob("*.tpl")).as_posix(), override_name, - parent_backdrop_name + parent_backdrop_name, + existing_names, ], } )["result"] @@ -63,9 +71,9 @@ def load(self, context, name=None, namespace=None, data=None): # We must validate the group_node return harmony.containerise( - backdrop_name, - namespace, - backdrop_name, - context, + backdrop_name, + namespace, + backdrop_name, + context, self_name ) diff --git a/client/ayon_harmony/plugins/load/load_template_workfile.py b/client/ayon_harmony/plugins/load/load_template_workfile.py index 390079a0..2cc8b394 100644 --- a/client/ayon_harmony/plugins/load/load_template_workfile.py +++ b/client/ayon_harmony/plugins/load/load_template_workfile.py @@ -6,7 +6,7 @@ from ayon_core.pipeline import load import ayon_harmony.api as harmony - +log_path = r"C:\Users\normaal\Documents\YuanDev\AYON-Development-Workbench\ayon-harmony\LOG.txt" class ImportTemplateLoader(load.LoaderPlugin): """Import Harmony workfiles.""" diff --git a/client/ayon_harmony/vendor/OpenHarmony b/client/ayon_harmony/vendor/OpenHarmony index 763169ba..61840044 160000 --- a/client/ayon_harmony/vendor/OpenHarmony +++ b/client/ayon_harmony/vendor/OpenHarmony @@ -1 +1 @@ -Subproject commit 763169ba8a6c5c941d9691ce9caaddf13c5d9b52 +Subproject commit 61840044f7d8139f178241ce4826383cf8a3d969 From 34303594858b4d2b5f696ff1533eddf0702ee03f Mon Sep 17 00:00:00 2001 From: "qi.shiyuan.ani" Date: Fri, 10 Jul 2026 17:37:02 +0200 Subject: [PATCH 2/6] first commit --- client/ayon_harmony/plugins/load/load_template.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/ayon_harmony/plugins/load/load_template.py b/client/ayon_harmony/plugins/load/load_template.py index 1f62ad93..88676481 100644 --- a/client/ayon_harmony/plugins/load/load_template.py +++ b/client/ayon_harmony/plugins/load/load_template.py @@ -28,6 +28,8 @@ def load(self, context, name=None, namespace=None, data=None): data (dict, optional): Additional data passed into loader. """ + # Load template. + self_name = self.__class__.__name__ temp_dir = tempfile.mkdtemp() zip_file = self.filepath_from_context(context) @@ -42,7 +44,6 @@ def load(self, context, name=None, namespace=None, data=None): parent_backdrop_name = self._resolve_parent_backdrop_name(context) scene_data = harmony.get_scene_data() or {} - existing_names = [ entity_name for entity_name, entity_data in scene_data.items() @@ -71,9 +72,9 @@ def load(self, context, name=None, namespace=None, data=None): # We must validate the group_node return harmony.containerise( - backdrop_name, - namespace, - backdrop_name, - context, + backdrop_name, + namespace, + backdrop_name, + context, self_name ) From 8de613d1ae6e5fc7ec87121043a06a34e7103ada Mon Sep 17 00:00:00 2001 From: "qi.shiyuan.ani" Date: Mon, 13 Jul 2026 17:16:41 +0200 Subject: [PATCH 3/6] cleaned code --- client/ayon_harmony/api/base_loaders.py | 4 ---- client/ayon_harmony/js/loaders/TemplateLoader.js | 1 - client/ayon_harmony/plugins/load/load_template.py | 3 +-- client/ayon_harmony/plugins/load/load_template_workfile.py | 2 +- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/client/ayon_harmony/api/base_loaders.py b/client/ayon_harmony/api/base_loaders.py index 3f67f258..637936cb 100644 --- a/client/ayon_harmony/api/base_loaders.py +++ b/client/ayon_harmony/api/base_loaders.py @@ -3,10 +3,8 @@ from pathlib import Path from ayon_core.pipeline import load -import traceback import ayon_harmony.api as harmony -log_path = r"C:\Users\normaal\Documents\YuanDev\AYON-Development-Workbench\ayon-harmony\LOG.txt" class BackdropBaseLoader(load.LoaderPlugin): @@ -98,7 +96,6 @@ def load(self, context, name=None, namespace=None, data=None): self_name ) - def remove(self, container): """Remove container. @@ -125,7 +122,6 @@ def update(self, container, context): """ return self.switch(container, context) - def switch(self, container, context): """Switch representation containers.""" backdrop_name = container["name"] diff --git a/client/ayon_harmony/js/loaders/TemplateLoader.js b/client/ayon_harmony/js/loaders/TemplateLoader.js index 95701e13..f98df231 100644 --- a/client/ayon_harmony/js/loaders/TemplateLoader.js +++ b/client/ayon_harmony/js/loaders/TemplateLoader.js @@ -73,7 +73,6 @@ TemplateLoader.prototype.loadContainer = function(args) { $.beginUndo('AYON: Load Template'); try { copyPaste.pasteNewNodes(_tpl, "Top", pasteOptions); - var pastedBackdrops = selection.selectedBackdrops(); var _allSelected = selection.selectedNodes(); var topPastedNodes = _allSelected.filter( diff --git a/client/ayon_harmony/plugins/load/load_template.py b/client/ayon_harmony/plugins/load/load_template.py index 88676481..af77ef88 100644 --- a/client/ayon_harmony/plugins/load/load_template.py +++ b/client/ayon_harmony/plugins/load/load_template.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- """Load template.""" - from pathlib import Path import tempfile import zipfile @@ -8,6 +7,7 @@ import ayon_harmony.api as harmony + class TemplateLoader(harmony.BackdropBaseLoader): """Load Harmony template as Backdrop container.""" @@ -29,7 +29,6 @@ def load(self, context, name=None, namespace=None, data=None): """ # Load template. - self_name = self.__class__.__name__ temp_dir = tempfile.mkdtemp() zip_file = self.filepath_from_context(context) diff --git a/client/ayon_harmony/plugins/load/load_template_workfile.py b/client/ayon_harmony/plugins/load/load_template_workfile.py index 2cc8b394..390079a0 100644 --- a/client/ayon_harmony/plugins/load/load_template_workfile.py +++ b/client/ayon_harmony/plugins/load/load_template_workfile.py @@ -6,7 +6,7 @@ from ayon_core.pipeline import load import ayon_harmony.api as harmony -log_path = r"C:\Users\normaal\Documents\YuanDev\AYON-Development-Workbench\ayon-harmony\LOG.txt" + class ImportTemplateLoader(load.LoaderPlugin): """Import Harmony workfiles.""" From ebdb13442b8c61297f260d0de10902f0e16d9e0d Mon Sep 17 00:00:00 2001 From: "qi.shiyuan.ani" Date: Mon, 13 Jul 2026 17:17:22 +0200 Subject: [PATCH 4/6] cleaned code --- client/ayon_harmony/api/base_loaders.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/ayon_harmony/api/base_loaders.py b/client/ayon_harmony/api/base_loaders.py index 637936cb..cf13fb18 100644 --- a/client/ayon_harmony/api/base_loaders.py +++ b/client/ayon_harmony/api/base_loaders.py @@ -121,7 +121,8 @@ def update(self, container, context): """ return self.switch(container, context) - + + def switch(self, container, context): """Switch representation containers.""" backdrop_name = container["name"] From 3d7b8e05021cea9d8671a08b17510542af2ab2c5 Mon Sep 17 00:00:00 2001 From: "qi.shiyuan.ani" Date: Mon, 13 Jul 2026 17:17:40 +0200 Subject: [PATCH 5/6] cleaned code --- client/ayon_harmony/api/base_loaders.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_harmony/api/base_loaders.py b/client/ayon_harmony/api/base_loaders.py index cf13fb18..7accab7d 100644 --- a/client/ayon_harmony/api/base_loaders.py +++ b/client/ayon_harmony/api/base_loaders.py @@ -122,7 +122,6 @@ def update(self, container, context): """ return self.switch(container, context) - def switch(self, container, context): """Switch representation containers.""" backdrop_name = container["name"] From 5f40b819452a4b92b68fe34a76cc2dd54945009b Mon Sep 17 00:00:00 2001 From: "qi.shiyuan.ani" Date: Wed, 15 Jul 2026 16:36:32 +0200 Subject: [PATCH 6/6] remove vendored OpenHarmony from tracking --- client/ayon_harmony/vendor/OpenHarmony | 1 - 1 file changed, 1 deletion(-) delete mode 160000 client/ayon_harmony/vendor/OpenHarmony diff --git a/client/ayon_harmony/vendor/OpenHarmony b/client/ayon_harmony/vendor/OpenHarmony deleted file mode 160000 index 61840044..00000000 --- a/client/ayon_harmony/vendor/OpenHarmony +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 61840044f7d8139f178241ce4826383cf8a3d969