mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-21 07:14:11 +00:00
Fixes #8882 Adds explicit type annotations to all extension callback parameters (`nodeCreated`, `beforeRegisterNodeDef`, `addCustomNodeDefs`) across 14 core extension files. While the types were already inferred from the `ComfyExtension` interface, explicit annotations improve readability and make the code self-documenting. ## Changes - Annotate `node` parameter as `LGraphNode` in all `nodeCreated` callbacks - Annotate `nodeType` as `typeof LGraphNode` and `nodeData` as `ComfyNodeDef` in all `beforeRegisterNodeDef` callbacks - Annotate `defs` as `Record<string, ComfyNodeDef>` in `addCustomNodeDefs` - Add necessary type imports where missing ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8966-fix-add-explicit-type-annotations-to-extension-callback-parameters-30b6d73d36508125b074f509aa38145f) by [Unito](https://www.unito.io)
119 lines
3.3 KiB
TypeScript
119 lines
3.3 KiB
TypeScript
import { nextTick } from 'vue'
|
|
|
|
import Load3D from '@/components/load3d/Load3D.vue'
|
|
import { useLoad3d } from '@/composables/useLoad3d'
|
|
import { createExportMenuItems } from '@/extensions/core/load3d/exportMenuHelper'
|
|
import Load3DConfiguration from '@/extensions/core/load3d/Load3DConfiguration'
|
|
import Load3dUtils from '@/extensions/core/load3d/Load3dUtils'
|
|
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
|
import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'
|
|
import type { NodeOutputWith, ResultItem } from '@/schemas/apiSchema'
|
|
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
|
|
|
|
type SaveMeshOutput = NodeOutputWith<{
|
|
'3d'?: ResultItem[]
|
|
}>
|
|
import type { CustomInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'
|
|
import { ComponentWidgetImpl, addWidget } from '@/scripts/domWidget'
|
|
import { useExtensionService } from '@/services/extensionService'
|
|
import { useLoad3dService } from '@/services/load3dService'
|
|
|
|
const inputSpec: CustomInputSpec = {
|
|
name: 'image',
|
|
type: 'Preview3D',
|
|
isPreview: true
|
|
}
|
|
|
|
useExtensionService().registerExtension({
|
|
name: 'Comfy.SaveGLB',
|
|
|
|
async beforeRegisterNodeDef(
|
|
_nodeType: typeof LGraphNode,
|
|
nodeData: ComfyNodeDef
|
|
) {
|
|
if ('SaveGLB' === nodeData.name) {
|
|
// @ts-expect-error InputSpec is not typed correctly
|
|
nodeData.input.required.image = ['PREVIEW_3D']
|
|
}
|
|
},
|
|
|
|
getCustomWidgets() {
|
|
return {
|
|
PREVIEW_3D(node) {
|
|
const widget = new ComponentWidgetImpl({
|
|
node,
|
|
name: inputSpec.name,
|
|
component: Load3D,
|
|
inputSpec,
|
|
options: {}
|
|
})
|
|
|
|
widget.type = 'load3D'
|
|
|
|
addWidget(node, widget)
|
|
|
|
return { widget }
|
|
}
|
|
}
|
|
},
|
|
|
|
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 []
|
|
|
|
if (load3d.isSplatModel()) return []
|
|
|
|
return createExportMenuItems(load3d)
|
|
},
|
|
|
|
async nodeCreated(node: LGraphNode) {
|
|
if (node.constructor.comfyClass !== 'SaveGLB') return
|
|
|
|
const [oldWidth, oldHeight] = node.size
|
|
|
|
node.setSize([Math.max(oldWidth, 400), Math.max(oldHeight, 550)])
|
|
|
|
await nextTick()
|
|
|
|
const onExecuted = node.onExecuted
|
|
|
|
node.onExecuted = function (output: SaveMeshOutput) {
|
|
onExecuted?.call(this, output)
|
|
|
|
const fileInfo = output['3d']?.[0]
|
|
|
|
if (!fileInfo) return
|
|
|
|
useLoad3d(node).waitForLoad3d((load3d) => {
|
|
const modelWidget = node.widgets?.find((w) => w.name === 'image')
|
|
|
|
if (load3d && modelWidget) {
|
|
const filePath =
|
|
(fileInfo.subfolder ?? '') + '/' + (fileInfo.filename ?? '')
|
|
|
|
modelWidget.value = filePath
|
|
|
|
const config = new Load3DConfiguration(load3d, node.properties)
|
|
|
|
const loadFolder = fileInfo.type as 'input' | 'output'
|
|
|
|
const onModelLoaded = () => {
|
|
load3d.removeEventListener('modelLoadingEnd', onModelLoaded)
|
|
void Load3dUtils.generateThumbnailIfNeeded(
|
|
load3d,
|
|
filePath,
|
|
loadFolder
|
|
)
|
|
}
|
|
load3d.addEventListener('modelLoadingEnd', onModelLoaded)
|
|
|
|
config.configureForSaveMesh(loadFolder, filePath)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
})
|