mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-20 06:44:32 +00:00
## Summary Add mesh_upload and upload_subfolder to combo input schema so WidgetSelect detects mesh uploads generically instead of hardcoding node type checks. Inject these flags in load3dLazy.ts so they are available before THREE.js loads. Also unify SUPPORTED_EXTENSIONS_ACCEPT across load3d and dropdown, pass uploadSubfolder prop through to WidgetSelectDropdown for correct upload path, and update error message to list all supported extensions. replacement for https://github.com/Comfy-Org/ComfyUI_frontend/pull/7975 (We should include thumbnail but not yet, will do it later) ## Screenshots (if applicable) https://github.com/user-attachments/assets/2cb4b1da-af4f-439b-9786-3ac780c2480d ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8765-Feat-3d-dropdown-3036d73d365081d8a10ee19d3ed7d295) by [Unito](https://www.unito.io) --------- Co-authored-by: Kelly Yang <124ykl@gmail.com>
79 lines
2.6 KiB
TypeScript
79 lines
2.6 KiB
TypeScript
/**
|
|
* Lazy loader for 3D extensions (Load3D, Preview3D, SaveGLB)
|
|
*
|
|
* This module defers loading of THREE.js (~1.8MB) until a 3D node is actually
|
|
* used in a workflow. The heavy imports are only loaded when:
|
|
* - A workflow containing 3D nodes is loaded
|
|
* - A user adds a 3D node from the node menu
|
|
*/
|
|
|
|
import { useExtensionService } from '@/services/extensionService'
|
|
import { app } from '@/scripts/app'
|
|
import { useExtensionStore } from '@/stores/extensionStore'
|
|
|
|
import type { ComfyExtension } from '@/types/comfy'
|
|
|
|
const LOAD3D_NODE_TYPES = new Set(['Load3D', 'Preview3D', 'SaveGLB'])
|
|
|
|
let load3dExtensionsLoaded = false
|
|
let load3dExtensionsLoading: Promise<ComfyExtension[]> | null = null
|
|
|
|
/**
|
|
* Dynamically load the 3D extensions (and THREE.js) on demand.
|
|
* Returns the list of newly registered extensions so the caller can
|
|
* replay hooks that they missed.
|
|
*/
|
|
async function loadLoad3dExtensions(): Promise<ComfyExtension[]> {
|
|
if (load3dExtensionsLoaded) return []
|
|
|
|
if (load3dExtensionsLoading) {
|
|
return load3dExtensionsLoading
|
|
}
|
|
|
|
load3dExtensionsLoading = (async () => {
|
|
const before = new Set(useExtensionStore().enabledExtensions)
|
|
// Import both extensions - they will self-register via useExtensionService()
|
|
await Promise.all([import('./load3d'), import('./saveMesh')])
|
|
load3dExtensionsLoaded = true
|
|
return useExtensionStore().enabledExtensions.filter(
|
|
(ext) => !before.has(ext)
|
|
)
|
|
})()
|
|
|
|
return load3dExtensionsLoading
|
|
}
|
|
|
|
/**
|
|
* Check if a node type is a 3D node that requires THREE.js
|
|
*/
|
|
function isLoad3dNodeType(nodeTypeName: string): boolean {
|
|
return LOAD3D_NODE_TYPES.has(nodeTypeName)
|
|
}
|
|
|
|
// Register a lightweight extension that triggers lazy loading
|
|
useExtensionService().registerExtension({
|
|
name: 'Comfy.Load3DLazy',
|
|
|
|
async beforeRegisterNodeDef(nodeType, nodeData) {
|
|
if (isLoad3dNodeType(nodeData.name)) {
|
|
// Inject mesh_upload spec flags so WidgetSelect.vue can detect
|
|
// Load3D's model_file as a mesh upload widget without hardcoding.
|
|
if (nodeData.name === 'Load3D') {
|
|
const modelFile = nodeData.input?.required?.model_file
|
|
if (modelFile?.[1]) {
|
|
modelFile[1].mesh_upload = true
|
|
modelFile[1].upload_subfolder = '3d'
|
|
}
|
|
}
|
|
|
|
// Load the 3D extensions and replay their beforeRegisterNodeDef hooks,
|
|
// since invokeExtensionsAsync already captured the extensions snapshot
|
|
// before these new extensions were registered.
|
|
const newExtensions = await loadLoad3dExtensions()
|
|
for (const ext of newExtensions) {
|
|
await ext.beforeRegisterNodeDef?.(nodeType, nodeData, app)
|
|
}
|
|
}
|
|
}
|
|
})
|