remove:forced control_before_generate
This commit is contained in:
@@ -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)**
|
||||
|
||||
@@ -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
@@ -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
@@ -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})
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
@import "theme.css";
|
||||
@import "dropdown.css";
|
||||
@import "selector.css";
|
||||
@import "groupmap.css";
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
:root {
|
||||
--theme-color:#3f3eed;
|
||||
--theme-color-light:#006691;
|
||||
--font-family: Inter, -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif;
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { app } from "../../../scripts/app.js";
|
||||
import { app } from "/scripts/app.js";
|
||||
|
||||
|
||||
app.registerExtension({
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
});
|
||||
@@ -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
@@ -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&family=JetBrains+Mono&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&family=JetBrains+Mono&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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user