pull/223/head
ThereforeGames 2023-07-20 08:12:17 -04:00
parent 9cc2a8f282
commit fee4c7a2b2
13 changed files with 337 additions and 198 deletions

View File

@ -33,7 +33,8 @@
"stable_diffusion":
{
"batch_support":true,
"show_extra_generation_params":true
"show_extra_generation_params":true,
"template_editor":true
},
"ui":
{

View File

@ -3,7 +3,18 @@ All notable changes to this project will be documented in this file.
For more details on new features, please check the [Manual](./MANUAL.md).
<details open><summary>9.6.0 - 20 July 2023</summary>
<details open><summary>9.7.0 - 20 July 2023</summary>
### Added
- New shortcode `[round]`: Rounds the first parg to a certain level of precision, e.g. 1.345 at `_place=1` yields 1.3, and 1644 at `_place=2` yields 1600
- `[remember]`: Added Wizard UI
- New WebUI Template Editor tab by o0oradaro0o (PR #146)
- Minor UI updates for the Template Editor after merging
- New config setting `stable_diffusion.template_editor`: you can set to `false` to disable the Template Editor tab
</details>
<details><summary>9.6.0 - 20 July 2023</summary>
### About
This update resolves a number of issues related to `batch_index` evaluation, which were causing degraded image quality with `[zoom_enhance]`.

View File

@ -1125,6 +1125,35 @@ Result: A photo of purple marbles.
</details>
<details><summary>[round {_precision}]</summary>
Allows you to round the first parg to a certain level of precision.
Supports the optional `_place` int kwarg which determines the level of precision. Defaults to 0.
Supports the optional `_up` parg which will round the number up (ceiling function) instead of normal rounding.
Supports the optional `_down` parg which will round the number down (flooring function) instead of normal rounding.
Supports rounding of both integer and float values.
```
Float example...
[round 1.345 _place=1]
```
```
RESULT: 1.3
```
```
Integer example...
[round 1678 _place=1]
```
```
RESULT: 1680
```
</details>
<details><summary>[set {_append} {_prepend}]</summary>
Sets a variable to the given content.

View File

@ -1,47 +0,0 @@
function loadFile(file_name) {
// print the filename to the console
console.log(file_name);
var textarea = gradioApp().querySelector("#save_name > label > textarea")
textarea.value = file_name;
console.log(textarea)
updateInput(textarea)
// wait 200 ms for the event to process then click the load button
setTimeout(clickLoad, 200);
}
function clickLoad() {
var loadFileButton = document.getElementById("load_button_unprompted");
loadFileButton.click();
}
function registerPrompt(tabname, id){
var textarea = gradioApp().querySelector("#" + id + " > label > textarea");
if (! activePromptTextarea[tabname]){
activePromptTextarea[tabname] = textarea
}
textarea.addEventListener("focus", function(){
activePromptTextarea[tabname] = textarea;
});
}
function unpromptedStartup() {
console.log("We are in unprompted startup");
var refreshButton = document.getElementById("refresh_button_unprompted");
refreshButton.click();
setupExtraNetworksForTab('unprompted_edit_space')
registerPrompt('unprompted_edit_space', 'unprompted_edit_space_prompt')
}
addEventListener('click', (event) => {
let target = event.originalTarget || event.composedPath()[0];
// check if the thing we clicked on it s button with the word unprompted in the content
if (! target.matches("button")) return;
if (! target.textContent.includes("Unprompted")) return;
if (! target.textContent.includes("Editor")) return;
loaded_unprompted_template_edit=true;
unpromptedStartup(event);
});

View File

@ -0,0 +1,54 @@
function loadFile(file_name)
{
// print the filename to the console
console.log(file_name);
var textarea = gradioApp().querySelector("#save_name > label > textarea");
textarea.value = file_name;
console.log(textarea);
updateInput(textarea);
// wait 200 ms for the event to process then click the load button
setTimeout(clickLoad, 200);
}
function clickLoad()
{
var loadFileButton = document.getElementById("load_button_unprompted");
loadFileButton.click();
}
function registerPrompt(tabname, id)
{
var textarea = gradioApp().querySelector("#" + id + " > label > textarea");
if (!activePromptTextarea[tabname])
{
activePromptTextarea[tabname] = textarea;
}
textarea.addEventListener("focus", function()
{
activePromptTextarea[tabname] = textarea;
});
}
function unpromptedStartup()
{
console.log("We are in unprompted startup");
var refreshButton = document.getElementById("refresh_button_unprompted");
refreshButton.click();
setupExtraNetworksForTab('unprompted_edit_space');
registerPrompt('unprompted_edit_space', 'unprompted_edit_space_prompt');
}
addEventListener('click', (event) =>
{
let target = event.originalTarget || event.composedPath()[0];
// check if the thing we clicked on it s button with the word unprompted in the content
if (!target.matches("button")) return;
if (!target.textContent.includes("Unprompted")) return;
if (!target.textContent.includes("Editor")) return;
loaded_unprompted_template_edit = true;
unpromptedStartup(event);
});

View File

@ -13,7 +13,7 @@ import time
class Unprompted:
def __init__(self, base_dir="."):
start_time = time.time()
self.VERSION = "9.6.0"
self.VERSION = "9.7.0"
self.log(f"Loading Unprompted v{self.VERSION} by Therefore Games", False, "SETUP")
self.log("Initializing Unprompted object...", False, "SETUP")

View File

@ -1,115 +0,0 @@
import os.path
from pathlib import Path
import pathlib
import os
import re
import glob
from modules import extra_networks
from modules.ui_components import FormRow, FormColumn, FormGroup, ToolButton, FormHTML
import modules.scripts as scripts
import gradio as gr
from modules.ui_components import ToolButton
from modules.processing import Processed, process_images
from modules.shared import opts
from modules import script_callbacks, sd_models, shared
refresh_symbol = '\U0001f504' # 🔄
folder_symbol_unprompted = '\U0001f5c1' # 🗁
save_style_symbol_unprompted = '\U0001f5ab' # 🖫
extra_networks_symbol = '\U0001F3B4' # 🎴
from lib_unprompted.shared import Unprompted
base_dir = scripts.basedir()
Unprompted = Unprompted(base_dir)
folder = f"{base_dir}/{Unprompted.Config.template_directory}"
def get_file_list(folder):
return [f for f in os.listdir(folder) if f.endswith('.txt')]
def generate_file_list_html(file_list):
html_content = "<div style='height: 300px; overflow-y: scroll;'><ul>"
for file in file_list:
# print(f"file: {file}")
html_content += f"<li><button style='background-color:FFFFFF00;' onMouseOver=\"this.style.backgroundColor='#8888AA99'\" onMouseOut=\"this.style.backgroundColor='#FFFFFF00'\" onclick='loadFile(\"{file}\")'>{file}</button></li>"
html_content += "</ul></div>"
return html_content
def on_ui_tabs():
def refresh_file_list():
# print(f"REFRESHING LIST: {folder}")
file_list = get_file_list(f"{folder}")
file_list_html = generate_file_list_html(file_list)
html_update = None
html_update = gr.HTML.update(file_list_html)
return html_update
def load_file(file_name):
# print(f"loading: {file_name}")
with open(f"{folder}/{file_name}", "r") as file:
content = file.read()
# print(f"content: {content}")
# update main_edit_space woth content
return content
def save_file(file_name, content):
# print(f"loading: {file_name}")
with open(f"{folder}/{file_name}", "w") as file:
file.write(content)
with gr.Blocks() as unprompted_editor_ui:
with gr.Row(elem_id=f"unprompted_toprow"):
with gr.Column(scale=1, min_width=200):
# Add HTML element for file list
templates = gr.HTML(value="", elem_id="file_list", css=".myButtons:hover {background-color: #4CAF50;color: white;}")
with gr.Row():
refresh_button_unprompted = ToolButton(value=refresh_symbol, elem_id=f"refresh_button_unprompted")
load_button_unprompted = ToolButton(value=folder_symbol_unprompted, elem_id=f"load_button_unprompted")
save_button_unprompted = ToolButton(value=save_style_symbol_unprompted, elem_id=f"save_button_unprompted")
with gr.Row():
# Add save name text box
save_name = gr.Textbox(value="", label="Save Name", elem_id="save_name")
with gr.Column(scale=4, min_width=900):
main_edit_space = gr.Textbox(value="", label="Main Editor", interactive=True, lines=20, elem_id="unprompted_edit_space_prompt")
extra_networks_button = ToolButton(value=extra_networks_symbol, elem_id=f"unprompted_edit_space_extra_networks_button")
with FormRow( elem_id="unprompted_edit_space_extra_networks", visible=False) as extra_networks:
from modules import ui_extra_networks
extra_networks_ui_unprompted_edit_space = ui_extra_networks.create_ui(extra_networks, extra_networks_button, 'unprompted_edit_space')
extra_networks_ui_unprompted_gallery = gr.Textbox(visible=False)
ui_extra_networks.setup_ui(extra_networks_ui_unprompted_edit_space, extra_networks_ui_unprompted_gallery)
refresh_button_unprompted.click(
fn=refresh_file_list,
inputs=[
],
outputs=[
templates,
]
)
load_button_unprompted.click(
fn=load_file,
inputs=[
save_name,
],
outputs=[
main_edit_space,
]
)
save_button_unprompted.click(
fn=save_file,
inputs=[
save_name,
main_edit_space,
],
outputs=[
]
)
return (unprompted_editor_ui, "Unprompted Template Editor", "unprompted_editor_ui"),
script_callbacks.on_ui_tabs(on_ui_tabs)

View File

@ -0,0 +1,103 @@
from lib_unprompted.shared import Unprompted
import modules.scripts as scripts
base_dir = scripts.basedir()
Unprompted = Unprompted(base_dir)
if Unprompted.Config.stable_diffusion.template_editor:
import os.path
from pathlib import Path
import pathlib
import os
import re
import glob
from modules import extra_networks
from modules.ui_components import FormRow, FormColumn, FormGroup, ToolButton, FormHTML
import gradio as gr
from modules.ui_components import ToolButton
from modules.processing import Processed, process_images
from modules.shared import opts
from modules import script_callbacks, sd_models, shared
refresh_symbol = '\U0001f504' # 🔄
folder_symbol_unprompted = '\U0001f5c1' # 🗁
save_style_symbol_unprompted = '\U0001f5ab' # 🖫
extra_networks_symbol = '\U0001F3B4' # 🎴
folder = f"{base_dir}/{Unprompted.Config.template_directory}"
def get_file_list(folder):
return [os.path.relpath(os.path.join(dirpath, file), folder).replace("\\", "/") for (dirpath, dirnames, filenames) in os.walk(folder) for file in filenames if file.endswith(".txt")]
def generate_file_list_html(file_list):
html_content = "<div style='height: 300px; overflow-y: scroll;'><ul>"
for file in file_list:
html_content += f"<li><button style='background-color:FFFFFF00;' onMouseOver=\"this.style.backgroundColor='#8888AA99'\" onMouseOut=\"this.style.backgroundColor='#FFFFFF00'\" onclick='loadFile(\"{file}\")'>{file}</button></li>"
html_content += "</ul></div>"
return html_content
def on_ui_tabs():
def refresh_file_list():
# print(f"REFRESHING LIST: {folder}")
file_list = get_file_list(f"{folder}")
file_list_html = generate_file_list_html(file_list)
html_update = None
html_update = gr.HTML.update(file_list_html)
return html_update
def load_file(file_name):
# print(f"loading: {file_name}")
with open(f"{folder}/{file_name}", "r") as file:
content = file.read()
# print(f"content: {content}")
# update main_edit_space woth content
return content
def save_file(file_name, content):
# print(f"loading: {file_name}")
with open(f"{folder}/{file_name}", "w") as file:
file.write(content)
with gr.Blocks() as unprompted_editor_ui:
with gr.Row(elem_id=f"unprompted_toprow"):
with gr.Column(scale=1, min_width=200):
# Add HTML element for file list
templates = gr.HTML(value="", elem_id="file_list", css=".myButtons:hover {background-color: #4CAF50;color: white;}")
with gr.Row():
refresh_button_unprompted = ToolButton(value=refresh_symbol, elem_id=f"refresh_button_unprompted")
load_button_unprompted = ToolButton(value=folder_symbol_unprompted, elem_id=f"load_button_unprompted")
save_button_unprompted = ToolButton(value=save_style_symbol_unprompted, elem_id=f"save_button_unprompted")
with gr.Row():
# Add save name text box
save_name = gr.Textbox(value="", label="Save Name", elem_id="save_name")
with gr.Column(scale=4, min_width=900):
main_edit_space = gr.Textbox(value="", label="Text Editor", interactive=True, lines=20, elem_id="unprompted_edit_space_prompt")
extra_networks_button = ToolButton(value=extra_networks_symbol, elem_id=f"unprompted_edit_space_extra_networks_button")
with FormRow(elem_id="unprompted_edit_space_extra_networks", visible=False) as extra_networks:
from modules import ui_extra_networks
extra_networks_ui_unprompted_edit_space = ui_extra_networks.create_ui(extra_networks, extra_networks_button, 'unprompted_edit_space')
extra_networks_ui_unprompted_gallery = gr.Textbox(visible=False)
ui_extra_networks.setup_ui(extra_networks_ui_unprompted_edit_space, extra_networks_ui_unprompted_gallery)
refresh_button_unprompted.click(fn=refresh_file_list, inputs=[], outputs=[
templates,
])
load_button_unprompted.click(fn=load_file, inputs=[
save_name,
], outputs=[
main_edit_space,
])
save_button_unprompted.click(fn=save_file, inputs=[
save_name,
main_edit_space,
], outputs=[])
return (unprompted_editor_ui, "Unprompted Template Editor", "unprompted_editor_ui"),
script_callbacks.on_ui_tabs(on_ui_tabs)
else:
Unprompted.log("Template Editor disabled per Unprompted.Config.stable_diffusion.template_editor")

View File

@ -1,21 +1,23 @@
import random
class Shortcode():
def __init__(self,Unprompted):
def __init__(self, Unprompted):
self.Unprompted = Unprompted
self.description = "Returns a random number between 0 and a given max value (inclusive)"
def run_atomic(self, pargs, kwargs, context):
_min = 0
if ("_min" in kwargs):
_min = self.Unprompted.parse_advanced(kwargs["_min"],context)
_max = self.Unprompted.parse_advanced(kwargs["_max"],context)
_min = self.Unprompted.parse_advanced(kwargs["_min"], context)
_max = self.Unprompted.parse_advanced(kwargs["_max"], context)
else:
_max = pargs[0]
if ("_float" in pargs): return(random.uniform(float(_min),float(_max)))
else: return(random.randint(int(_min), int(_max)))
if ("_float" in pargs): return (random.uniform(float(_min), float(_max)))
else: return (random.randint(int(_min), int(_max)))
def ui(self,gr):
gr.Number(label="Minimum number 🡢 _min",value=0,interactive=True)
gr.Number(label="Maximum number 🡢 _max",value=10,interactive=True)
def ui(self, gr):
gr.Number(label="Minimum number 🡢 _min", value=0, interactive=True)
gr.Number(label="Maximum number 🡢 _max", value=10, interactive=True)
gr.Checkbox(label="Evaluate as floats instead of integers 🡢 _float")

34
shortcodes/basic/round.py Normal file
View File

@ -0,0 +1,34 @@
class Shortcode():
def __init__(self, Unprompted):
self.Unprompted = Unprompted
self.description = "Rounds a given number to a certain level of precision. Works with integers and floats."
def run_atomic(self, pargs, kwargs, context):
import math
if not len(pargs):
self.Unprompted.log("No number found at pargs[0]", context="ERROR")
return ""
place = int(float(self.Unprompted.parse_advanced(kwargs["_place"]))) if "_place" in kwargs else 0
num = self.Unprompted.parse_advanced(pargs[0], context)
if "_up" in pargs: round_func = math.ceil
elif "_down" in pargs: round_func = math.floor
else: round_func = round
self.Unprompted.log(f"Rounding the following number: {num}")
if "." in str(num):
if (round_func == round): return round_func(num, place)
else: return round_func(num)
elif self.Unprompted.is_int(num):
multiplier = pow(10, place)
num = int(round_func(num / multiplier)) * multiplier
return num
else:
self.Unprompted.log_error("The number is not a valid type: ", num)
return ""
def ui(self, gr):
gr.Textbox(label="Round this number 🡢 str", max_lines=1, placeholder="1.345")
gr.Number(label="Digit precision 🡢 _place", value=0, interactive=True)

View File

@ -1,14 +0,0 @@
class Shortcode():
def __init__(self,Unprompted):
self.Unprompted = Unprompted
self.description = "changes the filename of the image."
def run_atomic(self, pargs, kwargs, context):
from modules.shared import opts, cmd_opts
opts.samples_filename_pattern = self.Unprompted.parse_advanced(pargs[0],context)
# #remove the original images from the output
return("")
def ui(self,gr):
pass

View File

@ -10,4 +10,7 @@ class Shortcode():
self.globals.append(parg)
def cleanup(self):
self.globals = []
self.globals = []
def ui(self, gr):
gr.Textbox(label="Arbitrary variable names to remember 🡢 verbatim", max_lines=1, placeholder="var_a var_b var_c")

View File

@ -1,10 +1,88 @@
details summary {font-size:20px;font-weight:bold;cursor:pointer;}
details > *:not(summary) {padding:0 20px !important;}
details[open] {padding-bottom:20px;}
.prose li {text-indent: -20px;padding-left: 2em;}
.gradio-container .prose a, .gradio-container .prose a:visited {text-decoration: underline;}
#unprompted_result {font-size:18px;padding:10px;font-family:IBM Plex Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;}
#unprompted_result strong {font-family:Source Sans Pro,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";display:block;margin-bottom:10px;letter-spacing:0.02em;font-size:20px;}
#promo {display:block;}
.wizard-autoinclude span {font-weight:1000;}
.patreon-symbol {letter-spacing:-7px;margin-right:7px;}
details summary
{
font-size: 20px;
font-weight: bold;
cursor: pointer;
}
details>*:not(summary)
{
padding: 0 20px !important;
}
details[open]
{
padding-bottom: 20px;
}
.prose li
{
text-indent: -20px;
padding-left: 2em;
}
.gradio-container .prose a,
.gradio-container .prose a:visited
{
text-decoration: underline;
}
#unprompted_result
{
font-size: 18px;
padding: 10px;
font-family: IBM Plex Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
}
#unprompted_result strong
{
font-family: Source Sans Pro, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", Segoe UI Symbol, "Noto Color Emoji";
display: block;
margin-bottom: 10px;
letter-spacing: 0.02em;
font-size: 20px;
}
#promo
{
display: block;
}
.wizard-autoinclude span
{
font-weight: 1000;
}
.patreon-symbol
{
letter-spacing: -7px;
margin-right: 7px;
}
#file_list li
{
padding-left: 0;
word-wrap: break-word;
}
#file_list ul
{
list-style-type: none;
overflow-x: hidden;
}
#file_list button:before
{
content: "\01F5CE";
position: absolute;
left: 0;
}
#file_list button
{
display: block;
text-align: left;
width: 100%;
padding-left: 15px;
position: relative;
}