scripts.py 3.7 KB
Newer Older
1 2 3 4
import os
import sys
import traceback

A
AUTOMATIC 已提交
5
import modules.ui as ui
6 7
import gradio as gr

A
AUTOMATIC 已提交
8 9
from modules.processing import StableDiffusionProcessing

10 11
class Script:
    filename = None
A
AUTOMATIC 已提交
12 13
    args_from = None
    args_to = None
14 15 16 17

    def title(self):
        raise NotImplementedError()

A
AUTOMATIC 已提交
18 19 20
    def ui(self, is_img2img):
        pass

A
AUTOMATIC 已提交
21 22 23
    def show(self, is_img2img):
        return True

A
AUTOMATIC 已提交
24 25 26 27 28 29
    def run(self, *args):
        raise NotImplementedError()

    def describe(self):
        return ""

30

A
AUTOMATIC 已提交
31
scripts_data = []
32 33


A
AUTOMATIC 已提交
34
def load_scripts(basedir):
35 36 37
    if not os.path.exists(basedir):
        return

38 39 40 41 42 43 44 45 46
    for filename in os.listdir(basedir):
        path = os.path.join(basedir, filename)

        if not os.path.isfile(path):
            continue

        with open(path, "r", encoding="utf8") as file:
            text = file.read()

47 48 49 50 51 52 53 54
        try:
            from types import ModuleType
            compiled = compile(text, path, 'exec')
            module = ModuleType(filename)
            exec(compiled, module.__dict__)

            for key, script_class in module.__dict__.items():
                if type(script_class) == type and issubclass(script_class, Script):
A
AUTOMATIC 已提交
55
                    scripts_data.append((script_class, path))
56 57 58 59

        except Exception:
            print(f"Error loading script: {filename}", file=sys.stderr)
            print(traceback.format_exc(), file=sys.stderr)
60 61 62 63


def wrap_call(func, filename, funcname, *args, default=None, **kwargs):
    try:
A
AUTOMATIC 已提交
64
        res = func(*args, **kwargs)
65 66
        return res
    except Exception:
A
AUTOMATIC 已提交
67
        print(f"Error calling: {filename}/{funcname}", file=sys.stderr)
68 69 70 71 72
        print(traceback.format_exc(), file=sys.stderr)

    return default


A
AUTOMATIC 已提交
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
class ScriptRunner:
    def __init__(self):
        self.scripts = []

    def setup_ui(self, is_img2img):
        for script_class, path in scripts_data:
            script = script_class()
            script.filename = path

            if not script.show(is_img2img):
                continue

            self.scripts.append(script)

        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")
        inputs = [dropdown]

        for script in self.scripts:
            script.args_from = len(inputs)

            controls = wrap_call(script.ui, script.filename, "ui", is_img2img)

            if controls is None:
                continue
A
AUTOMATIC 已提交
99

A
AUTOMATIC 已提交
100 101
            for control in controls:
                control.visible = False
A
AUTOMATIC 已提交
102

A
AUTOMATIC 已提交
103 104
            inputs += controls
            script.args_to = len(inputs)
A
AUTOMATIC 已提交
105

A
AUTOMATIC 已提交
106 107 108 109 110 111 112 113
        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:
                args_from = 0
                args_to = 0
A
AUTOMATIC 已提交
114

A
AUTOMATIC 已提交
115
            return [ui.gr_show(True if i == 0 else args_from <= i < args_to) for i in range(len(inputs))]
A
AUTOMATIC 已提交
116

A
AUTOMATIC 已提交
117 118 119 120 121
        dropdown.change(
            fn=select_script,
            inputs=[dropdown],
            outputs=inputs
        )
A
AUTOMATIC 已提交
122

A
AUTOMATIC 已提交
123
        return inputs
A
AUTOMATIC 已提交
124 125


A
AUTOMATIC 已提交
126 127
    def run(self, p: StableDiffusionProcessing, *args):
        script_index = args[0]
A
AUTOMATIC 已提交
128

A
AUTOMATIC 已提交
129 130
        if script_index == 0:
            return None
A
AUTOMATIC 已提交
131

A
AUTOMATIC 已提交
132
        script = self.scripts[script_index-1]
A
AUTOMATIC 已提交
133

A
AUTOMATIC 已提交
134 135
        if script is None:
            return None
A
AUTOMATIC 已提交
136

A
AUTOMATIC 已提交
137 138
        script_args = args[script.args_from:script.args_to]
        processed = script.run(p, *script_args)
A
AUTOMATIC 已提交
139

A
AUTOMATIC 已提交
140
        return processed
A
AUTOMATIC 已提交
141 142


A
AUTOMATIC 已提交
143 144
scripts_txt2img = ScriptRunner()
scripts_img2img = ScriptRunner()