From 81073b4cafab3dc337ed597b05a696d1975a893b Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 15 Mar 2024 09:55:45 +0000 Subject: [PATCH 1/7] If knob name exists only change value. --- client/ayon_core/hosts/nuke/api/lib.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/nuke/api/lib.py b/client/ayon_core/hosts/nuke/api/lib.py index e304b33dc7..32e9ace377 100644 --- a/client/ayon_core/hosts/nuke/api/lib.py +++ b/client/ayon_core/hosts/nuke/api/lib.py @@ -397,7 +397,13 @@ def imprint(node, data, tab=None): """ for knob in create_knobs(data, tab): - node.addKnob(knob) + # If knob name exists we set the value. Technically there could be + # multiple knobs with the same name, but the intent is not to have + # duplicated knobs so we do not account for that. + if knob.name() in node.knobs().keys(): + node[knob.name()].setValue(knob.value()) + else: + node.addKnob(knob) @deprecated From 404681e684892e63e4d26915364c24ed56f23c7d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 24 Mar 2024 10:32:08 +0100 Subject: [PATCH 2/7] Add list of attributes to always be included in alembic export even when not specified in publisher UI by user. This matches the Extract Camera Alembic logic for `bake_attributes` --- .../hosts/maya/plugins/publish/extract_pointcache.py | 9 +++++++++ server_addon/maya/server/settings/publishers.py | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/extract_pointcache.py b/client/ayon_core/hosts/maya/plugins/publish/extract_pointcache.py index f2187063fc..f83d2679cb 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/extract_pointcache.py +++ b/client/ayon_core/hosts/maya/plugins/publish/extract_pointcache.py @@ -1,4 +1,5 @@ import os +import json from maya import cmds @@ -25,6 +26,7 @@ class ExtractAlembic(publish.Extractor): hosts = ["maya"] families = ["pointcache", "model", "vrayproxy.alembic"] targets = ["local", "remote"] + bake_attributes = "[]" def process(self, instance): if instance.data.get("farm"): @@ -42,6 +44,13 @@ class ExtractAlembic(publish.Extractor): attrs += instance.data.get("userDefinedAttributes", []) attrs += ["cbId"] + # bake specified attributes in preset + bake_attributes = json.loads(self.bake_attributes) + assert isinstance(bake_attributes, list), ( + "Attributes to bake must be specified as a list" + ) + attrs += bake_attributes + attr_prefixes = instance.data.get("attrPrefix", "").split(";") attr_prefixes = [value for value in attr_prefixes if value.strip()] diff --git a/server_addon/maya/server/settings/publishers.py b/server_addon/maya/server/settings/publishers.py index 3a6de2eb44..ca99d8c57f 100644 --- a/server_addon/maya/server/settings/publishers.py +++ b/server_addon/maya/server/settings/publishers.py @@ -299,6 +299,11 @@ class ExtractAlembicModel(BaseSettingsModel): families: list[str] = SettingsField( default_factory=list, title="Families") + bake_attributes: str = SettingsField( + "[]", title="Bake Attributes", widget="textarea", + description="List of attributes that will be included in the alembic " + "export.", + ) class ExtractObjModel(BaseSettingsModel): @@ -1193,7 +1198,8 @@ DEFAULT_PUBLISH_SETTINGS = { "pointcache", "model", "vrayproxy.alembic" - ] + ], + "bake_attributes": "[]" }, "ExtractObj": { "enabled": False, From 3d9cd57df01aacde07e3424a9d9c0af8a5f834ec Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 24 Mar 2024 10:37:31 +0100 Subject: [PATCH 3/7] Expose bake attribute prefixes, plus make settings just a list of strings --- .../maya/plugins/publish/extract_pointcache.py | 15 ++++++--------- server_addon/maya/server/settings/publishers.py | 12 +++++++++--- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/client/ayon_core/hosts/maya/plugins/publish/extract_pointcache.py b/client/ayon_core/hosts/maya/plugins/publish/extract_pointcache.py index f83d2679cb..5de72f7674 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/extract_pointcache.py +++ b/client/ayon_core/hosts/maya/plugins/publish/extract_pointcache.py @@ -1,5 +1,4 @@ import os -import json from maya import cmds @@ -26,7 +25,10 @@ class ExtractAlembic(publish.Extractor): hosts = ["maya"] families = ["pointcache", "model", "vrayproxy.alembic"] targets = ["local", "remote"] - bake_attributes = "[]" + + # From settings + bake_attributes = [] + bake_attribute_prefixes = [] def process(self, instance): if instance.data.get("farm"): @@ -42,17 +44,12 @@ class ExtractAlembic(publish.Extractor): attrs = instance.data.get("attr", "").split(";") attrs = [value for value in attrs if value.strip()] attrs += instance.data.get("userDefinedAttributes", []) + attrs += self.bake_attributes attrs += ["cbId"] - # bake specified attributes in preset - bake_attributes = json.loads(self.bake_attributes) - assert isinstance(bake_attributes, list), ( - "Attributes to bake must be specified as a list" - ) - attrs += bake_attributes - attr_prefixes = instance.data.get("attrPrefix", "").split(";") attr_prefixes = [value for value in attr_prefixes if value.strip()] + attr_prefixes += self.bake_attribute_prefixes self.log.debug("Extracting pointcache..") dirname = self.staging_dir(instance) diff --git a/server_addon/maya/server/settings/publishers.py b/server_addon/maya/server/settings/publishers.py index ca99d8c57f..7ba2522e60 100644 --- a/server_addon/maya/server/settings/publishers.py +++ b/server_addon/maya/server/settings/publishers.py @@ -299,10 +299,15 @@ class ExtractAlembicModel(BaseSettingsModel): families: list[str] = SettingsField( default_factory=list, title="Families") - bake_attributes: str = SettingsField( - "[]", title="Bake Attributes", widget="textarea", + bake_attributes: list[str] = SettingsField( + "", title="Bake Attributes", widget="textarea", description="List of attributes that will be included in the alembic " "export.", + ), + bake_attribute_prefixes: list[str] = SettingsField( + "", title="Bake Attribute Prefixes", widget="textarea", + description="List of attribute prefixes for attributes that will be " + "included in the alembic export.", ) @@ -1199,7 +1204,8 @@ DEFAULT_PUBLISH_SETTINGS = { "model", "vrayproxy.alembic" ], - "bake_attributes": "[]" + "bake_attributes": [], + "bake_attribute_prefixes": [], }, "ExtractObj": { "enabled": False, From fadf720c9a9b33299a057527183f58d9d89027a6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 24 Mar 2024 10:38:20 +0100 Subject: [PATCH 4/7] Bump version --- server_addon/maya/server/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/maya/server/version.py b/server_addon/maya/server/version.py index 8202425a2d..a86a3ce0a1 100644 --- a/server_addon/maya/server/version.py +++ b/server_addon/maya/server/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring addon version.""" -__version__ = "0.1.9" +__version__ = "0.1.10" From 9a5d6427d5741186b4767107ae495bf36241ed09 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 24 Mar 2024 11:22:53 +0100 Subject: [PATCH 5/7] Fix settings --- server_addon/maya/server/settings/publishers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server_addon/maya/server/settings/publishers.py b/server_addon/maya/server/settings/publishers.py index 7ba2522e60..7c2688af55 100644 --- a/server_addon/maya/server/settings/publishers.py +++ b/server_addon/maya/server/settings/publishers.py @@ -300,12 +300,12 @@ class ExtractAlembicModel(BaseSettingsModel): default_factory=list, title="Families") bake_attributes: list[str] = SettingsField( - "", title="Bake Attributes", widget="textarea", + default_factory=list, title="Bake Attributes", description="List of attributes that will be included in the alembic " "export.", - ), + ) bake_attribute_prefixes: list[str] = SettingsField( - "", title="Bake Attribute Prefixes", widget="textarea", + default_factory=list, title="Bake Attribute Prefixes", description="List of attribute prefixes for attributes that will be " "included in the alembic export.", ) @@ -1205,7 +1205,7 @@ DEFAULT_PUBLISH_SETTINGS = { "vrayproxy.alembic" ], "bake_attributes": [], - "bake_attribute_prefixes": [], + "bake_attribute_prefixes": [] }, "ExtractObj": { "enabled": False, From 6717db4482c43f87b153f98567db20a183849b28 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 27 Mar 2024 15:30:16 +0100 Subject: [PATCH 6/7] Update ColorRGBA import and add regex validation for output name field. - Import statement changed to only import ColorRGBA_uint8. - Added regex validation for the 'name' field in ExtractOIIOTranscodeOutputModel. --- server/settings/publish_plugins.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/server/settings/publish_plugins.py b/server/settings/publish_plugins.py index f9ac1059ac..e61bf6986b 100644 --- a/server/settings/publish_plugins.py +++ b/server/settings/publish_plugins.py @@ -9,7 +9,7 @@ from ayon_server.settings import ( task_types_enum, ) -from ayon_server.types import ColorRGB_uint8, ColorRGBA_uint8 +from ayon_server.types import ColorRGBA_uint8 class ValidateBaseModel(BaseSettingsModel): @@ -221,7 +221,12 @@ class OIIOToolArgumentsModel(BaseSettingsModel): class ExtractOIIOTranscodeOutputModel(BaseSettingsModel): _layout = "expanded" - name: str = SettingsField("", title="Name") + name: str = SettingsField( + "", + title="Name", + description="Output name (no space)", + regex=r"[a-zA-Z0-9_]([a-zA-Z0-9_\.\-]*[a-zA-Z0-9_])?$", + ) extension: str = SettingsField("", title="Extension") transcoding_type: str = SettingsField( "colorspace", From 9669f62a44f8f33f5ae70e62986db807e0d5881e Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 27 Mar 2024 16:06:52 +0100 Subject: [PATCH 7/7] removed pysync from vendor --- .../ayon_core/vendor/python/common/pysync.py | 216 ------------------ 1 file changed, 216 deletions(-) delete mode 100644 client/ayon_core/vendor/python/common/pysync.py diff --git a/client/ayon_core/vendor/python/common/pysync.py b/client/ayon_core/vendor/python/common/pysync.py deleted file mode 100644 index 14a6dda34c..0000000000 --- a/client/ayon_core/vendor/python/common/pysync.py +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/local/bin/python3 -# https://github.com/snullp/pySync/blob/master/pySync.py - -import sys -import shutil -import os -import time -import configparser -from os.path import ( - getsize, - getmtime, - isfile, - isdir, - join, - abspath, - expanduser, - realpath -) -import logging - -log = logging.getLogger(__name__) - -ignoreFiles = ("Thumbs.db", ".DS_Store") - -# this feature is not yet implemented -ignorePaths = [] - -if os.name == 'nt': - # msvcrt can't function correctly in IDLE - if 'idlelib.run' in sys.modules: - print("Please don't run this script in IDLE.") - sys.exit(0) - import msvcrt - - def flush_input(str, set=None): - if not set: - while msvcrt.kbhit(): - ch = msvcrt.getch() - if ch == '\xff': - print("msvcrt is broken, this is weird.") - sys.exit(0) - return input(str) - else: - return set -else: - import select - - def flush_input(str, set=None): - if not set: - while len(select.select([sys.stdin.fileno()], [], [], 0.0)[0]) > 0: - os.read(sys.stdin.fileno(), 4096) - return input(str) - else: - return set - - -def compare(fa, fb, options_input=[]): - if isfile(fa) == isfile(fb): - if isdir(fa): - walktree(fa, fb, options_input) - elif isfile(fa): - if getsize(fa) != getsize(fb) \ - or int(getmtime(fa)) != int(getmtime(fb)): - log.info(str((fa, ': size=', getsize(fa), 'mtime=', - time.asctime(time.localtime(getmtime(fa)))))) - log.info(str((fb, ': size=', getsize(fb), 'mtime=', - time.asctime(time.localtime(getmtime(fb)))))) - if getmtime(fa) > getmtime(fb): - act = '>' - else: - act = '<' - - set = [i for i in options_input if i in [">", "<"]][0] - - s = flush_input('What to do?(>,<,r,n)[' + act + ']', set=set) - if len(s) > 0: - act = s[0] - if act == '>': - shutil.copy2(fa, fb) - elif act == '<': - shutil.copy2(fb, fa) - elif act == 'r': - if isdir(fa): - shutil.rmtree(fa) - elif isfile(fa): - os.remove(fa) - else: - log.info(str(('Remove: Skipping', fa))) - if isdir(fb): - shutil.rmtree(fb) - elif isfile(fb): - os.remove(fb) - else: - log.info(str(('Remove: Skipping', fb))) - - else: - log.debug(str(('Compare: Skipping non-dir and non-file', fa))) - else: - log.error(str(('Error:', fa, ',', fb, 'have different file type'))) - - -def copy(fa, fb, options_input=[]): - set = [i for i in options_input if i in ["y"]][0] - s = flush_input('Copy ' + fa + ' to another side?(r,y,n)[y]', set=set) - if len(s) > 0: - act = s[0] - else: - act = 'y' - if act == 'y': - if isdir(fa): - shutil.copytree(fa, fb) - elif isfile(fa): - shutil.copy2(fa, fb) - else: - log.debug(str(('Copy: Skipping ', fa))) - elif act == 'r': - if isdir(fa): - shutil.rmtree(fa) - elif isfile(fa): - os.remove(fa) - else: - log.debug(str(('Remove: Skipping ', fa))) - - -stoentry = [] -tarentry = [] - - -def walktree(source, target, options_input=[]): - srclist = os.listdir(source) - tarlist = os.listdir(target) - if '!sync' in srclist: - return - if '!sync' in tarlist: - return - # files in source dir... - for f in srclist: - if f in ignoreFiles: - continue - spath = join(source, f) - tpath = join(target, f) - if spath in ignorePaths: - continue - if spath in stoentry: - # just in case target also have this one - if f in tarlist: - del tarlist[tarlist.index(f)] - continue - - # if also exists in target dir - if f in tarlist: - del tarlist[tarlist.index(f)] - compare(spath, tpath, options_input) - - # exists in source dir only - else: - copy(spath, tpath, options_input) - - # exists in target dir only - set = [i for i in options_input if i in ["<"]] - - for f in tarlist: - if f in ignoreFiles: - continue - spath = join(source, f) - tpath = join(target, f) - if tpath in ignorePaths: - continue - if tpath in tarentry: - continue - if set: - copy(tpath, spath, options_input) - else: - print("REMOVING: {}".format(f)) - if os.path.isdir(tpath): - shutil.rmtree(tpath) - else: - os.remove(tpath) - print("REMOVING: {}".format(f)) - - -if __name__ == '__main__': - stoconf = configparser.RawConfigParser() - tarconf = configparser.RawConfigParser() - stoconf.read("pySync.ini") - tarconf.read(expanduser("~/.pysync")) - stoname = stoconf.sections()[0] - tarname = tarconf.sections()[0] - - # calculate storage's base folder - if stoconf.has_option(stoname, 'BASE'): - stobase = abspath(stoconf.get(stoname, 'BASE')) - stoconf.remove_option(stoname, 'BASE') - else: - stobase = os.getcwd() - - # same, for target's base folder - if tarconf.has_option(tarname, 'BASE'): - tarbase = abspath(tarconf.get(tarname, 'BASE')) - tarconf.remove_option(tarname, 'BASE') - else: - tarbase = expanduser('~/') - - print("Syncing between", stoname, "and", tarname) - sto_content = {x: realpath(join(stobase, stoconf.get(stoname, x))) - for x in stoconf.options(stoname)} - tar_content = {x: realpath(join(tarbase, tarconf.get(tarname, x))) - for x in tarconf.options(tarname)} - stoentry = [sto_content[x] for x in sto_content] - tarentry = [tar_content[x] for x in tar_content] - - for folder in sto_content: - if folder in tar_content: - print('Processing', folder) - walktree(sto_content[folder], tar_content[folder], options_input) - print("Done.")