@@ -366,6 +366,10 @@ def _regenerate_menu_py(self, griptape_dir: Path) -> None:
366366 ``nuke.plugins()`` to discover ALL versioned ``.gizmo`` files at call time,
367367 calls ``nuke.load()`` on each to force Nuke to re-read the TCL from disk,
368368 and rebuilds the Griptape node-creation entries on the Nodes toolbar.
369+ The refresh tracks the menu items it adds (module-level list in the
370+ generated code) and removes only those on each rescan, so the
371+ Nodes > Griptape menu can be shared with other plugins (e.g. Nuke's
372+ built-in Griptape workflow node).
369373
370374 "Refresh Griptape Gizmos" lives on the main Nuke menu bar (not the Nodes
371375 toolbar) so that clicking it never triggers Nuke's node-placement mode.
@@ -394,12 +398,20 @@ def _regenerate_menu_py(self, griptape_dir: Path) -> None:
394398# Module-level reference keeps the watcher alive (Python GC would drop a local).
395399_GRIPTAPE_WATCHER = None
396400
401+ # Labels of items THIS script added to Nodes > Griptape. The menu is shared --
402+ # other plugins (e.g. Nuke's built-in Griptape workflow node) may add items --
403+ # so a refresh must only remove entries we created, never the whole menu.
404+ _GRIPTAPE_MENU_ITEMS = []
405+
397406
398407def _refresh_griptape_menu():
399408 \" \" \" Rescan the griptape directory and rebuild the Griptape node-creation menu.
400409
401410 Call this after publishing a new or updated gizmo to make it available
402411 without restarting Nuke.
412+
413+ Only entries added by this script are removed and re-added; items other
414+ plugins placed in the Griptape menu are left untouched.
403415 \" \" \"
404416 # Remove then re-add the path to force Nuke to re-walk the directory.
405417 # pluginAddPath is idempotent on an already-registered path; the remove
@@ -429,15 +441,23 @@ def _refresh_griptape_menu():
429441 for stem in workflows:
430442 workflows[stem].sort()
431443
432- # Rebuild the Griptape submenu on the Nodes toolbar.
433- # Remove the existing entry first so repeated calls don't accumulate duplicates.
444+ # Get-or-create the Griptape submenu on the Nodes toolbar. addMenu()
445+ # returns the existing menu when one with this name already exists, so
446+ # items added by other plugins (e.g. Nuke's built-in Griptape workflow
447+ # node) are preserved. Never remove the menu itself.
434448 nodes_toolbar = nuke.menu('Nodes')
435- try:
436- nodes_toolbar.removeItem('Griptape')
437- except Exception:
438- pass
439449 griptape_nodes = nodes_toolbar.addMenu('Griptape')
440450
451+ # Remove only the entries added by a previous refresh so repeated calls
452+ # don't accumulate duplicates and deleted gizmos disappear from the menu.
453+ global _GRIPTAPE_MENU_ITEMS
454+ for _item_name in _GRIPTAPE_MENU_ITEMS:
455+ try:
456+ griptape_nodes.removeItem(_item_name)
457+ except Exception:
458+ pass
459+ _GRIPTAPE_MENU_ITEMS = []
460+
441461 for stem in sorted(workflows):
442462 label = stem.replace('_', ' ').title()
443463 versions = workflows[stem]
@@ -450,6 +470,7 @@ def _refresh_griptape_menu():
450470 workflow_submenu = griptape_nodes.addMenu(label)
451471 for ver, node_name in versions:
452472 workflow_submenu.addCommand('v{}'.format(ver), "nuke.createNode('{}')".format(node_name))
473+ _GRIPTAPE_MENU_ITEMS.append(label)
453474
454475
455476# "Refresh Griptape Gizmos" lives on the main Nuke menu bar so that clicking
0 commit comments