From 3d604948eaa5479ab6d468a52b873a6948b4a0b9 Mon Sep 17 00:00:00 2001 From: awsr <43862868+awsr@users.noreply.github.com> Date: Fri, 14 Nov 2025 01:50:20 -0800 Subject: [PATCH 1/3] Allow using `|` as a delimiter instead of `,` This useful for when you want to test combinations of multiple items that would need to be separated by a comma. --- scripts/xyz/xyz_grid_shared.py | 5 +-- scripts/xyz_grid.py | 57 ++++++++++++++++++++-------------- scripts/xyz_grid_on.py | 57 ++++++++++++++++++++-------------- 3 files changed, 71 insertions(+), 48 deletions(-) diff --git a/scripts/xyz/xyz_grid_shared.py b/scripts/xyz/xyz_grid_shared.py index a6829c715..ac66f5f8d 100644 --- a/scripts/xyz/xyz_grid_shared.py +++ b/scripts/xyz/xyz_grid_shared.py @@ -393,7 +393,8 @@ def str_permutations(x): return x -def list_to_csv_string(data_list): +def list_to_csv_string(data_list, alt=False): with StringIO() as o: - csv.writer(o).writerow(data_list) + delimiter = "|" if alt else "," + csv.writer(o, delimiter=delimiter).writerow(data_list) return o.getvalue().strip() diff --git a/scripts/xyz_grid.py b/scripts/xyz_grid.py index 3874deb5e..66ae5d383 100644 --- a/scripts/xyz_grid.py +++ b/scripts/xyz_grid.py @@ -56,6 +56,7 @@ class Script(scripts_manager.Script): with gr.Column(): draw_legend = gr.Checkbox(label='Draw legend', value=True, elem_id=self.elem_id("draw_legend"), container=False) csv_mode = gr.Checkbox(label='Use text inputs', value=False, elem_id=self.elem_id("csv_mode"), container=False) + csv_alt = gr.Checkbox(label='Delimit using |', value=False, elem_id=self.elem_id("csv_alt"), container=False) no_fixed_seeds = gr.Checkbox(label='Use random seeds', value=False, elem_id=self.elem_id("no_fixed_seeds"), container=False) include_time = gr.Checkbox(label='Add time info', value=False, elem_id=self.elem_id("include_time"), container=False) include_text = gr.Checkbox(label='Add text info', value=False, elem_id=self.elem_id("include_text"), container=False) @@ -87,21 +88,21 @@ class Script(scripts_manager.Script): xz_swap_args = [x_type, x_values, x_values_dropdown, z_type, z_values, z_values_dropdown] swap_xz_axes_button.click(swap_axes, inputs=xz_swap_args, outputs=xz_swap_args) - def fill(axis_type, csv_mode): + def fill(axis_type, csv_mode, csv_alt): axis = self.current_axis_options[axis_type] if axis.choices: if csv_mode: - return list_to_csv_string(axis.choices()), gr.update() + return list_to_csv_string(axis.choices(), csv_alt), gr.update() else: return gr.update(), axis.choices() else: return gr.update(), gr.update() - fill_x_button.click(fn=fill, inputs=[x_type, csv_mode], outputs=[x_values, x_values_dropdown]) - fill_y_button.click(fn=fill, inputs=[y_type, csv_mode], outputs=[y_values, y_values_dropdown]) - fill_z_button.click(fn=fill, inputs=[z_type, csv_mode], outputs=[z_values, z_values_dropdown]) + fill_x_button.click(fn=fill, inputs=[x_type, csv_mode, csv_alt], outputs=[x_values, x_values_dropdown]) + fill_y_button.click(fn=fill, inputs=[y_type, csv_mode, csv_alt], outputs=[y_values, y_values_dropdown]) + fill_z_button.click(fn=fill, inputs=[z_type, csv_mode, csv_alt], outputs=[z_values, z_values_dropdown]) - def select_axis(axis_type, axis_values, axis_values_dropdown, csv_mode): + def select_axis(axis_type, axis_values, axis_values_dropdown, csv_mode, csv_alt): choices = self.current_axis_options[axis_type].choices has_choices = choices is not None current_values = axis_values @@ -110,30 +111,39 @@ class Script(scripts_manager.Script): choices = choices() if csv_mode: current_dropdown_values = list(filter(lambda x: x in choices, current_dropdown_values)) - current_values = list_to_csv_string(current_dropdown_values) + current_values = list_to_csv_string(current_dropdown_values, csv_alt) else: - current_dropdown_values = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(axis_values)))] + delimiter = '|' if csv_alt or axis_values.find('|') > 0 else ',' + current_dropdown_values = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(axis_values), delimiter=delimiter))] current_dropdown_values = list(filter(lambda x: x in choices, current_dropdown_values)) return (gr.Button.update(visible=has_choices), gr.Textbox.update(visible=not has_choices or csv_mode, value=current_values), gr.update(choices=choices if has_choices else None, visible=has_choices and not csv_mode, value=current_dropdown_values)) - x_type.change(fn=select_axis, inputs=[x_type, x_values, x_values_dropdown, csv_mode], outputs=[fill_x_button, x_values, x_values_dropdown]) - y_type.change(fn=select_axis, inputs=[y_type, y_values, y_values_dropdown, csv_mode], outputs=[fill_y_button, y_values, y_values_dropdown]) - z_type.change(fn=select_axis, inputs=[z_type, z_values, z_values_dropdown, csv_mode], outputs=[fill_z_button, z_values, z_values_dropdown]) + x_type.change(fn=select_axis, inputs=[x_type, x_values, x_values_dropdown, csv_mode, csv_alt], outputs=[fill_x_button, x_values, x_values_dropdown]) + y_type.change(fn=select_axis, inputs=[y_type, y_values, y_values_dropdown, csv_mode, csv_alt], outputs=[fill_y_button, y_values, y_values_dropdown]) + z_type.change(fn=select_axis, inputs=[z_type, z_values, z_values_dropdown, csv_mode, csv_alt], outputs=[fill_z_button, z_values, z_values_dropdown]) - def change_choice_mode(csv_mode, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown): - _fill_x_button, _x_values, _x_values_dropdown = select_axis(x_type, x_values, x_values_dropdown, csv_mode) - _fill_y_button, _y_values, _y_values_dropdown = select_axis(y_type, y_values, y_values_dropdown, csv_mode) - _fill_z_button, _z_values, _z_values_dropdown = select_axis(z_type, z_values, z_values_dropdown, csv_mode) + def change_choice_mode(csv_mode, csv_alt, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown): + _fill_x_button, _x_values, _x_values_dropdown = select_axis(x_type, x_values, x_values_dropdown, csv_mode, csv_alt) + _fill_y_button, _y_values, _y_values_dropdown = select_axis(y_type, y_values, y_values_dropdown, csv_mode, csv_alt) + _fill_z_button, _z_values, _z_values_dropdown = select_axis(z_type, z_values, z_values_dropdown, csv_mode, csv_alt) return _fill_x_button, _x_values, _x_values_dropdown, _fill_y_button, _y_values, _y_values_dropdown, _fill_z_button, _z_values, _z_values_dropdown - csv_mode.change(fn=change_choice_mode, inputs=[csv_mode, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown], outputs=[fill_x_button, x_values, x_values_dropdown, fill_y_button, y_values, y_values_dropdown, fill_z_button, z_values, z_values_dropdown]) + def replace_csv_delimiter(value, csv_alt): + return gr.update(value=value.replace(',', '|') if csv_alt else value.replace('|', ',')) + + def change_csv_delimiter(csv_alt, x_values, y_values, z_values): + return (replace_csv_delimiter(x_values, csv_alt), replace_csv_delimiter(y_values, csv_alt), replace_csv_delimiter(z_values, csv_alt)) + + csv_mode.change(fn=change_choice_mode, inputs=[csv_mode, csv_alt, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown], outputs=[fill_x_button, x_values, x_values_dropdown, fill_y_button, y_values, y_values_dropdown, fill_z_button, z_values, z_values_dropdown]) + csv_alt.change(fn=change_csv_delimiter, inputs=[csv_alt, x_values, y_values, z_values], outputs=[x_values, y_values, z_values]) def get_dropdown_update_from_params(axis,params): val_key = f"{axis} Values" vals = params.get(val_key,"") - valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals))) if x] + delimiter = '|' if csv_alt or vals.find('|') > 0 else ',' + valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals), delimiter=delimiter)) if x] return gr.update(value = valslist) self.infotext_fields = ( @@ -152,7 +162,7 @@ class Script(scripts_manager.Script): x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, - csv_mode, draw_legend, no_fixed_seeds, + csv_mode, csv_alt, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, include_time, include_text, margin_size, create_video, video_type, video_duration, video_loop, video_pad, video_interpolate, @@ -162,7 +172,7 @@ class Script(scripts_manager.Script): x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, - csv_mode, draw_legend, no_fixed_seeds, + csv_mode, csv_alt, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, include_time, include_text, margin_size, create_video, video_type, video_duration, video_loop, video_pad, video_interpolate, @@ -177,7 +187,8 @@ class Script(scripts_manager.Script): if opt.choices is not None and not csv_mode: valslist = vals_dropdown else: - valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals))) if x] + delimiter = '|' if csv_alt or vals.find('|') > 0 else ',' + valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals), delimiter=delimiter)) if x] if opt.type == int: valslist_ext = [] for val in valslist: @@ -223,15 +234,15 @@ class Script(scripts_manager.Script): try: x_opt = self.current_axis_options[x_type] if x_opt.choices is not None and not csv_mode: - x_values = list_to_csv_string(x_values_dropdown) + x_values = list_to_csv_string(x_values_dropdown, csv_alt) xs = process_axis(x_opt, x_values, x_values_dropdown) y_opt = self.current_axis_options[y_type] if y_opt.choices is not None and not csv_mode: - y_values = list_to_csv_string(y_values_dropdown) + y_values = list_to_csv_string(y_values_dropdown, csv_alt) ys = process_axis(y_opt, y_values, y_values_dropdown) z_opt = self.current_axis_options[z_type] if z_opt.choices is not None and not csv_mode: - z_values = list_to_csv_string(z_values_dropdown) + z_values = list_to_csv_string(z_values_dropdown, csv_alt) zs = process_axis(z_opt, z_values, z_values_dropdown) except Exception as e: shared.log.error(f"XYZ grid: invalid axis values {e}") diff --git a/scripts/xyz_grid_on.py b/scripts/xyz_grid_on.py index 595536067..c30ac46fa 100644 --- a/scripts/xyz_grid_on.py +++ b/scripts/xyz_grid_on.py @@ -62,6 +62,7 @@ class Script(scripts_manager.Script): with gr.Column(): draw_legend = gr.Checkbox(label='Draw legend', value=True, elem_id=self.elem_id("draw_legend"), container=False) csv_mode = gr.Checkbox(label='Use text inputs', value=False, elem_id=self.elem_id("csv_mode"), container=False) + csv_alt = gr.Checkbox(label='Delimit using |', value=False, elem_id=self.elem_id("csv_alt"), container=False) no_fixed_seeds = gr.Checkbox(label='Use random seeds', value=False, elem_id=self.elem_id("no_fixed_seeds"), container=False) include_time = gr.Checkbox(label='Add time info', value=False, elem_id=self.elem_id("include_time"), container=False) include_text = gr.Checkbox(label='Add text info', value=False, elem_id=self.elem_id("include_text"), container=False) @@ -93,21 +94,21 @@ class Script(scripts_manager.Script): xz_swap_args = [x_type, x_values, x_values_dropdown, z_type, z_values, z_values_dropdown] swap_xz_axes_button.click(swap_axes, inputs=xz_swap_args, outputs=xz_swap_args) - def fill(axis_type, csv_mode): + def fill(axis_type, csv_mode, csv_alt): axis = self.current_axis_options[axis_type] if axis.choices: if csv_mode: - return list_to_csv_string(axis.choices()), gr.update() + return list_to_csv_string(axis.choices(), csv_alt), gr.update() else: return gr.update(), axis.choices() else: return gr.update(), gr.update() - fill_x_button.click(fn=fill, inputs=[x_type, csv_mode], outputs=[x_values, x_values_dropdown]) - fill_y_button.click(fn=fill, inputs=[y_type, csv_mode], outputs=[y_values, y_values_dropdown]) - fill_z_button.click(fn=fill, inputs=[z_type, csv_mode], outputs=[z_values, z_values_dropdown]) + fill_x_button.click(fn=fill, inputs=[x_type, csv_mode, csv_alt], outputs=[x_values, x_values_dropdown]) + fill_y_button.click(fn=fill, inputs=[y_type, csv_mode, csv_alt], outputs=[y_values, y_values_dropdown]) + fill_z_button.click(fn=fill, inputs=[z_type, csv_mode, csv_alt], outputs=[z_values, z_values_dropdown]) - def select_axis(axis_type, axis_values, axis_values_dropdown, csv_mode): + def select_axis(axis_type, axis_values, axis_values_dropdown, csv_mode, csv_alt): choices = self.current_axis_options[axis_type].choices has_choices = choices is not None current_values = axis_values @@ -116,30 +117,39 @@ class Script(scripts_manager.Script): choices = choices() if csv_mode: current_dropdown_values = list(filter(lambda x: x in choices, current_dropdown_values)) - current_values = list_to_csv_string(current_dropdown_values) + current_values = list_to_csv_string(current_dropdown_values, csv_alt) else: - current_dropdown_values = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(axis_values)))] + delimiter = '|' if csv_alt or axis_values.find('|') > 0 else ',' + current_dropdown_values = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(axis_values), delimiter=delimiter))] current_dropdown_values = list(filter(lambda x: x in choices, current_dropdown_values)) return (gr.Button.update(visible=has_choices), gr.Textbox.update(visible=not has_choices or csv_mode, value=current_values), gr.update(choices=choices if has_choices else None, visible=has_choices and not csv_mode, value=current_dropdown_values)) - x_type.change(fn=select_axis, inputs=[x_type, x_values, x_values_dropdown, csv_mode], outputs=[fill_x_button, x_values, x_values_dropdown]) - y_type.change(fn=select_axis, inputs=[y_type, y_values, y_values_dropdown, csv_mode], outputs=[fill_y_button, y_values, y_values_dropdown]) - z_type.change(fn=select_axis, inputs=[z_type, z_values, z_values_dropdown, csv_mode], outputs=[fill_z_button, z_values, z_values_dropdown]) + x_type.change(fn=select_axis, inputs=[x_type, x_values, x_values_dropdown, csv_mode, csv_alt], outputs=[fill_x_button, x_values, x_values_dropdown]) + y_type.change(fn=select_axis, inputs=[y_type, y_values, y_values_dropdown, csv_mode, csv_alt], outputs=[fill_y_button, y_values, y_values_dropdown]) + z_type.change(fn=select_axis, inputs=[z_type, z_values, z_values_dropdown, csv_mode, csv_alt], outputs=[fill_z_button, z_values, z_values_dropdown]) - def change_choice_mode(csv_mode, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown): - _fill_x_button, _x_values, _x_values_dropdown = select_axis(x_type, x_values, x_values_dropdown, csv_mode) - _fill_y_button, _y_values, _y_values_dropdown = select_axis(y_type, y_values, y_values_dropdown, csv_mode) - _fill_z_button, _z_values, _z_values_dropdown = select_axis(z_type, z_values, z_values_dropdown, csv_mode) + def change_choice_mode(csv_mode, csv_alt, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown): + _fill_x_button, _x_values, _x_values_dropdown = select_axis(x_type, x_values, x_values_dropdown, csv_mode, csv_alt) + _fill_y_button, _y_values, _y_values_dropdown = select_axis(y_type, y_values, y_values_dropdown, csv_mode, csv_alt) + _fill_z_button, _z_values, _z_values_dropdown = select_axis(z_type, z_values, z_values_dropdown, csv_mode, csv_alt) return _fill_x_button, _x_values, _x_values_dropdown, _fill_y_button, _y_values, _y_values_dropdown, _fill_z_button, _z_values, _z_values_dropdown - csv_mode.change(fn=change_choice_mode, inputs=[csv_mode, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown], outputs=[fill_x_button, x_values, x_values_dropdown, fill_y_button, y_values, y_values_dropdown, fill_z_button, z_values, z_values_dropdown]) + def replace_csv_delimiter(value, csv_alt): + return gr.update(value=value.replace(',', '|') if csv_alt else value.replace('|', ',')) + + def change_csv_delimiter(csv_alt, x_values, y_values, z_values): + return (replace_csv_delimiter(x_values, csv_alt), replace_csv_delimiter(y_values, csv_alt), replace_csv_delimiter(z_values, csv_alt)) + + csv_mode.change(fn=change_choice_mode, inputs=[csv_mode, csv_alt, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown], outputs=[fill_x_button, x_values, x_values_dropdown, fill_y_button, y_values, y_values_dropdown, fill_z_button, z_values, z_values_dropdown]) + csv_alt.change(fn=change_csv_delimiter, inputs=[csv_alt, x_values, y_values, z_values], outputs=[x_values, y_values, z_values]) def get_dropdown_update_from_params(axis,params): val_key = f"{axis} Values" vals = params.get(val_key,"") - valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals))) if x] + delimiter = '|' if csv_alt or vals.find('|') > 0 else ',' + valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals), delimiter=delimiter)) if x] return gr.update(value = valslist) self.infotext_fields = ( @@ -159,7 +169,7 @@ class Script(scripts_manager.Script): x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, - csv_mode, draw_legend, no_fixed_seeds, + csv_mode, csv_alt, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, include_time, include_text, margin_size, create_video, video_type, video_duration, video_loop, video_pad, video_interpolate, @@ -170,7 +180,7 @@ class Script(scripts_manager.Script): x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, - csv_mode, draw_legend, no_fixed_seeds, + csv_mode, csv_alt, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, include_time, include_text, margin_size, create_video, video_type, video_duration, video_loop, video_pad, video_interpolate, @@ -192,7 +202,8 @@ class Script(scripts_manager.Script): if opt.choices is not None and not csv_mode: valslist = vals_dropdown else: - valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals))) if x] + delimiter = '|' if csv_alt or vals.find('|') > 0 else ',' + valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals), delimiter=delimiter)) if x] if opt.type == int: valslist_ext = [] for val in valslist: @@ -238,15 +249,15 @@ class Script(scripts_manager.Script): try: x_opt = self.current_axis_options[x_type] if x_opt.choices is not None and not csv_mode: - x_values = list_to_csv_string(x_values_dropdown) + x_values = list_to_csv_string(x_values_dropdown, csv_alt) xs = process_axis(x_opt, x_values, x_values_dropdown) y_opt = self.current_axis_options[y_type] if y_opt.choices is not None and not csv_mode: - y_values = list_to_csv_string(y_values_dropdown) + y_values = list_to_csv_string(y_values_dropdown, csv_alt) ys = process_axis(y_opt, y_values, y_values_dropdown) z_opt = self.current_axis_options[z_type] if z_opt.choices is not None and not csv_mode: - z_values = list_to_csv_string(z_values_dropdown) + z_values = list_to_csv_string(z_values_dropdown, csv_alt) zs = process_axis(z_opt, z_values, z_values_dropdown) except Exception as e: shared.log.error(f"XYZ grid: invalid axis values {e}") From f928a4bf26944af8b6ea6161b373a5745fc8aad5 Mon Sep 17 00:00:00 2001 From: awsr <43862868+awsr@users.noreply.github.com> Date: Fri, 14 Nov 2025 02:30:02 -0800 Subject: [PATCH 2/3] Update locale_en.json --- html/locale_en.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/html/locale_en.json b/html/locale_en.json index 54f20deb1..a5697e2a9 100644 --- a/html/locale_en.json +++ b/html/locale_en.json @@ -286,9 +286,10 @@ {"id":"","label":"Unload adapter","localized":"","reload":"","hint":"Unload IP adapter immediately after generate. Otherwise IP adapter will remain loaded for faster use in next generate process"}, {"id":"","label":"Crop to portrait","localized":"","reload":"","hint":"Crop input image to portrait-only before using it as IP adapter input"}, {"id":"","label":"Layer options","localized":"","reload":"","hint":"Manually specify IP adapter advanced layer options"}, - {"id":"","label":"X values","localized":"","reload":"","hint":"Separate values for X axis using commas"}, - {"id":"","label":"Y values","localized":"","reload":"","hint":"Separate values for Y axis using commas"}, - {"id":"","label":"Z values","localized":"","reload":"","hint":"Separate values for Z axis using commas"}, + {"id":"","label":"Delimit using |","localized":"","reload":"","hint":"Use | (vertical bar) instead of commas to separate values"}, + {"id":"","label":"X values","localized":"","reload":"","hint":"Separate values for X axis using commas (unless 'Delimit using |' is enabled, then use vertical bars)"}, + {"id":"","label":"Y values","localized":"","reload":"","hint":"Separate values for Y axis using commas (unless 'Delimit using |' is enabled, then use vertical bars)"}, + {"id":"","label":"Z values","localized":"","reload":"","hint":"Separate values for Z axis using commas (unless 'Delimit using |' is enabled, then use vertical bars)"}, {"id":"","label":"Loops","localized":"","reload":"","hint":"How many times to process an image. Each output is used as the input of the next loop. If set to 1, behavior will be as if this script were not used"}, {"id":"","label":"Final denoising strength","localized":"","reload":"","hint":"The denoising strength for the final loop of each image in the batch"}, {"id":"","label":"Denoising strength curve","localized":"","reload":"","hint":"The denoising curve controls the rate of denoising strength change each loop. Aggressive: Most of the change will happen towards the start of the loops. Linear: Change will be constant through all loops. Lazy: Most of the change will happen towards the end of the loops"}, From 2e87e20c3002d80a11c0f56d55374c098a9c37f0 Mon Sep 17 00:00:00 2001 From: awsr <43862868+awsr@users.noreply.github.com> Date: Sat, 15 Nov 2025 13:06:57 -0800 Subject: [PATCH 3/3] Allow \, to prevent text splitting --- html/locale_en.json | 7 ++-- scripts/xyz/xyz_grid_shared.py | 14 ++++---- scripts/xyz_grid.py | 63 ++++++++++++++-------------------- scripts/xyz_grid_on.py | 63 ++++++++++++++-------------------- 4 files changed, 60 insertions(+), 87 deletions(-) diff --git a/html/locale_en.json b/html/locale_en.json index a5697e2a9..54f20deb1 100644 --- a/html/locale_en.json +++ b/html/locale_en.json @@ -286,10 +286,9 @@ {"id":"","label":"Unload adapter","localized":"","reload":"","hint":"Unload IP adapter immediately after generate. Otherwise IP adapter will remain loaded for faster use in next generate process"}, {"id":"","label":"Crop to portrait","localized":"","reload":"","hint":"Crop input image to portrait-only before using it as IP adapter input"}, {"id":"","label":"Layer options","localized":"","reload":"","hint":"Manually specify IP adapter advanced layer options"}, - {"id":"","label":"Delimit using |","localized":"","reload":"","hint":"Use | (vertical bar) instead of commas to separate values"}, - {"id":"","label":"X values","localized":"","reload":"","hint":"Separate values for X axis using commas (unless 'Delimit using |' is enabled, then use vertical bars)"}, - {"id":"","label":"Y values","localized":"","reload":"","hint":"Separate values for Y axis using commas (unless 'Delimit using |' is enabled, then use vertical bars)"}, - {"id":"","label":"Z values","localized":"","reload":"","hint":"Separate values for Z axis using commas (unless 'Delimit using |' is enabled, then use vertical bars)"}, + {"id":"","label":"X values","localized":"","reload":"","hint":"Separate values for X axis using commas"}, + {"id":"","label":"Y values","localized":"","reload":"","hint":"Separate values for Y axis using commas"}, + {"id":"","label":"Z values","localized":"","reload":"","hint":"Separate values for Z axis using commas"}, {"id":"","label":"Loops","localized":"","reload":"","hint":"How many times to process an image. Each output is used as the input of the next loop. If set to 1, behavior will be as if this script were not used"}, {"id":"","label":"Final denoising strength","localized":"","reload":"","hint":"The denoising strength for the final loop of each image in the batch"}, {"id":"","label":"Denoising strength curve","localized":"","reload":"","hint":"The denoising curve controls the rate of denoising strength change each loop. Aggressive: Most of the change will happen towards the start of the loops. Linear: Change will be constant through all loops. Lazy: Most of the change will happen towards the end of the loops"}, diff --git a/scripts/xyz/xyz_grid_shared.py b/scripts/xyz/xyz_grid_shared.py index ac66f5f8d..b8e856014 100644 --- a/scripts/xyz/xyz_grid_shared.py +++ b/scripts/xyz/xyz_grid_shared.py @@ -2,12 +2,15 @@ import os import re -import csv -from io import StringIO from modules import shared, processing, sd_samplers, sd_models, sd_vae, sd_unet re_range = re.compile(r'([-+]?[0-9]*\.?[0-9]+)-([-+]?[0-9]*\.?[0-9]+):?([0-9]+)?') +re_plain_comma = re.compile(r"(? 0 else ',' - current_dropdown_values = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(axis_values), delimiter=delimiter))] + current_dropdown_values = [restore_comma(x.strip()) for x in re_plain_comma.split(axis_values) if x] current_dropdown_values = list(filter(lambda x: x in choices, current_dropdown_values)) return (gr.Button.update(visible=has_choices), gr.Textbox.update(visible=not has_choices or csv_mode, value=current_values), gr.update(choices=choices if has_choices else None, visible=has_choices and not csv_mode, value=current_dropdown_values)) - x_type.change(fn=select_axis, inputs=[x_type, x_values, x_values_dropdown, csv_mode, csv_alt], outputs=[fill_x_button, x_values, x_values_dropdown]) - y_type.change(fn=select_axis, inputs=[y_type, y_values, y_values_dropdown, csv_mode, csv_alt], outputs=[fill_y_button, y_values, y_values_dropdown]) - z_type.change(fn=select_axis, inputs=[z_type, z_values, z_values_dropdown, csv_mode, csv_alt], outputs=[fill_z_button, z_values, z_values_dropdown]) + x_type.change(fn=select_axis, inputs=[x_type, x_values, x_values_dropdown, csv_mode], outputs=[fill_x_button, x_values, x_values_dropdown]) + y_type.change(fn=select_axis, inputs=[y_type, y_values, y_values_dropdown, csv_mode], outputs=[fill_y_button, y_values, y_values_dropdown]) + z_type.change(fn=select_axis, inputs=[z_type, z_values, z_values_dropdown, csv_mode], outputs=[fill_z_button, z_values, z_values_dropdown]) - def change_choice_mode(csv_mode, csv_alt, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown): - _fill_x_button, _x_values, _x_values_dropdown = select_axis(x_type, x_values, x_values_dropdown, csv_mode, csv_alt) - _fill_y_button, _y_values, _y_values_dropdown = select_axis(y_type, y_values, y_values_dropdown, csv_mode, csv_alt) - _fill_z_button, _z_values, _z_values_dropdown = select_axis(z_type, z_values, z_values_dropdown, csv_mode, csv_alt) + def change_choice_mode(csv_mode, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown): + _fill_x_button, _x_values, _x_values_dropdown = select_axis(x_type, x_values, x_values_dropdown, csv_mode) + _fill_y_button, _y_values, _y_values_dropdown = select_axis(y_type, y_values, y_values_dropdown, csv_mode) + _fill_z_button, _z_values, _z_values_dropdown = select_axis(z_type, z_values, z_values_dropdown, csv_mode) return _fill_x_button, _x_values, _x_values_dropdown, _fill_y_button, _y_values, _y_values_dropdown, _fill_z_button, _z_values, _z_values_dropdown - def replace_csv_delimiter(value, csv_alt): - return gr.update(value=value.replace(',', '|') if csv_alt else value.replace('|', ',')) - - def change_csv_delimiter(csv_alt, x_values, y_values, z_values): - return (replace_csv_delimiter(x_values, csv_alt), replace_csv_delimiter(y_values, csv_alt), replace_csv_delimiter(z_values, csv_alt)) - - csv_mode.change(fn=change_choice_mode, inputs=[csv_mode, csv_alt, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown], outputs=[fill_x_button, x_values, x_values_dropdown, fill_y_button, y_values, y_values_dropdown, fill_z_button, z_values, z_values_dropdown]) - csv_alt.change(fn=change_csv_delimiter, inputs=[csv_alt, x_values, y_values, z_values], outputs=[x_values, y_values, z_values]) + csv_mode.change(fn=change_choice_mode, inputs=[csv_mode, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown], outputs=[fill_x_button, x_values, x_values_dropdown, fill_y_button, y_values, y_values_dropdown, fill_z_button, z_values, z_values_dropdown]) def get_dropdown_update_from_params(axis,params): val_key = f"{axis} Values" vals = params.get(val_key,"") - delimiter = '|' if csv_alt or vals.find('|') > 0 else ',' - valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals), delimiter=delimiter)) if x] + valslist = [restore_comma(x.strip()) for x in re_plain_comma.split(vals) if x] return gr.update(value = valslist) self.infotext_fields = ( @@ -162,7 +150,7 @@ class Script(scripts_manager.Script): x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, - csv_mode, csv_alt, draw_legend, no_fixed_seeds, + csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, include_time, include_text, margin_size, create_video, video_type, video_duration, video_loop, video_pad, video_interpolate, @@ -172,7 +160,7 @@ class Script(scripts_manager.Script): x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, - csv_mode, csv_alt, draw_legend, no_fixed_seeds, + csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, include_time, include_text, margin_size, create_video, video_type, video_duration, video_loop, video_pad, video_interpolate, @@ -187,8 +175,7 @@ class Script(scripts_manager.Script): if opt.choices is not None and not csv_mode: valslist = vals_dropdown else: - delimiter = '|' if csv_alt or vals.find('|') > 0 else ',' - valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals), delimiter=delimiter)) if x] + valslist = [restore_comma(x.strip()) for x in re_plain_comma.split(vals) if x] if opt.type == int: valslist_ext = [] for val in valslist: @@ -234,15 +221,15 @@ class Script(scripts_manager.Script): try: x_opt = self.current_axis_options[x_type] if x_opt.choices is not None and not csv_mode: - x_values = list_to_csv_string(x_values_dropdown, csv_alt) + x_values = list_to_csv_string(x_values_dropdown) xs = process_axis(x_opt, x_values, x_values_dropdown) y_opt = self.current_axis_options[y_type] if y_opt.choices is not None and not csv_mode: - y_values = list_to_csv_string(y_values_dropdown, csv_alt) + y_values = list_to_csv_string(y_values_dropdown) ys = process_axis(y_opt, y_values, y_values_dropdown) z_opt = self.current_axis_options[z_type] if z_opt.choices is not None and not csv_mode: - z_values = list_to_csv_string(z_values_dropdown, csv_alt) + z_values = list_to_csv_string(z_values_dropdown) zs = process_axis(z_opt, z_values, z_values_dropdown) except Exception as e: shared.log.error(f"XYZ grid: invalid axis values {e}") diff --git a/scripts/xyz_grid_on.py b/scripts/xyz_grid_on.py index c30ac46fa..0eee4c548 100644 --- a/scripts/xyz_grid_on.py +++ b/scripts/xyz_grid_on.py @@ -1,16 +1,14 @@ # xyz grid that shows up as alwayson script import os -import csv import time import random from collections import namedtuple from copy import copy -from itertools import permutations, chain -from io import StringIO +from itertools import permutations from PIL import Image import numpy as np import gradio as gr -from scripts.xyz.xyz_grid_shared import str_permutations, list_to_csv_string, re_range # pylint: disable=no-name-in-module +from scripts.xyz.xyz_grid_shared import str_permutations, list_to_csv_string, restore_comma, re_range, re_plain_comma # pylint: disable=no-name-in-module from scripts.xyz.xyz_grid_classes import axis_options, AxisOption, SharedSettingsStackHelper # pylint: disable=no-name-in-module from scripts.xyz.xyz_grid_draw import draw_xyz_grid # pylint: disable=no-name-in-module from modules import shared, errors, scripts_manager, images, processing @@ -62,7 +60,6 @@ class Script(scripts_manager.Script): with gr.Column(): draw_legend = gr.Checkbox(label='Draw legend', value=True, elem_id=self.elem_id("draw_legend"), container=False) csv_mode = gr.Checkbox(label='Use text inputs', value=False, elem_id=self.elem_id("csv_mode"), container=False) - csv_alt = gr.Checkbox(label='Delimit using |', value=False, elem_id=self.elem_id("csv_alt"), container=False) no_fixed_seeds = gr.Checkbox(label='Use random seeds', value=False, elem_id=self.elem_id("no_fixed_seeds"), container=False) include_time = gr.Checkbox(label='Add time info', value=False, elem_id=self.elem_id("include_time"), container=False) include_text = gr.Checkbox(label='Add text info', value=False, elem_id=self.elem_id("include_text"), container=False) @@ -94,21 +91,21 @@ class Script(scripts_manager.Script): xz_swap_args = [x_type, x_values, x_values_dropdown, z_type, z_values, z_values_dropdown] swap_xz_axes_button.click(swap_axes, inputs=xz_swap_args, outputs=xz_swap_args) - def fill(axis_type, csv_mode, csv_alt): + def fill(axis_type, csv_mode): axis = self.current_axis_options[axis_type] if axis.choices: if csv_mode: - return list_to_csv_string(axis.choices(), csv_alt), gr.update() + return list_to_csv_string(axis.choices()), gr.update() else: return gr.update(), axis.choices() else: return gr.update(), gr.update() - fill_x_button.click(fn=fill, inputs=[x_type, csv_mode, csv_alt], outputs=[x_values, x_values_dropdown]) - fill_y_button.click(fn=fill, inputs=[y_type, csv_mode, csv_alt], outputs=[y_values, y_values_dropdown]) - fill_z_button.click(fn=fill, inputs=[z_type, csv_mode, csv_alt], outputs=[z_values, z_values_dropdown]) + fill_x_button.click(fn=fill, inputs=[x_type, csv_mode], outputs=[x_values, x_values_dropdown]) + fill_y_button.click(fn=fill, inputs=[y_type, csv_mode], outputs=[y_values, y_values_dropdown]) + fill_z_button.click(fn=fill, inputs=[z_type, csv_mode], outputs=[z_values, z_values_dropdown]) - def select_axis(axis_type, axis_values, axis_values_dropdown, csv_mode, csv_alt): + def select_axis(axis_type, axis_values, axis_values_dropdown, csv_mode): choices = self.current_axis_options[axis_type].choices has_choices = choices is not None current_values = axis_values @@ -117,39 +114,30 @@ class Script(scripts_manager.Script): choices = choices() if csv_mode: current_dropdown_values = list(filter(lambda x: x in choices, current_dropdown_values)) - current_values = list_to_csv_string(current_dropdown_values, csv_alt) + current_values = list_to_csv_string(current_dropdown_values) else: - delimiter = '|' if csv_alt or axis_values.find('|') > 0 else ',' - current_dropdown_values = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(axis_values), delimiter=delimiter))] + current_dropdown_values = [restore_comma(x.strip()) for x in re_plain_comma.split(axis_values) if x] current_dropdown_values = list(filter(lambda x: x in choices, current_dropdown_values)) return (gr.Button.update(visible=has_choices), gr.Textbox.update(visible=not has_choices or csv_mode, value=current_values), gr.update(choices=choices if has_choices else None, visible=has_choices and not csv_mode, value=current_dropdown_values)) - x_type.change(fn=select_axis, inputs=[x_type, x_values, x_values_dropdown, csv_mode, csv_alt], outputs=[fill_x_button, x_values, x_values_dropdown]) - y_type.change(fn=select_axis, inputs=[y_type, y_values, y_values_dropdown, csv_mode, csv_alt], outputs=[fill_y_button, y_values, y_values_dropdown]) - z_type.change(fn=select_axis, inputs=[z_type, z_values, z_values_dropdown, csv_mode, csv_alt], outputs=[fill_z_button, z_values, z_values_dropdown]) + x_type.change(fn=select_axis, inputs=[x_type, x_values, x_values_dropdown, csv_mode], outputs=[fill_x_button, x_values, x_values_dropdown]) + y_type.change(fn=select_axis, inputs=[y_type, y_values, y_values_dropdown, csv_mode], outputs=[fill_y_button, y_values, y_values_dropdown]) + z_type.change(fn=select_axis, inputs=[z_type, z_values, z_values_dropdown, csv_mode], outputs=[fill_z_button, z_values, z_values_dropdown]) - def change_choice_mode(csv_mode, csv_alt, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown): - _fill_x_button, _x_values, _x_values_dropdown = select_axis(x_type, x_values, x_values_dropdown, csv_mode, csv_alt) - _fill_y_button, _y_values, _y_values_dropdown = select_axis(y_type, y_values, y_values_dropdown, csv_mode, csv_alt) - _fill_z_button, _z_values, _z_values_dropdown = select_axis(z_type, z_values, z_values_dropdown, csv_mode, csv_alt) + def change_choice_mode(csv_mode, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown): + _fill_x_button, _x_values, _x_values_dropdown = select_axis(x_type, x_values, x_values_dropdown, csv_mode) + _fill_y_button, _y_values, _y_values_dropdown = select_axis(y_type, y_values, y_values_dropdown, csv_mode) + _fill_z_button, _z_values, _z_values_dropdown = select_axis(z_type, z_values, z_values_dropdown, csv_mode) return _fill_x_button, _x_values, _x_values_dropdown, _fill_y_button, _y_values, _y_values_dropdown, _fill_z_button, _z_values, _z_values_dropdown - def replace_csv_delimiter(value, csv_alt): - return gr.update(value=value.replace(',', '|') if csv_alt else value.replace('|', ',')) - - def change_csv_delimiter(csv_alt, x_values, y_values, z_values): - return (replace_csv_delimiter(x_values, csv_alt), replace_csv_delimiter(y_values, csv_alt), replace_csv_delimiter(z_values, csv_alt)) - - csv_mode.change(fn=change_choice_mode, inputs=[csv_mode, csv_alt, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown], outputs=[fill_x_button, x_values, x_values_dropdown, fill_y_button, y_values, y_values_dropdown, fill_z_button, z_values, z_values_dropdown]) - csv_alt.change(fn=change_csv_delimiter, inputs=[csv_alt, x_values, y_values, z_values], outputs=[x_values, y_values, z_values]) + csv_mode.change(fn=change_choice_mode, inputs=[csv_mode, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown], outputs=[fill_x_button, x_values, x_values_dropdown, fill_y_button, y_values, y_values_dropdown, fill_z_button, z_values, z_values_dropdown]) def get_dropdown_update_from_params(axis,params): val_key = f"{axis} Values" vals = params.get(val_key,"") - delimiter = '|' if csv_alt or vals.find('|') > 0 else ',' - valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals), delimiter=delimiter)) if x] + valslist = [restore_comma(x.strip()) for x in re_plain_comma.split(vals) if x] return gr.update(value = valslist) self.infotext_fields = ( @@ -169,7 +157,7 @@ class Script(scripts_manager.Script): x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, - csv_mode, csv_alt, draw_legend, no_fixed_seeds, + csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, include_time, include_text, margin_size, create_video, video_type, video_duration, video_loop, video_pad, video_interpolate, @@ -180,7 +168,7 @@ class Script(scripts_manager.Script): x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, - csv_mode, csv_alt, draw_legend, no_fixed_seeds, + csv_mode, draw_legend, no_fixed_seeds, include_grid, include_subgrids, include_images, include_time, include_text, margin_size, create_video, video_type, video_duration, video_loop, video_pad, video_interpolate, @@ -202,8 +190,7 @@ class Script(scripts_manager.Script): if opt.choices is not None and not csv_mode: valslist = vals_dropdown else: - delimiter = '|' if csv_alt or vals.find('|') > 0 else ',' - valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals), delimiter=delimiter)) if x] + valslist = [restore_comma(x.strip()) for x in re_plain_comma.split(vals) if x] if opt.type == int: valslist_ext = [] for val in valslist: @@ -249,15 +236,15 @@ class Script(scripts_manager.Script): try: x_opt = self.current_axis_options[x_type] if x_opt.choices is not None and not csv_mode: - x_values = list_to_csv_string(x_values_dropdown, csv_alt) + x_values = list_to_csv_string(x_values_dropdown) xs = process_axis(x_opt, x_values, x_values_dropdown) y_opt = self.current_axis_options[y_type] if y_opt.choices is not None and not csv_mode: - y_values = list_to_csv_string(y_values_dropdown, csv_alt) + y_values = list_to_csv_string(y_values_dropdown) ys = process_axis(y_opt, y_values, y_values_dropdown) z_opt = self.current_axis_options[z_type] if z_opt.choices is not None and not csv_mode: - z_values = list_to_csv_string(z_values_dropdown, csv_alt) + z_values = list_to_csv_string(z_values_dropdown) zs = process_axis(z_opt, z_values, z_values_dropdown) except Exception as e: shared.log.error(f"XYZ grid: invalid axis values {e}")