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
8de6f94f
Commit
8de6f94f
authored
Dec 05, 2023
by
pythongosssss
Browse files
Allow widget placeholder replacement on primitives
parent
be3468dd
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
83 additions
and
70 deletions
+83
-70
web/extensions/core/saveImageExtraOutput.js
web/extensions/core/saveImageExtraOutput.js
+4
-69
web/extensions/core/widgetInputs.js
web/extensions/core/widgetInputs.js
+12
-1
web/scripts/utils.js
web/scripts/utils.js
+67
-0
No files found.
web/extensions/core/saveImageExtraOutput.js
View file @
8de6f94f
import
{
app
}
from
"
../../scripts/app.js
"
;
import
{
applyTextReplacements
}
from
"
../../scripts/utils.js
"
;
// Use widget values and dates in output filenames
app
.
registerExtension
({
...
...
@@ -7,78 +7,13 @@ app.registerExtension({
async
beforeRegisterNodeDef
(
nodeType
,
nodeData
,
app
)
{
if
(
nodeData
.
name
===
"
SaveImage
"
)
{
const
onNodeCreated
=
nodeType
.
prototype
.
onNodeCreated
;
// Simple date formatter
const
parts
=
{
d
:
(
d
)
=>
d
.
getDate
(),
M
:
(
d
)
=>
d
.
getMonth
()
+
1
,
h
:
(
d
)
=>
d
.
getHours
(),
m
:
(
d
)
=>
d
.
getMinutes
(),
s
:
(
d
)
=>
d
.
getSeconds
(),
};
const
format
=
Object
.
keys
(
parts
)
.
map
((
k
)
=>
k
+
k
+
"
?
"
)
.
join
(
"
|
"
)
+
"
|yyy?y?
"
;
function
formatDate
(
text
,
date
)
{
return
text
.
replace
(
new
RegExp
(
format
,
"
g
"
),
function
(
text
)
{
if
(
text
===
"
yy
"
)
return
(
date
.
getFullYear
()
+
""
).
substring
(
2
);
if
(
text
===
"
yyyy
"
)
return
date
.
getFullYear
();
if
(
text
[
0
]
in
parts
)
{
const
p
=
parts
[
text
[
0
]](
date
);
return
(
p
+
""
).
padStart
(
text
.
length
,
"
0
"
);
}
return
text
;
});
}
// When the SaveImage node is created we want to override the serialization of the output name widget to run our S&R
nodeType
.
prototype
.
onNodeCreated
=
function
()
{
const
r
=
onNodeCreated
?
onNodeCreated
.
apply
(
this
,
arguments
)
:
undefined
;
const
widget
=
this
.
widgets
.
find
((
w
)
=>
w
.
name
===
"
filename_prefix
"
);
widget
.
serializeValue
=
()
=>
{
return
widget
.
value
.
replace
(
/%
([^
%
]
+
)
%/g
,
function
(
match
,
text
)
{
const
split
=
text
.
split
(
"
.
"
);
if
(
split
.
length
!==
2
)
{
// Special handling for dates
if
(
split
[
0
].
startsWith
(
"
date:
"
))
{
return
formatDate
(
split
[
0
].
substring
(
5
),
new
Date
());
}
if
(
text
!==
"
width
"
&&
text
!==
"
height
"
)
{
// Dont warn on standard replacements
console
.
warn
(
"
Invalid replacement pattern
"
,
text
);
}
return
match
;
}
// Find node with matching S&R property name
let
nodes
=
app
.
graph
.
_nodes
.
filter
((
n
)
=>
n
.
properties
?.[
"
Node name for S&R
"
]
===
split
[
0
]);
// If we cant, see if there is a node with that title
if
(
!
nodes
.
length
)
{
nodes
=
app
.
graph
.
_nodes
.
filter
((
n
)
=>
n
.
title
===
split
[
0
]);
}
if
(
!
nodes
.
length
)
{
console
.
warn
(
"
Unable to find node
"
,
split
[
0
]);
return
match
;
}
if
(
nodes
.
length
>
1
)
{
console
.
warn
(
"
Multiple nodes matched
"
,
split
[
0
],
"
using first match
"
);
}
const
node
=
nodes
[
0
];
const
widget
=
node
.
widgets
?.
find
((
w
)
=>
w
.
name
===
split
[
1
]);
if
(
!
widget
)
{
console
.
warn
(
"
Unable to find widget
"
,
split
[
1
],
"
on node
"
,
split
[
0
],
node
);
return
match
;
}
return
((
widget
.
value
??
""
)
+
""
).
replaceAll
(
/
\/
|
\\
/g
,
"
_
"
);
});
return
applyTextReplacements
(
app
,
widget
.
value
);
};
return
r
;
...
...
web/extensions/core/widgetInputs.js
View file @
8de6f94f
import
{
ComfyWidgets
,
addValueControlWidgets
}
from
"
../../scripts/widgets.js
"
;
import
{
app
}
from
"
../../scripts/app.js
"
;
import
{
applyTextReplacements
}
from
"
../../scripts/utils.js
"
;
const
CONVERTED_TYPE
=
"
converted-widget
"
;
const
VALID_TYPES
=
[
"
STRING
"
,
"
combo
"
,
"
number
"
,
"
BOOLEAN
"
];
...
...
@@ -405,11 +406,16 @@ app.registerExtension({
};
},
registerCustomNodes
()
{
const
replacePropertyName
=
"
Run widget replace on values
"
;
class
PrimitiveNode
{
constructor
()
{
this
.
addOutput
(
"
connect to widget input
"
,
"
*
"
);
this
.
serialize_widgets
=
true
;
this
.
isVirtualNode
=
true
;
if
(
!
this
.
properties
||
!
(
replacePropertyName
in
this
.
properties
))
{
this
.
addProperty
(
replacePropertyName
,
false
,
"
boolean
"
);
}
}
applyToGraph
(
extraLinks
=
[])
{
...
...
@@ -430,6 +436,11 @@ app.registerExtension({
}
let
links
=
[...
get_links
(
this
).
map
((
l
)
=>
app
.
graph
.
links
[
l
]),
...
extraLinks
];
let
v
=
this
.
widgets
?.[
0
].
value
;
if
(
v
&&
this
.
properties
[
replacePropertyName
])
{
v
=
applyTextReplacements
(
app
,
v
);
}
// For each output link copy our value over the original widget value
for
(
const
linkInfo
of
links
)
{
const
node
=
this
.
graph
.
getNodeById
(
linkInfo
.
target_id
);
...
...
@@ -438,7 +449,7 @@ app.registerExtension({
if
(
widgetName
)
{
const
widget
=
node
.
widgets
.
find
((
w
)
=>
w
.
name
===
widgetName
);
if
(
widget
)
{
widget
.
value
=
this
.
widgets
[
0
].
value
;
widget
.
value
=
v
;
if
(
widget
.
callback
)
{
widget
.
callback
(
widget
.
value
,
app
.
canvas
,
node
,
app
.
canvas
.
graph_mouse
,
{});
}
...
...
web/scripts/utils.js
0 → 100644
View file @
8de6f94f
// Simple date formatter
const
parts
=
{
d
:
(
d
)
=>
d
.
getDate
(),
M
:
(
d
)
=>
d
.
getMonth
()
+
1
,
h
:
(
d
)
=>
d
.
getHours
(),
m
:
(
d
)
=>
d
.
getMinutes
(),
s
:
(
d
)
=>
d
.
getSeconds
(),
};
const
format
=
Object
.
keys
(
parts
)
.
map
((
k
)
=>
k
+
k
+
"
?
"
)
.
join
(
"
|
"
)
+
"
|yyy?y?
"
;
function
formatDate
(
text
,
date
)
{
return
text
.
replace
(
new
RegExp
(
format
,
"
g
"
),
function
(
text
)
{
if
(
text
===
"
yy
"
)
return
(
date
.
getFullYear
()
+
""
).
substring
(
2
);
if
(
text
===
"
yyyy
"
)
return
date
.
getFullYear
();
if
(
text
[
0
]
in
parts
)
{
const
p
=
parts
[
text
[
0
]](
date
);
return
(
p
+
""
).
padStart
(
text
.
length
,
"
0
"
);
}
return
text
;
});
}
export
function
applyTextReplacements
(
app
,
value
)
{
return
value
.
replace
(
/%
([^
%
]
+
)
%/g
,
function
(
match
,
text
)
{
const
split
=
text
.
split
(
"
.
"
);
if
(
split
.
length
!==
2
)
{
// Special handling for dates
if
(
split
[
0
].
startsWith
(
"
date:
"
))
{
return
formatDate
(
split
[
0
].
substring
(
5
),
new
Date
());
}
if
(
text
!==
"
width
"
&&
text
!==
"
height
"
)
{
// Dont warn on standard replacements
console
.
warn
(
"
Invalid replacement pattern
"
,
text
);
}
return
match
;
}
// Find node with matching S&R property name
let
nodes
=
app
.
graph
.
_nodes
.
filter
((
n
)
=>
n
.
properties
?.[
"
Node name for S&R
"
]
===
split
[
0
]);
// If we cant, see if there is a node with that title
if
(
!
nodes
.
length
)
{
nodes
=
app
.
graph
.
_nodes
.
filter
((
n
)
=>
n
.
title
===
split
[
0
]);
}
if
(
!
nodes
.
length
)
{
console
.
warn
(
"
Unable to find node
"
,
split
[
0
]);
return
match
;
}
if
(
nodes
.
length
>
1
)
{
console
.
warn
(
"
Multiple nodes matched
"
,
split
[
0
],
"
using first match
"
);
}
const
node
=
nodes
[
0
];
const
widget
=
node
.
widgets
?.
find
((
w
)
=>
w
.
name
===
split
[
1
]);
if
(
!
widget
)
{
console
.
warn
(
"
Unable to find widget
"
,
split
[
1
],
"
on node
"
,
split
[
0
],
node
);
return
match
;
}
return
((
widget
.
value
??
""
)
+
""
).
replaceAll
(
/
\/
|
\\
/g
,
"
_
"
);
});
}
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