diff --git a/src/extensions/core/load3d.ts b/src/extensions/core/load3d.ts index 5bc4cdeee..7cbc489d3 100644 --- a/src/extensions/core/load3d.ts +++ b/src/extensions/core/load3d.ts @@ -3,11 +3,13 @@ import { nextTick } from 'vue' import Load3D from '@/components/load3d/Load3D.vue' import Load3DAnimation from '@/components/load3d/Load3DAnimation.vue' import Load3DViewerContent from '@/components/load3d/Load3dViewerContent.vue' -import { createExportMenuOptions } from '@/extensions/core/load3d/exportMenuHelper' +import { createExportMenuItems } from '@/extensions/core/load3d/exportMenuHelper' import Load3DConfiguration from '@/extensions/core/load3d/Load3DConfiguration' import Load3dAnimation from '@/extensions/core/load3d/Load3dAnimation' import Load3dUtils from '@/extensions/core/load3d/Load3dUtils' import { t } from '@/i18n' +import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode' +import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces' import type { IStringWidget } from '@/lib/litegraph/src/types/widgets' import { useToastStore } from '@/platform/updates/common/toastStore' import { type CustomInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2' @@ -288,6 +290,16 @@ useExtensionService().registerExtension({ } }, + getNodeMenuItems(node: LGraphNode): (IContextMenuValue | null)[] { + // Only show menu items for Load3D nodes + if (node.constructor.comfyClass !== 'Load3D') return [] + + const load3d = useLoad3dService().getLoad3d(node) + if (!load3d) return [] + + return createExportMenuItems(load3d) + }, + async nodeCreated(node) { if (node.constructor.comfyClass !== 'Load3D') return @@ -298,8 +310,6 @@ useExtensionService().registerExtension({ await nextTick() useLoad3dService().waitForLoad3d(node, (load3d) => { - node.getExtraMenuOptions = createExportMenuOptions(load3d) - let cameraState = node.properties['Camera Info'] const config = new Load3DConfiguration(load3d) @@ -508,6 +518,16 @@ useExtensionService().registerExtension({ } }, + getNodeMenuItems(node: LGraphNode): (IContextMenuValue | null)[] { + // Only show menu items for Preview3D nodes + if (node.constructor.comfyClass !== 'Preview3D') return [] + + const load3d = useLoad3dService().getLoad3d(node) + if (!load3d) return [] + + return createExportMenuItems(load3d) + }, + getCustomWidgets() { return { PREVIEW_3D(node) { @@ -545,8 +565,6 @@ useExtensionService().registerExtension({ const onExecuted = node.onExecuted useLoad3dService().waitForLoad3d(node, (load3d) => { - node.getExtraMenuOptions = createExportMenuOptions(load3d) - const config = new Load3DConfiguration(load3d) const modelWidget = node.widgets?.find((w) => w.name === 'model_file') diff --git a/src/extensions/core/load3d/exportMenuHelper.ts b/src/extensions/core/load3d/exportMenuHelper.ts index a47ec5eb5..d87146cc3 100644 --- a/src/extensions/core/load3d/exportMenuHelper.ts +++ b/src/extensions/core/load3d/exportMenuHelper.ts @@ -1,5 +1,4 @@ import { t } from '@/i18n' -import type { LGraphCanvas } from '@/lib/litegraph/src/LGraphCanvas' import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces' import { useToastStore } from '@/platform/updates/common/toastStore' import Load3d from '@/extensions/core/load3d/Load3d' @@ -11,17 +10,16 @@ const EXPORT_FORMATS = [ { label: 'STL', value: 'stl' } ] as const -export function createExportMenuOptions( +/** + * Creates export menu items for a 3D node using the new extension API. + * Returns an array of context menu items including a separator and export submenu. + */ +export function createExportMenuItems( load3d: Load3d -): ( - canvas: LGraphCanvas, - options: (IContextMenuValue | null)[] -) => (IContextMenuValue | null)[] { - return function ( - _canvas: LGraphCanvas, - options: (IContextMenuValue | null)[] - ): (IContextMenuValue | null)[] { - options.push(null, { +): (IContextMenuValue | null)[] { + return [ + null, // Separator + { content: 'Save', has_submenu: true, callback: (_value, _options, event, prev_menu) => { @@ -56,7 +54,6 @@ export function createExportMenuOptions( parentMenu: prev_menu }) } - }) - return options - } + } + ] } diff --git a/src/extensions/core/saveMesh.ts b/src/extensions/core/saveMesh.ts index a7ffbac89..6babf9c42 100644 --- a/src/extensions/core/saveMesh.ts +++ b/src/extensions/core/saveMesh.ts @@ -1,8 +1,10 @@ import { nextTick } from 'vue' import Load3D from '@/components/load3d/Load3D.vue' -import { createExportMenuOptions } from '@/extensions/core/load3d/exportMenuHelper' +import { createExportMenuItems } from '@/extensions/core/load3d/exportMenuHelper' import Load3DConfiguration from '@/extensions/core/load3d/Load3DConfiguration' +import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode' +import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces' import { type CustomInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2' import { ComponentWidgetImpl, addWidget } from '@/scripts/domWidget' import { useExtensionService } from '@/services/extensionService' @@ -43,6 +45,16 @@ useExtensionService().registerExtension({ } }, + getNodeMenuItems(node: LGraphNode): (IContextMenuValue | null)[] { + // Only show menu items for SaveGLB nodes + if (node.constructor.comfyClass !== 'SaveGLB') return [] + + const load3d = useLoad3dService().getLoad3d(node) + if (!load3d) return [] + + return createExportMenuItems(load3d) + }, + async nodeCreated(node) { if (node.constructor.comfyClass !== 'SaveGLB') return @@ -61,10 +73,6 @@ useExtensionService().registerExtension({ const load3d = useLoad3dService().getLoad3d(node) - if (load3d) { - node.getExtraMenuOptions = createExportMenuOptions(load3d) - } - const modelWidget = node.widgets?.find((w) => w.name === 'image') if (load3d && modelWidget) { diff --git a/src/types/comfy.ts b/src/types/comfy.ts index e8652c94f..db0760bbd 100644 --- a/src/types/comfy.ts +++ b/src/types/comfy.ts @@ -140,16 +140,16 @@ export interface ComfyExtension { /** * Allows the extension to add context menu items to canvas right-click menus * @param canvas The canvas instance - * @returns An array of context menu items to add + * @returns An array of context menu items to add (null values represent separators) */ - getCanvasMenuItems?(canvas: LGraphCanvas): IContextMenuValue[] + getCanvasMenuItems?(canvas: LGraphCanvas): (IContextMenuValue | null)[] /** * Allows the extension to add context menu items to node right-click menus * @param node The node being right-clicked - * @returns An array of context menu items to add + * @returns An array of context menu items to add (null values represent separators) */ - getNodeMenuItems?(node: LGraphNode): IContextMenuValue[] + getNodeMenuItems?(node: LGraphNode): (IContextMenuValue | null)[] /** * Allows the extension to add additional handling to the node before it is registered with **LGraph**