mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 02:32:18 +00:00
Use ComfyNodeDefImpl on NodePreview component (#228)
* store widgets * Use node def impl
This commit is contained in:
@@ -22,7 +22,7 @@ https://github.com/Nuked88/ComfyUI-N-Sidebar/blob/7ae7da4a9761009fb6629bc04c6830
|
|||||||
<div class="_sb_col">{{ slotInput ? slotInput.name : '' }}</div>
|
<div class="_sb_col">{{ slotInput ? slotInput.name : '' }}</div>
|
||||||
<div class="_sb_col middle-column"></div>
|
<div class="_sb_col middle-column"></div>
|
||||||
<div class="_sb_col _sb_inherit">
|
<div class="_sb_col _sb_inherit">
|
||||||
{{ slotOutput ? slotOutput.name : '' }}
|
{{ slotOutput ? slotOutput.display_name : '' }}
|
||||||
</div>
|
</div>
|
||||||
<div class="_sb_col">
|
<div class="_sb_col">
|
||||||
<div v-if="slotOutput" :class="['_sb_dot', slotOutput.type]"></div>
|
<div v-if="slotOutput" :class="['_sb_dot', slotOutput.type]"></div>
|
||||||
@@ -34,7 +34,7 @@ https://github.com/Nuked88/ComfyUI-N-Sidebar/blob/7ae7da4a9761009fb6629bc04c6830
|
|||||||
<div class="_sb_col _sb_arrow">◀</div>
|
<div class="_sb_col _sb_arrow">◀</div>
|
||||||
<div class="_sb_col">{{ widgetInput.name }}</div>
|
<div class="_sb_col">{{ widgetInput.name }}</div>
|
||||||
<div class="_sb_col middle-column"></div>
|
<div class="_sb_col middle-column"></div>
|
||||||
<div class="_sb_col _sb_inherit">{{ widgetInput.defaultValue }}</div>
|
<div class="_sb_col _sb_inherit">{{ widgetInput.default }}</div>
|
||||||
<div class="_sb_col _sb_arrow">▶</div>
|
<div class="_sb_col _sb_arrow">▶</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -45,67 +45,27 @@ https://github.com/Nuked88/ComfyUI-N-Sidebar/blob/7ae7da4a9761009fb6629bc04c6830
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { app } from '@/scripts/app'
|
import { ComfyNodeDefImpl, useNodeDefStore } from '@/stores/nodeDefStore'
|
||||||
import { type ComfyNodeDef } from '@/types/apiTypes'
|
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { PropType } from 'vue'
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
nodeDef: {
|
nodeDef: {
|
||||||
type: Object as PropType<ComfyNodeDef>,
|
type: ComfyNodeDefImpl,
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const nodeDef = props.nodeDef as ComfyNodeDef
|
const nodeDefStore = useNodeDefStore()
|
||||||
|
|
||||||
// --------------------------------------------------
|
const nodeDef = props.nodeDef
|
||||||
// TODO: Move out to separate file
|
const allInputDefs = nodeDef.input.all
|
||||||
interface IComfyNodeInputDef {
|
const allOutputDefs = Object.values(nodeDef.output)
|
||||||
name: string
|
const slotInputDefs = allInputDefs.filter(
|
||||||
type: string
|
(input) => !nodeDefStore.inputIsWidget(input)
|
||||||
widgetType: string | null
|
|
||||||
defaultValue: any
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IComfyNodeOutputDef {
|
|
||||||
name: string | null
|
|
||||||
type: string
|
|
||||||
isList: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
const allInputs = Object.assign(
|
|
||||||
{},
|
|
||||||
nodeDef.input.required || {},
|
|
||||||
nodeDef.input.optional || {}
|
|
||||||
)
|
)
|
||||||
const allInputDefs: IComfyNodeInputDef[] = Object.entries(allInputs).map(
|
const widgetInputDefs = allInputDefs.filter((input) =>
|
||||||
([inputName, inputData]) => {
|
nodeDefStore.inputIsWidget(input)
|
||||||
return {
|
|
||||||
name: inputName,
|
|
||||||
type: inputData[0],
|
|
||||||
widgetType: app.getWidgetType(inputData, inputName),
|
|
||||||
defaultValue:
|
|
||||||
inputData[1]?.default ||
|
|
||||||
(inputData[0] instanceof Array ? inputData[0][0] : '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const allOutputDefs: IComfyNodeOutputDef[] = _.zip(
|
|
||||||
nodeDef.output,
|
|
||||||
nodeDef.output_name || [],
|
|
||||||
nodeDef.output_is_list || []
|
|
||||||
).map(([outputType, outputName, isList]) => {
|
|
||||||
return {
|
|
||||||
name: outputName,
|
|
||||||
type: outputType instanceof Array ? 'COMBO' : outputType,
|
|
||||||
isList: isList
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const slotInputDefs = allInputDefs.filter((input) => !input.widgetType)
|
|
||||||
const widgetInputDefs = allInputDefs.filter((input) => !!input.widgetType)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="comfy-vue-node-search-container">
|
<div class="comfy-vue-node-search-container">
|
||||||
<div class="comfy-vue-node-preview-container">
|
<div class="comfy-vue-node-preview-container">
|
||||||
<NodePreview
|
<NodePreview
|
||||||
:nodeDef="hoveredSuggestion"
|
:nodeDef="plainToClass(ComfyNodeDefImpl, hoveredSuggestion)"
|
||||||
:key="hoveredSuggestion?.name || ''"
|
:key="hoveredSuggestion?.name || ''"
|
||||||
v-if="hoveredSuggestion"
|
v-if="hoveredSuggestion"
|
||||||
/>
|
/>
|
||||||
@@ -62,7 +62,8 @@ import NodeSourceChip from '@/components/NodeSourceChip.vue'
|
|||||||
import { ComfyNodeDef } from '@/types/apiTypes'
|
import { ComfyNodeDef } from '@/types/apiTypes'
|
||||||
import { type FilterAndValue } from '@/services/nodeSearchService'
|
import { type FilterAndValue } from '@/services/nodeSearchService'
|
||||||
import NodePreview from './NodePreview.vue'
|
import NodePreview from './NodePreview.vue'
|
||||||
import { useNodeDefStore } from '@/stores/nodeDefStore'
|
import { ComfyNodeDefImpl, useNodeDefStore } from '@/stores/nodeDefStore'
|
||||||
|
import { plainToClass } from 'class-transformer'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
filters: {
|
filters: {
|
||||||
|
|||||||
@@ -1965,10 +1965,12 @@ export class ComfyApp {
|
|||||||
async registerNodes() {
|
async registerNodes() {
|
||||||
// Load node definitions from the backend
|
// Load node definitions from the backend
|
||||||
const defs = await api.getNodeDefs()
|
const defs = await api.getNodeDefs()
|
||||||
if (this.vueAppReady) {
|
|
||||||
useNodeDefStore().addNodeDefs(Object.values(defs))
|
|
||||||
}
|
|
||||||
await this.registerNodesFromDefs(defs)
|
await this.registerNodesFromDefs(defs)
|
||||||
|
if (this.vueAppReady) {
|
||||||
|
const nodeDefStore = useNodeDefStore()
|
||||||
|
nodeDefStore.addNodeDefs(Object.values(defs))
|
||||||
|
nodeDefStore.updateWidgets(this.widgets)
|
||||||
|
}
|
||||||
await this.#invokeExtensionsAsync('registerCustomNodes')
|
await this.#invokeExtensionsAsync('registerCustomNodes')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { NodeSearchService } from '@/services/nodeSearchService'
|
|||||||
import { ComfyNodeDef } from '@/types/apiTypes'
|
import { ComfyNodeDef } from '@/types/apiTypes'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { Type, Transform, plainToClass } from 'class-transformer'
|
import { Type, Transform, plainToClass } from 'class-transformer'
|
||||||
|
import { ComfyWidgetConstructor } from '@/scripts/widgets'
|
||||||
|
|
||||||
export class BaseInputSpec<T = any> {
|
export class BaseInputSpec<T = any> {
|
||||||
name: string
|
name: string
|
||||||
@@ -124,6 +125,10 @@ export class ComfyInputsSpec {
|
|||||||
return plainToClass(CustomInputSpec, { name, type, ...spec })
|
return plainToClass(CustomInputSpec, { name, type, ...spec })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get all() {
|
||||||
|
return [...Object.values(this.required), ...Object.values(this.optional)]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ComfyOutputSpec {
|
export class ComfyOutputSpec {
|
||||||
@@ -224,11 +229,13 @@ const SYSTEM_NODE_DEFS_BY_NAME = SYSTEM_NODE_DEFS.reduce((acc, nodeDef) => {
|
|||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
nodeDefsByName: Record<string, ComfyNodeDef>
|
nodeDefsByName: Record<string, ComfyNodeDef>
|
||||||
|
widgets: Record<string, ComfyWidgetConstructor>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useNodeDefStore = defineStore('nodeDef', {
|
export const useNodeDefStore = defineStore('nodeDef', {
|
||||||
state: (): State => ({
|
state: (): State => ({
|
||||||
nodeDefsByName: SYSTEM_NODE_DEFS_BY_NAME
|
nodeDefsByName: SYSTEM_NODE_DEFS_BY_NAME,
|
||||||
|
widgets: {}
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
nodeDefs(state) {
|
nodeDefs(state) {
|
||||||
@@ -246,6 +253,23 @@ export const useNodeDefStore = defineStore('nodeDef', {
|
|||||||
for (const nodeDef of nodeDefs) {
|
for (const nodeDef of nodeDefs) {
|
||||||
this.nodeDefsByName[nodeDef.name] = nodeDef
|
this.nodeDefsByName[nodeDef.name] = nodeDef
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
updateWidgets(widgets: Record<string, ComfyWidgetConstructor>) {
|
||||||
|
this.widgets = widgets
|
||||||
|
},
|
||||||
|
getWidgetType(type: string, inputName: string) {
|
||||||
|
if (type === 'COMBO') {
|
||||||
|
return 'COMBO'
|
||||||
|
} else if (`${type}:${inputName}` in this.widgets) {
|
||||||
|
return `${type}:${inputName}`
|
||||||
|
} else if (type in this.widgets) {
|
||||||
|
return type
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inputIsWidget(spec: BaseInputSpec) {
|
||||||
|
return this.getWidgetType(spec.type, spec.name) !== null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user