From 4fc68beec71caade565638162244a5dec2c5ac1c Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Thu, 25 Jun 2026 17:26:36 +0200 Subject: [PATCH] Add full random prompt builder mode --- README.md | 14 ++++++++++---- __init__.py | 2 +- prompt_builder.py | 22 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 44ab62c..874955f 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,8 @@ The original `SxCP Prompt Builder` remains available as the full all-in-one node. For cleaner workflows, use the split nodes: - `SxCP Category Preset` outputs `category_config` for broad intent such as - women casual, men casual, couple casual, provocative erotic, or hardcore pose. + legacy random, full random, women casual, men casual, couple casual, + provocative erotic, or hardcore pose. - `SxCP Cast Control` outputs `cast_config` plus raw `women_count` and `men_count`, so couple/two-women/two-men/group setups can be reused. - `SxCP Cast Bias` outputs the same cast sockets, but chooses counts from @@ -545,7 +546,8 @@ Options: The node keeps the original generator controls: -- `category`: `auto_weighted`, `woman`, `man`, `couple`, `group_or_layout`, or a custom JSON category. +- `category`: `auto_weighted`, `auto_full`, `woman`, `man`, `couple`, + `group_or_layout`, `custom_random`, or a custom JSON category. - `clothing`: `random`, `full`, or `minimal`. - `minimal_clothing_ratio`: `-1` disables ratio mixing; `0.0` to `1.0` mixes minimal/full clothing when `clothing` is fixed. - `ethnicity`: `any`, `european`, `mediterranean_mena`, `latina`, @@ -570,7 +572,10 @@ The node keeps the original generator controls: too, including `Hardcore sexual poses`. `auto_weighted` uses the original batch mix: mostly women, then men, couples, and -group/layout rows. Direct categories generate only that selected category. +group/layout rows. `auto_full` keeps that original random source in the pool but +also rolls the JSON categories, so it can land on casual, erotic, or hardcore +categories from the same easy all-in-one node. `custom_random` rolls only JSON +categories. Direct categories generate only that selected category. ## Custom Categories @@ -827,7 +832,8 @@ Seed values in `auto` mode: Axes: -- `category_seed`: custom category selection when `custom_random` is used; also drives `SxCP Cast Bias` when its `seed_config` input is connected. +- `category_seed`: category selection when `auto_full` or `custom_random` is + used; also drives `SxCP Cast Bias` when its `seed_config` input is connected. - `subcategory_seed`: random subcategory selection. - `content_seed`: generated item content, such as outfit wording. - `person_seed`: appearance/person selection. diff --git a/__init__.py b/__init__.py index 7c4cc95..441ddca 100644 --- a/__init__.py +++ b/__init__.py @@ -49,7 +49,7 @@ COMMON_INPUT_TOOLTIPS = { "global_seed": "One seed that locks all prompt axes so the same inputs can recreate the same result.", "base_seed": "Base seed used by Seed Locker before applying a selected reroll axis.", "reroll_seed": "Seed for the selected reroll axis. Use -1 to derive it from the base seed.", - "category": "Main category source. Use category config nodes for cleaner workflow wiring.", + "category": "Main category source. auto_weighted is legacy random; auto_full mixes legacy random with JSON categories including hardcore.", "subcategory": "Specific subcategory, or random to choose within the selected category.", "category_config": "Category/subcategory config from SxCP Category Preset.", "cast_config": "Cast size config from SxCP Cast Control.", diff --git a/prompt_builder.py b/prompt_builder.py index 9bc70dc..c499269 100644 --- a/prompt_builder.py +++ b/prompt_builder.py @@ -20,6 +20,7 @@ PROFILE_DIR = ROOT_DIR / "profiles" BUILTIN_CATEGORIES = [ "auto_weighted", + "auto_full", "woman", "man", "couple", @@ -1307,6 +1308,7 @@ def seed_mode_choices() -> list[str]: CATEGORY_PRESETS = { "auto_weighted": ("auto_weighted", RANDOM_SUBCATEGORY), + "auto_full": ("auto_full", RANDOM_SUBCATEGORY), "women_casual": ("Casual clothes", RANDOM_SUBCATEGORY), "men_casual": ("Men casual clothes", RANDOM_SUBCATEGORY), "couple_casual": ("Couple casual clothes", RANDOM_SUBCATEGORY), @@ -3016,6 +3018,23 @@ def _build_direct_builtin_row( return row +def _auto_full_choice(seed_config: dict[str, int], seed: int, row_number: int) -> str: + categories = load_category_library() + if not categories: + return "auto_weighted" + category_rng = _axis_rng(seed_config, "category", seed, row_number) + choices: list[dict[str, Any]] = [{"category": "auto_weighted", "weight": 1.0}] + choices.extend( + { + "category": category["name"], + "weight": category.get("weight", 1.0), + } + for category in categories + ) + choice = _weighted_choice(category_rng, choices) + return str(choice.get("category") or "auto_weighted") + + def _find_category(categories: list[dict[str, Any]], name_or_slug: str) -> dict[str, Any] | None: wanted = name_or_slug.strip().lower() for category in categories: @@ -6025,6 +6044,9 @@ def build_prompt( exact_custom_subcategory = bool(subcategory and subcategory != RANDOM_SUBCATEGORY and " / " in subcategory) + if category == "auto_full" and not exact_custom_subcategory: + category = _auto_full_choice(parsed_seed_config, seed, row_number) + if category == "auto_weighted" and not exact_custom_subcategory: row = _build_auto_weighted_row( row_number,