File size: 4,121 Bytes
c6535db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

import {app} from "@/composable/comfyAPI.js";

export const ANIM_PREVIEW_WIDGET = '$$comfy_animation_preview'

export function createImageHost(node) {
    const el = $el('div.comfy-img-preview')
    let currentImgs
    let first = true

    function updateSize() {
        let w = null
        let h = null

        if (currentImgs) {
            let elH = el.clientHeight
            if (first) {
                first = false
                // On first run, if we are small then grow a bit
                if (elH < 190) {
                    elH = 190
                }
                el.style.setProperty('--comfy-widget-min-height', elH.toString())
            } else {
                el.style.setProperty('--comfy-widget-min-height', null)
            }

            const nw = node.size[0]
            ;({ cellWidth: w, cellHeight: h } = calculateImageGrid(
                currentImgs,
                nw - 20,
                elH
            ))
            w += 'px'
            h += 'px'

            el.style.setProperty('--comfy-img-preview-width', w)
            el.style.setProperty('--comfy-img-preview-height', h)
        }
    }
    return {
        el,
        updateImages(imgs) {
            if (imgs !== currentImgs) {
                if (currentImgs == null) {
                    requestAnimationFrame(() => {
                        updateSize()
                    })
                }
                el.replaceChildren(...imgs)
                currentImgs = imgs
                node.onResize(node.size)
                node.graph.setDirtyCanvas(true, true)
            }
        },
        getHeight() {
            updateSize()
        },
        onDraw() {
            // Element from point uses a hittest find elements so we need to toggle pointer events
            el.style.pointerEvents = 'all'
            const over = document.elementFromPoint(
                app.canvas.mouse[0],
                app.canvas.mouse[1]
            )
            el.style.pointerEvents = 'none'

            if (!over) return
            // Set the overIndex so Open Image etc work
            const idx = currentImgs.indexOf(over)
            node.overIndex = idx
        }
    }
}

/**
 * Composable for handling animated image previews in nodes
 */
export function useNodeVideoPreview() {
    /**
     * Shows animated image preview for a node
     * @param node The graph node to show the preview for
     */
    function showVideoPreview(node) {
        if (!node.video?.length) return
        if (!node.widgets) return

        const widgetIdx = node.widgets.findIndex(
            (w) => w.name === ANIM_PREVIEW_WIDGET
        )

        if (widgetIdx > -1) {
            // Replace content in existing widget
            // const widget = node.widgets[widgetIdx] || {options: { host: null}}
            // widget.options.host.updateImages(node.imgs)
        } else {
            // Create new widget
            // const host = createImageHost(node)
            // @ts-expect-error host is not a standard DOM widget option.
            // const widget = node.addDOMWidget(ANIM_PREVIEW_WIDGET, 'img', host.el, {
            //     host,
            //     // @ts-expect-error `getHeight` of image host returns void instead of number.
            //     getHeight: host.getHeight,
            //     onDraw: host.onDraw,
            //     hideOnZoom: false
            // }) || {
            //     options: { host: null }
            // }
            // widget.serializeValue = () => undefined
            // widget.options.host.updateImages(node.imgs)
        }
    }

    /**
     * Removes video image preview from a node
     * @param node The graph node to remove the preview from
     */
    function removeVideoPreview(node) {
        if (!node.widgets) return

        const widgetIdx = node.widgets.findIndex(
            (w) => w.name === 'video-preview'
        )

        if (widgetIdx > -1) {
            node.widgets[widgetIdx].onRemove?.()
            node.widgets.splice(widgetIdx, 1)
        }
    }

    return {
        showVideoPreview,
        removeVideoPreview
    }
}