Toggle nodes/containers on and off by tags

This commit is contained in:
space-nuko
2023-05-07 21:29:36 -05:00
parent e7f4638093
commit 8e363cdd51
27 changed files with 529 additions and 149 deletions

View File

@@ -13,6 +13,7 @@
import layoutState, { type ContainerLayout, type WidgetLayout, type IDragItem } from "$lib/stores/layoutState";
import { startDrag, stopDrag } from "$lib/utils"
import type { Writable } from "svelte/store";
import { isHidden } from "$lib/widgets/utils";
export let container: ContainerLayout | null = null;
export let zIndex: number = 0;
@@ -73,7 +74,7 @@
on:finalize="{handleFinalize}"
>
{#each children.filter(item => item.id !== SHADOW_PLACEHOLDER_ITEM_ID) as item(item.id)}
{@const hidden = item?.attrs?.hidden}
{@const hidden = isHidden(item)}
<div class="animation-wrapper"
class:hidden={hidden}
animate:flip={{duration:flipDurationMs}}
@@ -86,7 +87,7 @@
</div>
{/each}
</div>
{#if container.attrs.hidden && edit}
{#if isHidden(container) && edit}
<div class="handle handle-hidden" class:hidden={!edit} style="z-index: {zIndex+100}"/>
{/if}
{#if showHandles}

View File

@@ -12,6 +12,7 @@
import layoutState, { type ContainerLayout, type WidgetLayout, type IDragItem } from "$lib/stores/layoutState";
import { startDrag, stopDrag } from "$lib/utils"
import type { Writable } from "svelte/store";
import { isHidden } from "$lib/widgets/utils";
export let container: ContainerLayout | null = null;
export let zIndex: number = 0;
@@ -75,7 +76,7 @@
on:finalize="{handleFinalize}"
>
{#each children.filter(item => item.id !== SHADOW_PLACEHOLDER_ITEM_ID) as item(item.id)}
{@const hidden = item?.attrs?.hidden}
{@const hidden = isHidden(item)}
<div class="animation-wrapper"
class:hidden={hidden}
animate:flip={{duration:flipDurationMs}}
@@ -88,7 +89,7 @@
</div>
{/each}
</div>
{#if container.attrs.hidden && edit}
{#if isHidden(container) && edit}
<div class="handle handle-hidden" class:hidden={!edit} style="z-index: {zIndex+100}"/>
{/if}
{#if showHandles}
@@ -239,6 +240,10 @@
flex-grow: 100;
}
.handle-hidden {
background-color: #40404080;
}
.handle-widget:hover {
background-color: #add8e680;
}

View File

@@ -201,7 +201,7 @@
})
async function doRefreshCombos() {
await app.refreshComboInNodes()
await app.refreshComboInNodes(true)
}
</script>

View File

@@ -9,6 +9,7 @@ import type TypedEmitter from "typed-emitter";
// Import nodes
import "@litegraph-ts/nodes-basic"
import "@litegraph-ts/nodes-events"
import "@litegraph-ts/nodes-logic"
import "@litegraph-ts/nodes-math"
import "@litegraph-ts/nodes-strings"
import "$lib/nodes/index"
@@ -70,6 +71,27 @@ export type Progress = {
max: number
}
function isActiveBackendNode(node: ComfyGraphNode, tag: string | null): boolean {
if (!node.isBackendNode)
return false;
if (tag && !hasTag(node, tag)) {
console.debug("Skipping tagged node", tag, node.properties.tags, node)
return false;
}
if (node.mode === NodeMode.NEVER) {
// Don't serialize muted nodes
return false;
}
return true;
}
function hasTag(node: LGraphNode, tag: string): boolean {
return "tags" in node.properties && node.properties.tags.indexOf(tag) !== -1
}
export default class ComfyApp {
api: ComfyAPI;
rootEl: HTMLDivElement | null = null;
@@ -443,23 +465,12 @@ export default class ComfyApp {
for (const node_ of this.lGraph.computeExecutionOrder<ComfyGraphNode>(false, null)) {
const n = workflow.nodes.find((n) => n.id === node_.id);
if (!node_.isBackendNode) {
// console.debug("Not serializing node: ", node_.type)
if (!isActiveBackendNode(node_, tag)) {
continue;
}
const node = node_ as ComfyBackendNode;
if (tag && node.tags.indexOf(tag) === -1) {
console.debug("Skipping tagged node", tag, node.tags)
continue;
}
if (node.mode === NodeMode.NEVER) {
// Don't serialize muted nodes
continue;
}
const inputs = {};
// Store all link values
@@ -469,7 +480,11 @@ export default class ComfyApp {
const inputLink = node.getInputLink(i)
const inputNode = node.getInputNode(i)
if (inputNode && tag && "tags" in inputNode && (inputNode.tags as string[]).indexOf(tag) === -1) {
// We don't check tags for non-backend nodes.
// Just check for node inactivity (so you can toggle groups of
// tagged frontend nodes on/off)
if (inputNode && inputNode.mode === NodeMode.NEVER) {
console.debug("Skipping inactive node", inputNode)
continue;
}
@@ -515,7 +530,7 @@ export default class ComfyApp {
const isValidParent = (parent: ComfyGraphNode) => {
if (!parent || parent.isBackendNode)
return false;
if ("tags" in parent && (parent.tags as string[]).indexOf(tag) === -1)
if (tag && !hasTag(parent, tag))
return false;
return true;
}
@@ -525,8 +540,8 @@ export default class ComfyApp {
if (link && !seen[link.id]) {
seen[link.id] = true
const inputNode = parent.getInputNode(link.origin_slot) as ComfyGraphNode;
if (inputNode && "tags" in inputNode && tag && (inputNode.tags as string[]).indexOf(tag) === -1) {
console.debug("Skipping tagged parent node", tag, node.tags)
if (inputNode && tag && !hasTag(inputNode, tag)) {
console.debug("Skipping tagged parent node", tag, node.properties.tags)
parent = null;
}
else {
@@ -538,7 +553,7 @@ export default class ComfyApp {
}
if (link && parent && parent.isBackendNode) {
if ("tags" in parent && tag && (parent.tags as string[]).indexOf(tag) === -1)
if (tag && !hasTag(parent, tag))
continue;
const input = node.inputs[i]
@@ -669,7 +684,7 @@ export default class ComfyApp {
/**
* Refresh combo list on whole nodes
*/
async refreshComboInNodes() {
async refreshComboInNodes(flashUI: boolean = false) {
const defs = await this.api.getNodeDefs();
for (let nodeNum in this.lGraph._nodes) {
@@ -687,11 +702,13 @@ export default class ComfyApp {
const inputNode = node.getInputNode(index)
if (inputNode && "doAutoConfig" in inputNode) {
const comfyInputNode = inputNode as nodes.ComfyWidgetNode;
comfyInputNode.doAutoConfig(comfyInput)
if (!comfyInput.config.values.includes(get(comfyInputNode.value))) {
comfyInputNode.setValue(comfyInput.config.defaultValue || comfyInput.config.values[0])
const comfyComboNode = inputNode as nodes.ComfyComboNode;
comfyComboNode.doAutoConfig(comfyInput)
if (!comfyInput.config.values.includes(get(comfyComboNode.value))) {
comfyComboNode.setValue(comfyInput.config.defaultValue || comfyInput.config.values[0])
}
if (flashUI)
comfyComboNode.comboRefreshed.set(true)
}
}
}

View File

@@ -142,7 +142,7 @@
value = spec.deserialize(value)
target.attrs[name] = value
target.attrsChanged.set(!get(target.attrsChanged))
target.attrsChanged.set(get(target.attrsChanged) + 1)
if (node && "propsChanged" in node) {
const comfyNode = node as ComfyWidgetNode
@@ -151,27 +151,39 @@
console.warn(spec)
if (spec.refreshPanelOnChange) {
console.error("A! refresh")
$refreshPanel += 1;
doRefreshPanel()
}
}
function getProperty(node: LGraphNode, spec: AttributesSpec) {
let value = node.properties[spec.name]
if (value == null)
value = spec.defaultValue
else if (spec.serialize)
value = spec.serialize(value)
console.debug("[ComfyProperties] getProperty", spec, value, node)
return value
}
function updateProperty(spec: AttributesSpec, value: any) {
if (node == null || !spec.editable)
return
const name = spec.name
console.warn("updateProperty", name, value)
console.warn("[ComfyProperties] updateProperty", name, value)
if (spec.deserialize)
value = spec.deserialize(value)
node.properties[name] = value;
if ("propsChanged" in node) {
const comfyNode = node as ComfyWidgetNode
comfyNode.propsChanged.set(get(comfyNode.propsChanged) + 1)
comfyNode.notifyPropsChanged();
}
if (spec.refreshPanelOnChange)
$refreshPanel += 1;
doRefreshPanel()
}
function getVar(node: LGraphNode, spec: AttributesSpec) {
@@ -201,8 +213,14 @@
comfyNode.propsChanged.set(get(comfyNode.propsChanged) + 1)
}
if (spec.refreshPanelOnChange)
$refreshPanel += 1;
if (spec.refreshPanelOnChange) {
doRefreshPanel()
}
}
function doRefreshPanel() {
console.warn("[ComfyProperties] doRefreshPanel")
$refreshPanel += 1;
}
function updateWorkflowAttribute(spec: AttributesSpec, value: any) {
@@ -214,6 +232,9 @@
$layoutState.attrs[name] = value
$layoutState = $layoutState
if (spec.refreshPanelOnChange)
doRefreshPanel()
}
</script>
@@ -281,7 +302,7 @@
<div class="props-entry">
{#if spec.type === "string"}
<TextBox
value={node.properties[spec.name] || spec.defaultValue}
value={getProperty(node, spec)}
on:change={(e) => updateProperty(spec, e.detail)}
on:input={(e) => updateProperty(spec, e.detail)}
label={spec.name}
@@ -290,7 +311,7 @@
/>
{:else if spec.type === "boolean"}
<Checkbox
value={node.properties[spec.name] || spec.defaultValue}
value={getProperty(node, spec)}
label={spec.name}
disabled={!$uiState.uiUnlocked || !spec.editable}
on:change={(e) => updateProperty(spec, e.detail)}
@@ -298,7 +319,7 @@
{:else if spec.type === "number"}
<ComfyNumberProperty
name={spec.name}
value={node.properties[spec.name] || spec.defaultValue}
value={getProperty(node, spec)}
step={spec.step || 1}
min={spec.min || -1024}
max={spec.max || 1024}
@@ -308,7 +329,7 @@
{:else if spec.type === "enum"}
<ComfyComboProperty
name={spec.name}
value={node.properties[spec.name] || spec.defaultValue}
value={getProperty(node, spec)}
values={spec.values}
disabled={!$uiState.uiUnlocked || !spec.editable}
on:change={(e) => updateProperty(spec, e.detail)}

View File

@@ -81,7 +81,7 @@
<span>Node: {getNodeInfo($queueState.runningNodeId)}</span>
</div>
<div>
<ProgressBar value={$queueState.progress?.value} max={$queueState.progress?.max} />
<ProgressBar value={$queueState.progress?.value} max={$queueState.progress?.max} styles="height: 30px;" />
</div>
{/if}
{#if typeof $queueState.queueRemaining === "number" && $queueState.queueRemaining > 0}

View File

@@ -14,6 +14,8 @@
import { flip } from 'svelte/animate';
import layoutState, { type ContainerLayout, type WidgetLayout, type IDragItem } from "$lib/stores/layoutState";
import { startDrag, stopDrag } from "$lib/utils"
import type { Writable } from "svelte/store";
import { isHidden } from "$lib/widgets/utils";
export let container: ContainerLayout | null = null;
export let zIndex: number = 0;
@@ -34,12 +36,14 @@
{@const edit = $uiState.uiUnlocked && $uiState.uiEditMode === "widgets" && zIndex > 1}
{@const dragDisabled = zIndex === 0 || $layoutState.currentSelection.length > 2 || !$uiState.uiUnlocked}
{#key $attrsChanged}
{#if container.attrs.variant === "tabs"}
<TabsContainer {container} {zIndex} {classes} {showHandles} {edit} {dragDisabled} {isMobile} />
{:else if container.attrs.variant === "accordion"}
<AccordionContainer {container} {zIndex} {classes} {showHandles} {edit} {dragDisabled} {isMobile} />
{:else}
<BlockContainer {container} {zIndex} {classes} {showHandles} {edit} {dragDisabled} {isMobile} />
{#if edit || !isHidden(container)}
{#if container.attrs.variant === "tabs"}
<TabsContainer {container} {zIndex} {classes} {showHandles} {edit} {dragDisabled} {isMobile} />
{:else if container.attrs.variant === "accordion"}
<AccordionContainer {container} {zIndex} {classes} {showHandles} {edit} {dragDisabled} {isMobile} />
{:else}
<BlockContainer {container} {zIndex} {classes} {showHandles} {edit} {dragDisabled} {isMobile} />
{/if}
{/if}
{/key}
{/if}

View File

@@ -13,6 +13,7 @@
import layoutState, { type ContainerLayout, type WidgetLayout, type IDragItem } from "$lib/stores/layoutState";
import { startDrag, stopDrag } from "$lib/utils"
import type { Writable } from "svelte/store";
import { isHidden } from "$lib/widgets/utils";
export let container: ContainerLayout | null = null;
export let zIndex: number = 0;
@@ -86,7 +87,7 @@
on:finalize="{handleFinalize}"
>
{#each children.filter(item => item.id !== SHADOW_PLACEHOLDER_ITEM_ID) as item, i(item.id)}
{@const hidden = item?.attrs?.hidden}
{@const hidden = isHidden(item)}
{@const tabName = getTabName(container, i)}
<div class="animation-wrapper"
class:hidden={hidden}
@@ -104,7 +105,7 @@
</div>
{/each}
</div>
{#if container.attrs.hidden && edit}
{#if isHidden(container) && edit}
<div class="handle handle-hidden" class:hidden={!edit} style="z-index: {zIndex+100}"/>
{/if}
{#if showHandles}

View File

@@ -7,6 +7,8 @@
import Container from "./Container.svelte"
import { type Writable } from "svelte/store"
import type { ComfyWidgetNode } from "$lib/nodes";
import { NodeMode } from "@litegraph-ts/core";
import { isHidden } from "$lib/widgets/utils";
export let dragItem: IDragItem | null = null;
export let zIndex: number = 0;
@@ -64,17 +66,18 @@
{/key}
{:else if widget && widget.node}
{@const edit = $uiState.uiUnlocked && $uiState.uiEditMode === "widgets" && zIndex > 1}
{@const hidden = isHidden(widget)}
{#key $attrsChanged}
{#key $propsChanged}
<div class="widget {widget.attrs.classes} {getWidgetClass()}"
class:edit={edit}
class:selected={$uiState.uiUnlocked && $layoutState.currentSelection.includes(widget.id)}
class:is-executing={$queueState.runningNodeId && $queueState.runningNodeId == widget.node.id}
class:hidden={widget.attrs.hidden}
class:hidden={hidden}
>
<svelte:component this={widget.node.svelteComponentType} {widget} {isMobile} />
</div>
{#if widget.attrs.hidden && edit}
{#if hidden && edit}
<div class="handle handle-hidden" class:hidden={!edit} style="z-index: {zIndex+100}"/>
{/if}
{#if showHandles}