Compare commits

...

7 Commits

5 changed files with 88 additions and 9 deletions

View File

@ -183,3 +183,48 @@ onUiUpdate(function(){
json_elem.parentElement.style.display="none"
})
/**
* Implement script-dependent UI restraints, e.g. forcing a specific sampling method
*/
let prev_ui_states = {};
function updateScriptRestraints() {
const currentTab = get_uiCurrentTab()?.textContent.trim();
const restraintsField = Array.from(gradioApp().querySelectorAll(`#${currentTab}_script_restraints_json textarea`))
.filter(el => uiElementIsVisible(el.closest('.gr-form')))?.[0];
if ( ! restraintsField ) {
return;
}
if ( typeof prev_ui_states[currentTab] === 'undefined' ) {
prev_ui_states[currentTab] = {};
}
window.requestAnimationFrame(() => {
const restraints = JSON.parse(restraintsField.value);
// const scriptSelect = gradioApp().querySelector(`#${currentTab}_scripts select`);
const methodRadios = gradioApp().querySelectorAll(`[name="radio-${currentTab}_sampling"]`);
if( restraints?.methods?.length ) {
prev_ui_states[currentTab].sampling_method = gradioApp().querySelector(`[name="radio-${currentTab}_sampling"]:checked`);
methodRadios.forEach(radio => {
const isAllowed = restraints.methods.includes(radio.value);
const label = radio.closest('label');
radio.disabled = !isAllowed;
radio.checked = isAllowed;
label.classList[isAllowed ? 'remove' : 'add']('!cursor-not-allowed','disabled');
label.title = !isAllowed ? `The selected script does not work with this method` : '';
});
} else {
// reset to previously selected method
methodRadios.forEach(radio => {
const label = radio.closest('label');
radio.disabled = false;
radio.checked = radio === prev_ui_states[currentTab].sampling_method;
label.classList.remove('!cursor-not-allowed','disabled');
label.title = '';
});
}
})
}

View File

@ -1,6 +1,7 @@
import os
import sys
import traceback
import json
import modules.ui as ui
import gradio as gr
@ -24,6 +25,14 @@ class Script:
def ui(self, is_img2img):
pass
# Put restraints on UI elements when this script is selected.
# Restricting the available sampling methods:
# {
# "methods": [ "Euler", "DDIM" ]
# }
def ui_restraints(self):
return {}
# Determines when the script should be shown in the dropdown menu via the
# returned value. As an example:
# is_img2img is True if the current tab is img2img, and False if it is txt2img.
@ -46,8 +55,7 @@ class Script:
# your description as the value.
def describe(self):
return ""
scripts_data = []
@ -106,7 +114,9 @@ class ScriptRunner:
titles = [wrap_call(script.title, script.filename, "title") or f"{script.filename} [error]" for script in self.scripts]
dropdown = gr.Dropdown(label="Script", choices=["None"] + titles, value="None", type="index")
id_prefix = "img2img_" if is_img2img else "txt2img_"
dropdown = gr.Dropdown(label="Script", choices=["None"] + titles, value="None", type="index", elem_id=id_prefix+"scripts")
inputs = [dropdown]
for script in self.scripts:
@ -121,20 +131,27 @@ class ScriptRunner:
for control in controls:
control.custom_script_source = os.path.basename(script.filename)
control.visible = False
inputs += controls
script.args_to = len(inputs)
script_restraints_json = gr.Textbox(value="{}", elem_id=id_prefix+"script_restraints_json", show_label=False, visible=False)
inputs += [script_restraints_json];
def select_script(script_index):
if 0 < script_index <= len(self.scripts):
script = self.scripts[script_index-1]
args_from = script.args_from
args_to = script.args_to
else:
script = None
args_from = 0
args_to = 0
return [ui.gr_show(True if i == 0 else args_from <= i < args_to) for i in range(len(inputs))]
return (
[ui.gr_show(True if i == 0 else args_from <= i < args_to) for i in range(len(inputs)-1)]
+ [gr.Textbox.update(value=json.dumps(script.ui_restraints() if script is not None else {}), visible=False)]
)
dropdown.change(
fn=select_script,
@ -142,6 +159,13 @@ class ScriptRunner:
outputs=inputs
)
script_restraints_json.change(
_js="updateScriptRestraints",
fn=lambda: None,
inputs=[],
outputs=[]
)
return inputs
def run(self, p: StableDiffusionProcessing, *args):

View File

@ -410,7 +410,7 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo, run_modelmerger):
with gr.Row().style(equal_height=False):
with gr.Column(variant='panel'):
steps = gr.Slider(minimum=1, maximum=150, step=1, label="Sampling Steps", value=20)
steps = gr.Slider(minimum=1, maximum=150, step=1, label="Sampling Steps", value=20, elem_id="txt2img_steps")
sampler_index = gr.Radio(label='Sampling method', elem_id="txt2img_sampling", choices=[x.name for x in samplers], value=samplers[0].name, type="index")
with gr.Group():
@ -589,8 +589,8 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo, run_modelmerger):
with gr.Row():
resize_mode = gr.Radio(label="Resize mode", elem_id="resize_mode", show_label=False, choices=["Just resize", "Crop and resize", "Resize and fill"], type="index", value="Just resize")
steps = gr.Slider(minimum=1, maximum=150, step=1, label="Sampling Steps", value=20)
sampler_index = gr.Radio(label='Sampling method', choices=[x.name for x in samplers_for_img2img], value=samplers_for_img2img[0].name, type="index")
steps = gr.Slider(minimum=1, maximum=150, step=1, label="Sampling Steps", value=20, elem_id="img2img_steps")
sampler_index = gr.Radio(label='Sampling method', elem_id="img2img_sampling", choices=[x.name for x in samplers_for_img2img], value=samplers_for_img2img[0].name, type="index")
with gr.Group():
width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=512)

View File

@ -119,7 +119,7 @@ class Script(scripts.Script):
def show(self, is_img2img):
return is_img2img
def ui(self, is_img2img):
original_prompt = gr.Textbox(label="Original prompt", lines=1)
original_negative_prompt = gr.Textbox(label="Original negative prompt", lines=1)
@ -129,6 +129,12 @@ class Script(scripts.Script):
sigma_adjustment = gr.Checkbox(label="Sigma adjustment for finding noise for image", value=False)
return [original_prompt, original_negative_prompt, cfg, st, randomness, sigma_adjustment]
def ui_restraints(self):
restraints = {
"methods": ["Euler"]
}
return restraints
def run(self, p, original_prompt, original_negative_prompt, cfg, st, randomness, sigma_adjustment):
p.batch_size = 1
p.batch_count = 1

View File

@ -222,6 +222,10 @@ input[type="range"]{
margin: 0.5em 0 -0.3em 0;
}
.gr-input-label.disabled {
opacity: 0.48;
}
#txt2img_sampling label{
padding-left: 0.6em;
padding-right: 0.6em;