Toggle nodes/containers on and off by tags
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { get, writable } from 'svelte/store';
|
||||
import type { Readable, Writable } from 'svelte/store';
|
||||
import type ComfyApp from "$lib/components/ComfyApp"
|
||||
import type { LGraphNode, IWidget, LGraph } from "@litegraph-ts/core"
|
||||
import { type LGraphNode, type IWidget, type LGraph, NodeMode } from "@litegraph-ts/core"
|
||||
import { dndzone, SHADOW_PLACEHOLDER_ITEM_ID } from 'svelte-dnd-action';
|
||||
import type { ComfyWidgetNode } from '$lib/nodes';
|
||||
|
||||
@@ -116,6 +116,12 @@ export type Attributes = {
|
||||
*/
|
||||
containerVariant?: "block" | "hidden",
|
||||
|
||||
/*
|
||||
* Tags for hiding containers with
|
||||
* For WidgetLayouts this will be ignored, it will use node.properties.tags instead
|
||||
*/
|
||||
tags: string[],
|
||||
|
||||
/*
|
||||
* If true, don't show this component in the UI
|
||||
*/
|
||||
@@ -142,6 +148,12 @@ export type Attributes = {
|
||||
*/
|
||||
variant?: string,
|
||||
|
||||
/*
|
||||
* What state to set this widget to in the frontend if its corresponding
|
||||
* node is disabled in the graph.
|
||||
*/
|
||||
nodeDisabledState: "visible" | "disabled" | "hidden",
|
||||
|
||||
/*********************************************/
|
||||
/* Special attributes for widgets/containers */
|
||||
/*********************************************/
|
||||
@@ -154,6 +166,9 @@ export type Attributes = {
|
||||
buttonSize?: "large" | "small"
|
||||
}
|
||||
|
||||
/*
|
||||
* Defines something that can be edited in the properties side panel.
|
||||
*/
|
||||
export type AttributesSpec = {
|
||||
/*
|
||||
* ID necessary for svelte's keyed each, autoset at the top level in this source file.
|
||||
@@ -256,9 +271,13 @@ export type AttributesCategorySpec = {
|
||||
|
||||
export type AttributesSpecList = AttributesCategorySpec[]
|
||||
|
||||
const serializeStringArray = (arg: string[]) => arg.join(",")
|
||||
const serializeStringArray = (arg: string[]) => {
|
||||
if (arg == null)
|
||||
arg = []
|
||||
return arg.join(",")
|
||||
}
|
||||
const deserializeStringArray = (arg: string) => {
|
||||
if (arg === "")
|
||||
if (arg === "" || arg == null)
|
||||
return []
|
||||
return arg.split(",").map(s => s.trim())
|
||||
}
|
||||
@@ -315,6 +334,15 @@ const ALL_ATTRIBUTES: AttributesSpecList = [
|
||||
defaultValue: "",
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
name: "nodeDisabledState",
|
||||
type: "enum",
|
||||
location: "widget",
|
||||
editable: true,
|
||||
values: ["visible", "disabled", "hidden"],
|
||||
defaultValue: "disabled",
|
||||
canShow: (di: IDragItem) => di.type === "widget"
|
||||
},
|
||||
|
||||
// Container variants
|
||||
{
|
||||
@@ -372,15 +400,6 @@ const ALL_ATTRIBUTES: AttributesSpecList = [
|
||||
categoryName: "behavior",
|
||||
specs: [
|
||||
// Node variables
|
||||
{
|
||||
name: "tags",
|
||||
type: "string",
|
||||
location: "nodeVars",
|
||||
editable: true,
|
||||
defaultValue: [],
|
||||
serialize: serializeStringArray,
|
||||
deserialize: deserializeStringArray
|
||||
},
|
||||
{
|
||||
name: "saveUserState",
|
||||
type: "boolean",
|
||||
@@ -388,6 +407,39 @@ const ALL_ATTRIBUTES: AttributesSpecList = [
|
||||
editable: true,
|
||||
defaultValue: true,
|
||||
},
|
||||
{
|
||||
name: "mode",
|
||||
type: "enum",
|
||||
location: "nodeVars",
|
||||
editable: true,
|
||||
values: ["ALWAYS", "NEVER"],
|
||||
defaultValue: "ALWAYS",
|
||||
serialize: (s) => s === NodeMode.ALWAYS ? "ALWAYS" : "NEVER",
|
||||
deserialize: (m) => m === "ALWAYS" ? NodeMode.ALWAYS : NodeMode.NEVER
|
||||
},
|
||||
|
||||
// Node properties
|
||||
{
|
||||
name: "tags",
|
||||
type: "string",
|
||||
location: "nodeProps",
|
||||
editable: true,
|
||||
defaultValue: [],
|
||||
serialize: serializeStringArray,
|
||||
deserialize: deserializeStringArray
|
||||
},
|
||||
|
||||
// Container tags are contained in the widget attributes
|
||||
{
|
||||
name: "tags",
|
||||
type: "string",
|
||||
location: "widget",
|
||||
editable: true,
|
||||
defaultValue: [],
|
||||
serialize: serializeStringArray,
|
||||
deserialize: deserializeStringArray,
|
||||
canShow: (di: IDragItem) => di.type === "container"
|
||||
},
|
||||
|
||||
// Range
|
||||
{
|
||||
@@ -457,14 +509,23 @@ const ALL_ATTRIBUTES: AttributesSpecList = [
|
||||
// This is needed so the specs can be iterated with svelte's keyed #each.
|
||||
let i = 0;
|
||||
for (const cat of Object.values(ALL_ATTRIBUTES)) {
|
||||
for (const val of Object.values(cat.specs)) {
|
||||
val.id = i;
|
||||
for (const spec of Object.values(cat.specs)) {
|
||||
spec.id = i;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
export { ALL_ATTRIBUTES };
|
||||
|
||||
const defaultWidgetAttributes: Attributes = {} as any
|
||||
for (const cat of Object.values(ALL_ATTRIBUTES)) {
|
||||
for (const spec of Object.values(cat.specs)) {
|
||||
if (spec.location === "widget" && spec.defaultValue != null) {
|
||||
defaultWidgetAttributes[spec.name] = spec.defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Something that can be dragged around in the frontend - a widget or a container.
|
||||
*/
|
||||
@@ -494,7 +555,7 @@ export interface IDragItem {
|
||||
* Hackish thing to indicate to Svelte that an attribute changed.
|
||||
* TODO Use Writeable<Attributes> instead!
|
||||
*/
|
||||
attrsChanged: Writable<boolean>
|
||||
attrsChanged: Writable<number>
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -528,7 +589,8 @@ type LayoutStateOps = {
|
||||
groupItems: (dragItems: IDragItem[], attrs?: Partial<Attributes>) => ContainerLayout,
|
||||
ungroup: (container: ContainerLayout) => void,
|
||||
getCurrentSelection: () => IDragItem[],
|
||||
findLayoutForNode: (nodeId: number) => IDragItem | null;
|
||||
findLayoutEntryForNode: (nodeId: number) => DragItemEntry | null,
|
||||
findLayoutForNode: (nodeId: number) => IDragItem | null,
|
||||
serialize: () => SerializedLayoutState,
|
||||
deserialize: (data: SerializedLayoutState, graph: LGraph) => void,
|
||||
initDefaultLayout: () => void,
|
||||
@@ -575,13 +637,10 @@ function addContainer(parent: ContainerLayout | null, attrs: Partial<Attributes>
|
||||
const dragItem: ContainerLayout = {
|
||||
type: "container",
|
||||
id: `${state.currentId++}`,
|
||||
attrsChanged: writable(false),
|
||||
attrsChanged: writable(0),
|
||||
attrs: {
|
||||
...defaultWidgetAttributes,
|
||||
title: "Container",
|
||||
direction: "vertical",
|
||||
classes: "",
|
||||
containerVariant: "block",
|
||||
flexGrow: 100,
|
||||
...attrs
|
||||
}
|
||||
}
|
||||
@@ -602,12 +661,11 @@ function addWidget(parent: ContainerLayout, node: ComfyWidgetNode, attrs: Partia
|
||||
type: "widget",
|
||||
id: `${state.currentId++}`,
|
||||
node: node,
|
||||
attrsChanged: writable(false),
|
||||
attrsChanged: writable(0),
|
||||
attrs: {
|
||||
...defaultWidgetAttributes,
|
||||
title: widgetName,
|
||||
direction: "horizontal",
|
||||
classes: "",
|
||||
flexGrow: 100,
|
||||
nodeDisabledState: "disabled",
|
||||
...attrs
|
||||
}
|
||||
}
|
||||
@@ -778,16 +836,23 @@ function ungroup(container: ContainerLayout) {
|
||||
store.set(state)
|
||||
}
|
||||
|
||||
function findLayoutForNode(nodeId: number): WidgetLayout | null {
|
||||
function findLayoutEntryForNode(nodeId: number): DragItemEntry | null {
|
||||
const state = get(store)
|
||||
const found = Object.entries(state.allItems).find(pair =>
|
||||
pair[1].dragItem.type === "widget"
|
||||
&& (pair[1].dragItem as WidgetLayout).node.id === nodeId)
|
||||
if (found)
|
||||
return found[1].dragItem as WidgetLayout
|
||||
return found[1]
|
||||
return null;
|
||||
}
|
||||
|
||||
function findLayoutForNode(nodeId: number): WidgetLayout | null {
|
||||
const found = findLayoutEntryForNode(nodeId);
|
||||
if (!found)
|
||||
return null;
|
||||
return found.dragItem as WidgetLayout
|
||||
}
|
||||
|
||||
function initDefaultLayout() {
|
||||
store.set({
|
||||
root: null,
|
||||
@@ -869,8 +934,8 @@ function deserialize(data: SerializedLayoutState, graph: LGraph) {
|
||||
const dragItem: IDragItem = {
|
||||
type: entry.dragItem.type,
|
||||
id: entry.dragItem.id,
|
||||
attrs: entry.dragItem.attrs,
|
||||
attrsChanged: writable(false)
|
||||
attrs: { ...defaultWidgetAttributes, ...entry.dragItem.attrs },
|
||||
attrsChanged: writable(0)
|
||||
};
|
||||
|
||||
const dragEntry: DragItemEntry = {
|
||||
@@ -939,6 +1004,7 @@ const layoutStateStore: WritableLayoutStateStore =
|
||||
nodeRemoved,
|
||||
getCurrentSelection,
|
||||
groupItems,
|
||||
findLayoutEntryForNode,
|
||||
findLayoutForNode,
|
||||
ungroup,
|
||||
initDefaultLayout,
|
||||
|
||||
Reference in New Issue
Block a user