From 7b16c6837b1c02defd73fcba984909d085cce61e Mon Sep 17 00:00:00 2001 From: "clement.hector" Date: Mon, 6 Jun 2022 17:08:37 +0200 Subject: [PATCH] refacto code to have simpler menu --- openpype/hosts/nuke/api/gizmo_menu.py | 90 ++++++++------ openpype/hosts/nuke/api/lib.py | 109 ++++++++++------ openpype/hosts/nuke/startup/menu.py | 70 +---------- .../defaults/project_settings/nuke.json | 8 +- .../schemas/schema_nuke_scriptsgizmo.json | 117 +++++++++++++++--- 5 files changed, 222 insertions(+), 172 deletions(-) diff --git a/openpype/hosts/nuke/api/gizmo_menu.py b/openpype/hosts/nuke/api/gizmo_menu.py index dd04f4a42e..7f8121372c 100644 --- a/openpype/hosts/nuke/api/gizmo_menu.py +++ b/openpype/hosts/nuke/api/gizmo_menu.py @@ -1,67 +1,75 @@ import os -import logging +import re import nuke -log = logging.getLogger(__name__) +from openpype.api import Logger + +log = Logger.get_logger(__name__) class GizmoMenu(): - def __init__(self, *args, **kwargs): + def __init__(self, title, icon=None): + + self.toolbar = self._create_toolbar_menu( + title, + icon=icon + ) + self._script_actions = [] - def build_from_configuration(self, parent, configuration): + def _create_toolbar_menu(self, name, icon=None): + nuke_node_menu = nuke.menu("Nodes") + return nuke_node_menu.addMenu( + name, + icon=icon + ) + + def _make_menu_path(self, path, icon=None): + parent = self.toolbar + for folder in re.split(r"/|\\",path): + if not folder: + continue + existing_menu = parent.findItem(folder) + if existing_menu: + parent = existing_menu + else: + parent = parent.addMenu(folder, icon=icon) + + return parent + + def build_from_configuration(self, configuration): for item in configuration: assert isinstance(item, dict), "Configuration is wrong!" - # skip items which have no `type` key - item_type = item.get('type', None) - if not item_type: - log.warning("Missing 'type' from configuration item") - continue + # Construct parent path else parent is toolbar + parent = self.toolbar + gizmo_toolbar_path = item.get("gizmo_toolbar_path") + if gizmo_toolbar_path: + parent = self._make_menu_path(gizmo_toolbar_path) - if item_type == "action": - # filter out `type` from the item dict - config = {key: value for key, value in - item.items() if key != "type"} - - command = str(config['command']) - - icon = config.get('icon', None) - if icon: - try: - icon = icon.format(**os.environ) - except KeyError as e: - log.warning("This environment variable doesn't exist: " - "{}".format(e)) - - hotkey = config.get('hotkey', None) + item_type = item.get("sourcetype") + if item_type == ("python" or "file"): parent.addCommand( - config['title'], - command=command, - icon=icon, - shortcut=hotkey + item['title'], + command=str(item["command"]), + icon=item.get("icon"), + shortcut=item.get('hotkey') ) # add separator # Special behavior for separators - if item_type == "separator": + elif item_type == "separator": parent.addSeparator() # add submenu # items should hold a collection of submenu items (dict) elif item_type == "menu": - assert "items" in item, "Menu is missing 'items' key" - - icon = item.get('icon', None) - if icon: - try: - icon = icon.format(**os.environ) - except KeyError as e: - log.warning("This environment variable doesn't exist: " - "{}".format(e)) - menu = parent.addMenu(item['title'], icon=icon) - self.build_from_configuration(menu, item["items"]) + # assert "items" in item, "Menu is missing 'items' key" + parent.addMenu( + item['title'], + icon=item.get('icon') + ) def add_gizmo_path(self, gizmo_paths): for gizmo_path in gizmo_paths: diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index a1ac50ae1a..335e7190a0 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2500,50 +2500,77 @@ def recreate_instance(origin_node, avalon_data=None): return new_node -def find_scripts_gizmo(title, parent): - """ - Check if the menu exists with the given title in the parent - - Args: - title (str): the title name of the scripts menu - - parent (QtWidgets.QMenuBar): the menubar to check - - Returns: - QtWidgets.QMenu or None - - """ - - menu = None - search = [i for i in parent.items() if - isinstance(i, gizmo_menu.GizmoMenu) - and i.title() == title] - - if search: - assert len(search) < 2, ("Multiple instances of menu '{}' " - "in toolbar".format(title)) - menu = search[0] - - return menu - - -def gizmo_creation(title="Gizmos", parent=None, objectName=None, icon=None): +def add_scripts_gizmo(): try: - toolbar = find_scripts_gizmo(title, parent) - if not toolbar: - log.info("Attempting to build toolbar...") - object_name = objectName or title.lower() - toolbar = gizmo_menu.GizmoMenu( - title=title, - parent=parent, - objectName=object_name, - icon=icon - ) - except Exception as e: - log.error(e) + from openpype.hosts.nuke.api import lib + except ImportError: + log.warning( + "Skipping studio.gizmo install, because " + "'scriptsgizmo' module seems unavailable." + ) return - return toolbar + # load configuration of custom menu + project_settings = get_project_settings(os.getenv("AVALON_PROJECT")) + platform_name = platform.system().lower() + + for gizmo_settings in project_settings["nuke"]["gizmo"]: + gizmo_list_definition = gizmo_settings["gizmo_definition"] + print(1, gizmo_list_definition) + toolbar_name = gizmo_settings["toolbar_menu_name"] + # gizmo_toolbar_path = gizmo_settings["gizmo_toolbar_path"] + gizmo_source_dir = gizmo_settings.get( + "gizmo_source_dir", {}).get(platform_name) + toolbar_icon_path = gizmo_settings.get( + "toolbar_icon_path", {}).get(platform_name) + + if not gizmo_source_dir: + log.debug("Skipping studio gizmo `{}`, no gizmo path found.".format( + toolbar_name + )) + return + + if not gizmo_list_definition: + log.debug("Skipping studio gizmo `{}`, no definition found.".format( + toolbar_name + )) + return + + if toolbar_icon_path: + try: + toolbar_icon_path = toolbar_icon_path.format(**os.environ) + except KeyError as e: + log.error( + "This environment variable doesn't exist: {}".format(e) + ) + + existing_gizmo_path = [] + for source_dir in gizmo_source_dir: + try: + resolve_source_dir = source_dir.format(**os.environ) + except KeyError as e: + log.error( + "This environment variable doesn't exist: {}".format(e) + ) + continue + if not os.path.exists(resolve_source_dir): + log.warning( + "The source of gizmo `{}` does not exists".format( + resolve_source_dir + ) + ) + continue + existing_gizmo_path.append(resolve_source_dir) + + # run the launcher for Nuke toolbar + toolbar_menu = gizmo_menu.GizmoMenu( + title=toolbar_name, + icon=toolbar_icon_path + ) + + # apply configuration + toolbar_menu.add_gizmo_path(existing_gizmo_path) + toolbar_menu.build_from_configuration(gizmo_list_definition) class NukeDirmap(HostDirmap): diff --git a/openpype/hosts/nuke/startup/menu.py b/openpype/hosts/nuke/startup/menu.py index 715bab8ea5..1461d41385 100644 --- a/openpype/hosts/nuke/startup/menu.py +++ b/openpype/hosts/nuke/startup/menu.py @@ -8,7 +8,8 @@ from openpype.hosts.nuke.api.lib import ( on_script_load, check_inventory_versions, WorkfileSettings, - dirmap_file_name_filter + dirmap_file_name_filter, + add_scripts_gizmo ) from openpype.settings import get_project_settings @@ -60,71 +61,4 @@ def add_scripts_menu(): add_scripts_menu() - -def add_scripts_gizmo(): - try: - from openpype.hosts.nuke.api import lib - except ImportError: - log.warning( - "Skipping studio.gizmo install, because " - "'scriptsgizmo' module seems unavailable." - ) - return - - # load configuration of custom menu - project_settings = get_project_settings(os.getenv("AVALON_PROJECT")) - - for gizmo in project_settings["nuke"]["gizmo"]: - config = gizmo["gizmo_definition"] - toolbar_name = gizmo["toolbar_menu_name"] - gizmo_path = gizmo["gizmo_path"] - icon = gizmo['toolbar_icon_path'] - - if not any(gizmo_path): - log.warning("Skipping studio gizmo, no gizmo path found.") - return - - if not config: - log.warning("Skipping studio gizmo, no definition found.") - return - - try: - icon = icon.format(**os.environ) - except KeyError as e: - log.warning( - "This environment variable doesn't exist: {}".format(e) - ) - - existing_gizmo_path = [] - for gizmo in gizmo_path: - try: - gizmo = gizmo.format(**os.environ) - except KeyError as e: - log.warning( - "This environment variable doesn't exist: {}".format(e) - ) - continue - if not os.path.exists(gizmo): - log.warning( - "The source of gizmo `{}` does not exists".format(gizmo) - ) - continue - existing_gizmo_path.append(gizmo) - - nuke_toolbar = nuke.menu("Nodes") - toolbar = nuke_toolbar.addMenu(toolbar_name, icon=icon) - - # run the launcher for Nuke toolbar - studio_menu = lib.gizmo_creation( - title=toolbar_name, - parent=toolbar, - objectName=toolbar_name.lower().replace(" ", "_"), - icon=icon - ) - - # apply configuration - studio_menu.add_gizmo_path(existing_gizmo_path) - studio_menu.build_from_configuration(toolbar, config) - - add_scripts_gizmo() diff --git a/openpype/settings/defaults/project_settings/nuke.json b/openpype/settings/defaults/project_settings/nuke.json index 6c6454de36..63978ad1be 100644 --- a/openpype/settings/defaults/project_settings/nuke.json +++ b/openpype/settings/defaults/project_settings/nuke.json @@ -293,8 +293,12 @@ "gizmo": [ { "toolbar_menu_name": "OpenPype Gizmo", - "toolbar_icon_path": "path/to/nuke/icon.png", - "gizmo_path": ["path/to/nuke/gizmo"], + "gizmo_path": { + "windows": [], + "darwin": [], + "linux": [] + }, + "toolbar_icon_path": {}, "gizmo_definition": [ { "type": "action", diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_scriptsgizmo.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_scriptsgizmo.json index c1e67842ce..80fda56175 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_scriptsgizmo.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_scriptsgizmo.json @@ -14,28 +14,105 @@ }, { "type": "path", - "key": "toolbar_icon_path", - "label": "Toolbar Icon Path", - "multipath": false + "key": "gizmo_source_dir", + "label": "Gizmo directory path", + "multipath": true, + "multiplatform": true }, { - "type": "splitter" - }, - { - "type": "label", - "label": "Absolute path to gizmo folders." - }, - { - "type": "path", - "key": "gizmo_path", - "label": "Gizmo Path", - "multipath": true - }, - { - "type": "raw-json", - "key": "gizmo_definition", - "label": "Gizmo definition", - "is_list": true + "type": "collapsible-wrap", + "label": "Options", + "collapsible": true, + "collapsed": true, + "children": [ + { + "type": "path", + "key": "toolbar_icon_path", + "label": "Toolbar Icon Path", + "multipath": false, + "multiplatform": true + }, + { + "type": "splitter" + }, + { + "type": "list", + "key": "gizmo_definition", + "label": "Gizmo definitions", + "use_label_wrap": true, + "object_type": { + "type": "dict-conditional", + "enum_key": "sourcetype", + "enum_label": "Type of usage", + "enum_children": [ + { + "key": "python", + "label": "Python", + "children": [ + { + "type": "text", + "key": "title", + "label": "Title" + }, + { + "type": "text", + "key": "gizmo_toolbar_path", + "label": "Toolbar path" + }, + { + "type": "text", + "key": "command", + "label": "Python command" + }, + { + "type": "text", + "key": "shortcut", + "label": "Hotkey" + } + ] + }, + { + "key": "file", + "label": "File", + "children": [ + { + "type": "text", + "key": "title", + "label": "Title" + }, + { + "type": "text", + "key": "gizmo_toolbar_path", + "label": "Toolbar path" + }, + { + "type": "text", + "key": "file_name", + "label": "Gizmo file name" + }, + { + "type": "text", + "key": "shortcut", + "label": "Hotkey" + } + + ] + }, + { + "key": "separator", + "label": "Separator", + "children": [ + { + "type": "text", + "key": "gizmo_toolbar_path", + "label": "Toolbar path" + } + ] + } + ] + } + } + ] } ] }