mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 14:30:41 +00:00
feat: support disabled state and upstream value display for curve widget
This commit is contained in:
@@ -3,8 +3,13 @@
|
||||
ref="svgRef"
|
||||
viewBox="-0.04 -0.04 1.08 1.08"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
class="aspect-square w-full cursor-crosshair rounded-[5px] bg-node-component-surface"
|
||||
@pointerdown.stop="handleSvgPointerDown"
|
||||
:class="
|
||||
cn(
|
||||
'aspect-square w-full rounded-[5px] bg-node-component-surface',
|
||||
disabled ? 'cursor-default' : 'cursor-crosshair'
|
||||
)
|
||||
"
|
||||
@pointerdown.stop="onSvgPointerDown"
|
||||
@contextmenu.prevent.stop
|
||||
>
|
||||
<line
|
||||
@@ -56,20 +61,23 @@
|
||||
:stroke="curveColor"
|
||||
stroke-width="0.008"
|
||||
stroke-linecap="round"
|
||||
:opacity="disabled ? 0.5 : 1"
|
||||
/>
|
||||
|
||||
<circle
|
||||
v-for="(point, i) in modelValue"
|
||||
:key="i"
|
||||
:cx="point[0]"
|
||||
:cy="1 - point[1]"
|
||||
r="0.02"
|
||||
:fill="curveColor"
|
||||
stroke="white"
|
||||
stroke-width="0.004"
|
||||
class="cursor-grab"
|
||||
@pointerdown.stop="startDrag(i, $event)"
|
||||
/>
|
||||
<template v-if="!disabled">
|
||||
<circle
|
||||
v-for="(point, i) in modelValue"
|
||||
:key="i"
|
||||
:cx="point[0]"
|
||||
:cy="1 - point[1]"
|
||||
r="0.02"
|
||||
:fill="curveColor"
|
||||
stroke="white"
|
||||
stroke-width="0.004"
|
||||
class="cursor-grab"
|
||||
@pointerdown.stop="startDrag(i, $event)"
|
||||
/>
|
||||
</template>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
@@ -77,14 +85,20 @@
|
||||
import { computed, useTemplateRef } from 'vue'
|
||||
|
||||
import { useCurveEditor } from '@/composables/useCurveEditor'
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
|
||||
import type { CurvePoint } from './types'
|
||||
|
||||
import { histogramToPath } from './curveUtils'
|
||||
|
||||
const { curveColor = 'white', histogram } = defineProps<{
|
||||
const {
|
||||
curveColor = 'white',
|
||||
histogram,
|
||||
disabled = false
|
||||
} = defineProps<{
|
||||
curveColor?: string
|
||||
histogram?: Uint32Array | null
|
||||
disabled?: boolean
|
||||
}>()
|
||||
|
||||
const modelValue = defineModel<CurvePoint[]>({
|
||||
@@ -98,6 +112,10 @@ const { curvePath, handleSvgPointerDown, startDrag } = useCurveEditor({
|
||||
modelValue
|
||||
})
|
||||
|
||||
function onSvgPointerDown(e: PointerEvent) {
|
||||
if (!disabled) handleSvgPointerDown(e)
|
||||
}
|
||||
|
||||
const histogramPath = computed(() =>
|
||||
histogram ? histogramToPath(histogram) : ''
|
||||
)
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
<template>
|
||||
<CurveEditor v-model="modelValue" />
|
||||
<CurveEditor
|
||||
:model-value="effectivePoints"
|
||||
:disabled="isDisabled"
|
||||
@update:model-value="modelValue = $event"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { CurvePoint } from './types'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useLinkedWidgetValue } from '@/composables/useLinkedWidgetValue'
|
||||
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
||||
|
||||
import CurveEditor from './CurveEditor.vue'
|
||||
import type { CurvePoint } from './types'
|
||||
|
||||
const { widget, nodeId } = defineProps<{
|
||||
widget: SimplifiedWidget
|
||||
nodeId: string
|
||||
}>()
|
||||
|
||||
const modelValue = defineModel<CurvePoint[]>({
|
||||
default: () => [
|
||||
@@ -13,4 +26,14 @@ const modelValue = defineModel<CurvePoint[]>({
|
||||
[1, 1]
|
||||
]
|
||||
})
|
||||
|
||||
const isDisabled = computed(() => !!widget.options?.disabled)
|
||||
|
||||
const upstreamValue = useLinkedWidgetValue(nodeId, widget.name, 'curve')
|
||||
|
||||
const effectivePoints = computed(() =>
|
||||
isDisabled.value && upstreamValue.value
|
||||
? (upstreamValue.value as CurvePoint[])
|
||||
: modelValue.value
|
||||
)
|
||||
</script>
|
||||
|
||||
50
src/composables/useLinkedWidgetValue.ts
Normal file
50
src/composables/useLinkedWidgetValue.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import type { ComputedRef } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
||||
import { useWidgetValueStore } from '@/stores/widgetValueStore'
|
||||
|
||||
/**
|
||||
* Returns the upstream widget value for a connected input slot.
|
||||
* Matches by output slot name first, then falls back to widget type.
|
||||
*/
|
||||
export function useLinkedWidgetValue(
|
||||
nodeId: string,
|
||||
widgetName: string,
|
||||
widgetType: string
|
||||
): ComputedRef<unknown | undefined> {
|
||||
const canvasStore = useCanvasStore()
|
||||
const widgetValueStore = useWidgetValueStore()
|
||||
|
||||
return computed(() => {
|
||||
const graph = canvasStore.canvas?.graph
|
||||
if (!graph) return undefined
|
||||
|
||||
const node = graph.getNodeById(nodeId)
|
||||
if (!node?.inputs) return undefined
|
||||
|
||||
const slot = node.inputs.find((s) => s.name === widgetName)
|
||||
if (!slot?.link) return undefined
|
||||
|
||||
const link = graph.getLink(slot.link)
|
||||
if (!link) return undefined
|
||||
|
||||
const graphId = graph.rootGraph.id
|
||||
const originNode = graph.getNodeById(link.origin_id)
|
||||
const outputName = originNode?.outputs?.[link.origin_slot]?.name
|
||||
|
||||
const upstreamWidgets = widgetValueStore.getNodeWidgets(
|
||||
graphId,
|
||||
link.origin_id
|
||||
)
|
||||
|
||||
const matched = outputName
|
||||
? upstreamWidgets.find((w) => w.name === outputName)
|
||||
: undefined
|
||||
|
||||
if (matched) return matched.value
|
||||
|
||||
const typeMatches = upstreamWidgets.filter((w) => w.type === widgetType)
|
||||
return typeMatches.length === 1 ? typeMatches[0].value : undefined
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user