Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
ComfyUI
Commits
0b9246d9
Commit
0b9246d9
authored
Oct 04, 2023
by
pythongosssss
Browse files
allow connecting numbers merging config
parent
6fc73143
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
188 additions
and
38 deletions
+188
-38
web/extensions/core/widgetInputs.js
web/extensions/core/widgetInputs.js
+188
-38
No files found.
web/extensions/core/widgetInputs.js
View file @
0b9246d9
...
@@ -3,6 +3,7 @@ import { app } from "../../scripts/app.js";
...
@@ -3,6 +3,7 @@ import { app } from "../../scripts/app.js";
const
CONVERTED_TYPE
=
"
converted-widget
"
;
const
CONVERTED_TYPE
=
"
converted-widget
"
;
const
VALID_TYPES
=
[
"
STRING
"
,
"
combo
"
,
"
number
"
,
"
BOOLEAN
"
];
const
VALID_TYPES
=
[
"
STRING
"
,
"
combo
"
,
"
number
"
,
"
BOOLEAN
"
];
const
CONFIG
=
Symbol
();
function
getConfig
(
widgetName
)
{
function
getConfig
(
widgetName
)
{
const
{
nodeData
}
=
this
.
constructor
;
const
{
nodeData
}
=
this
.
constructor
;
...
@@ -154,9 +155,6 @@ app.registerExtension({
...
@@ -154,9 +155,6 @@ app.registerExtension({
input
.
widget
.
getConfig
=
getConfig
.
bind
(
this
,
input
.
widget
.
name
);
input
.
widget
.
getConfig
=
getConfig
.
bind
(
this
,
input
.
widget
.
name
);
}
}
const
config
=
input
.
widget
.
getConfig
();
if
(
config
[
1
]?.
forceInput
)
continue
;
const
w
=
this
.
widgets
.
find
((
w
)
=>
w
.
name
===
input
.
widget
.
name
);
const
w
=
this
.
widgets
.
find
((
w
)
=>
w
.
name
===
input
.
widget
.
name
);
if
(
w
)
{
if
(
w
)
{
hideWidget
(
this
,
w
);
hideWidget
(
this
,
w
);
...
@@ -306,26 +304,40 @@ app.registerExtension({
...
@@ -306,26 +304,40 @@ app.registerExtension({
this
.
#
onFirstConnection
();
this
.
#
onFirstConnection
();
// Populate widget values from config data
// Populate widget values from config data
if
(
this
.
widgets
)
{
for
(
let
i
=
0
;
i
<
this
.
widgets_values
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
this
.
widgets_values
.
length
;
i
++
)
{
this
.
widgets
[
i
].
value
=
this
.
widgets_values
[
i
];
const
w
=
this
.
widgets
[
i
];
if
(
w
)
{
w
.
value
=
this
.
widgets_values
[
i
];
}
}
}
}
}
}
// Merge values if required
this
.
#
mergeWidgetConfig
();
}
}
onConnectionsChange
(
_
,
index
,
connected
)
{
onConnectionsChange
(
_
,
index
,
connected
)
{
if
(
app
.
configuringGraph
)
{
if
(
app
.
configuringGraph
)
{
// Dont run while the graph is still setting up
// Dont run while the graph is still setting up
return
;
return
;
}
}
const
links
=
this
.
outputs
[
0
].
links
;
if
(
connected
)
{
if
(
connected
)
{
if
(
this
.
outputs
[
0
].
links
?.
length
&&
!
this
.
widgets
?.
length
)
{
if
(
links
?.
length
&&
!
this
.
widgets
?.
length
)
{
this
.
#
onFirstConnection
();
this
.
#
onFirstConnection
();
}
}
}
else
if
(
!
this
.
outputs
[
0
].
links
?.
length
)
{
}
else
{
// We may have removed a link that caused the constraints to change
this
.
#
mergeWidgetConfig
();
if
(
!
links
?.
length
)
{
this
.
#
onLastDisconnect
();
this
.
#
onLastDisconnect
();
}
}
}
}
}
onConnectOutput
(
slot
,
type
,
input
,
target_node
,
target_slot
)
{
onConnectOutput
(
slot
,
type
,
input
,
target_node
,
target_slot
)
{
// Fires before the link is made allowing us to reject it if it isn't valid
// Fires before the link is made allowing us to reject it if it isn't valid
...
@@ -340,7 +352,7 @@ app.registerExtension({
...
@@ -340,7 +352,7 @@ app.registerExtension({
}
}
}
}
#
onFirstConnection
()
{
#
onFirstConnection
(
recreating
)
{
// First connection can fire before the graph is ready on initial load so random things can be missing
// First connection can fire before the graph is ready on initial load so random things can be missing
const
linkId
=
this
.
outputs
[
0
].
links
[
0
];
const
linkId
=
this
.
outputs
[
0
].
links
[
0
];
const
link
=
this
.
graph
.
links
[
linkId
];
const
link
=
this
.
graph
.
links
[
linkId
];
...
@@ -366,10 +378,10 @@ app.registerExtension({
...
@@ -366,10 +378,10 @@ app.registerExtension({
this
.
outputs
[
0
].
name
=
type
;
this
.
outputs
[
0
].
name
=
type
;
this
.
outputs
[
0
].
widget
=
widget
;
this
.
outputs
[
0
].
widget
=
widget
;
this
.
#
createWidget
(
widget
.
getConfig
(),
theirNode
,
widget
.
name
);
this
.
#
createWidget
(
widget
[
CONFIG
]
??
widget
.
getConfig
(),
theirNode
,
widget
.
name
,
recreating
);
}
}
#
createWidget
(
inputData
,
node
,
widgetName
)
{
#
createWidget
(
inputData
,
node
,
widgetName
,
recreating
)
{
let
type
=
inputData
[
0
];
let
type
=
inputData
[
0
];
if
(
type
instanceof
Array
)
{
if
(
type
instanceof
Array
)
{
...
@@ -404,6 +416,7 @@ app.registerExtension({
...
@@ -404,6 +416,7 @@ app.registerExtension({
return
r
;
return
r
;
};
};
if
(
!
recreating
)
{
// Grow our node if required
// Grow our node if required
const
sz
=
this
.
computeSize
();
const
sz
=
this
.
computeSize
();
if
(
this
.
size
[
0
]
<
sz
[
0
])
{
if
(
this
.
size
[
0
]
<
sz
[
0
])
{
...
@@ -419,10 +432,54 @@ app.registerExtension({
...
@@ -419,10 +432,54 @@ app.registerExtension({
}
}
});
});
}
}
}
#
recreateWidget
()
{
const
values
=
this
.
widgets
.
map
((
w
)
=>
w
.
value
);
this
.
#
removeWidgets
();
this
.
#
onFirstConnection
(
true
);
for
(
let
i
=
0
;
i
<
this
.
widgets
?.
length
;
i
++
)
this
.
widgets
[
i
].
value
=
values
[
i
];
}
#
mergeWidgetConfig
()
{
// Merge widget configs if the node has multiple outputs
const
output
=
this
.
outputs
[
0
];
const
links
=
output
.
links
;
const
hasConfig
=
!!
output
.
widget
[
CONFIG
];
if
(
hasConfig
)
{
delete
output
.
widget
[
CONFIG
];
}
if
(
links
?.
length
<
2
&&
hasConfig
)
{
// Copy the widget options from the source
if
(
links
.
length
)
{
this
.
#
recreateWidget
();
}
return
;
}
#
isValidConnection
(
input
)
{
const
config1
=
output
.
widget
.
getConfig
();
const
isNumber
=
config1
[
0
]
===
"
INT
"
||
config1
[
0
]
===
"
FLOAT
"
;
if
(
!
isNumber
)
return
;
for
(
const
linkId
of
links
)
{
const
link
=
app
.
graph
.
links
[
linkId
];
if
(
!
link
)
continue
;
// Can be null when removing a node
const
theirNode
=
app
.
graph
.
getNodeById
(
link
.
target_id
);
const
theirInput
=
theirNode
.
inputs
[
link
.
target_slot
];
// Call is valid connection so it can merge the configs when validating
this
.
#
isValidConnection
(
theirInput
,
hasConfig
);
}
}
#
isValidConnection
(
input
,
forceUpdate
)
{
// Only allow connections where the configs match
// Only allow connections where the configs match
const
config1
=
this
.
outputs
[
0
].
widget
.
getConfig
();
const
output
=
this
.
outputs
[
0
];
const
config1
=
output
.
widget
[
CONFIG
]
??
output
.
widget
.
getConfig
();
const
config2
=
input
.
widget
.
getConfig
();
const
config2
=
input
.
widget
.
getConfig
();
if
(
config1
[
0
]
instanceof
Array
)
{
if
(
config1
[
0
]
instanceof
Array
)
{
...
@@ -430,34 +487,117 @@ app.registerExtension({
...
@@ -430,34 +487,117 @@ app.registerExtension({
// but double checking doesn't hurt
// but double checking doesn't hurt
// New input isnt a combo
// New input isnt a combo
if
(
!
(
config2
[
0
]
instanceof
Array
))
return
false
;
if
(
!
(
config2
[
0
]
instanceof
Array
))
{
console
.
log
(
`connection rejected: tried to connect combo to
${
config2
[
0
]}
`
);
return
false
;
}
// New imput combo has a different size
// New imput combo has a different size
if
(
config1
[
0
].
length
!==
config2
[
0
].
length
)
return
false
;
if
(
config1
[
0
].
length
!==
config2
[
0
].
length
)
{
console
.
log
(
`connection rejected: combo lists dont match`
);
return
false
;
}
// New input combo has different elements
// New input combo has different elements
if
(
config1
[
0
].
find
((
v
,
i
)
=>
config2
[
0
][
i
]
!==
v
))
return
false
;
if
(
config1
[
0
].
find
((
v
,
i
)
=>
config2
[
0
][
i
]
!==
v
))
{
console
.
log
(
`connection rejected: combo lists dont match`
);
return
false
;
}
}
else
if
(
config1
[
0
]
!==
config2
[
0
])
{
}
else
if
(
config1
[
0
]
!==
config2
[
0
])
{
// Configs dont match
// Types dont match
console
.
log
(
`connection rejected: types dont match`
,
config1
[
0
],
config2
[
0
]);
return
false
;
return
false
;
}
}
for
(
const
k
in
config1
[
1
])
{
const
keys
=
new
Set
([...
Object
.
keys
(
config1
[
1
]
??
{}),
...
Object
.
keys
(
config2
[
1
]
??
{})]);
if
(
k
!==
"
default
"
&&
k
!==
"
forceInput
"
)
{
if
(
config1
[
1
][
k
]
!==
config2
[
1
][
k
])
{
let
customConfig
;
const
getCustomConfig
=
()
=>
{
if
(
!
customConfig
)
{
if
(
typeof
structuredClone
===
"
undefined
"
)
{
customConfig
=
JSON
.
parse
(
JSON
.
stringify
(
config1
[
1
]
??
{}));
}
else
{
customConfig
=
structuredClone
(
config1
[
1
]
??
{});
}
}
return
customConfig
;
};
const
isNumber
=
config1
[
0
]
===
"
INT
"
||
config1
[
0
]
===
"
FLOAT
"
;
for
(
const
k
of
keys
.
values
())
{
if
(
k
!==
"
default
"
&&
k
!==
"
forceInput
"
&&
k
!==
"
defaultInput
"
)
{
let
v1
=
config1
[
1
][
k
];
let
v2
=
config2
[
1
][
k
];
if
(
v1
===
v2
||
(
!
v1
&&
!
v2
))
continue
;
if
(
isNumber
)
{
if
(
k
===
"
min
"
)
{
const
theirMax
=
config2
[
1
][
"
max
"
];
if
(
theirMax
!=
null
&&
v1
>
theirMax
)
{
console
.
log
(
"
Invalid connection, min > max
"
);
return
false
;
return
false
;
}
}
getCustomConfig
()[
k
]
=
v1
==
null
?
v2
:
v2
==
null
?
v1
:
Math
.
max
(
v1
,
v2
);
continue
;
}
else
if
(
k
===
"
max
"
)
{
const
theirMin
=
config2
[
1
][
"
min
"
];
if
(
theirMin
!=
null
&&
v1
<
theirMin
)
{
console
.
log
(
"
Invalid connection, max < min
"
);
return
false
;
}
getCustomConfig
()[
k
]
=
v1
==
null
?
v2
:
v2
==
null
?
v1
:
Math
.
min
(
v1
,
v2
);
continue
;
}
else
if
(
k
===
"
step
"
)
{
let
step
;
if
(
v1
==
null
)
{
step
=
v2
;
}
else
if
(
v2
==
null
)
{
step
=
v1
;
}
else
{
if
(
v1
<
v2
)
{
const
a
=
v2
;
v2
=
v1
;
v1
=
a
;
}
}
if
(
v1
%
v2
)
{
console
.
log
(
"
Steps not divisible
"
,
"
current:
"
,
v1
,
"
new:
"
,
v2
);
return
false
;
}
}
return
true
;
step
=
v1
;
}
}
#
onLastDisconnect
()
{
getCustomConfig
()[
k
]
=
step
;
// We cant remove + re-add the output here as if you drag a link over the same link
continue
;
// it removes, then re-adds, causing it to break
}
this
.
outputs
[
0
].
type
=
"
*
"
;
}
this
.
outputs
[
0
].
name
=
"
connect to widget input
"
;
delete
this
.
outputs
[
0
].
widget
;
console
.
log
(
`connection rejected: config
${
k
}
values dont match`
,
v1
,
v2
);
return
false
;
}
}
if
(
customConfig
||
forceUpdate
)
{
if
(
customConfig
)
{
output
.
widget
[
CONFIG
]
=
[
config1
[
0
],
customConfig
];
}
this
.
#
recreateWidget
();
const
widget
=
this
.
widgets
[
0
];
// When deleting a node this can be null
if
(
widget
)
{
const
min
=
widget
.
options
.
min
;
const
max
=
widget
.
options
.
max
;
if
(
min
!=
null
&&
widget
.
value
<
min
)
widget
.
value
=
min
;
if
(
max
!=
null
&&
widget
.
value
>
max
)
widget
.
value
=
max
;
widget
.
callback
(
widget
.
value
);
}
}
return
true
;
}
#
removeWidgets
()
{
if
(
this
.
widgets
)
{
if
(
this
.
widgets
)
{
// Allow widgets to cleanup
// Allow widgets to cleanup
for
(
const
w
of
this
.
widgets
)
{
for
(
const
w
of
this
.
widgets
)
{
...
@@ -468,6 +608,16 @@ app.registerExtension({
...
@@ -468,6 +608,16 @@ app.registerExtension({
this
.
widgets
.
length
=
0
;
this
.
widgets
.
length
=
0
;
}
}
}
}
#
onLastDisconnect
()
{
// We cant remove + re-add the output here as if you drag a link over the same link
// it removes, then re-adds, causing it to break
this
.
outputs
[
0
].
type
=
"
*
"
;
this
.
outputs
[
0
].
name
=
"
connect to widget input
"
;
delete
this
.
outputs
[
0
].
widget
;
this
.
#
removeWidgets
();
}
}
}
LiteGraph
.
registerNodeType
(
LiteGraph
.
registerNodeType
(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment