mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-02 22:37:32 +00:00
Complete context menu migration for Load3D, Preview3D, and SaveGLB (#6454)
This pull request refactors how export menu options are added to 3D-related nodes, updating the API to use a new `getNodeMenuItems` hook and simplifying the menu item creation logic. The changes improve consistency and maintainability across extensions handling 3D nodes, and clarify the expected return types for menu item hooks. **Refactoring and API updates for node menu items:** * Replaced usage of the legacy `createExportMenuOptions` function with the new `createExportMenuItems` function in `load3d.ts`, `saveMesh.ts`, and related imports, aligning all 3D node extensions to the new API. [[1]](diffhunk://#diff-a5c612d9322ca4cbbeda097d13e2fa1ef017d4c3076d23fc228afee5a79a56e3L6-R12) [[2]](diffhunk://#diff-7dede72060130d77ce5191fc86d115bd9b93311cb0438400730d8e20b2aa8e43L4-R7) * Introduced and implemented the `getNodeMenuItems` hook in the extension registration for `Load3D`, `Preview3D`, and `SaveGLB` nodes, ensuring export menu items are only shown for the appropriate node types. [[1]](diffhunk://#diff-a5c612d9322ca4cbbeda097d13e2fa1ef017d4c3076d23fc228afee5a79a56e3R293-R302) [[2]](diffhunk://#diff-a5c612d9322ca4cbbeda097d13e2fa1ef017d4c3076d23fc228afee5a79a56e3R521-R530) [[3]](diffhunk://#diff-7dede72060130d77ce5191fc86d115bd9b93311cb0438400730d8e20b2aa8e43R48-R57) * Removed assignment of `getExtraMenuOptions` to nodes, fully migrating to the new menu item hook approach for context menus. [[1]](diffhunk://#diff-a5c612d9322ca4cbbeda097d13e2fa1ef017d4c3076d23fc228afee5a79a56e3L301-L302) [[2]](diffhunk://#diff-a5c612d9322ca4cbbeda097d13e2fa1ef017d4c3076d23fc228afee5a79a56e3L548-L549) [[3]](diffhunk://#diff-7dede72060130d77ce5191fc86d115bd9b93311cb0438400730d8e20b2aa8e43L64-L67) **Menu item creation logic simplification:** * Refactored `createExportMenuOptions` to `createExportMenuItems` in `exportMenuHelper.ts`, changing it to directly return an array of menu items (with separators) instead of a function, simplifying its usage and reducing boilerplate. [[1]](diffhunk://#diff-42404da1a87a52d304371a13d5f021bdad837765b94d86d186abb2d99a8cb707L14-R22) [[2]](diffhunk://#diff-42404da1a87a52d304371a13d5f021bdad837765b94d86d186abb2d99a8cb707L59-R58) **Type and documentation improvements:** * Updated the `ComfyExtension` interface in `comfy.ts` to clarify that menu item hooks (`getCanvasMenuItems`, `getNodeMenuItems`) now return arrays that may include `null` values as separators, improving type safety and documentation. See before and after below <img width="1459" height="897" alt="Screenshot 2025-10-30 at 07 08 04" src="https://github.com/user-attachments/assets/ec4464c9-f733-4b4c-87c4-bb5060ccaa68" /> ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6454-Complete-context-menu-migration-for-Load3D-Preview3D-and-SaveGLB-29c6d73d3650819995b4c4dc1582cd86) by [Unito](https://www.unito.io)
This commit is contained in:
committed by
GitHub
parent
9e309308ed
commit
c642ed5703
@@ -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')
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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**
|
||||
|
||||
Reference in New Issue
Block a user