Toggle nodes/containers on and off by tags
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
})
|
||||
|
||||
async function doRefreshCombos() {
|
||||
await app.refreshComboInNodes()
|
||||
await app.refreshComboInNodes(true)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user