Add per-axis seed modes
This commit is contained in:
@@ -532,7 +532,15 @@ alone.
|
||||
## Seed Control
|
||||
|
||||
The main `seed` input is still the default master seed. Connect `SxCP Seed
|
||||
Control` to `seed_config` when you want to lock or vary specific axes.
|
||||
Control` to `seed_config` when you want to lock or vary specific axes. Each
|
||||
axis has its own mode plus seed value:
|
||||
|
||||
- `auto`: legacy behavior; `-1` follows the main seed, `0` or higher fixes that
|
||||
axis to the entered value.
|
||||
- `follow_main`: always follows the final generator's main `seed` input and
|
||||
ignores the entered axis seed.
|
||||
- `fixed`: always uses the entered axis seed.
|
||||
- `random`: generates a fresh axis seed when the node runs.
|
||||
|
||||
For normal prompt iteration, `SxCP Seed Locker` is usually simpler:
|
||||
|
||||
@@ -542,7 +550,7 @@ For normal prompt iteration, `SxCP Seed Locker` is usually simpler:
|
||||
- `reroll_seed`: `-1` makes the selected axis follow the main prompt seed;
|
||||
`0` or higher pins that selected axis to a specific seed.
|
||||
|
||||
Seed values:
|
||||
Seed values in `auto` mode:
|
||||
|
||||
- `-1`: follow the main seed.
|
||||
- `0` or higher: override only that axis.
|
||||
|
||||
+45
-11
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import random
|
||||
|
||||
try:
|
||||
from .prompt_builder import (
|
||||
@@ -40,6 +41,7 @@ try:
|
||||
ethnicity_choices,
|
||||
generation_profile_choices,
|
||||
load_character_profile_json,
|
||||
seed_mode_choices,
|
||||
subcategory_choices,
|
||||
)
|
||||
from .caption_naturalizer import naturalize_caption
|
||||
@@ -82,6 +84,7 @@ except ImportError:
|
||||
ethnicity_choices,
|
||||
generation_profile_choices,
|
||||
load_character_profile_json,
|
||||
seed_mode_choices,
|
||||
subcategory_choices,
|
||||
)
|
||||
from caption_naturalizer import naturalize_caption
|
||||
@@ -192,21 +195,27 @@ class SxCPPromptBuilder:
|
||||
|
||||
|
||||
class SxCPSeedControl:
|
||||
SEED_AXES = (
|
||||
"category",
|
||||
"subcategory",
|
||||
"content",
|
||||
"person",
|
||||
"scene",
|
||||
"pose",
|
||||
"role",
|
||||
"expression",
|
||||
"composition",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
seed_spec = {"default": -1, "min": -1, "max": 0xFFFFFFFF, "step": 1}
|
||||
required = {}
|
||||
for axis in cls.SEED_AXES:
|
||||
required[f"{axis}_seed_mode"] = (seed_mode_choices(), {"default": "auto"})
|
||||
required[f"{axis}_seed"] = ("INT", seed_spec)
|
||||
return {
|
||||
"required": {
|
||||
"category_seed": ("INT", seed_spec),
|
||||
"subcategory_seed": ("INT", seed_spec),
|
||||
"content_seed": ("INT", seed_spec),
|
||||
"person_seed": ("INT", seed_spec),
|
||||
"scene_seed": ("INT", seed_spec),
|
||||
"pose_seed": ("INT", seed_spec),
|
||||
"role_seed": ("INT", seed_spec),
|
||||
"expression_seed": ("INT", seed_spec),
|
||||
"composition_seed": ("INT", seed_spec),
|
||||
}
|
||||
"required": required
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
@@ -214,16 +223,32 @@ class SxCPSeedControl:
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, *args, **kwargs):
|
||||
values = list(args) + list(kwargs.values())
|
||||
if "random" in values:
|
||||
return random.random()
|
||||
return tuple(args), tuple(sorted(kwargs.items()))
|
||||
|
||||
def build(
|
||||
self,
|
||||
category_seed_mode,
|
||||
category_seed,
|
||||
subcategory_seed_mode,
|
||||
subcategory_seed,
|
||||
content_seed_mode,
|
||||
content_seed,
|
||||
person_seed_mode,
|
||||
person_seed,
|
||||
scene_seed_mode,
|
||||
scene_seed,
|
||||
pose_seed_mode,
|
||||
pose_seed,
|
||||
role_seed_mode,
|
||||
role_seed,
|
||||
expression_seed_mode,
|
||||
expression_seed,
|
||||
composition_seed_mode,
|
||||
composition_seed,
|
||||
):
|
||||
return (
|
||||
@@ -237,6 +262,15 @@ class SxCPSeedControl:
|
||||
role_seed=role_seed,
|
||||
expression_seed=expression_seed,
|
||||
composition_seed=composition_seed,
|
||||
category_seed_mode=category_seed_mode,
|
||||
subcategory_seed_mode=subcategory_seed_mode,
|
||||
content_seed_mode=content_seed_mode,
|
||||
person_seed_mode=person_seed_mode,
|
||||
scene_seed_mode=scene_seed_mode,
|
||||
pose_seed_mode=pose_seed_mode,
|
||||
role_seed_mode=role_seed_mode,
|
||||
expression_seed_mode=expression_seed_mode,
|
||||
composition_seed_mode=composition_seed_mode,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
+35
-9
@@ -60,6 +60,7 @@ SEED_LOCK_AXES = (
|
||||
"expression",
|
||||
"composition",
|
||||
)
|
||||
SEED_MODE_CHOICES = ["auto", "follow_main", "fixed", "random"]
|
||||
|
||||
ETHNICITY_FILTER_CHOICES = [
|
||||
"any",
|
||||
@@ -860,6 +861,10 @@ def subcategory_choices() -> list[str]:
|
||||
return choices
|
||||
|
||||
|
||||
def seed_mode_choices() -> list[str]:
|
||||
return list(SEED_MODE_CHOICES)
|
||||
|
||||
|
||||
CATEGORY_PRESETS = {
|
||||
"auto_weighted": ("auto_weighted", RANDOM_SUBCATEGORY),
|
||||
"women_casual": ("Casual clothes", RANDOM_SUBCATEGORY),
|
||||
@@ -1192,18 +1197,39 @@ def build_seed_config_json(
|
||||
role_seed: int = -1,
|
||||
expression_seed: int = -1,
|
||||
composition_seed: int = -1,
|
||||
category_seed_mode: str = "auto",
|
||||
subcategory_seed_mode: str = "auto",
|
||||
content_seed_mode: str = "auto",
|
||||
person_seed_mode: str = "auto",
|
||||
scene_seed_mode: str = "auto",
|
||||
pose_seed_mode: str = "auto",
|
||||
role_seed_mode: str = "auto",
|
||||
expression_seed_mode: str = "auto",
|
||||
composition_seed_mode: str = "auto",
|
||||
) -> str:
|
||||
rng = random.SystemRandom()
|
||||
|
||||
def axis_seed(value: int, mode: str) -> int:
|
||||
mode = mode if mode in SEED_MODE_CHOICES else "auto"
|
||||
if mode == "auto":
|
||||
return int(value)
|
||||
if mode == "random":
|
||||
return rng.randint(0, 0xFFFFFFFF)
|
||||
if mode == "fixed":
|
||||
return max(0, int(value))
|
||||
return -1
|
||||
|
||||
return json.dumps(
|
||||
{
|
||||
"category_seed": int(category_seed),
|
||||
"subcategory_seed": int(subcategory_seed),
|
||||
"content_seed": int(content_seed),
|
||||
"person_seed": int(person_seed),
|
||||
"scene_seed": int(scene_seed),
|
||||
"pose_seed": int(pose_seed),
|
||||
"role_seed": int(role_seed),
|
||||
"expression_seed": int(expression_seed),
|
||||
"composition_seed": int(composition_seed),
|
||||
"category_seed": axis_seed(category_seed, category_seed_mode),
|
||||
"subcategory_seed": axis_seed(subcategory_seed, subcategory_seed_mode),
|
||||
"content_seed": axis_seed(content_seed, content_seed_mode),
|
||||
"person_seed": axis_seed(person_seed, person_seed_mode),
|
||||
"scene_seed": axis_seed(scene_seed, scene_seed_mode),
|
||||
"pose_seed": axis_seed(pose_seed, pose_seed_mode),
|
||||
"role_seed": axis_seed(role_seed, role_seed_mode),
|
||||
"expression_seed": axis_seed(expression_seed, expression_seed_mode),
|
||||
"composition_seed": axis_seed(composition_seed, composition_seed_mode),
|
||||
},
|
||||
ensure_ascii=True,
|
||||
sort_keys=True,
|
||||
|
||||
Reference in New Issue
Block a user