remove:forced control_before_generate

This commit is contained in:
yolain
2024-03-16 16:29:20 +08:00
parent edb5f9dffc
commit 0e6c3999d8
20 changed files with 752 additions and 678 deletions
+1
View File
@@ -47,6 +47,7 @@ you need to run `pip install -r requirements.txt` to install python dependencies
**v1.1.1 (2024/3/16)**
- Remove forced **control_before_generate** settings。 If you want to use control_before_generate, change widget_value_control_mode to before in system settings
- Added `easy imageRemBg` - The default is BriaAI's RMBG-1.4 model, which removes the background effect more and faster
**v1.1.0 (d5ff84e)**
+3 -1
View File
@@ -19,7 +19,6 @@
- 沿用了 [tinyterraNodes](https://github.com/TinyTerra/ComfyUI_tinyterraNodes) 的思路,大大减少了折腾工作流的时间成本。
- UI界面美化,首次安装的用户,如需使用UI主题,请在 Settings -> Color Palette 中自行切换主题并**刷新页面**即可
- 增加了预采样参数配置的节点,可与采样节点分离,更方便预览。
- 预采样/采样器中的随机种使用提示词队列运行前操作的方式,兼容保留了 [cg-everywhere](https://github.com/chrisgoringe/cg-use-everywhere) 的**highlight**功能
- 支持通配符与Lora的提示词节点,如需使用Lora Block Weight用法,需先保证自定义节点包中安装了 [ComfyUI-Inspire-Pack](https://github.com/ltdrdata/ComfyUI-Inspire-Pack)
- 可多选的风格化提示词选择器,默认是Fooocus的样式json,可自定义
- 加载器可开启A1111提示词风格模式,可重现与webui生成近乎相同的图像,需先安装 [ComfyUI_smZNodes](https://github.com/shiimizu/ComfyUI_smZNodes)
@@ -31,11 +30,14 @@
- 扩展 XYplot 的可用性
- 整合了Fooocus Inpaint功能
- 整合了常用的逻辑计算、转换类型、展示所有类型等
- 支持BriaAI的RMBG-1.4模型的背景去除节点,[技术参考](https://huggingface.co/briaai/RMBG-1.4)
## 更新日志
**v1.1.1 (2024/3/16)**
- 修补官方BUG: 当control_mode为before 在首次加载页面时未修改节点中widget名称为 control_before_generate
- 去除强制**control_before_generate**设定
- 增加 `easy imageRemBg` - 默认为BriaAI的RMBG-1.4模型, 移除背景效果更加,速度更快
**v1.1.0 (d5ff84e)**
+13 -13
View File
@@ -78,7 +78,7 @@ class wildcardsPrompt:
"text": ("STRING", {"default": "", "multiline": True, "dynamicPrompts": False, "placeholder": "(Support Lora Block Weight and wildcard)"}),
"Select to add LoRA": (["Select the LoRA to add to the text"] + folder_paths.get_filename_list("loras"),),
"Select to add Wildcard": (["Select the Wildcard to add to the text"] + wildcard_list,),
"seed_num": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"seed_num": ("INT:seed", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
},
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO", "my_unique_id": "UNIQUE_ID"},
}
@@ -455,7 +455,7 @@ class latentNoisy:
"start_at_step": ("INT", {"default": 0, "min": 0, "max": 10000}),
"end_at_step": ("INT", {"default": 10000, "min": 1, "max": 10000}),
"source": (["CPU", "GPU"],),
"seed_num": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
"seed_num": ("INT:seed", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
},
"optional": {
"pipe": ("PIPE_LINE",),
@@ -596,12 +596,12 @@ class easySeed:
def INPUT_TYPES(s):
return {
"required": {
"seed_num": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"seed_num": ("INT:seed", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
},
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO", "my_unique_id": "UNIQUE_ID"},
}
RETURN_TYPES = ("INT",)
RETURN_TYPES = ("INT:seed",)
RETURN_NAMES = ("seed_num",)
FUNCTION = "doit"
@@ -1744,7 +1744,7 @@ class samplerSettings:
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
"scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
"denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
"seed_num": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"seed_num": ("INT:seed", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
},
"optional": {
"image_to_latent": ("IMAGE",),
@@ -1819,7 +1819,7 @@ class samplerSettingsAdvanced:
"start_at_step": ("INT", {"default": 0, "min": 0, "max": 10000}),
"end_at_step": ("INT", {"default": 10000, "min": 0, "max": 10000}),
"add_noise": (["enable", "disable"],),
"seed_num": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"seed_num": ("INT:seed", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
},
"optional": {
"image_to_latent": ("IMAGE",),
@@ -1895,7 +1895,7 @@ class samplerSettingsNoiseIn:
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
"scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
"denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
"seed_num": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"seed_num": ("INT:seed", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
},
"optional": {
"optional_noise_seed": ("INT",{"forceInput": True}),
@@ -2052,7 +2052,7 @@ class sdTurboSettings:
"unsharp_kernel_size": ("INT", {"default": 3, "min": 1, "max": 21, "step": 1}),
"unsharp_sigma": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 10.0, "step": 0.01, "round": False}),
"unsharp_strength": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 10.0, "step": 0.01, "round": False}),
"seed_num": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"seed_num": ("INT:seed", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
},
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO", "my_unique_id": "UNIQUE_ID"},
}
@@ -2145,7 +2145,7 @@ class cascadeSettings:
"sampler_name": (comfy.samplers.KSampler.SAMPLERS, {"default":"euler_ancestral"}),
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, {"default":"simple"}),
"denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
"seed_num": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"seed_num": ("INT:seed", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
},
"optional": {
"image_to_latent_c": ("IMAGE",),
@@ -2250,7 +2250,7 @@ class layerDiffusionSettings:
"sampler_name": (comfy.samplers.KSampler.SAMPLERS, {"default": "euler_ancestral"}),
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, {"default": "simple"}),
"denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
"seed_num": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"seed_num": ("INT:seed", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
},
"optional": {
"image": ("IMAGE",),
@@ -2410,7 +2410,7 @@ class dynamicCFGSettings:
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
"scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
"denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
"seed_num": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"seed_num": ("INT:seed", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
},
"optional":{
"image_to_latent": ("IMAGE",),
@@ -2554,7 +2554,7 @@ class samplerFull(LayerDiffuse):
"save_prefix": ("STRING", {"default": "ComfyUI"}),
},
"optional": {
"seed_num": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"seed_num": ("INT:seed", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"model": ("MODEL",),
"positive": ("CONDITIONING",),
"negative": ("CONDITIONING",),
@@ -3254,7 +3254,7 @@ class samplerCascadeFull:
"image_output": (["Hide", "Preview", "Save", "Hide/Save", "Sender", "Sender/Save"],),
"link_id": ("INT", {"default": 0, "min": 0, "max": sys.maxsize, "step": 1}),
"save_prefix": ("STRING", {"default": "ComfyUI"}),
"seed_num": ("INT", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
"seed_num": ("INT:seed", {"default": 0, "min": 0, "max": MAX_SEED_NUM}),
},
"optional": {
+46 -46
View File
@@ -123,40 +123,40 @@ def prompt_seed_update(json_data):
# control after generated
if mode is not None and not mode:
control_seed(node[1], action, seed_is_global)
else:
prompts = json_data['prompt'].items()
for k, v in prompts:
if 'class_type' not in v:
continue
cls = v['class_type']
if cls in seed_nodes:
extra_data = next((x for x in workflow["nodes"] if str(x["id"]) == k), None)
if extra_data is not None:
inputs = extra_data.get('inputs')
widgets_value = extra_data.get('widgets_values')
widgets_length = len(widgets_value)
if "disable" in widgets_value:
break
if inputs is not None and inputs != []:
seed_num_input = next((x for x in inputs if x['name'] == 'seed_num' and x['type'] == 'INT'), None)
if seed_num_input is not None:
action = 'fixed'
else:
action = widgets_value[widgets_length - 1]
else:
control_index = widgets_length - 2 if cls == 'easy seed' else widgets_length - 1
action = widgets_value[control_index]
# print(action)
node = k, v
value = control_seed(node[1], action, False)
if k not in seed_widget_map:
continue
if 'seed_num' in v['inputs']:
if isinstance(v['inputs']['seed_num'], int):
v['inputs']['seed_num'] = value
# else:
# prompts = json_data['prompt'].items()
# for k, v in prompts:
# if 'class_type' not in v:
# continue
# cls = v['class_type']
# if cls in seed_nodes:
# extra_data = next((x for x in workflow["nodes"] if str(x["id"]) == k), None)
# if extra_data is not None:
# inputs = extra_data.get('inputs')
# widgets_value = extra_data.get('widgets_values')
# widgets_length = len(widgets_value)
# if "disable" in widgets_value:
# break
# if inputs is not None and inputs != []:
# seed_num_input = next((x for x in inputs if x['name'] == 'seed_num' and x['type'] == 'INT'), None)
# if seed_num_input is not None:
# action = 'fixed'
# else:
# action = widgets_value[widgets_length - 1]
# else:
# control_index = widgets_length - 2 if cls == 'easy seed' else widgets_length - 1
# action = widgets_value[control_index]
#
# # print(action)
# node = k, v
# value = control_seed(node[1], action, False)
#
# if k not in seed_widget_map:
# continue
#
# if 'seed_num' in v['inputs']:
# if isinstance(v['inputs']['seed_num'], int):
# v['inputs']['seed_num'] = value
return value is not None
@@ -178,18 +178,18 @@ def workflow_seed_update(json_data):
length = len(node['widgets_values'])
node['widgets_values'][length-1] = node['widgets_values'][0]
node['widgets_values'][0] = value
elif node_id in seed_widget_map:
widget_idx = seed_widget_map[node_id]
if 'seed_num' in prompt[node_id]['inputs']:
seed = prompt[node_id]['inputs']['seed_num']
elif 'noise_seed' in prompt[node_id]['inputs']:
seed = prompt[node_id]['inputs']['noise_seed']
else:
seed = prompt[node_id]['inputs']['seed']
node['widgets_values'][widget_idx] = seed
updated_seed_map[node_id] = seed
# elif node_id in seed_widget_map:
# widget_idx = seed_widget_map[node_id]
#
# if 'seed_num' in prompt[node_id]['inputs']:
# seed = prompt[node_id]['inputs']['seed_num']
# elif 'noise_seed' in prompt[node_id]['inputs']:
# seed = prompt[node_id]['inputs']['noise_seed']
# else:
# seed = prompt[node_id]['inputs']['seed']
#
# node['widgets_values'][widget_idx] = seed
# updated_seed_map[node_id] = seed
server.PromptServer.instance.send_sync("easyuse-global-seed", {"id": node_id, "value": value, "seed_map": updated_seed_map})
+68
View File
@@ -0,0 +1,68 @@
.easy-dropdown, .easy-nested-dropdown {
position: relative;
box-sizing: border-box;
background-color: #171717;
box-shadow: 0 4px 4px rgba(255, 255, 255, .25);
padding: 0;
margin: 0;
list-style: none;
z-index: 1000;
overflow: visible;
max-height: fit-content;
max-width: fit-content;
}
.easy-dropdown {
position: absolute;
border-radius: 0;
}
/* Style for final items */
.easy-dropdown li.item, .easy-nested-dropdown li.item {
font-weight: normal;
min-width: max-content;
}
/* Style for folders (parent items) */
.easy-dropdown li.folder, .easy-nested-dropdown li.folder {
cursor: default;
position: relative;
border-right: 3px solid cyan;
}
.easy-dropdown li.folder::after, .easy-nested-dropdown li.folder::after {
content: ">";
position: absolute;
right: 2px;
font-weight: normal;
}
.easy-dropdown li, .easy-nested-dropdown li {
padding: 4px 10px;
cursor: pointer;
font-family: system-ui;
font-size: 0.7rem;
position: relative;
}
/* Style for nested dropdowns */
.easy-nested-dropdown {
position: absolute;
top: 0;
left: 100%;
margin: 0;
border: none;
display: none;
}
.easy-dropdown li.selected > .easy-nested-dropdown,
.easy-nested-dropdown li.selected > .easy-nested-dropdown {
display: block;
border: none;
}
.easy-dropdown li.selected,
.easy-nested-dropdown li.selected {
background-color: #e5e5e5;
border: none;
}
+115
View File
@@ -0,0 +1,115 @@
.pysssss-workflow-popup{
min-width:200px!important;
right:0px!important;
left:auto!important;
}
body{
font-family: var(--font-family)!important;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
textarea{
font-family: var(--font-family)!important;
}
.comfy-multiline-input{
background-color: transparent;
border:1px solid var(--border-color);
border-radius:8px;
padding: 8px;
font-size: 12px;
}
.comfy-modal {
border:1px solid var(--border-color);
box-shadow:none;
backdrop-filter: blur(8px) brightness(120%);
}
.comfy-menu{
top:38%;
border-radius:16px;
box-shadow:0 0 1px var(--descrip-text);
backdrop-filter: blur(8px) brightness(120%);
}
.comfy-menu button,.comfy-modal button {
font-size: 16px;
padding:6px 0;
margin-bottom:8px;
}
.comfy-menu button.comfy-settings-btn{
font-size: 12px;
}
.comfy-menu-btns {
margin-bottom: 4px;
}
.comfy-menu-btns button,.comfy-list-actions button{
font-size: 12px;
}
.comfy-menu > button,
.comfy-menu-btns button,
.comfy-menu .comfy-list button,
.comfy-modal button {
border-width:1px;
}
dialog{
border:1px solid var(--border-color);
background:transparent;
backdrop-filter: blur(8px) brightness(120%);
box-shadow:none;
}
.cm-title{
background-color:transparent!important;
}
.cm-notice-board{
border-radius:10px!important;
border:1px solid var(--border-color)!important;
}
.cm-menu-container{
margin-bottom:50px!important;
}
hr{
border:1px solid var(--border-color);
}
#shareButton{
background:linear-gradient(to left,var(--theme-color),var(--theme-color-light))!important;
color:white!important;
}
#queue-button{
position:relative;
overflow:hidden;
z-index:1;
}
#queue-button:after{
content:attr(data-attr);
background:green;
color:#FFF;
width:var(--process-bar-width);
height:100%;
position:absolute;
top:0;
left:0;
z-index:0;
text-align:center;
display:flex;
justify-content:center;
align-items:center;
}
.litegraph .litemenu-entry.has_submenu {
border-right: 2px solid var(--theme-color);
}
::-webkit-scrollbar {
width: 0em;
}
::-webkit-scrollbar-track {
background-color: transparent;
}
::-webkit-scrollbar-thumb {
background-color: transparent;
border-radius: 2px;
}
::-webkit-scrollbar-thumb:hover {
background-color: transparent;
}
+13
View File
@@ -0,0 +1,13 @@
#easyuse_groups_map{
flex-direction: column;
align-items: end;
display:flex;position: absolute;
top: 50px; left: 10px; width: 180px;
border-radius:12px;
min-height:100px;
max-height:400px;
color: var(--descrip-text);
background-color: var(--comfy-menu-bg);
padding: 10px 4px;
border: 1px solid var(--border-color);z-index: 999999999;padding-top: 0;
}
+4
View File
@@ -0,0 +1,4 @@
@import "theme.css";
@import "dropdown.css";
@import "selector.css";
@import "groupmap.css";
+101
View File
@@ -0,0 +1,101 @@
.easyuse-prompt-styles .tools{
display:flex;
justify-content:space-between;
height:30px;
padding-bottom:10px;
border-bottom:2px solid var(--border-color);
}
.easyuse-prompt-styles .tools button.delete{
height:30px;
border-radius: 8px;
border: 2px solid var(--border-color);
font-size:11px;
background:var(--comfy-input-bg);
color:var(--error-text);
box-shadow:none;
cursor:pointer;
}
.easyuse-prompt-styles .tools button.delete:hover{
filter: brightness(1.2);
}
.easyuse-prompt-styles .tools textarea.search{
flex:1;
margin-left:10px;
height:20px;
line-height:20px;
border-radius: 8px;
border: 2px solid var(--border-color);
font-size:11px;
background:var(--comfy-input-bg);
color:var(--input-text);
box-shadow:none;
padding:4px 10px;
outline: none;
resize: none;
appearance:none;
}
.easyuse-prompt-styles-list{
list-style: none;
padding: 0;
margin: 0;
min-height: 150px;
height: calc(100% - 40px);
overflow: auto;
// display: flex;
// flex-wrap: wrap;
}
.easyuse-prompt-styles-tag{
display: inline-block;
vertical-align: middle;
margin-top: 8px;
margin-right: 8px;
padding:4px;
color: var(--input-text);
background-color: var(--comfy-input-bg);
border-radius: 8px;
border: 2px solid var(--border-color);
font-size:11px;
cursor:pointer;
}
.easyuse-prompt-styles-tag.hide{
display:none;
}
.easyuse-prompt-styles-tag:hover{
filter: brightness(1.2);
}
.easyuse-prompt-styles-tag input{
--ring-color: transparent;
position: relative;
box-shadow: none;
border: 2px solid var(--border-color);
border-radius: 2px;
background: linear-gradient(135deg, var(--comfy-menu-bg) 0%, var(--comfy-input-bg) 60%);
}
.easyuse-prompt-styles-tag input[type=checkbox]:checked{
border: 1px solid var(--theme-color-light);
background-color: var(--theme-color-light);
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
}
.easyuse-prompt-styles-tag input[type=checkbox]{
color-adjust: exact;
display: inline-block;
flex-shrink: 0;
vertical-align: middle;
appearance: none;
border: 2px solid var(--border-color);
background-origin: border-box;
padding: 0;
width: 1rem;
height: 1rem;
border-radius:4px;
color:var(--theme-color-light);
user-select: none;
}
.easyuse-prompt-styles-tag span{
margin:0 4px;
vertical-align: middle;
}
#show_image_id{
width:128px;
height:128px;
}
+5
View File
@@ -0,0 +1,5 @@
:root {
--theme-color:#3f3eed;
--theme-color-light:#006691;
--font-family: Inter, -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif;
}
+1 -1
View File
@@ -1,4 +1,4 @@
import { app } from "../../../scripts/app.js";
import { app } from "/scripts/app.js";
app.registerExtension({
+218
View File
@@ -0,0 +1,218 @@
let activeDropdown = null;
export function removeDropdown() {
if (activeDropdown) {
activeDropdown.removeEventListeners();
activeDropdown.dropdown.remove();
activeDropdown = null;
}
}
export function createDropdown(inputEl, suggestions, onSelect, isDict = false) {
removeDropdown();
new Dropdown(inputEl, suggestions, onSelect, isDict);
}
class Dropdown {
constructor(inputEl, suggestions, onSelect, isDict = false) {
this.dropdown = document.createElement('ul');
this.dropdown.setAttribute('role', 'listbox');
this.dropdown.classList.add('easy-dropdown');
this.selectedIndex = -1;
this.inputEl = inputEl;
this.suggestions = suggestions;
this.onSelect = onSelect;
this.isDict = isDict;
this.focusedDropdown = this.dropdown;
this.buildDropdown();
this.onKeyDownBound = this.onKeyDown.bind(this);
this.onWheelBound = this.onWheel.bind(this);
this.onClickBound = this.onClick.bind(this);
this.addEventListeners();
}
buildDropdown() {
if (this.isDict) {
this.buildNestedDropdown(this.suggestions, this.dropdown);
} else {
this.suggestions.forEach((suggestion, index) => {
this.addListItem(suggestion, index, this.dropdown);
});
}
const inputRect = this.inputEl.getBoundingClientRect();
this.dropdown.style.top = (inputRect.top + inputRect.height - 10) + 'px';
this.dropdown.style.left = inputRect.left + 'px';
document.body.appendChild(this.dropdown);
activeDropdown = this;
}
buildNestedDropdown(dictionary, parentElement) {
let index = 0;
Object.keys(dictionary).forEach((key) => {
const item = dictionary[key];
if (typeof item === "object" && item !== null) {
const nestedDropdown = document.createElement('ul');
nestedDropdown.setAttribute('role', 'listbox');
nestedDropdown.classList.add('easy-nested-dropdown');
const parentListItem = document.createElement('li');
parentListItem.classList.add('folder');
parentListItem.textContent = key;
parentListItem.appendChild(nestedDropdown);
parentListItem.addEventListener('mouseover', this.onMouseOver.bind(this, index, parentElement));
parentElement.appendChild(parentListItem);
this.buildNestedDropdown(item, nestedDropdown);
index = index + 1;
} else {
const listItem = document.createElement('li');
listItem.classList.add('item');
listItem.setAttribute('role', 'option');
listItem.textContent = key;
listItem.addEventListener('mouseover', this.onMouseOver.bind(this, index, parentElement));
listItem.addEventListener('mousedown', this.onMouseDown.bind(this, key));
parentElement.appendChild(listItem);
index = index + 1;
}
});
}
addListItem(item, index, parentElement) {
const listItem = document.createElement('li');
listItem.setAttribute('role', 'option');
listItem.textContent = item;
listItem.addEventListener('mouseover', this.onMouseOver.bind(this, index));
listItem.addEventListener('mousedown', this.onMouseDown.bind(this, item));
parentElement.appendChild(listItem);
}
addEventListeners() {
document.addEventListener('keydown', this.onKeyDownBound);
this.dropdown.addEventListener('wheel', this.onWheelBound);
document.addEventListener('click', this.onClickBound);
}
removeEventListeners() {
document.removeEventListener('keydown', this.onKeyDownBound);
this.dropdown.removeEventListener('wheel', this.onWheelBound);
document.removeEventListener('click', this.onClickBound);
}
onMouseOver(index, parentElement) {
if (parentElement) {
this.focusedDropdown = parentElement;
}
this.selectedIndex = index;
this.updateSelection();
}
onMouseOut() {
this.selectedIndex = -1;
this.updateSelection();
}
onMouseDown(suggestion, event) {
event.preventDefault();
this.onSelect(suggestion);
this.dropdown.remove();
this.removeEventListeners();
}
onKeyDown(event) {
const enterKeyCode = 13;
const escKeyCode = 27;
const arrowUpKeyCode = 38;
const arrowDownKeyCode = 40;
const arrowRightKeyCode = 39;
const arrowLeftKeyCode = 37;
const tabKeyCode = 9;
const items = Array.from(this.focusedDropdown.children);
const selectedItem = items[this.selectedIndex];
if (activeDropdown) {
if (event.keyCode === arrowUpKeyCode) {
event.preventDefault();
this.selectedIndex = Math.max(0, this.selectedIndex - 1);
this.updateSelection();
}
else if (event.keyCode === arrowDownKeyCode) {
event.preventDefault();
this.selectedIndex = Math.min(items.length - 1, this.selectedIndex + 1);
this.updateSelection();
}
else if (event.keyCode === arrowRightKeyCode) {
event.preventDefault();
if (selectedItem && selectedItem.classList.contains('folder')) {
const nestedDropdown = selectedItem.querySelector('.easy-nested-dropdown');
if (nestedDropdown) {
this.focusedDropdown = nestedDropdown;
this.selectedIndex = 0;
this.updateSelection();
}
}
}
else if (event.keyCode === arrowLeftKeyCode && this.focusedDropdown !== this.dropdown) {
const parentDropdown = this.focusedDropdown.closest('.easy-dropdown, .easy-nested-dropdown').parentNode.closest('.easy-dropdown, .easy-nested-dropdown');
if (parentDropdown) {
this.focusedDropdown = parentDropdown;
this.selectedIndex = Array.from(parentDropdown.children).indexOf(this.focusedDropdown.parentNode);
this.updateSelection();
}
}
else if ((event.keyCode === enterKeyCode || event.keyCode === tabKeyCode) && this.selectedIndex >= 0) {
event.preventDefault();
if (selectedItem.classList.contains('item')) {
this.onSelect(items[this.selectedIndex].textContent);
this.dropdown.remove();
this.removeEventListeners();
}
const nestedDropdown = selectedItem.querySelector('.easy-nested-dropdown');
if (nestedDropdown) {
this.focusedDropdown = nestedDropdown;
this.selectedIndex = 0;
this.updateSelection();
}
}
else if (event.keyCode === escKeyCode) {
this.dropdown.remove();
this.removeEventListeners();
}
}
}
onWheel(event) {
const top = parseInt(this.dropdown.style.top);
if (localStorage.getItem("Comfy.Settings.Comfy.InvertMenuScrolling")) {
this.dropdown.style.top = (top + (event.deltaY < 0 ? 10 : -10)) + "px";
} else {
this.dropdown.style.top = (top + (event.deltaY < 0 ? -10 : 10)) + "px";
}
}
onClick(event) {
if (!this.dropdown.contains(event.target) && event.target !== this.inputEl) {
this.dropdown.remove();
this.removeEventListeners();
}
}
updateSelection() {
Array.from(this.focusedDropdown.children).forEach((li, index) => {
if (index === this.selectedIndex) {
li.classList.add('selected');
} else {
li.classList.remove('selected');
}
});
}
}
+19
View File
@@ -0,0 +1,19 @@
import {getLocale} from './utils.js'
const locale = getLocale()
const zhCN = {
// GroupMap
"Groups Map (EasyUse)": "管理组 (EasyUse)",
"Always": "启用中",
"Bypass": "已忽略",
"Never": "已停用",
"Auto Sorting": "自动排序",
"Toggle `Show/Hide` can set mode of group, LongPress can set group nodes to never": "点击`启用中/已忽略`可设置组模式, 长按可停用该组节点",
// Quick
"Enable ALT+1~9 to paste nodes from nodes template (ComfyUI-Easy-Use)": "启用ALT1~9从节点模板粘贴到工作流(ComfyUI-Easy-Use)",
"Enable process bar in queue button (ComfyUI-Easy-Use)": "启用提示词队列进度显示条(ComfyUI-Easy-Use)"
}
export const $t = (key) => {
return locale === 'zh-CN' ? zhCN[key] : key
}
+41
View File
@@ -0,0 +1,41 @@
export function addPreconnect(href, crossorigin=false){
const preconnect = document.createElement("link");
preconnect.rel = 'preconnect'
preconnect.href = href
if(crossorigin) preconnect.crossorigin = ''
document.head.appendChild(preconnect);
}
export function addCss(href, base=true) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = base ? "extensions/ComfyUI-Easy-Use/"+href : href;
document.head.appendChild(link);
}
export function deepEqual(obj1, obj2) {
if (typeof obj1 !== typeof obj2) {
return false
}
if (typeof obj1 !== 'object' || obj1 === null || obj2 === null) {
return obj1 === obj2
}
const keys1 = Object.keys(obj1)
const keys2 = Object.keys(obj2)
if (keys1.length !== keys2.length) {
return false
}
for (let key of keys1) {
if (!deepEqual(obj1[key], obj2[key])) {
return false
}
}
return true
}
export function getLocale(){
const locale = localStorage['AGL.Locale'] || localStorage['Comfy.Settings.AGL.Locale'] || 'en-US'
return locale
}
+25 -350
View File
@@ -1,28 +1,8 @@
import { app } from "/scripts/app.js";
import { ComfyWidgets } from "/scripts/widgets.js";
import { $el } from "/scripts/ui.js";
import { api } from "/scripts/api.js";
import {deepEqual,addCss} from "../common/utils.js";
import {$t} from '../common/i18n.js';
function deepEqual (obj1, obj2) {
if (typeof obj1 !== typeof obj2) {
return false
}
if (typeof obj1 !== 'object' || obj1 === null || obj2 === null) {
return obj1 === obj2
}
const keys1 = Object.keys(obj1)
const keys2 = Object.keys(obj2)
if (keys1.length !== keys2.length) {
return false
}
for (let key of keys1) {
if (!deepEqual(obj1[key], obj2[key])) {
return false
}
}
return true
}
addCss('css/index.css')
app.registerExtension({
name: "comfy.easyUse",
@@ -31,36 +11,23 @@ app.registerExtension({
const getCanvasMenuOptions = LGraphCanvas.prototype.getCanvasMenuOptions;
LGraphCanvas.prototype.getCanvasMenuOptions = function () {
const options = getCanvasMenuOptions.apply(this, arguments);
const locale = localStorage['AGL.Locale'] || localStorage['Comfy.Settings.AGL.Locale'] || 'en-US'
let draggerEl = null
let isGroupMapcanMove = true
let old_groups = []
let emptyImg = new Image()
emptyImg.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=";
options.push(null,
{
content: locale == 'zh-CN' ? "📜管理组 (EasyUse)" : "📜Groups Map (EasyUse)",
callback: () => {
content: '📜 '+ $t('Groups Map (EasyUse)'),
callback: async() => {
let groups = app.canvas.graph._groups
let nodes = app.canvas.graph._nodes
let groups_len = groups.length
let old_nodes = groups.length
let div =
document.querySelector('#easyuse_groups_map') ||
document.createElement('div')
div.id = 'easyuse_groups_map'
div.style = `
flex-direction: column;
align-items: end;
display:flex;position: absolute;
top: 50px; left: 10px; width: 180px;
border-radius:12px;
min-height:100px;
max-height:400px;
color: var(--descrip-text);
background-color: var(--comfy-menu-bg);
padding: 10px 4px;
border: 1px solid var(--border-color);z-index: 999999999;padding-top: 0;`
div.innerHTML = ''
let btn = document.createElement('div')
btn.style = `display: flex;
@@ -74,10 +41,12 @@ app.registerExtension({
btn.appendChild(textB)
btn.appendChild(hideBtn)
textB.style.fontSize = '11px'
textB.innerHTML = locale == 'zh-CN' ? `<b>管理组 (EasyUse)</b>` : `<b>Groups Map (EasyUse)</b>`
textB.innerHTML = `<b>${$t('Groups Map (EasyUse)')}</b>`
hideBtn.style = `float: right;color: var(--input-text);border-radius:6px;font-size:9px;
background-color: var(--comfy-input-bg); border: 1px solid var(--border-color);cursor: pointer;padding: 5px;aspect-ratio: 1 / 1;`
hideBtn.addEventListener('click', () => {div.style.display = 'none'})
hideBtn.addEventListener('click', () => {
div.style.display = 'none'
})
hideBtn.innerText = '❌'
div.appendChild(btn)
@@ -114,9 +83,9 @@ app.registerExtension({
for (let index in groups) {
const group = groups[index]
const title = group.title
const show_text = locale == 'zh-CN' ? '启用中' : 'Always'
const hide_text = locale == 'zh-CN' ? '已忽略' : 'Bypass'
const mute_text = locale == 'zh-CN' ? '已停用' : 'Never'
const show_text = $t('Always')
const hide_text = $t('Bypass')
const mute_text = $t('Never')
let group_item = document.createElement('div')
let group_item_style = `justify-content: space-between;display:flex;background-color: var(--comfy-input-bg);border-radius: 5px;border:1px solid var(--border-color);margin-top:5px;`
group_item.addEventListener("mouseover",event=>{
@@ -247,7 +216,7 @@ app.registerExtension({
let autoSortDiv = document.createElement('button')
autoSortDiv.style = `cursor:pointer;font-size:10px;padding:2px 4px;color:var(--input-text);background-color: var(--comfy-input-bg);border: 1px solid var(--border-color);border-radius:4px;`
autoSortDiv.innerText = locale == 'zh-CN' ? '自动排序' : 'Automatic sorting'
autoSortDiv.innerText = $t('Auto Sorting')
autoSortDiv.addEventListener('click',e=>{
e.preventDefault()
groupsDiv.innerHTML = ``
@@ -261,21 +230,23 @@ app.registerExtension({
let remarkDiv = document.createElement('p')
remarkDiv.style = `text-align:center; font-size:10px; padding:0 10px;color:var(--descrip-text)`
remarkDiv.innerText = locale == 'zh-CN' ? "点击`启用中/已忽略`可设置组模式, 长按可停用该组节点" : "Toggle `Show/Hide` can set mode of group, LongPress can set group nodes to never"
remarkDiv.innerText = $t('Toggle `Show/Hide` can set mode of group, LongPress can set group nodes to never')
div.appendChild(groupsDiv)
div.appendChild(remarkDiv)
div.appendChild(autoSortDiv)
let graphDiv = document.getElementById("graph-canvas")
graphDiv.addEventListener('mouseover', async () => {
let n = (await app.graphToPrompt()).output
if (!deepEqual(n, nodes)) {
groupsDiv.innerHTML = ``
let new_groups = app.canvas.graph._groups
updateGroups(new_groups, groupsDiv, autoSortDiv)
}
groupsDiv.innerHTML = ``
let new_groups = app.canvas.graph._groups
updateGroups(new_groups, groupsDiv, autoSortDiv)
old_nodes = nodes
})
if (!document.querySelector('#easyuse_groups_map')){
document.body.appendChild(div)
}else{
div.style.display = 'flex'
}
}
@@ -293,300 +264,4 @@ app.registerExtension({
};
}
},
});
// easy Dropdown
var styleElement = document.createElement("style");
const cssCode = `
.easy-dropdown, .easy-nested-dropdown {
position: relative;
box-sizing: border-box;
background-color: #171717;
box-shadow: 0 4px 4px rgba(255, 255, 255, .25);
padding: 0;
margin: 0;
list-style: none;
z-index: 1000;
overflow: visible;
max-height: fit-content;
max-width: fit-content;
}
.easy-dropdown {
position: absolute;
border-radius: 0;
}
/* Style for final items */
.easy-dropdown li.item, .easy-nested-dropdown li.item {
font-weight: normal;
min-width: max-content;
}
/* Style for folders (parent items) */
.easy-dropdown li.folder, .easy-nested-dropdown li.folder {
cursor: default;
position: relative;
border-right: 3px solid cyan;
}
.easy-dropdown li.folder::after, .easy-nested-dropdown li.folder::after {
content: ">";
position: absolute;
right: 2px;
font-weight: normal;
}
.easy-dropdown li, .easy-nested-dropdown li {
padding: 4px 10px;
cursor: pointer;
font-family: system-ui;
font-size: 0.7rem;
position: relative;
}
/* Style for nested dropdowns */
.easy-nested-dropdown {
position: absolute;
top: 0;
left: 100%;
margin: 0;
border: none;
display: none;
}
.easy-dropdown li.selected > .easy-nested-dropdown,
.easy-nested-dropdown li.selected > .easy-nested-dropdown {
display: block;
border: none;
}
.easy-dropdown li.selected,
.easy-nested-dropdown li.selected {
background-color: #e5e5e5;
border: none;
}
`
styleElement.innerHTML = cssCode
document.head.appendChild(styleElement);
let activeDropdown = null;
export function easy_RemoveDropdown() {
if (activeDropdown) {
activeDropdown.removeEventListeners();
activeDropdown.dropdown.remove();
activeDropdown = null;
}
}
class Dropdown {
constructor(inputEl, suggestions, onSelect, isDict = false) {
this.dropdown = document.createElement('ul');
this.dropdown.setAttribute('role', 'listbox');
this.dropdown.classList.add('easy-dropdown');
this.selectedIndex = -1;
this.inputEl = inputEl;
this.suggestions = suggestions;
this.onSelect = onSelect;
this.isDict = isDict;
this.focusedDropdown = this.dropdown;
this.buildDropdown();
this.onKeyDownBound = this.onKeyDown.bind(this);
this.onWheelBound = this.onWheel.bind(this);
this.onClickBound = this.onClick.bind(this);
this.addEventListeners();
}
buildDropdown() {
if (this.isDict) {
this.buildNestedDropdown(this.suggestions, this.dropdown);
} else {
this.suggestions.forEach((suggestion, index) => {
this.addListItem(suggestion, index, this.dropdown);
});
}
const inputRect = this.inputEl.getBoundingClientRect();
this.dropdown.style.top = (inputRect.top + inputRect.height - 10) + 'px';
this.dropdown.style.left = inputRect.left + 'px';
document.body.appendChild(this.dropdown);
activeDropdown = this;
}
buildNestedDropdown(dictionary, parentElement) {
let index = 0;
Object.keys(dictionary).forEach((key) => {
const item = dictionary[key];
if (typeof item === "object" && item !== null) {
const nestedDropdown = document.createElement('ul');
nestedDropdown.setAttribute('role', 'listbox');
nestedDropdown.classList.add('easy-nested-dropdown');
const parentListItem = document.createElement('li');
parentListItem.classList.add('folder');
parentListItem.textContent = key;
parentListItem.appendChild(nestedDropdown);
parentListItem.addEventListener('mouseover', this.onMouseOver.bind(this, index, parentElement));
parentElement.appendChild(parentListItem);
this.buildNestedDropdown(item, nestedDropdown);
index = index + 1;
} else {
const listItem = document.createElement('li');
listItem.classList.add('item');
listItem.setAttribute('role', 'option');
listItem.textContent = key;
listItem.addEventListener('mouseover', this.onMouseOver.bind(this, index, parentElement));
listItem.addEventListener('mousedown', this.onMouseDown.bind(this, key));
parentElement.appendChild(listItem);
index = index + 1;
}
});
}
addListItem(item, index, parentElement) {
const listItem = document.createElement('li');
listItem.setAttribute('role', 'option');
listItem.textContent = item;
listItem.addEventListener('mouseover', this.onMouseOver.bind(this, index));
listItem.addEventListener('mousedown', this.onMouseDown.bind(this, item));
parentElement.appendChild(listItem);
}
addEventListeners() {
document.addEventListener('keydown', this.onKeyDownBound);
this.dropdown.addEventListener('wheel', this.onWheelBound);
document.addEventListener('click', this.onClickBound);
}
removeEventListeners() {
document.removeEventListener('keydown', this.onKeyDownBound);
this.dropdown.removeEventListener('wheel', this.onWheelBound);
document.removeEventListener('click', this.onClickBound);
}
onMouseOver(index, parentElement) {
if (parentElement) {
this.focusedDropdown = parentElement;
}
this.selectedIndex = index;
this.updateSelection();
}
onMouseOut() {
this.selectedIndex = -1;
this.updateSelection();
}
onMouseDown(suggestion, event) {
event.preventDefault();
this.onSelect(suggestion);
this.dropdown.remove();
this.removeEventListeners();
}
onKeyDown(event) {
const enterKeyCode = 13;
const escKeyCode = 27;
const arrowUpKeyCode = 38;
const arrowDownKeyCode = 40;
const arrowRightKeyCode = 39;
const arrowLeftKeyCode = 37;
const tabKeyCode = 9;
const items = Array.from(this.focusedDropdown.children);
const selectedItem = items[this.selectedIndex];
if (activeDropdown) {
if (event.keyCode === arrowUpKeyCode) {
event.preventDefault();
this.selectedIndex = Math.max(0, this.selectedIndex - 1);
this.updateSelection();
}
else if (event.keyCode === arrowDownKeyCode) {
event.preventDefault();
this.selectedIndex = Math.min(items.length - 1, this.selectedIndex + 1);
this.updateSelection();
}
else if (event.keyCode === arrowRightKeyCode) {
event.preventDefault();
if (selectedItem && selectedItem.classList.contains('folder')) {
const nestedDropdown = selectedItem.querySelector('.easy-nested-dropdown');
if (nestedDropdown) {
this.focusedDropdown = nestedDropdown;
this.selectedIndex = 0;
this.updateSelection();
}
}
}
else if (event.keyCode === arrowLeftKeyCode && this.focusedDropdown !== this.dropdown) {
const parentDropdown = this.focusedDropdown.closest('.easy-dropdown, .easy-nested-dropdown').parentNode.closest('.easy-dropdown, .easy-nested-dropdown');
if (parentDropdown) {
this.focusedDropdown = parentDropdown;
this.selectedIndex = Array.from(parentDropdown.children).indexOf(this.focusedDropdown.parentNode);
this.updateSelection();
}
}
else if ((event.keyCode === enterKeyCode || event.keyCode === tabKeyCode) && this.selectedIndex >= 0) {
event.preventDefault();
if (selectedItem.classList.contains('item')) {
this.onSelect(items[this.selectedIndex].textContent);
this.dropdown.remove();
this.removeEventListeners();
}
const nestedDropdown = selectedItem.querySelector('.easy-nested-dropdown');
if (nestedDropdown) {
this.focusedDropdown = nestedDropdown;
this.selectedIndex = 0;
this.updateSelection();
}
}
else if (event.keyCode === escKeyCode) {
this.dropdown.remove();
this.removeEventListeners();
}
}
}
onWheel(event) {
const top = parseInt(this.dropdown.style.top);
if (localStorage.getItem("Comfy.Settings.Comfy.InvertMenuScrolling")) {
this.dropdown.style.top = (top + (event.deltaY < 0 ? 10 : -10)) + "px";
} else {
this.dropdown.style.top = (top + (event.deltaY < 0 ? -10 : 10)) + "px";
}
}
onClick(event) {
if (!this.dropdown.contains(event.target) && event.target !== this.inputEl) {
this.dropdown.remove();
this.removeEventListeners();
}
}
updateSelection() {
Array.from(this.focusedDropdown.children).forEach((li, index) => {
if (index === this.selectedIndex) {
li.classList.add('selected');
} else {
li.classList.remove('selected');
}
});
}
}
export function easy_CreateDropdown(inputEl, suggestions, onSelect, isDict = false) {
easy_RemoveDropdown();
new Dropdown(inputEl, suggestions, onSelect, isDict);
}
});
+9 -7
View File
@@ -783,14 +783,16 @@ app.registerExtension({
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = async function () {
onNodeCreated ? onNodeCreated.apply(this, []) : undefined;
const values = ["randomize", "fixed", "increment", "decrement"]
// const values = ["randomize", "fixed", "increment", "decrement"]
// const seed_widget = this.widgets.find(w => w.name == 'seed_num')
// const seed_control = this.addWidget("combo", "control_before_generate", values[0], () => {
// }, {
// values,
// serialize: false
// })
// seed_widget.linkedWidgets = [seed_control]
const seed_widget = this.widgets.find(w => w.name == 'seed_num')
const seed_control = this.addWidget("combo", "control_before_generate", values[0], () => {
}, {
values,
serialize: false
})
seed_widget.linkedWidgets = [seed_control]
const seed_control = this.widgets.find(w=> ['control_before_generate','control_after_generate'].includes(w.name))
if(nodeData.name == 'easy seed'){
this.addWidget("button", "🎲 Manual Random Seed", null, _=>{
if(seed_control.value != 'fixed'){
+62 -145
View File
@@ -1,6 +1,7 @@
import { app } from "/scripts/app.js";
import { api } from "/scripts/api.js";
import { $el } from "/scripts/ui.js";
import {addPreconnect, addCss} from "../common/utils.js";
const locale = localStorage['AGL.Locale'] || localStorage['Comfy.Settings.AGL.Locale'] || 'en-US'
@@ -88,8 +89,8 @@ const ui = {
}
}
const custom_theme_name = 'custom_obsidian'
let custom_theme = null
let control_mode = null
try{
custom_theme = localStorage.getItem('Comfy.Settings.Comfy.CustomColorPalettes') ? JSON.parse(localStorage.getItem('Comfy.Settings.Comfy.CustomColorPalettes')) : {};
}
@@ -108,25 +109,53 @@ try{
localStorage.setItem('Comfy.Settings.Comfy.CustomColorPalettes', JSON.stringify(custom_theme));
}
let theme_name = localStorage.getItem('Comfy.Settings.Comfy.ColorPalette')
control_mode = localStorage.getItem('Comfy.Settings.Comfy.WidgetControlMode')
if(control_mode) {
control_mode = JSON.parse(control_mode)
if(control_mode == 'before'){
localStorage['Comfy.Settings.AE.mouseover'] = false
localStorage['Comfy.Settings.AE.highlight'] = false
}
}
// 兼容 ComfyUI Revision: 1887 [235727fe] 以上版本
if(api.storeSettings){
const _settings = await api.getSettings()
let settings = null
// 运行操作设置
if(!control_mode && _settings['Comfy.WidgetControlMode']) {
control_mode = _settings['Comfy.WidgetControlMode']
}else if(!control_mode) control_mode = 'after'
if(control_mode == 'before'){
if(!settings) settings = {}
settings["AE.mouseover"] = false
settings["AE.highlight"] = false
}
// 主题设置
console.log(theme_name)
if(!theme_name && _settings['Comfy.ColorPalette']) {
theme_name = _settings['Comfy.ColorPalette']
localStorage.setItem('Comfy.Settings.Comfy.ColorPalette',`"${theme_name}"`)
theme_name = `"${_settings['Comfy.ColorPalette']}"`
localStorage.setItem('Comfy.Settings.Comfy.ColorPalette', theme_name)
}
const settings = {
"Comfy.CustomColorPalettes": localStorage.getItem('Comfy.Settings.Comfy.CustomColorPalettes') ? JSON.parse(localStorage.getItem('Comfy.Settings.Comfy.CustomColorPalettes')) : {},
if(['"custom_obsidian"','"custom_obsidian_dark"'].includes(theme_name)) {
if(!settings) settings = {}
settings["Comfy.ColorPalette"] = JSON.parse(theme_name)
}
if(['"custom_obsidian"','"custom_obsidian_dark"'].includes(theme_name)) settings["Comfy.ColorPalette"] = custom_theme_name
if(!_settings || !_settings["Comfy.CustomColorPalettes"] || !_settings["Comfy.CustomColorPalettes"]["obsidian"] || _settings["Comfy.CustomColorPalettes"]["obsidian"]['version']<ui.version){
if(!settings) settings = {}
settings["Comfy.CustomColorPalettes"] = localStorage.getItem('Comfy.Settings.Comfy.CustomColorPalettes') ? JSON.parse(localStorage.getItem('Comfy.Settings.Comfy.CustomColorPalettes')) : {}
await api.storeSettings(settings);
app.ui.settings.load()
}else if(settings){
await api.storeSettings(settings);
}
}
// 判断主题为黑曜石时改变扩展UI
if(['"custom_obsidian"','"custom_obsidian_dark"'].includes(theme_name)){
// 字体文件
addPreconnect("https://fonts.googleapis.com", true)
addCss("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700&amp;family=JetBrains+Mono&amp;display=swap", false)
// 添加easy的主题样式
addCss('css/easy.css')
// canvas
const bgcolor = LGraphCanvas.node_colors.bgcolor;
LGraphCanvas.node_colors = {
@@ -693,146 +722,21 @@ try{
ctx.restore();
ctx.textAlign = "left";
};
// 字体文件
const preconnect1 = document.createElement("link");
preconnect1.rel = 'preconnect'
preconnect1.href = 'https://fonts.googleapis.com'
document.head.appendChild(preconnect1);
const preconnect2 = document.createElement("link");
preconnect2.rel = 'preconnect'
preconnect2.href = 'https://fonts.googleapis.com'
preconnect2.crossorigin = ''
document.head.appendChild(preconnect2);
const fontFile = document.createElement("link")
fontFile.rel = "stylesheet"
fontFile.href = "https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700&amp;family=JetBrains+Mono&amp;display=swap"
document.head.appendChild(fontFile);
// 样式
const styleElement = document.createElement("style");
const fontFamily = 'Inter,-apple-system,BlinkMacSystemFont,Helvetica Neue,sans-serif'
const cssCode = `
.pysssss-workflow-popup{
min-width:200px!important;
right:0px!important;
left:auto!important;
}
body{
font-family: ${fontFamily}!important;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
textarea{
font-family: ${fontFamily}!important;
}
.comfy-multiline-input{
background-color: transparent;
border:1px solid var(--border-color);
border-radius:8px;
padding: 8px;
font-size: 12px;
}
.comfy-modal {
border:1px solid var(--border-color);
box-shadow:none;
backdrop-filter: blur(8px) brightness(120%);
}
.comfy-menu{
top:38%;
border-radius:16px;
box-shadow:0 0 1px var(--descrip-text);
backdrop-filter: blur(8px) brightness(120%);
}
.comfy-menu button,.comfy-modal button {
font-size: 16px;
padding:6px 0;
margin-bottom:8px;
}
.comfy-menu button.comfy-settings-btn{
font-size: 12px;
}
.comfy-menu-btns {
margin-bottom: 4px;
}
.comfy-menu-btns button,.comfy-list-actions button{
font-size: 12px;
}
.comfy-menu > button,
.comfy-menu-btns button,
.comfy-menu .comfy-list button,
.comfy-modal button {
border-width:1px;
}
dialog{
border:1px solid var(--border-color);
background:transparent;
backdrop-filter: blur(8px) brightness(120%);
box-shadow:none;
}
.cm-title{
background-color:transparent!important;
}
.cm-notice-board{
border-radius:10px!important;
border:1px solid var(--border-color)!important;
}
.cm-menu-container{
margin-bottom:50px!important;
}
hr{
border:1px solid var(--border-color);
}
#shareButton{
background:linear-gradient(to left,${customThemeColor},${LGraphCanvas.node_colors.pale_blue.color})!important;
color:white!important;
}
#queue-button{
position:relative;
overflow:hidden;
z-index:1;
}
#queue-button:after{
content:attr(data-attr);
background:green;
color:#FFF;
width:var(--process-bar-width);
height:100%;
position:absolute;
top:0;
left:0;
z-index:0;
text-align:center;
display:flex;
justify-content:center;
align-items:center;
}
.litegraph .litemenu-entry.has_submenu {
border-right: 2px solid #3f3eed;
}
::-webkit-scrollbar {
width: 0em;
}
::-webkit-scrollbar-track {
background-color: transparent;
}
::-webkit-scrollbar-thumb {
background-color: transparent;
border-radius: 2px;
}
::-webkit-scrollbar-thumb:hover {
background-color: transparent;
}
`
styleElement.innerHTML = cssCode
document.head.appendChild(styleElement);
}
}catch(e){
console.error(e)
}
function updateControlWidgetLabel(widget, controlValueRunBefore=false) {
let replacement = "after";
let find = "before";
if (controlValueRunBefore) {
[find, replacement] = [replacement, find]
}
widget.label = (widget.label ?? widget.name).replace(find, replacement);
widget.name = widget.label;
}
// 节点颜色
const COLOR_THEMES = LGraphCanvas.node_colors
const NODE_COLORS = {
@@ -857,12 +761,25 @@ app.registerExtension({
Object.assign(LGraphCanvas.link_type_colors, customLinkColors);
},
nodeCreated(node) {
async nodeCreated(node) {
if (NODE_COLORS.hasOwnProperty(node.comfyClass)) {
const colorKey = NODE_COLORS[node.comfyClass]
const theme = COLOR_THEMES[colorKey];
setNodeColors(node, theme);
}
}
// 修复官方bug: 应该初始化修改节点的control_mode name
if(control_mode && control_mode == 'before'){
const controlValueRunBefore = control_mode == 'before'
for (const w of node.widgets) {
if (['control_before_generate','control_after_generate'].includes(w.name)) {
await updateControlWidgetLabel(w, controlValueRunBefore);
if (w.linkedWidgets) {
for (const l of w.linkedWidgets) {
await updateControlWidgetLabel(l, controlValueRunBefore);
}
}
}
}
}
},
})
+5 -5
View File
@@ -2,18 +2,18 @@
import { app } from "/scripts/app.js";
import { GroupNodeConfig } from "/extensions/core/groupNode.js";
import { api } from "/scripts/api.js";
import { $t } from "../common/i18n.js"
const nodeTemplateShortcutId = "Comfy.EasyUse.NodeTemplateShortcut"
const processBarId = "Comfy.EasyUse.queueProcessBar"
let enableNodeTemplateShortcut = true
let enableQueueProcess = false
const locale = localStorage['AGL.Locale'] || localStorage['Comfy.Settings.AGL.Locale'] || 'en-US'
export function addNodeTemplateShortcutSetting(app) {
app.ui.settings.addSetting({
id: nodeTemplateShortcutId,
name: locale == 'zh-CN' ? "启用ALT1~9从节点模板粘贴到工作流(ComfyUI-Easy-Use)" : "Enable ALT+1~9 to paste nodes from nodes template (ComfyUI-Easy-Use)",
name: $t("Enable ALT+1~9 to paste nodes from nodes template (ComfyUI-Easy-Use)"),
type: "boolean",
defaultValue: enableNodeTemplateShortcut,
onChange(value) {
@@ -24,11 +24,11 @@ export function addNodeTemplateShortcutSetting(app) {
export function addQueueProcessSetting(app) {
app.ui.settings.addSetting({
id: processBarId,
name: locale == 'zh-CN' ? "启用提示词队列进度显示条(ComfyUI-Easy-Use)" : "Enable process bar in queue button (ComfyUI-Easy-Use)",
name: $t("Enable process bar in queue button (ComfyUI-Easy-Use)"),
type: "boolean",
defaultValue: enableNodeTemplateShortcut,
defaultValue: enableQueueProcess,
onChange(value) {
enableNodeTemplateShortcut = !!value;
enableQueueProcess = !!value;
},
});
}
-107
View File
@@ -3,113 +3,6 @@ import { app } from "/scripts/app.js";
import { api } from "/scripts/api.js";
import { $el } from "/scripts/ui.js";
// 添加样式
const styleElement = document.createElement("style");
const cssCode = `
.easyuse-prompt-styles .tools{
display:flex;
justify-content:flex-between;
height:30px;
padding-bottom:10px;
border-bottom:2px solid var(--border-color);
}
.easyuse-prompt-styles .tools button.delete{
height:30px;
border-radius: 8px;
border: 2px solid var(--border-color);
font-size:11px;
background:var(--comfy-input-bg);
color:var(--error-text);
box-shadow:none;
cursor:pointer;
}
.easyuse-prompt-styles .tools button.delete:hover{
filter: brightness(1.2);
}
.easyuse-prompt-styles .tools textarea.search{
flex:1;
margin-left:10px;
height:20px;
line-height:20px;
border-radius: 8px;
border: 2px solid var(--border-color);
font-size:11px;
background:var(--comfy-input-bg);
color:var(--input-text);
box-shadow:none;
padding:4px 10px;
outline: none;
resize: none;
appearance:none;
}
.easyuse-prompt-styles-list{
list-style: none;
padding: 0;
margin: 0;
min-height: 150px;
height: calc(100% - 40px);
overflow: auto;
// display: flex;
// flex-wrap: wrap;
}
.easyuse-prompt-styles-tag{
display: inline-block;
vertical-align: middle;
margin-top: 8px;
margin-right: 8px;
padding:4px;
color: var(--input-text);
background-color: var(--comfy-input-bg);
border-radius: 8px;
border: 2px solid var(--border-color);
font-size:11px;
cursor:pointer;
}
.easyuse-prompt-styles-tag.hide{
display:none;
}
.easyuse-prompt-styles-tag:hover{
filter: brightness(1.2);
}
.easyuse-prompt-styles-tag input{
--ring-color: transparent;
position: relative;
box-shadow: none;
border: 2px solid var(--border-color);
border-radius: 2px;
background: linear-gradient(135deg, var(--comfy-menu-bg) 0%, var(--comfy-input-bg) 60%);
}
.easyuse-prompt-styles-tag input[type=checkbox]:checked{
border: 1px solid #006691;
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
background-color: #006691;
}
.easyuse-prompt-styles-tag input[type=checkbox]{
color-adjust: exact;
display: inline-block;
flex-shrink: 0;
vertical-align: middle;
appearance: none;
border: 2px solid var(--border-color);
background-origin: border-box;
padding: 0;
width: 1rem;
height: 1rem;
border-radius:4px;
color:#006691;
user-select: none;
}
.easyuse-prompt-styles-tag span{
margin:0 4px;
vertical-align: middle;
}
#show_image_id{
width:128px;
height:128px;
}
`
styleElement.innerHTML = cssCode
document.head.appendChild(styleElement);
// 获取风格列表
let styles_list_cache = {}
let styles_image_cache = {}
+3 -3
View File
@@ -1,5 +1,5 @@
import { app } from "/scripts/app.js";
import { easy_CreateDropdown, easy_RemoveDropdown } from "./easy.js";
import {removeDropdown, createDropdown} from "../common/dropdown.js";
function generateNumList(dictionary) {
const minimum = dictionary["min"] || 0;
@@ -154,13 +154,13 @@ function dropdownCreator(node) {
const filteredOptionsList = optionsList.filter(option => option.toLowerCase().includes(currentSegmentLower)).map(option => option.replace(/; /g, ''));
if (filteredOptionsList.length > 0) {
easy_CreateDropdown(w.inputEl, filteredOptionsList, (selectedOption) => {
createDropdown(w.inputEl, filteredOptionsList, (selectedOption) => {
const verifiedText = replaceOptionSegments(selectedOption, inputSegments, cursorSegmentIndex, optionsList);
w.inputEl.value = verifiedText;
});
}
else {
easy_RemoveDropdown();
removeDropdown();
const verifiedText = replaceOptionSegments(null, inputSegments, cursorSegmentIndex, optionsList);
w.inputEl.value = verifiedText;
}