From df82d4ec079585137b3c040024f9d68d1da43cd3 Mon Sep 17 00:00:00 2001 From: Aodhan Collins Date: Sun, 8 Feb 2026 01:54:18 +0000 Subject: [PATCH] Initial implementation of Character Browser & Generator: Gallery, ComfyUI integration, progress tracking, and batch processing. --- .gitignore | 33 ++ README.md | 67 +++ app.py | 544 +++++++++++++++++++++++ characters/aerith_gainsborough.json | 38 ++ characters/android_18.json | 39 ++ characters/anya_forger.json | 39 ++ characters/biwa_hayahide.json | 39 ++ characters/bulma.json | 39 ++ characters/camilla.json | 39 ++ characters/cammy.json | 39 ++ characters/chun_li.json | 39 ++ characters/ciri.json | 39 ++ characters/delinquent_mother_flim13.json | 39 ++ characters/gold_city.json | 39 ++ characters/gold_ship.json | 39 ++ characters/hatsune_miku.json | 39 ++ characters/jessica_rabbit.json | 39 ++ characters/jessie.json | 39 ++ characters/jinx.json | 39 ++ characters/kagamine_rin.json | 39 ++ characters/kagari_atsuko.json | 39 ++ characters/kda_all_out_ahri.json | 39 ++ characters/kda_all_out_akali.json | 39 ++ characters/kda_all_out_evelynn.json | 39 ++ characters/kda_all_out_kaisa.json | 39 ++ characters/komi_shouko.json | 39 ++ characters/lara_croft_classic.json | 39 ++ characters/lisa_minci.json | 39 ++ characters/lulu.json | 39 ++ characters/majin_android_21.json | 39 ++ characters/marin_kitagawa.json | 39 ++ characters/megurine_luka.json | 39 ++ characters/meiko.json | 39 ++ characters/nessa.json | 39 ++ characters/olivier_mira_armstrong.json | 39 ++ characters/princess_peach.json | 39 ++ characters/princess_zelda_botw.json | 39 ++ characters/rice_shower.json | 39 ++ characters/riju.json | 39 ++ characters/rosalina.json | 39 ++ characters/rouge_the_bat.json | 39 ++ characters/ryouko_hakubi.json | 39 ++ characters/samus_aran_zero_suit.json | 39 ++ characters/sarah_miller.json | 39 ++ characters/shantae.json | 39 ++ characters/sucy_manbavaran.json | 39 ++ characters/tifa_lockhart.json | 39 ++ characters/tracer.json | 39 ++ characters/urbosa.json | 39 ++ characters/widowmaker.json | 39 ++ characters/yor_briar.json | 39 ++ characters/yshtola_rhul.json | 39 ++ characters/yuffie_kisaragi.json | 39 ++ characters/yuna_ffx.json | 39 ++ comfy_workflow.json | 173 +++++++ launch.sh | 32 ++ models.py | 15 + requirements.txt | 4 + templates/detail.html | 288 ++++++++++++ templates/generator.html | 70 +++ templates/index.html | 178 ++++++++ templates/layout.html | 41 ++ 62 files changed, 3433 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 app.py create mode 100644 characters/aerith_gainsborough.json create mode 100644 characters/android_18.json create mode 100644 characters/anya_forger.json create mode 100644 characters/biwa_hayahide.json create mode 100644 characters/bulma.json create mode 100644 characters/camilla.json create mode 100644 characters/cammy.json create mode 100644 characters/chun_li.json create mode 100644 characters/ciri.json create mode 100644 characters/delinquent_mother_flim13.json create mode 100644 characters/gold_city.json create mode 100644 characters/gold_ship.json create mode 100644 characters/hatsune_miku.json create mode 100644 characters/jessica_rabbit.json create mode 100644 characters/jessie.json create mode 100644 characters/jinx.json create mode 100644 characters/kagamine_rin.json create mode 100644 characters/kagari_atsuko.json create mode 100644 characters/kda_all_out_ahri.json create mode 100644 characters/kda_all_out_akali.json create mode 100644 characters/kda_all_out_evelynn.json create mode 100644 characters/kda_all_out_kaisa.json create mode 100644 characters/komi_shouko.json create mode 100644 characters/lara_croft_classic.json create mode 100644 characters/lisa_minci.json create mode 100644 characters/lulu.json create mode 100644 characters/majin_android_21.json create mode 100644 characters/marin_kitagawa.json create mode 100644 characters/megurine_luka.json create mode 100644 characters/meiko.json create mode 100644 characters/nessa.json create mode 100644 characters/olivier_mira_armstrong.json create mode 100644 characters/princess_peach.json create mode 100644 characters/princess_zelda_botw.json create mode 100644 characters/rice_shower.json create mode 100644 characters/riju.json create mode 100644 characters/rosalina.json create mode 100644 characters/rouge_the_bat.json create mode 100644 characters/ryouko_hakubi.json create mode 100644 characters/samus_aran_zero_suit.json create mode 100644 characters/sarah_miller.json create mode 100644 characters/shantae.json create mode 100644 characters/sucy_manbavaran.json create mode 100644 characters/tifa_lockhart.json create mode 100644 characters/tracer.json create mode 100644 characters/urbosa.json create mode 100644 characters/widowmaker.json create mode 100644 characters/yor_briar.json create mode 100644 characters/yshtola_rhul.json create mode 100644 characters/yuffie_kisaragi.json create mode 100644 characters/yuna_ffx.json create mode 100644 comfy_workflow.json create mode 100644 launch.sh create mode 100644 models.py create mode 100644 requirements.txt create mode 100644 templates/detail.html create mode 100644 templates/generator.html create mode 100644 templates/index.html create mode 100644 templates/layout.html diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d24b89c --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +# Python +__pycache__/ +*.pyc +*.pyo +*.pyd +.Python +env/ +venv/ +pip-log.txt +pip-delete-this-directory.txt +.venv/ +.env +.flaskenv + +# SQLite Database +database.db + +# Uploads / Generated Images +static/uploads/* +!static/uploads/.gitkeep + +# IDEs / Editors +.vscode/ +.idea/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log diff --git a/README.md b/README.md new file mode 100644 index 0000000..c69b527 --- /dev/null +++ b/README.md @@ -0,0 +1,67 @@ +# Character Browser & Generator + +A local web-based GUI for managing character profiles (JSON) and generating consistent images using ComfyUI. + +## Features + +- **Character Gallery**: Automatically scans your `characters/` folder and builds a searchable, sortable database. +- **Granular Prompt Control**: Every field in your character JSON (Identity, Wardrobe, Styles) has a checkbox. You decide exactly what is sent to the AI. +- **ComfyUI Integration**: + - **SDXL Optimized**: Designed for high-quality SDXL workflows. + - **Localized ADetailer**: Automated Face and Hand detailing with focused prompts (e.g., only eye color and expression are sent to the face detailer). + - **LoRA Support**: Automatically detects and applies LoRAs specified in your character sheets. + - **Real-time Progress**: Live progress bars and queue status via WebSockets (with a reliable polling fallback). +- **Batch Processing**: + - **Fill Missing**: Generate covers for every character missing one with a single click. + - **Refresh All**: Unassign all current covers and generate a fresh set for the whole collection. +- **Advanced Generator**: A dedicated page to mix-and-match characters with different checkpoints (Illustrious/Noob support) and custom prompt additions. +- **Smart URLs**: Sanitized, human-readable URLs (slugs) that handle special characters and slashes gracefully. + +## Prerequisites + +1. **Python 3.10+** +2. **ComfyUI** running locally (default: `http://127.0.0.1:8188`). +3. **ComfyUI Custom Nodes**: + - [ComfyUI-Impact-Pack](https://github.com/ltdrdata/ComfyUI-Impact-Pack) (Required for FaceDetailer). +4. **Models**: + - Ensure your Checkpoints are in the folders defined in `app.py`. + - Face detection model: `bbox/face_yolov9c.pt` (or update `comfy_workflow.json`). + - Hand detection model: `bbox/hand_yolov8s.pt`. + +## Setup & Installation + +1. **Clone the repository** to your local machine. +2. **Configure Paths**: Open `app.py` and update the following variables to match your system: + ```python + app.config['COMFYUI_URL'] = 'http://127.0.0.1:8188' + app.config['ILLUSTRIOUS_MODELS_DIR'] = '/path/to/your/Illustrious/models' + app.config['NOOB_MODELS_DIR'] = '/path/to/your/Noob/models' + ``` +3. **Launch**: Simply run the launch script. It will handle the virtual environment and dependencies automatically. + ```bash + chmod +x launch.sh + ./launch.sh + ``` + +## Usage + +### Gallery Management +- **Rescan**: Use the "Rescan Character Files" button if you've added new JSON files or manually edited them. +- **Save Defaults**: On a character page, select your favorite prompt combination and click "Save as Default Selection" to remember it for future quick generations. + +### Generation +- **Preview**: Generates an image and shows it to you without replacing your current cover. +- **Replace**: Generates an image and sets it as the character's official gallery cover. +- **Clean Start**: If you want to wipe the database and all generated images to start fresh: + ```bash + ./launch.sh --clean + ``` + +## File Structure + +- `/characters`: Your character JSON files. +- `/static/uploads`: Generated images (organized by character subfolders). +- `/templates`: HTML UI using Bootstrap 5. +- `app.py`: Flask backend and prompt-building logic. +- `comfy_workflow.json`: The API-format workflow used for generations. +- `models.py`: SQLite database schema. diff --git a/app.py b/app.py new file mode 100644 index 0000000..bd57da0 --- /dev/null +++ b/app.py @@ -0,0 +1,544 @@ +import os +import json +import time +import re +import requests +import random +from flask import Flask, render_template, request, redirect, url_for, flash, session +from werkzeug.utils import secure_filename +from models import db, Character + +app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +app.config['UPLOAD_FOLDER'] = 'static/uploads' +app.config['SECRET_KEY'] = 'dev-key-123' +app.config['CHARACTERS_DIR'] = 'characters' +app.config['COMFYUI_URL'] = 'http://127.0.0.1:8188' +app.config['ILLUSTRIOUS_MODELS_DIR'] = '/mnt/alexander/AITools/Image Models/Stable-diffusion/Illustrious/' +app.config['NOOB_MODELS_DIR'] = '/mnt/alexander/AITools/Image Models/Stable-diffusion/Noob/' + +db.init_app(app) + +ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'webp'} + +def get_available_checkpoints(): + checkpoints = [] + + # Scan Illustrious + if os.path.exists(app.config['ILLUSTRIOUS_MODELS_DIR']): + for f in os.listdir(app.config['ILLUSTRIOUS_MODELS_DIR']): + if f.endswith('.safetensors') or f.endswith('.ckpt'): + checkpoints.append(f"Illustrious/{f}") + + # Scan Noob + if os.path.exists(app.config['NOOB_MODELS_DIR']): + for f in os.listdir(app.config['NOOB_MODELS_DIR']): + if f.endswith('.safetensors') or f.endswith('.ckpt'): + checkpoints.append(f"Noob/{f}") + + return sorted(checkpoints) + +def allowed_file(filename): + return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS + +def build_prompt(data, selected_fields=None, default_fields=None): + def is_selected(section, key): + # Priority: + # 1. Manual selection from form (if list is not empty) + # 2. Database defaults (if they exist) + # 3. Select all (default behavior) + if selected_fields: + return f"{section}::{key}" in selected_fields + if default_fields: + return f"{section}::{key}" in default_fields + return True + + identity = data.get('identity', {}) + wardrobe = data.get('wardrobe', {}) + + # Pre-calculate Hand/Glove priority + hand_val = "" + if wardrobe.get('gloves') and is_selected('wardrobe', 'gloves'): + hand_val = wardrobe.get('gloves') + elif identity.get('hands') and is_selected('identity', 'hands'): + hand_val = identity.get('hands') + + # 1. Main Prompt + parts = ["(solo:1.2)"] + # Use character_id (underscores to spaces) for tags compatibility + char_tag = data.get('character_id', '').replace('_', ' ') + if char_tag and is_selected('special', 'name'): + parts.append(char_tag) + + for key in ['base_specs', 'hair', 'eyes', 'expression', 'distinguishing_marks']: + val = identity.get(key) + if val and is_selected('identity', key): + parts.append(val) + + # Add hand priority value to main prompt + if hand_val: + parts.append(hand_val) + + for key in ['outer_layer', 'inner_layer', 'lower_body', 'footwear', 'accessories']: + val = wardrobe.get(key) + if val and is_selected('wardrobe', key): + parts.append(val) + + style = data.get('styles', {}).get('aesthetic') + if style and is_selected('styles', 'aesthetic'): + parts.append(f"{style} style") + + tags = data.get('tags', []) + if tags and is_selected('special', 'tags'): + parts.extend(tags) + + lora = data.get('lora', {}) + if lora.get('lora_triggers') and is_selected('lora', 'lora_triggers'): + parts.append(lora.get('lora_triggers')) + + # 2. Face Prompt: Tag, Eyes, Expression + face_parts = [] + if char_tag and is_selected('special', 'name'): face_parts.append(char_tag) + if identity.get('eyes') and is_selected('identity', 'eyes'): face_parts.append(identity.get('eyes')) + if identity.get('expression') and is_selected('identity', 'expression'): face_parts.append(identity.get('expression')) + + # 3. Hand Prompt: Hand value (Gloves or Hands) + hand_parts = [hand_val] if hand_val else [] + + return { + "main": ", ".join(parts), + "face": ", ".join(face_parts), + "hand": ", ".join(hand_parts) + } + +def queue_prompt(prompt_workflow, client_id=None): + p = {"prompt": prompt_workflow} + if client_id: + p["client_id"] = client_id + data = json.dumps(p).encode('utf-8') + response = requests.post(f"{app.config['COMFYUI_URL']}/prompt", data=data) + return response.json() + +def get_history(prompt_id): + response = requests.get(f"{app.config['COMFYUI_URL']}/history/{prompt_id}") + return response.json() + +def get_image(filename, subfolder, folder_type): + data = {"filename": filename, "subfolder": subfolder, "type": folder_type} + response = requests.get(f"{app.config['COMFYUI_URL']}/view", params=data) + return response.content + +from sqlalchemy.orm.attributes import flag_modified + +def sync_characters(): + if not os.path.exists(app.config['CHARACTERS_DIR']): + return + + current_ids = [] + + for filename in os.listdir(app.config['CHARACTERS_DIR']): + if filename.endswith('.json'): + file_path = os.path.join(app.config['CHARACTERS_DIR'], filename) + try: + with open(file_path, 'r') as f: + data = json.load(f) + char_id = data.get('character_id') + if not char_id: + continue + + current_ids.append(char_id) + + # Generate URL-safe slug: remove special characters from character_id + slug = re.sub(r'[^a-zA-Z0-9_]', '', char_id) + + # Check if character already exists + character = Character.query.filter_by(character_id=char_id).first() + name = data.get('character_name', char_id.replace('_', ' ').title()) + + if character: + character.data = data + character.name = name + character.slug = slug + + # Check if cover image still exists + if character.image_path: + full_img_path = os.path.join(app.config['UPLOAD_FOLDER'], character.image_path) + if not os.path.exists(full_img_path): + print(f"Image missing for {character.name}, clearing path.") + character.image_path = None + + # Explicitly tell SQLAlchemy the JSON field was modified + flag_modified(character, "data") + else: + new_char = Character( + character_id=char_id, + slug=slug, + name=name, + data=data + ) + db.session.add(new_char) + except Exception as e: + print(f"Error importing {filename}: {e}") + + # Remove characters that are no longer in the folder + all_characters = Character.query.all() + for char in all_characters: + if char.character_id not in current_ids: + db.session.delete(char) + + db.session.commit() + +@app.route('/') +def index(): + characters = Character.query.order_by(Character.name).all() + return render_template('index.html', characters=characters) + +@app.route('/rescan', methods=['POST']) +def rescan(): + sync_characters() + flash('Database synced with character files.') + return redirect(url_for('index')) + +@app.route('/generator', methods=['GET', 'POST']) +def generator(): + characters = Character.query.order_by(Character.name).all() + checkpoints = get_available_checkpoints() + + if not checkpoints: + checkpoints = ["Noob/oneObsession_v19Atypical.safetensors"] + + if request.method == 'POST': + char_slug = request.form.get('character') + checkpoint = request.form.get('checkpoint') + custom_positive = request.form.get('positive_prompt', '') + custom_negative = request.form.get('negative_prompt', '') + + character = Character.query.filter_by(slug=char_slug).first_or_404() + + try: + with open('comfy_workflow.json', 'r') as f: + workflow = json.load(f) + + # Build base prompts from character defaults + prompts = build_prompt(character.data, default_fields=character.default_fields) + + # Append custom additions to the "main" prompt + if custom_positive: + prompts["main"] = f"{prompts['main']}, {custom_positive}" + + # Prepare workflow with custom checkpoint and negative prompt + workflow = _prepare_workflow(workflow, character, prompts, checkpoint, custom_negative) + + print(f"Queueing generator prompt for {character.character_id}") + prompt_response = queue_prompt(workflow) + + if 'prompt_id' not in prompt_response: + raise Exception(f"ComfyUI failed: {prompt_response.get('error', 'Unknown error')}") + + prompt_id = prompt_response['prompt_id'] + flash("Generation started...") + + max_retries = 120 + while max_retries > 0: + history = get_history(prompt_id) + if prompt_id in history: + outputs = history[prompt_id]['outputs'] + for node_id in outputs: + if 'images' in outputs[node_id]: + image_info = outputs[node_id]['images'][0] + image_data = get_image(image_info['filename'], image_info['subfolder'], image_info['type']) + + char_folder = os.path.join(app.config['UPLOAD_FOLDER'], character.slug) + os.makedirs(char_folder, exist_ok=True) + filename = f"gen_{int(time.time())}.png" + file_path = os.path.join(char_folder, filename) + with open(file_path, 'wb') as f: + f.write(image_data) + + relative_path = f"{character.slug}/{filename}" + return render_template('generator.html', characters=characters, checkpoints=checkpoints, + generated_image=relative_path, selected_char=char_slug, selected_ckpt=checkpoint) + time.sleep(2) + max_retries -= 1 + flash("Generation timed out.") + except Exception as e: + print(f"Generator error: {e}") + flash(f"Error: {str(e)}") + + return render_template('generator.html', characters=characters, checkpoints=checkpoints) + +@app.route('/character/') +def detail(slug): + character = Character.query.filter_by(slug=slug).first_or_404() + + # Load state from session + preferences = session.get(f'prefs_{slug}') + preview_image = session.get(f'preview_{slug}') + + return render_template('detail.html', character=character, preferences=preferences, preview_image=preview_image) + +@app.route('/character//upload', methods=['POST']) +def upload_image(slug): + character = Character.query.filter_by(slug=slug).first_or_404() + + if 'image' not in request.files: + flash('No file part') + return redirect(request.url) + + file = request.files['image'] + if file.filename == '': + flash('No selected file') + return redirect(request.url) + + if file and allowed_file(file.filename): + # Create character subfolder + char_folder = os.path.join(app.config['UPLOAD_FOLDER'], slug) + os.makedirs(char_folder, exist_ok=True) + + filename = secure_filename(file.filename) + file_path = os.path.join(char_folder, filename) + file.save(file_path) + + # Store relative path in DB + character.image_path = f"{slug}/{filename}" + db.session.commit() + flash('Image uploaded successfully!') + + return redirect(url_for('detail', slug=slug)) + +@app.route('/character//finalize_generation/', methods=['POST']) +def finalize_generation(slug, prompt_id): + character = Character.query.filter_by(slug=slug).first_or_404() + action = request.form.get('action', 'preview') + + try: + history = get_history(prompt_id) + if prompt_id not in history: + return {'error': 'History not found'}, 404 + + outputs = history[prompt_id]['outputs'] + for node_id in outputs: + if 'images' in outputs[node_id]: + image_info = outputs[node_id]['images'][0] + image_data = get_image(image_info['filename'], image_info['subfolder'], image_info['type']) + + # Create character subfolder + char_folder = os.path.join(app.config['UPLOAD_FOLDER'], slug) + os.makedirs(char_folder, exist_ok=True) + + filename = f"gen_{int(time.time())}.png" + file_path = os.path.join(char_folder, filename) + with open(file_path, 'wb') as f: + f.write(image_data) + + print(f"Image saved to: {os.path.abspath(file_path)}") + + # Handle actions + relative_path = f"{slug}/{filename}" + + if action == 'replace': + character.image_path = relative_path + db.session.commit() + flash('Cover image updated!') + else: + # Preview mode + session[f'preview_{slug}'] = relative_path + + return {'success': True, 'image_url': url_for('static', filename=f'uploads/{relative_path}')} + + return {'error': 'No image found in output'}, 404 + except Exception as e: + print(f"Finalize error: {e}") + return {'error': str(e)}, 500 + +def _prepare_workflow(workflow, character, prompts, checkpoint=None, custom_negative=None): + # 1. Update prompts using replacement to preserve embeddings + workflow["6"]["inputs"]["text"] = workflow["6"]["inputs"]["text"].replace("{{POSITIVE_PROMPT}}", prompts["main"]) + + if custom_negative: + workflow["7"]["inputs"]["text"] = f"{workflow['7']['inputs']['text']}, {custom_negative}" + + if "14" in workflow: + workflow["14"]["inputs"]["text"] = workflow["14"]["inputs"]["text"].replace("{{FACE_PROMPT}}", prompts["face"]) + if "15" in workflow: + workflow["15"]["inputs"]["text"] = workflow["15"]["inputs"]["text"].replace("{{HAND_PROMPT}}", prompts["hand"]) + + print("--- DEBUG: COMFYUI PROMPTS ---") + print(f"Main Positive (6): {workflow['6']['inputs']['text']}") + print(f"Main Negative (7): {workflow['7']['inputs']['text']}") + if "14" in workflow: + print(f"Face Detailer (14): {workflow['14']['inputs']['text']}") + if "15" in workflow: + print(f"Hand Detailer (15): {workflow['15']['inputs']['text']}") + print("-------------------------------") + + # 2. Update Checkpoint + if checkpoint: + workflow["4"]["inputs"]["ckpt_name"] = checkpoint + + # 3. Handle LoRA + lora_data = character.data.get('lora', {}) + lora_name = lora_data.get('lora_name') + + model_source = ["4", 0] + clip_source = ["4", 1] + + if lora_name and "16" in workflow: + workflow["16"]["inputs"]["lora_name"] = lora_name + workflow["16"]["inputs"]["strength_model"] = lora_data.get('lora_weight', 1.0) + workflow["16"]["inputs"]["strength_clip"] = lora_data.get('lora_weight', 1.0) + model_source = ["16", 0] + clip_source = ["16", 1] + + # Apply connections to all model/clip consumers + workflow["3"]["inputs"]["model"] = model_source + workflow["11"]["inputs"]["model"] = model_source + workflow["13"]["inputs"]["model"] = model_source + + workflow["6"]["inputs"]["clip"] = clip_source + workflow["7"]["inputs"]["clip"] = clip_source + workflow["11"]["inputs"]["clip"] = clip_source + workflow["13"]["inputs"]["clip"] = clip_source + workflow["14"]["inputs"]["clip"] = clip_source + workflow["15"]["inputs"]["clip"] = clip_source + + # 4. Randomize seeds + gen_seed = random.randint(1, 10**15) + workflow["3"]["inputs"]["seed"] = gen_seed + if "11" in workflow: workflow["11"]["inputs"]["seed"] = gen_seed + if "13" in workflow: workflow["13"]["inputs"]["seed"] = gen_seed + + return workflow + +def _queue_generation(character, action='preview', selected_fields=None, client_id=None): + # 1. Load workflow + with open('comfy_workflow.json', 'r') as f: + workflow = json.load(f) + + # 2. Build prompts + prompts = build_prompt(character.data, selected_fields, character.default_fields) + + # 3. Prepare workflow + workflow = _prepare_workflow(workflow, character, prompts) + + return queue_prompt(workflow, client_id=client_id) +@app.route('/get_missing_characters') +def get_missing_characters(): + missing = Character.query.filter((Character.image_path == None) | (Character.image_path == '')).all() + return {'missing': [{'slug': c.slug, 'name': c.name} for c in missing]} + +@app.route('/clear_all_covers', methods=['POST']) +def clear_all_covers(): + characters = Character.query.all() + for char in characters: + char.image_path = None + db.session.commit() + return {'success': True} + +@app.route('/generate_missing', methods=['POST']) +def generate_missing(): + missing = Character.query.filter((Character.image_path == None) | (Character.image_path == '')).all() + if not missing: + flash("No characters missing cover images.") + return redirect(url_for('index')) + + success_count = 0 + for character in missing: + try: + print(f"Batch generating for: {character.name}") + prompt_response = _queue_generation(character, action='replace') + prompt_id = prompt_response['prompt_id'] + + # Simple synchronous wait for each + max_retries = 120 + while max_retries > 0: + history = get_history(prompt_id) + if prompt_id in history: + outputs = history[prompt_id]['outputs'] + for node_id in outputs: + if 'images' in outputs[node_id]: + image_info = outputs[node_id]['images'][0] + image_data = get_image(image_info['filename'], image_info['subfolder'], image_info['type']) + + char_folder = os.path.join(app.config['UPLOAD_FOLDER'], character.slug) + os.makedirs(char_folder, exist_ok=True) + filename = f"gen_{int(time.time())}.png" + file_path = os.path.join(char_folder, filename) + with open(file_path, 'wb') as f: + f.write(image_data) + + character.image_path = f"{character.slug}/{filename}" + db.session.commit() + success_count += 1 + break + break + time.sleep(2) + max_retries -= 1 + except Exception as e: + print(f"Error generating for {character.name}: {e}") + + flash(f"Batch generation complete. Generated {success_count} images.") + return redirect(url_for('index')) + +@app.route('/check_status/') +def check_status(prompt_id): + try: + history = get_history(prompt_id) + if prompt_id in history: + return {'status': 'finished'} + return {'status': 'pending'} + except Exception: + return {'status': 'error'}, 500 + +@app.route('/character//generate', methods=['POST']) +def generate_image(slug): + character = Character.query.filter_by(slug=slug).first_or_404() + + try: + # Get action type + action = request.form.get('action', 'preview') + client_id = request.form.get('client_id') + + # Get selected fields + selected_fields = request.form.getlist('include_field') + + # Save preferences + session[f'prefs_{slug}'] = selected_fields + + # Queue generation using helper + prompt_response = _queue_generation(character, action, selected_fields, client_id=client_id) + + if 'prompt_id' not in prompt_response: + raise Exception(f"ComfyUI failed: {prompt_response.get('error', 'Unknown error')}") + + prompt_id = prompt_response['prompt_id'] + + # Return JSON if AJAX request + if request.headers.get('X-Requested-With') == 'XMLHttpRequest': + return {'status': 'queued', 'prompt_id': prompt_id} + + return redirect(url_for('detail', slug=slug)) + + except Exception as e: + print(f"Generation error: {e}") + if request.headers.get('X-Requested-With') == 'XMLHttpRequest': + return {'error': str(e)}, 500 + flash(f"Error during generation: {str(e)}") + return redirect(url_for('detail', slug=slug)) + +@app.route('/character//save_defaults', methods=['POST']) +def save_defaults(slug): + character = Character.query.filter_by(slug=slug).first_or_404() + selected_fields = request.form.getlist('include_field') + character.default_fields = selected_fields + db.session.commit() + flash('Default prompt selection saved for this character!') + return redirect(url_for('detail', slug=slug)) + +if __name__ == '__main__': + with app.app_context(): + os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) + db.create_all() + sync_characters() + app.run(debug=True, port=5000) diff --git a/characters/aerith_gainsborough.json b/characters/aerith_gainsborough.json new file mode 100644 index 0000000..cc2e9e5 --- /dev/null +++ b/characters/aerith_gainsborough.json @@ -0,0 +1,38 @@ +{ + "character_id": "aerith_gainsborough", + "identity": { + "base_specs": "1girl, slender build, fair skin", + "hair": "long brown hair, braided, pink ribbon", + "eyes": "green eyes", + "expression": "cheerful expression", + "hands": "pink nails", + "arms": "", + "torso": "small breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "pink dress, red bolero jacket", + "lower_body": "long skirt", + "footwear": "brown boots", + "gloves": "", + "accessories": "gold bracelets, flower basket" + }, + "styles": { + "aesthetic": "floral, gentle, final fantasy style", + "primary_color": "pink", + "secondary_color": "red", + "tertiary_color": "brown" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Final Fantasy VII" + ] +} \ No newline at end of file diff --git a/characters/android_18.json b/characters/android_18.json new file mode 100644 index 0000000..1549ac7 --- /dev/null +++ b/characters/android_18.json @@ -0,0 +1,39 @@ +{ + "character_id": "android_18", + "character_name": "Android 18", + "identity": { + "base_specs": "1girl, slender build, fair skin", + "hair": "shoulder-length blonde hair, tucked behind one ear", + "eyes": "blue eyes", + "expression": "cool, indifferent expression", + "hands": "blue nails", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "gold hoop earrings" + }, + "wardrobe": { + "inner_layer": "black short-sleeved shirt", + "outer_layer": "blue denim vest, 'RR' text on back", + "lower_body": "blue denim skirt, black leggings", + "footwear": "brown boots", + "gloves": "", + "accessories": "" + }, + "styles": { + "aesthetic": "90s casual, anime, dragon ball style", + "primary_color": "blue", + "secondary_color": "black", + "tertiary_color": "white" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Dragon Ball Z" + ] +} \ No newline at end of file diff --git a/characters/anya_forger.json b/characters/anya_forger.json new file mode 100644 index 0000000..162e2c6 --- /dev/null +++ b/characters/anya_forger.json @@ -0,0 +1,39 @@ +{ + "character_id": "anya_(spy_x_family)", + "character_name": "Anya Forger", + "identity": { + "base_specs": "1girl, small build, loli, fair skin", + "hair": "short pink hair, two small horns (hair ornaments)", + "eyes": "green eyes", + "expression": "smirk", + "hands": "pink nails", + "arms": "", + "torso": "flat chest", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "black Eden Academy uniform, gold trim", + "lower_body": "uniform skirt", + "footwear": "black shoes, white socks", + "gloves": "", + "accessories": "black and gold hair cones" + }, + "styles": { + "aesthetic": "cute, academic, spy x family style", + "primary_color": "pink", + "secondary_color": "black", + "tertiary_color": "gold" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Spy x Family" + ] +} \ No newline at end of file diff --git a/characters/biwa_hayahide.json b/characters/biwa_hayahide.json new file mode 100644 index 0000000..6e8c170 --- /dev/null +++ b/characters/biwa_hayahide.json @@ -0,0 +1,39 @@ +{ + "character_id": "biwa_hayahide_(Umamusume)", + "character_name": "Biwa Hayahide", + "identity": { + "base_specs": "1girl, horse ears, horse tail, tall", + "hair": "long grey hair, wild hair", + "eyes": "purple eyes, red framed glasses", + "expression": "thinking", + "hands": "", + "arms": "", + "torso": "large breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "white shirt", + "outer_layer": "tracen school uniform", + "lower_body": "pleated skirt", + "footwear": "heeled shoes", + "gloves": "", + "accessories": "" + }, + "styles": { + "aesthetic": "intellectual, cool", + "primary_color": "maroon", + "secondary_color": "white", + "tertiary_color": "grey" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Umamusume" + ] +} \ No newline at end of file diff --git a/characters/bulma.json b/characters/bulma.json new file mode 100644 index 0000000..bc79d40 --- /dev/null +++ b/characters/bulma.json @@ -0,0 +1,39 @@ +{ + "character_id": "bulma", + "character_name": "Bulma Briefs", + "identity": { + "base_specs": "1girl, slender build, fair skin", + "hair": "turquoise hair, ponytail", + "eyes": "blue eyes", + "expression": "energetic smile", + "hands": "turquoise nails", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "black playboy bunny", + "lower_body": "pantyhose", + "footwear": "red high heels", + "gloves": "detatched cuffs", + "accessories": "red hair ribbon, dragon radar" + }, + "styles": { + "aesthetic": "retro-futuristic, anime, dragon ball style", + "primary_color": "pink", + "secondary_color": "turquoise", + "tertiary_color": "purple" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Dragon Ball" + ] +} \ No newline at end of file diff --git a/characters/camilla.json b/characters/camilla.json new file mode 100644 index 0000000..58a75c0 --- /dev/null +++ b/characters/camilla.json @@ -0,0 +1,39 @@ +{ + "character_id": "camilla_(fire_emblem)", + "character_name": "Camilla Nohr", + "identity": { + "base_specs": "1girl, curvaceous build, fair skin", + "hair": "long wavy lavender hair, hair covering one eye", + "eyes": "purple eyes", + "expression": "seductive smile", + "hands": "purple nails", + "arms": "", + "torso": "large breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "black headband with horns" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "black armor, cleavage", + "lower_body": "black leggings, armored plates", + "footwear": "black armored boots", + "gloves": "", + "accessories": "purple cape, large axe" + }, + "styles": { + "aesthetic": "dark fantasy, gothic, fire emblem style", + "primary_color": "black", + "secondary_color": "gold", + "tertiary_color": "purple" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Fire Emblem" + ] +} \ No newline at end of file diff --git a/characters/cammy.json b/characters/cammy.json new file mode 100644 index 0000000..dbf6172 --- /dev/null +++ b/characters/cammy.json @@ -0,0 +1,39 @@ +{ + "character_id": "cammy", + "character_name": "Cammy White", + "identity": { + "base_specs": "1girl, muscular build, fair skin", + "hair": "long blonde hair, twin braids", + "eyes": "blue eyes", + "expression": "serious look", + "hands": "green nails", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "scar on left cheek, green camouflage paint on legs" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "green high-leg leotard", + "lower_body": "bare legs", + "footwear": "black combat boots, green socks", + "gloves": "red gauntlets", + "accessories": "red beret" + }, + "styles": { + "aesthetic": "military, athletic, street fighter style", + "primary_color": "green", + "secondary_color": "red", + "tertiary_color": "black" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Street Fighter" + ] +} \ No newline at end of file diff --git a/characters/chun_li.json b/characters/chun_li.json new file mode 100644 index 0000000..27265f5 --- /dev/null +++ b/characters/chun_li.json @@ -0,0 +1,39 @@ +{ + "character_id": "chun_li", + "character_name": "Chun-Li", + "identity": { + "base_specs": "1girl, muscular build, fair skin, asian", + "hair": "black hair, hair buns", + "eyes": "brown eyes", + "expression": "determined smile", + "hands": "blue nails", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "thick thighs", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "blue qipao, gold embroidery, white accents", + "lower_body": "brown tights", + "footwear": "white combat boots", + "gloves": "", + "accessories": "white hair ribbons, spiked bracelets" + }, + "styles": { + "aesthetic": "chinese style", + "primary_color": "blue", + "secondary_color": "white", + "tertiary_color": "gold" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Street Fighter" + ] +} \ No newline at end of file diff --git a/characters/ciri.json b/characters/ciri.json new file mode 100644 index 0000000..f7bbcc9 --- /dev/null +++ b/characters/ciri.json @@ -0,0 +1,39 @@ +{ + "character_id": "ciri", + "character_name": "Ciri", + "identity": { + "base_specs": "1girl, athletic build", + "hair": "ashen grey hair, messy bun", + "eyes": "emerald green eyes, mascara", + "expression": "determined look", + "hands": "green nails", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "scar over eye" + }, + "wardrobe": { + "inner_layer": "white blouse", + "outer_layer": "", + "lower_body": "brown leather trousers", + "footwear": "brown leather boots", + "gloves": "brown leather gloves", + "accessories": "silver sword on back, witcher medallion" + }, + "styles": { + "aesthetic": "gritty, fantasy, witcher style", + "primary_color": "white", + "secondary_color": "brown", + "tertiary_color": "silver" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "The Witcher 3" + ] +} \ No newline at end of file diff --git a/characters/delinquent_mother_flim13.json b/characters/delinquent_mother_flim13.json new file mode 100644 index 0000000..80e7e10 --- /dev/null +++ b/characters/delinquent_mother_flim13.json @@ -0,0 +1,39 @@ +{ + "character_id": "delinquent_mother_flim13", + "character_name": "Delinquent Mother", + "identity": { + "base_specs": "1girl, milf, gyaru, tall", + "hair": "blonde hair, long hair", + "eyes": "sharp eyes", + "expression": "smirk, sharp teeth", + "hands": "painted nails", + "arms": "", + "torso": "very large breasts", + "pelvis": "wide hips", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "biege sweater, cleavage", + "outer_layer": "", + "lower_body": "pencil skirt", + "footwear": "high heels", + "gloves": "", + "accessories": "necklace, rings" + }, + "styles": { + "aesthetic": "gyaru, milf, pink leopard print", + "primary_color": "pink", + "secondary_color": "black", + "tertiary_color": "gold" + }, + "lora": { + "lora_name": "Illustrious/Looks/Gyaru_mom_Flim13_IL_V1.safetensors", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Original","flim13" + ] +} \ No newline at end of file diff --git a/characters/gold_city.json b/characters/gold_city.json new file mode 100644 index 0000000..1bbf326 --- /dev/null +++ b/characters/gold_city.json @@ -0,0 +1,39 @@ +{ + "character_id": "gold_city_(Umamusume)", + "character_name": "Gold City", + "identity": { + "base_specs": "1girl, horse ears, horse tail, tall", + "hair": "blonde hair, wavy hair", + "eyes": "blue eyes", + "expression": "confident expression", + "hands": "", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "white shirt", + "outer_layer": "tracen school uniform", + "lower_body": "pleated skirt", + "footwear": "heeled shoes", + "gloves": "", + "accessories": "choker, earrings" + }, + "styles": { + "aesthetic": "fashionable, model", + "primary_color": "gold", + "secondary_color": "white", + "tertiary_color": "black" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Umamusume" + ] +} \ No newline at end of file diff --git a/characters/gold_ship.json b/characters/gold_ship.json new file mode 100644 index 0000000..338017e --- /dev/null +++ b/characters/gold_ship.json @@ -0,0 +1,39 @@ +{ + "character_id": "gold_ship_(Umamusume)", + "character_name": "Gold Ship", + "identity": { + "base_specs": "1girl, horse ears, horse tail, tall", + "hair": "grey hair, short hair", + "eyes": "red eyes", + "expression": "crazy expression, grin", + "hands": "", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "white shirt", + "outer_layer": "tracen school uniform", + "lower_body": "pleated skirt", + "footwear": "heeled shoes", + "gloves": "", + "accessories": "ear covers, hat" + }, + "styles": { + "aesthetic": "energetic, sporty", + "primary_color": "red", + "secondary_color": "white", + "tertiary_color": "gold" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Umamusume" + ] +} \ No newline at end of file diff --git a/characters/hatsune_miku.json b/characters/hatsune_miku.json new file mode 100644 index 0000000..1fc375d --- /dev/null +++ b/characters/hatsune_miku.json @@ -0,0 +1,39 @@ +{ + "character_id": "hatsune_miku", + "character_name": "Hatsune Miku", + "identity": { + "base_specs": "1girl, slender build, fair skin", + "hair": "long turquoise hair, twin tails, floor-length", + "eyes": "turquoise eyes", + "expression": "cheerful smile", + "hands": "turquoise nails", + "arms": "01 tattoo on left shoulder", + "torso": "small breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "grey sleeveless shirt, turquoise tie", + "lower_body": "grey miniskirt, turquoise trim", + "footwear": "black thigh-high boots, turquoise trim", + "gloves": "black arm warmers, turquoise trim", + "accessories": "hair ornament, headset" + }, + "styles": { + "aesthetic": "vocaloid, futuristic, anime style", + "primary_color": "teal", + "secondary_color": "grey", + "tertiary_color": "black" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Vocaloid" + ] +} \ No newline at end of file diff --git a/characters/jessica_rabbit.json b/characters/jessica_rabbit.json new file mode 100644 index 0000000..ed8e413 --- /dev/null +++ b/characters/jessica_rabbit.json @@ -0,0 +1,39 @@ +{ + "character_id": "jessica_rabbit", + "character_name": "Jessica Rabbit", + "identity": { + "base_specs": "1girl, voluptuous build, tall,", + "hair": "long red hair, side part, hair over one eye", + "eyes": "green eyes, heavy makeup, purple eyeshadow", + "expression": "seductive smile", + "hands": "purple elbow gloves", + "arms": "", + "torso": "large breasts", + "pelvis": "narrow waist", + "legs": "", + "feet": "", + "distinguishing_marks": "red lips" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "red sequin dress, strapless, high slit, backless", + "lower_body": "side_slit,", + "footwear": "red high heels", + "gloves": "purple opera gloves", + "accessories": "gold earrings, glitter" + }, + "styles": { + "aesthetic": "noir, cartoon, glamorous", + "primary_color": "red", + "secondary_color": "purple", + "tertiary_color": "gold" + }, + "lora": { + "lora_name": "", + "lora_weight": 0.8, + "lora_triggers": "" + }, + "tags": [ + "Who Framed Roger Rabbit" + ] +} \ No newline at end of file diff --git a/characters/jessie.json b/characters/jessie.json new file mode 100644 index 0000000..1cc3acb --- /dev/null +++ b/characters/jessie.json @@ -0,0 +1,39 @@ +{ + "character_id": "jessie_(pokemon)", + "character_name": "Jessie", + "identity": { + "base_specs": "1girl, slender build, fair skin", + "hair": "long magenta hair, curved back", + "eyes": "blue eyes", + "expression": "arrogant smirk", + "hands": "white nails", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "green earrings" + }, + "wardrobe": { + "inner_layer": "black crop top", + "outer_layer": "white Team Rocket uniform jacket, bare stomach, red R logo", + "lower_body": "white miniskirt", + "footwear": "black thigh-high boots", + "gloves": "black elbow gloves", + "accessories": "green earrings" + }, + "styles": { + "aesthetic": "villainous, anime, pokemon style", + "primary_color": "white", + "secondary_color": "magenta", + "tertiary_color": "black" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Pokemon" + ] +} \ No newline at end of file diff --git a/characters/jinx.json b/characters/jinx.json new file mode 100644 index 0000000..91b27a2 --- /dev/null +++ b/characters/jinx.json @@ -0,0 +1,39 @@ +{ + "character_id": "jinx_(league_of_legends)", + "character_name": "Jinx", + "identity": { + "base_specs": "1girl, slender build, pale skin,", + "hair": "long aqua hair, twin braids, very long hair, bangs", + "eyes": "pink eyes, ", + "expression": "crazy eyes, crazy smile", + "hands": "black and pink nails", + "arms": "", + "torso": "flat chest,", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "cloud tattoo," + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "pink and black bikini, asymmetrical_bikini ", + "lower_body": "pink shorts, single pink stocking", + "footwear": "combat boots", + "gloves": "black fingerless gloves, fishnet elbow gloves,", + "accessories": "ammo belts, choker, bullet necklace," + }, + "styles": { + "aesthetic": "punk, chaotic,", + "primary_color": "pink", + "secondary_color": "black", + "tertiary_color": "aqua" + }, + "lora": { + "lora_name": "Illustrious/Looks/jinx_default_lol-000021.safetensors", + "lora_weight": 0.8, + "lora_triggers": "" + }, + "tags": [ + "League of Legends" + ] +} \ No newline at end of file diff --git a/characters/kagamine_rin.json b/characters/kagamine_rin.json new file mode 100644 index 0000000..378c8d4 --- /dev/null +++ b/characters/kagamine_rin.json @@ -0,0 +1,39 @@ +{ + "character_id": "kagamine_rin", + "character_name": "Kagamine Rin", + "identity": { + "base_specs": "1girl, petite", + "hair": "blonde hair, short hair, hair bow", + "eyes": "blue eyes", + "expression": "smile, energetic", + "hands": "", + "arms": "detached sleeves", + "torso": "flat chest", + "pelvis": "", + "legs": "leg warmers", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "white shirt, sailor collar", + "outer_layer": "", + "lower_body": "black shorts, yellow belt", + "footwear": "white shoes", + "gloves": "", + "accessories": "headset, hair bow" + }, + "styles": { + "aesthetic": "vocaloid, cyber", + "primary_color": "yellow", + "secondary_color": "white", + "tertiary_color": "black" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Vocaloid" + ] +} \ No newline at end of file diff --git a/characters/kagari_atsuko.json b/characters/kagari_atsuko.json new file mode 100644 index 0000000..8cde169 --- /dev/null +++ b/characters/kagari_atsuko.json @@ -0,0 +1,39 @@ +{ + "character_id": "kagari_atsuko", + "character_name": "Kagari Atsuko", + "identity": { + "base_specs": "1girl, slender build, fair skin", + "hair": "long brown hair, half-ponytail, bangs", + "eyes": "red eyes", + "expression": "determined smile", + "hands": "", + "arms": "", + "torso": "small breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "white shirt", + "outer_layer": "dark blue witch robes", + "lower_body": "dark blue skirt", + "footwear": "brown boots, white socks", + "gloves": "", + "accessories": "pointed witch hat, brown belt, magic wand" + }, + "styles": { + "aesthetic": "fantasy, magical girl, little witch academia style", + "primary_color": "dark blue", + "secondary_color": "brown", + "tertiary_color": "red" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Little Witch Academia" + ] +} \ No newline at end of file diff --git a/characters/kda_all_out_ahri.json b/characters/kda_all_out_ahri.json new file mode 100644 index 0000000..ad7104d --- /dev/null +++ b/characters/kda_all_out_ahri.json @@ -0,0 +1,39 @@ +{ + "character_id": "k/da_all_out_ahri", + "character_name": "Ahri", + "identity": { + "base_specs": "1girl, slender build, fair skin, fox ears", + "hair": "long blonde hair, flowing", + "eyes": "yellow eyes", + "expression": "charming smile", + "hands": "silver nails", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "whisker markings on cheeks, crystal tails" + }, + "wardrobe": { + "inner_layer": "silver crop top", + "outer_layer": "white and silver jacket", + "lower_body": "black leather shorts", + "footwear": "black thigh-high boots", + "gloves": "", + "accessories": "crystal heart, silver jewelry" + }, + "styles": { + "aesthetic": "pop star, mystical, k/da style", + "primary_color": "silver", + "secondary_color": "white", + "tertiary_color": "blue" + }, + "lora": { + "lora_name": "Illustrious/Looks/KDA AhriIlluLoRA.safetensors", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "League of Legends", "K/DA", "KDA", "K-Pop" + ] +} \ No newline at end of file diff --git a/characters/kda_all_out_akali.json b/characters/kda_all_out_akali.json new file mode 100644 index 0000000..3347ef3 --- /dev/null +++ b/characters/kda_all_out_akali.json @@ -0,0 +1,39 @@ +{ + "character_id": "k/da_all_out_akali", + "character_name": "Akali", + "identity": { + "base_specs": "1girl, athletic build, fair skin", + "hair": "long dark blue hair, blonde streaks, high ponytail", + "eyes": "blue eyes", + "expression": "cool, rebellious look", + "hands": "blue nails", + "arms": "tattoos on arms", + "torso": "small breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "black crop top", + "outer_layer": "blue and silver motorcycle jacket", + "lower_body": "black leather pants", + "footwear": "blue sneakers", + "gloves": "black fingerless gloves", + "accessories": "kama and kunai" + }, + "styles": { + "aesthetic": "pop star, street, k/da style", + "primary_color": "blue", + "secondary_color": "purple", + "tertiary_color": "silver" + }, + "lora": { + "lora_name": "Illustrious/Looks/KDAAkaliIlluLoRA.safetensors", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "League of Legends", "K/DA", "KDA", "K-Pop" + ] +} \ No newline at end of file diff --git a/characters/kda_all_out_evelynn.json b/characters/kda_all_out_evelynn.json new file mode 100644 index 0000000..adc6ef8 --- /dev/null +++ b/characters/kda_all_out_evelynn.json @@ -0,0 +1,39 @@ +{ + "character_id": "k/da_all_out_evelynn", + "character_name": "Evelynn", + "identity": { + "base_specs": "1girl, curvaceous build, fair skin", + "hair": "light blue hair,", + "eyes": "yellow glowing eyes, slit pupils", + "expression": "seductive, confident look", + "hands": "metal claws", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "two long lashers (shadow tendrils)" + }, + "wardrobe": { + "inner_layer": "black leather bra", + "outer_layer": "iridescent blue jacket, fur collar", + "lower_body": "black leather skirt", + "footwear": "black high-heeled boots", + "gloves": "", + "accessories": "diamond earrings" + }, + "styles": { + "aesthetic": "pop star, glamorous, k/da style", + "primary_color": "blue", + "secondary_color": "purple", + "tertiary_color": "silver" + }, + "lora": { + "lora_name": "Illustrious/Looks/KDA EvelynnIlluLoRA.safetensors", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "League of Legends", "K/DA", "KDA", "K-Pop" + ] +} \ No newline at end of file diff --git a/characters/kda_all_out_kaisa.json b/characters/kda_all_out_kaisa.json new file mode 100644 index 0000000..62852a3 --- /dev/null +++ b/characters/kda_all_out_kaisa.json @@ -0,0 +1,39 @@ +{ + "character_id": "k/da_all_out_kai'sa", + "character_name": "Kai'Sa", + "identity": { + "base_specs": "1girl, athletic build, fair skin", + "hair": "long hair, purple hair, hair ornament, ponytail, green highlights", + "eyes": "purple eyes", + "expression": "focused expression", + "hands": "silver nails", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "silver bodysuit", + "outer_layer": "white and silver jacket", + "lower_body": "silver leggings", + "footwear": "silver high-heeled boots", + "gloves": "", + "accessories": "crystal shoulder pods" + }, + "styles": { + "aesthetic": "pop star, futuristic, k/da style", + "primary_color": "silver", + "secondary_color": "white", + "tertiary_color": "purple" + }, + "lora": { + "lora_name": "Illustrious/Looks/KDA KaisaIlluLoRA.safetensors", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "League of Legends", "K/DA", "KDA", "K-Pop" + ] +} \ No newline at end of file diff --git a/characters/komi_shouko.json b/characters/komi_shouko.json new file mode 100644 index 0000000..1a0abcb --- /dev/null +++ b/characters/komi_shouko.json @@ -0,0 +1,39 @@ +{ + "character_id": "komi_shouko", + "character_name": "Komi Shouko", + "identity": { + "base_specs": "1girl, slender build, pale skin, asian", + "hair": "long dark purple hair, hime cut,", + "eyes": "dark purple eyes,", + "expression": "neutral expression, stoic, cat ears", + "hands": "", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "black pantyhose", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "white shirt", + "outer_layer": "itan private high school uniform, blazer, striped bow tie", + "lower_body": "plaid skirt", + "footwear": "loafers", + "gloves": "", + "accessories": "" + }, + "styles": { + "aesthetic": "anime, manga, clean lines", + "primary_color": "purple", + "secondary_color": "magenta", + "tertiary_color": "white" + }, + "lora": { + "lora_name": "", + "lora_weight": 0.8, + "lora_triggers": "komi shouko, itan private high school uniform" + }, + "tags": [ + "Komi Can't Communicate" + ] +} \ No newline at end of file diff --git a/characters/lara_croft_classic.json b/characters/lara_croft_classic.json new file mode 100644 index 0000000..105f42c --- /dev/null +++ b/characters/lara_croft_classic.json @@ -0,0 +1,39 @@ +{ + "character_id": "lara_croft_classic", + "character_name": "Lara Croft", + "identity": { + "base_specs": "1girl, athletic build,", + "hair": "long brown hair, single braid", + "eyes": "brown eyes", + "expression": "light smile, raised eyebrow", + "hands": "", + "arms": "", + "torso": "large breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "teal tank top,", + "lower_body": "brown shorts", + "footwear": "brown combat boots, red laces", + "gloves": "black fingerless gloves", + "accessories": "dual thigh pistol holsters, brown leatherbackpack, red circular sunglasses" + }, + "styles": { + "aesthetic": "adventure, retro, 90s style", + "primary_color": "teal", + "secondary_color": "brown", + "tertiary_color": "black" + }, + "lora": { + "lora_name": "Illustrious/Looks/LaraCroft_ClassicV2_Illu_Dwnsty.safetensors", + "lora_weight": 0.8, + "lora_triggers": "" + }, + "tags": [ + "Tomb Raider" + ] +} \ No newline at end of file diff --git a/characters/lisa_minci.json b/characters/lisa_minci.json new file mode 100644 index 0000000..7117869 --- /dev/null +++ b/characters/lisa_minci.json @@ -0,0 +1,39 @@ +{ + "character_id": "lisa_(genshin_impact)", + "character_name": "Lisa Minci", + "identity": { + "base_specs": "1girl, tall, mature female", + "hair": "brown hair, wavy hair, side ponytail", + "eyes": "green eyes", + "expression": "seductive smile", + "hands": "", + "arms": "detached sleeves", + "torso": "large breasts", + "pelvis": "wide hips", + "legs": "black pantyhose", + "feet": "", + "distinguishing_marks": "beauty mark" + }, + "wardrobe": { + "inner_layer": "purple dress, corset", + "outer_layer": "purple shawl", + "lower_body": "slit skirt", + "footwear": "black heels", + "gloves": "purple gloves", + "accessories": "witch hat, rose, necklace" + }, + "styles": { + "aesthetic": "genshin impact, witch, librarian", + "primary_color": "purple", + "secondary_color": "white", + "tertiary_color": "gold" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Genshin Impact" + ] +} \ No newline at end of file diff --git a/characters/lulu.json b/characters/lulu.json new file mode 100644 index 0000000..104377b --- /dev/null +++ b/characters/lulu.json @@ -0,0 +1,39 @@ +{ + "character_id": "lulu (ff10)", + "character_name": "Lulu", + "identity": { + "base_specs": "1girl, curvaceous build, fair skin", + "hair": "long black hair, complex braids, hairpins", + "eyes": "red eyes", + "expression": "thinking, raised eyebrow", + "hands": "black nails", + "arms": "", + "torso": "large breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "dark purple lipstick" + }, + "wardrobe": { + "inner_layer": "black corset", + "outer_layer": "black fur-trimmed dress, many belts on front", + "lower_body": "long skirt made of belts", + "footwear": "black boots", + "gloves": "", + "accessories": "moogle doll, silver jewelry" + }, + "styles": { + "aesthetic": "gothic, ornate, final fantasy x style", + "primary_color": "black", + "secondary_color": "white", + "tertiary_color": "purple" + }, + "lora": { + "lora_name": "Illustrious/Looks/Lulu DG illuLoRA_1337272.safetensors", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Final Fantasy X" + ] +} \ No newline at end of file diff --git a/characters/majin_android_21.json b/characters/majin_android_21.json new file mode 100644 index 0000000..b66998f --- /dev/null +++ b/characters/majin_android_21.json @@ -0,0 +1,39 @@ +{ + "character_id": "majin_android_21", + "character_name": "Majin Android 21", + "identity": { + "base_specs": "1girl, curvaceous build, pink skin", + "hair": "long voluminous white hair", + "eyes": "red eyes, black sclera", + "expression": "evil smile", + "hands": "black claws, pink nails", + "arms": "", + "torso": "large breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "pink skin, long tail, pointy ears" + }, + "wardrobe": { + "inner_layer": "black tube top", + "outer_layer": "", + "lower_body": "white harem pants", + "footwear": "black and yellow boots", + "gloves": "black sleeves", + "accessories": "gold bracelets, gold neck ring, hoop earrings" + }, + "styles": { + "aesthetic": "supernatural, anime, dragon ball style", + "primary_color": "pink", + "secondary_color": "white", + "tertiary_color": "gold" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Dragon Ball FighterZ" + ] +} \ No newline at end of file diff --git a/characters/marin_kitagawa.json b/characters/marin_kitagawa.json new file mode 100644 index 0000000..c26c33e --- /dev/null +++ b/characters/marin_kitagawa.json @@ -0,0 +1,39 @@ +{ + "character_id": "marin_kitagawa", + "character_name": "Marin Kitagawa", + "identity": { + "base_specs": "1girl, slender build, fair skin, asian", + "hair": "long blonde hair, pink tips", + "eyes": "pink eyes (contacts)", + "expression": "excited smile", + "hands": "long pink nails", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "piercings" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "white school shirt, loosely tied blue tie", + "lower_body": "blue plaid miniskirt", + "footwear": "black loafers, black socks", + "gloves": "", + "accessories": "choker, various bracelets" + }, + "styles": { + "aesthetic": "gyaru, modern, anime style", + "primary_color": "white", + "secondary_color": "blue", + "tertiary_color": "pink" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "My Dress-Up Darling" + ] +} \ No newline at end of file diff --git a/characters/megurine_luka.json b/characters/megurine_luka.json new file mode 100644 index 0000000..0613b50 --- /dev/null +++ b/characters/megurine_luka.json @@ -0,0 +1,39 @@ +{ + "character_id": "megurine_luka", + "character_name": "Megurine Luka", + "identity": { + "base_specs": "1girl, tall, mature female", + "hair": "pink hair, long hair", + "eyes": "blue eyes", + "expression": "light smile", + "hands": "", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "crop top, detached sleeves, gold trim", + "lower_body": "side slit, lace-up skirt", + "footwear": "thinghighs, lace-up boots, gold boots, gold armlet", + "gloves": "", + "accessories": "headset" + }, + "styles": { + "aesthetic": "vocaloid, elegant", + "primary_color": "black", + "secondary_color": "gold", + "tertiary_color": "pink" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Vocaloid" + ] +} \ No newline at end of file diff --git a/characters/meiko.json b/characters/meiko.json new file mode 100644 index 0000000..79b4c3d --- /dev/null +++ b/characters/meiko.json @@ -0,0 +1,39 @@ +{ + "character_id": "meiko", + "character_name": "Meiko", + "identity": { + "base_specs": "1girl, mature female", + "hair": "brown hair, short hair", + "eyes": "brown eyes", + "expression": "smile, confident", + "hands": "", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "red crop top, sleeveless", + "outer_layer": "", + "lower_body": "red skirt, mini skirt", + "footwear": "brown boots", + "gloves": "", + "accessories": "choker" + }, + "styles": { + "aesthetic": "vocaloid, casual", + "primary_color": "red", + "secondary_color": "brown", + "tertiary_color": "black" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Vocaloid" + ] +} \ No newline at end of file diff --git a/characters/nessa.json b/characters/nessa.json new file mode 100644 index 0000000..3fa76f2 --- /dev/null +++ b/characters/nessa.json @@ -0,0 +1,39 @@ +{ + "character_id": "nessa", + "character_name": "Nessa", + "identity": { + "base_specs": "1girl, athletic build, dark skin", + "hair": "long hair, light blue highlights", + "eyes": "blue eyes", + "expression": "confident smile", + "hands": "blue nails", + "arms": "", + "torso": "small breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "blue earrings" + }, + "wardrobe": { + "inner_layer": "white and blue bikini top", + "outer_layer": "gym uniform, number 049", + "lower_body": "white and blue shorts", + "footwear": "blue and white sandals", + "gloves": "", + "accessories": "wristband, life buoy, pokeball" + }, + "styles": { + "aesthetic": "sporty, aquatic, pokemon style", + "primary_color": "blue", + "secondary_color": "white", + "tertiary_color": "orange" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Pokemon" + ] +} \ No newline at end of file diff --git a/characters/olivier_mira_armstrong.json b/characters/olivier_mira_armstrong.json new file mode 100644 index 0000000..f96dca4 --- /dev/null +++ b/characters/olivier_mira_armstrong.json @@ -0,0 +1,39 @@ +{ + "character_id": "olivier_mira_armstrong", + "character_name": "Olivier Mira Armstrong", + "identity": { + "base_specs": "1girl, tall, mature female", + "hair": "blonde hair, long hair, hair over one eye", + "eyes": "blue eyes, sharp eyes", + "expression": "serious", + "hands": "", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "thick lips" + }, + "wardrobe": { + "inner_layer": "black shirt", + "outer_layer": "blue military coat, fur collar", + "lower_body": "black pants", + "footwear": "black boots", + "gloves": "black gloves", + "accessories": "sword" + }, + "styles": { + "aesthetic": "military, amestris uniform", + "primary_color": "blue", + "secondary_color": "black", + "tertiary_color": "gold" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Fullmetal Alchemist" + ] +} \ No newline at end of file diff --git a/characters/princess_peach.json b/characters/princess_peach.json new file mode 100644 index 0000000..c3bd203 --- /dev/null +++ b/characters/princess_peach.json @@ -0,0 +1,39 @@ +{ + "character_id": "princess_peach", + "character_name": "Princess Peach", + "identity": { + "base_specs": "1girl, slender build, fair skin", + "hair": "long blonde hair, voluminous, crown", + "eyes": "blue eyes, long eyelashes", + "expression": "gentle smile", + "hands": "", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "pink lips, blue earrings" + }, + "wardrobe": { + "inner_layer": "white petticoat", + "outer_layer": "pink floor-length ball gown, puffy sleeves, dark pink panniers", + "lower_body": "long skirt", + "footwear": "red high heels", + "gloves": "white opera gloves", + "accessories": "gold crown with red and blue jewels, blue brooch" + }, + "styles": { + "aesthetic": "royal, whimsical, nintendo style", + "primary_color": "pink", + "secondary_color": "gold", + "tertiary_color": "blue" + }, + "lora": { + "lora_name": "Illustrious/Looks/Princess_Peach_Shiny_Style_V4.0_Illustrious_1652958.safetensors", + "lora_weight": 0.8, + "lora_triggers": "princess peach, crown, pink dress, shiny skin, royal elegance" + }, + "tags": [ + "Super Mario" + ] +} \ No newline at end of file diff --git a/characters/princess_zelda_botw.json b/characters/princess_zelda_botw.json new file mode 100644 index 0000000..b5a9b60 --- /dev/null +++ b/characters/princess_zelda_botw.json @@ -0,0 +1,39 @@ +{ + "character_id": "princess_zelda_botw", + "character_name": "Princess Zelda", + "identity": { + "base_specs": "1girl, slender build, fair skin, pointed ears", + "hair": "long blonde hair, braided, gold hair clips", + "eyes": "green eyes", + "expression": "curious", + "hands": "gold nails", + "arms": "", + "torso": "small breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "tri-force symbol, elf ears" + }, + "wardrobe": { + "inner_layer": "blue tunic", + "outer_layer": "blue champion's tunic, brown leather belts", + "lower_body": "tan trousers", + "footwear": "brown leather boots", + "gloves": "brown fingerless gloves", + "accessories": "sheikah slate, gold jewelry" + }, + "styles": { + "aesthetic": "fantasy, adventurous, zelda style", + "primary_color": "blue", + "secondary_color": "gold", + "tertiary_color": "brown" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "The Legend of Zelda" + ] +} \ No newline at end of file diff --git a/characters/rice_shower.json b/characters/rice_shower.json new file mode 100644 index 0000000..db03c31 --- /dev/null +++ b/characters/rice_shower.json @@ -0,0 +1,39 @@ +{ + "character_id": "rice_shower_(Umamusume)", + "character_name": "Rice Shower", + "identity": { + "base_specs": "1girl, petite, horse ears, horse tail", + "hair": "long dark brown hair, bangs, hair over one eye", + "eyes": "purple eyes", + "expression": "shy expression", + "hands": "", + "arms": "", + "torso": "small breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "white shirt", + "outer_layer": "tracen school uniform", + "lower_body": "pleated skirt", + "footwear": "heeled shoes", + "gloves": "", + "accessories": "blue rose, hair flower, small hat, dagger" + }, + "styles": { + "aesthetic": "gothic lolita, elegant", + "primary_color": "purple", + "secondary_color": "blue", + "tertiary_color": "black" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Umamusume" + ] +} \ No newline at end of file diff --git a/characters/riju.json b/characters/riju.json new file mode 100644 index 0000000..57dcb30 --- /dev/null +++ b/characters/riju.json @@ -0,0 +1,39 @@ +{ + "character_id": "riju", + "character_name": "Riju", + "identity": { + "base_specs": "1girl, young, dark skin, gerudo", + "hair": "short red hair, braided ponytail, gold hair ornament", + "eyes": "green eyes", + "expression": "serious", + "hands": "", + "arms": "", + "torso": "small breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "darkblue lipstick," + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "black top, blue sash", + "lower_body": "black skirt, pelvic curtain,", + "footwear": "gold high heels", + "gloves": "", + "accessories": "gold jewelry, earrings" + }, + "styles": { + "aesthetic": "fantasy, desert, gerudo style", + "primary_color": "gold", + "secondary_color": "black", + "tertiary_color": "red" + }, + "lora": { + "lora_name": "", + "lora_weight": 0.8, + "lora_triggers": "" + }, + "tags": [ + "The Legend of Zelda" + ] +} \ No newline at end of file diff --git a/characters/rosalina.json b/characters/rosalina.json new file mode 100644 index 0000000..e1f196b --- /dev/null +++ b/characters/rosalina.json @@ -0,0 +1,39 @@ +{ + "character_id": "rosalina", + "character_name": "Rosalina", + "identity": { + "base_specs": "1girl, tall, slender build, fair skin", + "hair": "long platinum blonde hair, side-swept bangs covering one eye", + "eyes": "light blue eyes", + "expression": "serene expression", + "hands": "turquoise nails", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "star-shaped earrings" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "turquoise off-the-shoulder gown, silver trim", + "lower_body": "long skirt", + "footwear": "silver high heels", + "gloves": "", + "accessories": "silver crown with blue jewels, star wand, luma" + }, + "styles": { + "aesthetic": "celestial, elegant, nintendo style", + "primary_color": "turquoise", + "secondary_color": "silver", + "tertiary_color": "yellow" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Super Mario" + ] +} \ No newline at end of file diff --git a/characters/rouge_the_bat.json b/characters/rouge_the_bat.json new file mode 100644 index 0000000..550c014 --- /dev/null +++ b/characters/rouge_the_bat.json @@ -0,0 +1,39 @@ +{ + "character_id": "rouge_the_bat", + "character_name": "Rouge the Bat", + "identity": { + "base_specs": "1girl, anthro, bat girl, white fur", + "hair": "short white hair", + "eyes": "teal eyes", + "expression": "sly smirk", + "hands": "white gloves", + "arms": "", + "torso": "large breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "bat wings, eyeshadow" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "black skin-tight jumpsuit, pink heart-shaped chest plate, bare shoulders, cleavage", + "lower_body": "jumpsuit", + "footwear": "white boots, pink heart motifs", + "gloves": "white gloves, pink cuffs", + "accessories": "blue eyeshadow" + }, + "styles": { + "aesthetic": "jewels, museum,sleek, spy, sonic style", + "primary_color": "white", + "secondary_color": "pink", + "tertiary_color": "black" + }, + "lora": { + "lora_name": "Illustrious/Looks/Rouge_the_bat_v2.safetensors", + "lora_weight": 0.8, + "lora_triggers": "" + }, + "tags": [ + "Sonic the Hedgehog" + ] +} \ No newline at end of file diff --git a/characters/ryouko_hakubi.json b/characters/ryouko_hakubi.json new file mode 100644 index 0000000..9a637f4 --- /dev/null +++ b/characters/ryouko_hakubi.json @@ -0,0 +1,39 @@ +{ + "character_id": "ryouko_(tenchi_muyou!)", + "character_name": "Ryouko Hakubi", + "identity": { + "base_specs": "1girl, slim build,", + "hair": "long teal hair, spiky, voluminous", + "eyes": "golden eyes, cat-like pupils", + "expression": "confident smirk", + "hands": "", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "red gem on forehead," + }, + "wardrobe": { + "inner_layer": "long white dress, plunging neckline, black belt", + "outer_layer": "black and orange long sleeve jacket with purple trim,", + "lower_body": "side_slit,, red trousers", + "footwear": "", + "gloves": "red gloves", + "accessories": "red gems, wristbands" + }, + "styles": { + "aesthetic": "90s anime, sci-fi", + "primary_color": "teal", + "secondary_color": "white", + "tertiary_color": "red" + }, + "lora": { + "lora_name": "", + "lora_weight": 0.8, + "lora_triggers": "ryouko hakubi, space pirate" + }, + "tags": [ + "Tenchi Muyou!", "Tenchi Muyo!" + ] +} \ No newline at end of file diff --git a/characters/samus_aran_zero_suit.json b/characters/samus_aran_zero_suit.json new file mode 100644 index 0000000..3f3234f --- /dev/null +++ b/characters/samus_aran_zero_suit.json @@ -0,0 +1,39 @@ +{ + "character_id": "samus_aran", + "character_name": "Samus Aran", + "identity": { + "base_specs": "1girl, athletic build, fair skin", + "hair": "long blonde hair, ponytail", + "eyes": "blue eyes", + "expression": "serious expression", + "hands": "blue nails", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "beauty mark on chin" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "blue skin-tight bodysuit, pink symbols", + "lower_body": "bodysuit", + "footwear": "blue high-heeled boots", + "gloves": "zero suit", + "accessories": "paralyzer pistol" + }, + "styles": { + "aesthetic": "sci-fi, sleek, metroid style", + "primary_color": "blue", + "secondary_color": "pink", + "tertiary_color": "yellow" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Metroid" + ] +} \ No newline at end of file diff --git a/characters/sarah_miller.json b/characters/sarah_miller.json new file mode 100644 index 0000000..70325f3 --- /dev/null +++ b/characters/sarah_miller.json @@ -0,0 +1,39 @@ +{ + "character_id": "sarah_miller_(the_last_of_us)", + "character_name": "Sarah Miller", + "identity": { + "base_specs": "1girl, loli, small build", + "hair": "blonde hair, short hair", + "eyes": "blue eyes", + "expression": "smile", + "hands": "", + "arms": "", + "torso": "flat chest", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "grey t-shirt, white shirt", + "outer_layer": "", + "lower_body": "blue jeans", + "footwear": "sneakers", + "gloves": "", + "accessories": "wristwatch" + }, + "styles": { + "aesthetic": "casual, 2013 fashion", + "primary_color": "grey", + "secondary_color": "blue", + "tertiary_color": "white" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "The Last of Us" + ] +} \ No newline at end of file diff --git a/characters/shantae.json b/characters/shantae.json new file mode 100644 index 0000000..1820bdc --- /dev/null +++ b/characters/shantae.json @@ -0,0 +1,39 @@ +{ + "character_id": "shantae", + "character_name": "Shantae", + "identity": { + "base_specs": "1girl, dark skin, pointy ears", + "hair": "purple hair, very long hair, ponytail", + "eyes": "blue eyes", + "expression": "smile, energetic", + "hands": "", + "arms": "gold bracelets", + "torso": "small breasts, perky breasts", + "pelvis": "wide hips", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "red bikini top, red harem pants, gold trim", + "lower_body": "", + "footwear": "gold shoes", + "gloves": "", + "accessories": "gold tiara, hoop earrings" + }, + "styles": { + "aesthetic": "genie, dancer, arabian", + "primary_color": "red", + "secondary_color": "gold", + "tertiary_color": "purple" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Shantae" + ] +} \ No newline at end of file diff --git a/characters/sucy_manbavaran.json b/characters/sucy_manbavaran.json new file mode 100644 index 0000000..5a4d3ee --- /dev/null +++ b/characters/sucy_manbavaran.json @@ -0,0 +1,39 @@ +{ + "character_id": "sucy_manbavaran", + "character_name": "Sucy Manbavaran", + "identity": { + "base_specs": "1girl, lanky build, pale skin", + "hair": "light purple hair, hair covering one eye", + "eyes": "red eyes", + "expression": "deadpan expression", + "hands": "black nails", + "arms": "", + "torso": "small breasts", + "pelvis": "narrow waist", + "legs": "", + "feet": "", + "distinguishing_marks": "dark circles under eyes" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "dark purple witch robes", + "lower_body": "long skirt with frayed edges", + "footwear": "brown boots", + "gloves": "", + "accessories": "pointed witch hat, potion bottle" + }, + "styles": { + "aesthetic": "gothic, whimsical, little witch academia style", + "primary_color": "purple", + "secondary_color": "mauve", + "tertiary_color": "green" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Little Witch Academia" + ] +} \ No newline at end of file diff --git a/characters/tifa_lockhart.json b/characters/tifa_lockhart.json new file mode 100644 index 0000000..b088cbb --- /dev/null +++ b/characters/tifa_lockhart.json @@ -0,0 +1,39 @@ +{ + "character_id": "tifa_lockhart", + "character_name": "Tifa Lockhart", + "identity": { + "base_specs": "1girl, athletic build, fair skin", + "hair": "long black hair, tied end", + "eyes": "red eyes", + "expression": "kind smile", + "hands": "dark red nails", + "arms": "", + "torso": "large breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "black sports bra", + "outer_layer": "white tank top, black suspenders", + "lower_body": "black miniskirt", + "footwear": "red boots, black socks", + "gloves": "red fingerless gloves", + "accessories": "silver earrings" + }, + "styles": { + "aesthetic": "urban, martial arts, final fantasy style", + "primary_color": "white", + "secondary_color": "black", + "tertiary_color": "red" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Final Fantasy VII" + ] +} \ No newline at end of file diff --git a/characters/tracer.json b/characters/tracer.json new file mode 100644 index 0000000..4ca535e --- /dev/null +++ b/characters/tracer.json @@ -0,0 +1,39 @@ +{ + "character_id": "tracer", + "character_name": "Tracer", + "identity": { + "base_specs": "1girl, slender build, fair skin", + "hair": "short spiky brown hair", + "eyes": "brown eyes", + "expression": "energetic smile", + "hands": "", + "arms": "", + "torso": "small breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "freckles" + }, + "wardrobe": { + "inner_layer": "orange leggings", + "outer_layer": "brown flight jacket, yellow vest", + "lower_body": "orange leggings", + "footwear": "white and orange sneakers", + "gloves": "", + "accessories": "chronal accelerator, yellow goggles" + }, + "styles": { + "aesthetic": "sci-fi, pilot, overwatch style", + "primary_color": "orange", + "secondary_color": "brown", + "tertiary_color": "white" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Overwatch" + ] +} \ No newline at end of file diff --git a/characters/urbosa.json b/characters/urbosa.json new file mode 100644 index 0000000..c51bc28 --- /dev/null +++ b/characters/urbosa.json @@ -0,0 +1,39 @@ +{ + "character_id": "urbosa", + "character_name": "Urbosa", + "identity": { + "base_specs": "1girl, tall, muscular, dark skin, gerudo", + "hair": "long red hair, wild hair", + "eyes": "green eyes", + "expression": "confident", + "hands": "gold nails", + "arms": "muscular arms", + "torso": "abs, mediumS breasts", + "pelvis": "wide hips", + "legs": "muscular legs", + "feet": "", + "distinguishing_marks": "dark blue lipstick, gerudo markings" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "blue top, blue champion's skirt, green sash, green shoulder guards,", + "lower_body": "blue skirt", + "footwear": "gold heels", + "gloves": "", + "accessories": "gold jewelry, scimitar" + }, + "styles": { + "aesthetic": "fantasy, warrior, gerudo style", + "primary_color": "gold", + "secondary_color": "blue", + "tertiary_color": "red" + }, + "lora": { + "lora_name": "", + "lora_weight": 0.8, + "lora_triggers": "" + }, + "tags": [ + "The Legend of Zelda" + ] +} \ No newline at end of file diff --git a/characters/widowmaker.json b/characters/widowmaker.json new file mode 100644 index 0000000..ebdb77d --- /dev/null +++ b/characters/widowmaker.json @@ -0,0 +1,39 @@ +{ + "character_id": "widowmaker", + "character_name": "Widowmaker", + "identity": { + "base_specs": "1girl, slender build, blue skin", + "hair": "long purple hair, ponytail", + "eyes": "yellow eyes", + "expression": "cold expression", + "hands": "", + "arms": "spider tattoo on arm", + "torso": "large breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "blue skin" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "purple tactical bodysuit, plunging neckline", + "lower_body": "bodysuit", + "footwear": "purple high-heeled boots", + "gloves": "purple gauntlets", + "accessories": "sniper visor, grappling hook" + }, + "styles": { + "aesthetic": "sci-fi, assassin, overwatch style", + "primary_color": "purple", + "secondary_color": "black", + "tertiary_color": "pink" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Overwatch" + ] +} \ No newline at end of file diff --git a/characters/yor_briar.json b/characters/yor_briar.json new file mode 100644 index 0000000..e9deda7 --- /dev/null +++ b/characters/yor_briar.json @@ -0,0 +1,39 @@ +{ + "character_id": "yor_briar", + "character_name": "Yor Briar", + "identity": { + "base_specs": "1girl, slender build, fair skin", + "hair": "long black hair, styled with gold headband", + "eyes": "red eyes", + "expression": "gentle yet mysterious smile", + "hands": "black nails", + "arms": "", + "torso": "medium breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "black backless halter dress, red rose pattern inside", + "lower_body": "black thigh-high boots", + "footwear": "black boots", + "gloves": "black fingerless gloves", + "accessories": "gold rose-themed headband, gold needle weapons" + }, + "styles": { + "aesthetic": "elegant, assassin, spy x family style", + "primary_color": "black", + "secondary_color": "red", + "tertiary_color": "gold" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Spy x Family" + ] +} \ No newline at end of file diff --git a/characters/yshtola_rhul.json b/characters/yshtola_rhul.json new file mode 100644 index 0000000..6764142 --- /dev/null +++ b/characters/yshtola_rhul.json @@ -0,0 +1,39 @@ +{ + "character_id": "y'shtola_rhul", + "character_name": "Y'shtola Rhul", + "identity": { + "base_specs": "1girl, miqo'te, slender build, fair skin, cat ears", + "hair": "short white hair, bangs", + "eyes": "blind, white eyes", + "expression": "stoic expression", + "hands": "black nails", + "arms": "", + "torso": "small breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "facial markings, cat tail" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "black sorceress robes, fur trim", + "lower_body": "long skirt", + "footwear": "black boots", + "gloves": "", + "accessories": "wooden staff" + }, + "styles": { + "aesthetic": "magical, scholarly, final fantasy xiv style", + "primary_color": "black", + "secondary_color": "white", + "tertiary_color": "purple" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Final Fantasy XIV" + ] +} \ No newline at end of file diff --git a/characters/yuffie_kisaragi.json b/characters/yuffie_kisaragi.json new file mode 100644 index 0000000..a8eda5b --- /dev/null +++ b/characters/yuffie_kisaragi.json @@ -0,0 +1,39 @@ +{ + "character_id": "yuffie_kisaragi", + "character_name": "Yuffie Kisaragi", + "identity": { + "base_specs": "1girl, slender build, fair skin", + "hair": "short black hair, bob cut", + "eyes": "brown eyes", + "expression": "playful grin", + "hands": "", + "arms": "black sleeve on one arm", + "torso": "small breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "headband" + }, + "wardrobe": { + "inner_layer": "", + "outer_layer": "green turtleneck sweater vest, midriff", + "lower_body": "beige shorts", + "footwear": "boots, socks", + "gloves": "fingerless glove on one hand, large gauntlet on one arm", + "accessories": "shuriken" + }, + "styles": { + "aesthetic": "ninja, adventurer, final fantasy style", + "primary_color": "green", + "secondary_color": "beige", + "tertiary_color": "black" + }, + "lora": { + "lora_name": "", + "lora_weight": 1.0, + "lora_triggers": "" + }, + "tags": [ + "Final Fantasy VII" + ] +} \ No newline at end of file diff --git a/characters/yuna_ffx.json b/characters/yuna_ffx.json new file mode 100644 index 0000000..f1567d1 --- /dev/null +++ b/characters/yuna_ffx.json @@ -0,0 +1,39 @@ +{ + "character_id": "yuna_(ff10)", + "character_name": "Yuna", + "identity": { + "base_specs": "1girl, slender, fair skin", + "hair": "short brown hair, bob cut", + "eyes": "heterochromia, blue eye, green eye", + "expression": "gentle", + "hands": "", + "arms": "", + "torso": "small breasts", + "pelvis": "", + "legs": "", + "feet": "", + "distinguishing_marks": "" + }, + "wardrobe": { + "inner_layer": "white kimono top, yellow obi", + "outer_layer": "", + "lower_body": "long blue skirt, floral pattern", + "footwear": "boots", + "gloves": "detached sleeves", + "accessories": "summoner staff, necklace" + }, + "styles": { + "aesthetic": "fantasy, final fantasy x style", + "primary_color": "white", + "secondary_color": "blue", + "tertiary_color": "yellow" + }, + "lora": { + "lora_name": "", + "lora_weight": 0.8, + "lora_triggers": "" + }, + "tags": [ + "Final Fantasy X" + ] +} \ No newline at end of file diff --git a/comfy_workflow.json b/comfy_workflow.json new file mode 100644 index 0000000..1a3b426 --- /dev/null +++ b/comfy_workflow.json @@ -0,0 +1,173 @@ +{ + "3": { + "inputs": { + "seed": 8566257, + "steps": 20, + "cfg": 3.5, + "sampler_name": "euler_ancestral", + "scheduler": "normal", + "denoise": 1, + "model": ["4", 0], + "positive": ["6", 0], + "negative": ["7", 0], + "latent_image": ["5", 0] + }, + "class_type": "KSampler" + }, + "4": { + "inputs": { + "ckpt_name": "Noob/oneObsession_v19Atypical.safetensors" + }, + "class_type": "CheckpointLoaderSimple" + }, + "5": { + "inputs": { + "width": 1024, + "height": 1024, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage" + }, + "6": { + "inputs": { + "text": "embedding:Illustrious/lazypos_1733353, {{POSITIVE_PROMPT}}", + "clip": ["4", 1] + }, + "class_type": "CLIPTextEncode" + }, + "7": { + "inputs": { + "text": "embedding:Illustrious/lazyneg_1760455, embedding:Illustrious/lazyhand", + "clip": ["4", 1] + }, + "class_type": "CLIPTextEncode" + }, + "8": { + "inputs": { + "samples": ["3", 0], + "vae": ["4", 2] + }, + "class_type": "VAEDecode" + }, + "9": { + "inputs": { + "filename_prefix": "ComfyUI", + "images": ["13", 0] + }, + "class_type": "SaveImage" + }, + "10": { + "inputs": { + "model_name": "bbox/face_yolov9c.pt" + }, + "class_type": "UltralyticsDetectorProvider" + }, + "11": { + "inputs": { + "guide_size": 384, + "guide_size_for": "bbox", + "max_size": 1024, + "seed": 123456, + "steps": 20, + "cfg": 3.5, + "sampler_name": "euler_ancestral", + "scheduler": "normal", + "denoise": 0.5, + "feather": 5, + "noise_mask": true, + "force_inpaint": true, + "bbox_threshold": 0.5, + "bbox_dilation": 10, + "bbox_crop_factor": 3, + "sam_threshold": 0.6, + "sam_dilation": 0, + "sam_mask_hint_threshold": 0.7, + "sam_mask_hint_use_negative": "False", + "sam_bbox_expansion": 0, + "sam_detection_hint": "none", + "sam_mask_hint_area": "bbox", + "drop_size": 10, + "wildcard": "", + "cycle": 1, + "inpaint_model": false, + "noise_mask_feather": 20, + "image": ["8", 0], + "model": ["4", 0], + "clip": ["4", 1], + "vae": ["4", 2], + "positive": ["14", 0], + "negative": ["7", 0], + "bbox_detector": ["10", 0] + }, + "class_type": "FaceDetailer" + }, + "12": { + "inputs": { + "model_name": "bbox/hand_yolov8s.pt" + }, + "class_type": "UltralyticsDetectorProvider" + }, + "13": { + "inputs": { + "guide_size": 384, + "guide_size_for": "bbox", + "max_size": 1024, + "seed": 123456, + "steps": 20, + "cfg": 3.5, + "sampler_name": "euler_ancestral", + "scheduler": "normal", + "denoise": 0.5, + "feather": 5, + "noise_mask": true, + "force_inpaint": true, + "bbox_threshold": 0.5, + "bbox_dilation": 10, + "bbox_crop_factor": 3, + "sam_threshold": 0.6, + "sam_dilation": 0, + "sam_mask_hint_threshold": 0.7, + "sam_mask_hint_use_negative": "False", + "sam_bbox_expansion": 0, + "sam_detection_hint": "none", + "sam_mask_hint_area": "bbox", + "drop_size": 10, + "wildcard": "", + "cycle": 1, + "inpaint_model": false, + "noise_mask_feather": 20, + "image": ["11", 0], + "model": ["4", 0], + "clip": ["4", 1], + "vae": ["4", 2], + "positive": ["15", 0], + "negative": ["7", 0], + "bbox_detector": ["12", 0] + }, + "class_type": "FaceDetailer" + }, + "14": { + "inputs": { + "text": "{{FACE_PROMPT}}", + "clip": ["4", 1] + }, + "class_type": "CLIPTextEncode" + }, + "15": { + "inputs": { + "text": "{{HAND_PROMPT}}", + "clip": ["4", 1] + }, + "class_type": "CLIPTextEncode" + }, + "16": { + "inputs": { + "lora_name": "", + "strength_model": 1.0, + "strength_clip": 1.0, + "model": ["4", 0], + "clip": ["4", 1] + }, + "class_type": "LoraLoader" + } +} diff --git a/launch.sh b/launch.sh new file mode 100644 index 0000000..eee3e5b --- /dev/null +++ b/launch.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# Exit on error +set -e + +VENV_DIR="venv" + +echo "Checking for virtual environment..." +if [ ! -d "$VENV_DIR" ]; then + echo "Creating virtual environment..." + python3 -m venv "$VENV_DIR" +fi + +echo "Activating virtual environment..." +source "$VENV_DIR/bin/activate" + +if [ "$1" == "--clean" ]; then + echo "Performing clean start..." + echo "Removing database..." + rm -f database.db + echo "Clearing uploads..." + rm -rf static/uploads/* +fi + +echo "Upgrading pip and setuptools..." +pip install --upgrade pip setuptools wheel + +echo "Installing/Updating requirements..." +pip install -r requirements.txt + +echo "Starting Character Browser..." +python3 app.py diff --git a/models.py b/models.py new file mode 100644 index 0000000..f9d0f36 --- /dev/null +++ b/models.py @@ -0,0 +1,15 @@ +from flask_sqlalchemy import SQLAlchemy + +db = SQLAlchemy() + +class Character(db.Model): + id = db.Column(db.Integer, primary_key=True) + character_id = db.Column(db.String(100), unique=True, nullable=False) + slug = db.Column(db.String(100), unique=True, nullable=False) + name = db.Column(db.String(100), nullable=False) + data = db.Column(db.JSON, nullable=False) + default_fields = db.Column(db.JSON, nullable=True) + image_path = db.Column(db.String(255), nullable=True) + + def __repr__(self): + return f'' diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0998bbc --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +Flask +Flask-SQLAlchemy +Pillow +requests \ No newline at end of file diff --git a/templates/detail.html b/templates/detail.html new file mode 100644 index 0000000..40bd9f4 --- /dev/null +++ b/templates/detail.html @@ -0,0 +1,288 @@ +{% extends "layout.html" %} + +{% block content %} +
+
+
+
+ {% if character.image_path %} + {{ character.name }} + {% else %} + No Image Attached + {% endif %} +
+
+
+
+ + +
+ +
+
+ + + +
+
+
+ +
+ +
+
0%
+
+
+ + {% if preview_image %} +
+
Latest Preview
+
+
+ Preview +
+
+
+ {% else %} +
+
Latest Preview
+
+
+ Preview +
+
+
+ {% endif %} + +
+
+ Tags +
+ + +
+
+
+ {% for tag in character.data.tags %} + {{ tag }} + {% endfor %} +
+
+
+ +
+
+

{{ character.name }}

+ Back to Gallery +
+ +
+ {% for section, details in character.data.items() %} + {% if section not in ['character_id', 'tags', 'name'] and details is mapping %} +
+
{{ section.replace('_', ' ') }}
+
+
+ {% if section == 'identity' %} +
+ + Character ID +
+
{{ character.character_id }}
+ {% endif %} + + {% for key, value in details.items() %} +
+ + {{ key.replace('_', ' ') }} +
+
{{ value if value else '--' }}
+ {% endfor %} +
+
+
+ {% endif %} + {% endfor %} +
+
+
+{% endblock %} + +{% block scripts %} + +{% endblock %} diff --git a/templates/generator.html b/templates/generator.html new file mode 100644 index 0000000..37c4b5f --- /dev/null +++ b/templates/generator.html @@ -0,0 +1,70 @@ +{% extends "layout.html" %} + +{% block content %} +
+
+
+
+
Generator Settings
+
+
+
+ + +
+ +
+ + +
Listing models from Illustrious/ folder
+
+ +
+ + +
+ +
+ + +
+ + +
+
+
+
+ +
+
+
Result
+
+ {% if generated_image %} +
+ Generated Result +
+ {% else %} +
+

Select settings and click Generate

+
+ {% endif %} +
+ {% if generated_image %} + + {% endif %} +
+
+
+
+{% endblock %} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..c2ad2a7 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,178 @@ +{% extends "layout.html" %} + +{% block content %} +
+

Character Gallery

+
+ + +
+ +
+
+
+ + +
+
+
Batch Generating...
+
+
0%
+
+

+
+
+ +
+ {% for char in characters %} +
+
+
+ {% if char.image_path %} + {{ char.name }} + No Image + {% else %} + {{ char.name }} + No Image + {% endif %} +
+
+
{{ char.name }}
+

{{ char.data.tags | join(', ') }}

+
+
+
+ {% endfor %} +
+{% endblock %} + +{% block scripts %} + +{% endblock %} diff --git a/templates/layout.html b/templates/layout.html new file mode 100644 index 0000000..b4cbe7f --- /dev/null +++ b/templates/layout.html @@ -0,0 +1,41 @@ + + + + + + Character Browser + + + + + + +
+ {% with messages = get_flashed_messages() %} + {% if messages %} + {% for message in messages %} +
{{ message }}
+ {% endfor %} + {% endif %} + {% endwith %} + + {% block content %}{% endblock %} +
+ + + {% block scripts %}{% endblock %} + +