import os import re import json import math from modules.util import get_files_from_folder # cannot use modules.config - validators causing circular imports styles_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../sdxl_styles/')) wildcards_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../wildcards/')) wildcards_max_bfs_depth = 64 def normalize_key(k): k = k.replace('-', ' ') words = k.split(' ') words = [w[:1].upper() + w[1:].lower() for w in words] k = ' '.join(words) k = k.replace('3d', '3D') k = k.replace('Sai', 'SAI') k = k.replace('Mre', 'MRE') k = k.replace('(s', '(S') return k styles = {} styles_files = get_files_from_folder(styles_path, ['.json']) for x in ['sdxl_styles_fooocus.json', 'sdxl_styles_sai.json', 'sdxl_styles_mre.json', 'sdxl_styles_twri.json', 'sdxl_styles_diva.json', 'sdxl_styles_marc_k3nt3l.json']: if x in styles_files: styles_files.remove(x) styles_files.append(x) for styles_file in styles_files: try: with open(os.path.join(styles_path, styles_file), encoding='utf-8') as f: for entry in json.load(f): name = normalize_key(entry['name']) prompt = entry['prompt'] if 'prompt' in entry else '' negative_prompt = entry['negative_prompt'] if 'negative_prompt' in entry else '' styles[name] = (prompt, negative_prompt) except Exception as e: print(str(e)) print(f'Failed to load style file {styles_file}') style_keys = list(styles.keys()) fooocus_expansion = "Fooocus V2" legal_style_names = [fooocus_expansion] + style_keys def apply_style(style, positive): p, n = styles[style] return p.replace('{prompt}', positive).splitlines(), n.splitlines() def apply_wildcards(wildcard_text, rng, directory=wildcards_path): for _ in range(wildcards_max_bfs_depth): placeholders = re.findall(r'__([\w-]+)__', wildcard_text) if len(placeholders) == 0: return wildcard_text print(f'[Wildcards] processing: {wildcard_text}') for placeholder in placeholders: try: words = open(os.path.join(directory, f'{placeholder}.txt'), encoding='utf-8').read().splitlines() words = [x for x in words if x != ''] assert len(words) > 0 wildcard_text = wildcard_text.replace(f'__{placeholder}__', rng.choice(words), 1) except: print(f'[Wildcards] Warning: {placeholder}.txt missing or empty. ' f'Using "{placeholder}" as a normal word.') wildcard_text = wildcard_text.replace(f'__{placeholder}__', placeholder) print(f'[Wildcards] {wildcard_text}') print(f'[Wildcards] BFS stack overflow. Current text: {wildcard_text}') return wildcard_text def get_words(arrays, totalMult, index): if(len(arrays) == 1): return [arrays[0].split(',')[index]] else: words = arrays[0].split(',') word = words[index % len(words)] index -= index % len(words) index /= len(words) index = math.floor(index) return [word] + get_words(arrays[1:], math.floor(totalMult/len(words)), index) def apply_arrays(text, index): arrays = re.findall(r'\[\[(.*?)\]\]', text) if len(arrays) == 0: return text print(f'[Arrays] processing: {text}') mult = 1 for arr in arrays: words = arr.split(',') mult *= len(words) index %= mult chosen_words = get_words(arrays, mult, index) i = 0 for arr in arrays: text = text.replace(f'[[{arr}]]', chosen_words[i], 1) i = i+1 return text