Merge branch 'master' of https://github.com/comfyanonymous/ComfyUI into ci-quality-workflows

This commit is contained in:
enzymezoo-code 2023-09-06 15:50:40 -05:00
commit 26c8e8bcdb
5 changed files with 62 additions and 14 deletions

View File

@ -390,11 +390,20 @@ def get_mask_aabb(masks):
return bounding_boxes, is_empty return bounding_boxes, is_empty
def resolve_cond_masks(conditions, h, w, device): def resolve_areas_and_cond_masks(conditions, h, w, device):
# We need to decide on an area outside the sampling loop in order to properly generate opposite areas of equal sizes. # We need to decide on an area outside the sampling loop in order to properly generate opposite areas of equal sizes.
# While we're doing this, we can also resolve the mask device and scaling for performance reasons # While we're doing this, we can also resolve the mask device and scaling for performance reasons
for i in range(len(conditions)): for i in range(len(conditions)):
c = conditions[i] c = conditions[i]
if 'area' in c[1]:
area = c[1]['area']
if area[0] == "percentage":
modified = c[1].copy()
area = (max(1, round(area[1] * h)), max(1, round(area[2] * w)), round(area[3] * h), round(area[4] * w))
modified['area'] = area
c = [c[0], modified]
conditions[i] = c
if 'mask' in c[1]: if 'mask' in c[1]:
mask = c[1]['mask'] mask = c[1]['mask']
mask = mask.to(device=device) mask = mask.to(device=device)
@ -622,8 +631,8 @@ class KSampler:
positive = positive[:] positive = positive[:]
negative = negative[:] negative = negative[:]
resolve_cond_masks(positive, noise.shape[2], noise.shape[3], self.device) resolve_areas_and_cond_masks(positive, noise.shape[2], noise.shape[3], self.device)
resolve_cond_masks(negative, noise.shape[2], noise.shape[3], self.device) resolve_areas_and_cond_masks(negative, noise.shape[2], noise.shape[3], self.device)
calculate_start_end_timesteps(self.model_wrap, negative) calculate_start_end_timesteps(self.model_wrap, negative)
calculate_start_end_timesteps(self.model_wrap, positive) calculate_start_end_timesteps(self.model_wrap, positive)

View File

@ -121,17 +121,22 @@ def add_model_folder_path(folder_name, full_folder_path):
def get_folder_paths(folder_name): def get_folder_paths(folder_name):
return folder_names_and_paths[folder_name][0][:] return folder_names_and_paths[folder_name][0][:]
def recursive_search(directory): def recursive_search(directory, excluded_dir_names=None):
if not os.path.isdir(directory): if not os.path.isdir(directory):
return [], {} return [], {}
if excluded_dir_names is None:
excluded_dir_names = []
result = [] result = []
dirs = {directory: os.path.getmtime(directory)} dirs = {directory: os.path.getmtime(directory)}
for root, subdir, file in os.walk(directory, followlinks=True): for dirpath, subdirs, filenames in os.walk(directory, followlinks=True, topdown=True):
for filepath in file: subdirs[:] = [d for d in subdirs if d not in excluded_dir_names]
#we os.path,join directory with a blank string to generate a path separator at the end. for file_name in filenames:
result.append(os.path.join(root, filepath).replace(os.path.join(directory,''),'')) relative_path = os.path.relpath(os.path.join(dirpath, file_name), directory)
for d in subdir: result.append(relative_path)
path = os.path.join(root, d) for d in subdirs:
path = os.path.join(dirpath, d)
dirs[path] = os.path.getmtime(path) dirs[path] = os.path.getmtime(path)
return result, dirs return result, dirs
@ -159,7 +164,7 @@ def get_filename_list_(folder_name):
folders = folder_names_and_paths[folder_name] folders = folder_names_and_paths[folder_name]
output_folders = {} output_folders = {}
for x in folders[0]: for x in folders[0]:
files, folders_all = recursive_search(x) files, folders_all = recursive_search(x, excluded_dir_names=[".git"])
output_list.update(filter_files_extensions(files, folders[1])) output_list.update(filter_files_extensions(files, folders[1]))
output_folders = {**output_folders, **folders_all} output_folders = {**output_folders, **folders_all}

View File

@ -159,6 +159,31 @@ class ConditioningSetArea:
c.append(n) c.append(n)
return (c, ) return (c, )
class ConditioningSetAreaPercentage:
@classmethod
def INPUT_TYPES(s):
return {"required": {"conditioning": ("CONDITIONING", ),
"width": ("FLOAT", {"default": 1.0, "min": 0, "max": 1.0, "step": 0.01}),
"height": ("FLOAT", {"default": 1.0, "min": 0, "max": 1.0, "step": 0.01}),
"x": ("FLOAT", {"default": 0, "min": 0, "max": 1.0, "step": 0.01}),
"y": ("FLOAT", {"default": 0, "min": 0, "max": 1.0, "step": 0.01}),
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
}}
RETURN_TYPES = ("CONDITIONING",)
FUNCTION = "append"
CATEGORY = "conditioning"
def append(self, conditioning, width, height, x, y, strength):
c = []
for t in conditioning:
n = [t[0], t[1].copy()]
n[1]['area'] = ("percentage", height, width, y, x)
n[1]['strength'] = strength
n[1]['set_area_to_bounds'] = False
c.append(n)
return (c, )
class ConditioningSetMask: class ConditioningSetMask:
@classmethod @classmethod
def INPUT_TYPES(s): def INPUT_TYPES(s):
@ -1583,6 +1608,7 @@ NODE_CLASS_MAPPINGS = {
"ConditioningCombine": ConditioningCombine, "ConditioningCombine": ConditioningCombine,
"ConditioningConcat": ConditioningConcat, "ConditioningConcat": ConditioningConcat,
"ConditioningSetArea": ConditioningSetArea, "ConditioningSetArea": ConditioningSetArea,
"ConditioningSetAreaPercentage": ConditioningSetAreaPercentage,
"ConditioningSetMask": ConditioningSetMask, "ConditioningSetMask": ConditioningSetMask,
"KSamplerAdvanced": KSamplerAdvanced, "KSamplerAdvanced": KSamplerAdvanced,
"SetLatentNoiseMask": SetLatentNoiseMask, "SetLatentNoiseMask": SetLatentNoiseMask,
@ -1644,6 +1670,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"ConditioningAverage ": "Conditioning (Average)", "ConditioningAverage ": "Conditioning (Average)",
"ConditioningConcat": "Conditioning (Concat)", "ConditioningConcat": "Conditioning (Concat)",
"ConditioningSetArea": "Conditioning (Set Area)", "ConditioningSetArea": "Conditioning (Set Area)",
"ConditioningSetAreaPercentage": "Conditioning (Set Area with Percentage)",
"ConditioningSetMask": "Conditioning (Set Mask)", "ConditioningSetMask": "Conditioning (Set Mask)",
"ControlNetApply": "Apply ControlNet", "ControlNetApply": "Apply ControlNet",
"ControlNetApplyAdvanced": "Apply ControlNet (Advanced)", "ControlNetApplyAdvanced": "Apply ControlNet (Advanced)",

View File

@ -11529,7 +11529,7 @@ LGraphNode.prototype.executeAction = function(action)
if (timeout) { if (timeout) {
clearInterval(timeout); clearInterval(timeout);
} }
timeout = setTimeout(refreshHelper, 250); timeout = setTimeout(refreshHelper, 10);
return; return;
} }
e.preventDefault(); e.preventDefault();

View File

@ -717,8 +717,12 @@ export class ComfyApp {
this.loadGraphData(workflow); this.loadGraphData(workflow);
} }
else { else {
if (e.target.type === "text" || e.target.type === "textarea") {
return;
}
// Litegraph default paste // Litegraph default paste
this.canvas.pasteFromClipboard(); this.canvas.pasteFromClipboard();
} }
@ -1224,6 +1228,7 @@ export class ComfyApp {
const inputData = inputs[inputName]; const inputData = inputs[inputName];
const type = inputData[0]; const type = inputData[0];
let widgetCreated = true;
if (Array.isArray(type)) { if (Array.isArray(type)) {
// Enums // Enums
Object.assign(config, widgets.COMBO(this, inputName, inputData, app) || {}); Object.assign(config, widgets.COMBO(this, inputName, inputData, app) || {});
@ -1236,8 +1241,10 @@ export class ComfyApp {
} else { } else {
// Node connection inputs // Node connection inputs
this.addInput(inputName, type); this.addInput(inputName, type);
widgetCreated = false;
} }
if(inputData[1]?.forceInput && config?.widget) {
if(widgetCreated && inputData[1]?.forceInput && config?.widget) {
if (!config.widget.options) config.widget.options = {}; if (!config.widget.options) config.widget.options = {};
config.widget.options.forceInput = inputData[1].forceInput; config.widget.options.forceInput = inputData[1].forceInput;
} }