Add gender-specific character slot nodes
This commit is contained in:
@@ -14,6 +14,8 @@ The node is registered as:
|
||||
- `prompt_builder / SxCP Generation Profile`
|
||||
- `prompt_builder / SxCP Advanced Filters`
|
||||
- `prompt_builder / SxCP Prompt Builder From Configs`
|
||||
- `prompt_builder / SxCP Woman Slot`
|
||||
- `prompt_builder / SxCP Man Slot`
|
||||
- `prompt_builder / SxCP Character Slot`
|
||||
- `prompt_builder / SxCP Character Profile Save`
|
||||
- `prompt_builder / SxCP Character Profile Load`
|
||||
@@ -53,7 +55,7 @@ The practical compact workflow is:
|
||||
|
||||
`Category Preset` + `Cast Control` + `Generation Profile` + optional
|
||||
`Advanced Filters`, `Seed Locker` or `Seed Control`, `Camera Control`,
|
||||
`Character Slot`, and `Character Profile`
|
||||
`Woman Slot` / `Man Slot`, and `Character Profile`
|
||||
into `Prompt Builder From Configs`.
|
||||
|
||||
An importable default workflow is included at
|
||||
@@ -70,11 +72,18 @@ as one long chain:
|
||||
|
||||
## Character Profiles
|
||||
|
||||
`SxCP Character Slot` is the scalable per-participant control node. Each slot
|
||||
defines one woman or man with optional overrides for age, ethnicity, figure,
|
||||
body/body phrase, skin, hair, and eyes. Leave any field on `random` or blank to
|
||||
let the generator fill that part from the normal pools; set exact values only
|
||||
where you want control.
|
||||
`SxCP Woman Slot` and `SxCP Man Slot` are the scalable per-participant control
|
||||
nodes. `Cast Control` still decides how many women and men are generated; slot
|
||||
nodes decide who those people are. Each slot defines one participant with
|
||||
optional overrides for age, ethnicity, body/body phrase, skin, hair, and eyes.
|
||||
Leave any field on `random` or blank to let the generator fill that part from
|
||||
the normal pools; set exact values only where you want control.
|
||||
|
||||
Use `Woman Slot` for women because it exposes woman-focused body choices and a
|
||||
`figure_bias` selector. Use `Man Slot` for men because it exposes man-focused
|
||||
body choices and omits figure bias. The older generic `SxCP Character Slot`
|
||||
remains available for compatibility and manual mixed use, but the gendered
|
||||
slots are the cleaner default.
|
||||
|
||||
Slots are chainable through the `character_cast` input/output. In automatic
|
||||
label mode, the slot closest to the final generator becomes `A` for its gender,
|
||||
@@ -225,11 +234,11 @@ and location. The generated positive prompts are still standalone: each output
|
||||
lists the relevant cast descriptors directly and does not depend on the image
|
||||
model carrying context from another prompt.
|
||||
|
||||
For per-character control, chain `SxCP Character Slot` nodes into the pair
|
||||
node's `character_cast` input. The nearest woman slot controls the shared
|
||||
primary creator (`Woman A`) in both softcore and hardcore outputs; additional
|
||||
woman/man slots fill partner descriptors before random fallback descriptors are
|
||||
used.
|
||||
For per-character control, chain `SxCP Woman Slot` and `SxCP Man Slot` nodes
|
||||
into the pair node's `character_cast` input. The nearest woman slot controls
|
||||
the shared primary creator (`Woman A`) in both softcore and hardcore outputs;
|
||||
additional woman/man slots fill partner descriptors before random fallback
|
||||
descriptors are used.
|
||||
|
||||
It outputs:
|
||||
|
||||
|
||||
+132
@@ -34,7 +34,9 @@ try:
|
||||
character_ethnicity_choices,
|
||||
character_figure_choices,
|
||||
character_label_choices,
|
||||
character_man_body_choices,
|
||||
character_profile_choices,
|
||||
character_woman_body_choices,
|
||||
ethnicity_choices,
|
||||
generation_profile_choices,
|
||||
load_character_profile_json,
|
||||
@@ -74,7 +76,9 @@ except ImportError:
|
||||
character_ethnicity_choices,
|
||||
character_figure_choices,
|
||||
character_label_choices,
|
||||
character_man_body_choices,
|
||||
character_profile_choices,
|
||||
character_woman_body_choices,
|
||||
ethnicity_choices,
|
||||
generation_profile_choices,
|
||||
load_character_profile_json,
|
||||
@@ -606,6 +610,130 @@ class SxCPCharacterSlot:
|
||||
return result["character_cast"], result["character_slot"], result["summary"], result["status"]
|
||||
|
||||
|
||||
class SxCPWomanSlot:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"enabled": ("BOOLEAN", {"default": True}),
|
||||
"label": (character_label_choices(), {"default": "auto_chain"}),
|
||||
"age": (character_age_choices(), {"default": "random"}),
|
||||
"manual_age": ("STRING", {"default": ""}),
|
||||
"ethnicity": (character_ethnicity_choices(), {"default": "random"}),
|
||||
"figure_bias": (character_figure_choices(), {"default": "random"}),
|
||||
"body": (character_woman_body_choices(), {"default": "random"}),
|
||||
"manual_body": ("STRING", {"default": ""}),
|
||||
"body_phrase": ("STRING", {"default": ""}),
|
||||
"skin": ("STRING", {"default": ""}),
|
||||
"hair": ("STRING", {"default": ""}),
|
||||
"eyes": ("STRING", {"default": ""}),
|
||||
},
|
||||
"optional": {
|
||||
"character_cast": ("STRING", {"default": "", "multiline": True}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING")
|
||||
RETURN_NAMES = ("character_cast", "character_slot", "summary", "status")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(
|
||||
self,
|
||||
enabled,
|
||||
label,
|
||||
age,
|
||||
manual_age,
|
||||
ethnicity,
|
||||
figure_bias,
|
||||
body,
|
||||
manual_body,
|
||||
body_phrase,
|
||||
skin,
|
||||
hair,
|
||||
eyes,
|
||||
character_cast="",
|
||||
):
|
||||
result = build_character_slot_json(
|
||||
subject_type="woman",
|
||||
label=label,
|
||||
age=age,
|
||||
manual_age=manual_age,
|
||||
ethnicity=ethnicity,
|
||||
figure=figure_bias,
|
||||
body=body,
|
||||
manual_body=manual_body,
|
||||
body_phrase=body_phrase,
|
||||
skin=skin,
|
||||
hair=hair,
|
||||
eyes=eyes,
|
||||
enabled=enabled,
|
||||
character_cast=character_cast or "",
|
||||
)
|
||||
return result["character_cast"], result["character_slot"], result["summary"], result["status"]
|
||||
|
||||
|
||||
class SxCPManSlot:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"enabled": ("BOOLEAN", {"default": True}),
|
||||
"label": (character_label_choices(), {"default": "auto_chain"}),
|
||||
"age": (character_age_choices(), {"default": "random"}),
|
||||
"manual_age": ("STRING", {"default": ""}),
|
||||
"ethnicity": (character_ethnicity_choices(), {"default": "random"}),
|
||||
"body": (character_man_body_choices(), {"default": "random"}),
|
||||
"manual_body": ("STRING", {"default": ""}),
|
||||
"body_phrase": ("STRING", {"default": ""}),
|
||||
"skin": ("STRING", {"default": ""}),
|
||||
"hair": ("STRING", {"default": ""}),
|
||||
"eyes": ("STRING", {"default": ""}),
|
||||
},
|
||||
"optional": {
|
||||
"character_cast": ("STRING", {"default": "", "multiline": True}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING")
|
||||
RETURN_NAMES = ("character_cast", "character_slot", "summary", "status")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(
|
||||
self,
|
||||
enabled,
|
||||
label,
|
||||
age,
|
||||
manual_age,
|
||||
ethnicity,
|
||||
body,
|
||||
manual_body,
|
||||
body_phrase,
|
||||
skin,
|
||||
hair,
|
||||
eyes,
|
||||
character_cast="",
|
||||
):
|
||||
result = build_character_slot_json(
|
||||
subject_type="man",
|
||||
label=label,
|
||||
age=age,
|
||||
manual_age=manual_age,
|
||||
ethnicity=ethnicity,
|
||||
figure="random",
|
||||
body=body,
|
||||
manual_body=manual_body,
|
||||
body_phrase=body_phrase,
|
||||
skin=skin,
|
||||
hair=hair,
|
||||
eyes=eyes,
|
||||
enabled=enabled,
|
||||
character_cast=character_cast or "",
|
||||
)
|
||||
return result["character_cast"], result["character_slot"], result["summary"], result["status"]
|
||||
|
||||
|
||||
class SxCPCharacterProfileSave:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
@@ -985,6 +1113,8 @@ NODE_CLASS_MAPPINGS = {
|
||||
"SxCPGenerationProfile": SxCPGenerationProfile,
|
||||
"SxCPAdvancedFilters": SxCPAdvancedFilters,
|
||||
"SxCPPromptBuilderFromConfigs": SxCPPromptBuilderFromConfigs,
|
||||
"SxCPWomanSlot": SxCPWomanSlot,
|
||||
"SxCPManSlot": SxCPManSlot,
|
||||
"SxCPCharacterSlot": SxCPCharacterSlot,
|
||||
"SxCPCharacterProfileSave": SxCPCharacterProfileSave,
|
||||
"SxCPCharacterProfileLoad": SxCPCharacterProfileLoad,
|
||||
@@ -1004,6 +1134,8 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"SxCPGenerationProfile": "SxCP Generation Profile",
|
||||
"SxCPAdvancedFilters": "SxCP Advanced Filters",
|
||||
"SxCPPromptBuilderFromConfigs": "SxCP Prompt Builder From Configs",
|
||||
"SxCPWomanSlot": "SxCP Woman Slot",
|
||||
"SxCPManSlot": "SxCP Man Slot",
|
||||
"SxCPCharacterSlot": "SxCP Character Slot",
|
||||
"SxCPCharacterProfileSave": "SxCP Character Profile Save",
|
||||
"SxCPCharacterProfileLoad": "SxCP Character Profile Load",
|
||||
|
||||
@@ -137,6 +137,42 @@ CHARACTER_BODY_CHOICES = [
|
||||
"broad",
|
||||
"muscular",
|
||||
]
|
||||
CHARACTER_WOMAN_BODY_CHOICES = [
|
||||
"random",
|
||||
"manual",
|
||||
"slim",
|
||||
"petite adult",
|
||||
"toned",
|
||||
"athletic",
|
||||
"average",
|
||||
"curvy",
|
||||
"soft curvy",
|
||||
"curvy athletic",
|
||||
"hourglass",
|
||||
"slim busty",
|
||||
"busty",
|
||||
"busty curvy",
|
||||
"voluptuous",
|
||||
"plus-size",
|
||||
"heavyset",
|
||||
"fat",
|
||||
]
|
||||
CHARACTER_MAN_BODY_CHOICES = [
|
||||
"random",
|
||||
"manual",
|
||||
"slim",
|
||||
"lean",
|
||||
"lean athletic",
|
||||
"toned",
|
||||
"average",
|
||||
"athletic",
|
||||
"muscular",
|
||||
"broad",
|
||||
"broad-shouldered",
|
||||
"stocky",
|
||||
"heavyset",
|
||||
"fat",
|
||||
]
|
||||
CHARACTER_RANDOM_TOKENS = {"", "random", "auto", "global", "from_global", "default"}
|
||||
|
||||
CAMERA_DETAIL_CHOICES = ["off", "compact", "full"]
|
||||
@@ -1296,6 +1332,14 @@ def character_body_choices() -> list[str]:
|
||||
return list(CHARACTER_BODY_CHOICES)
|
||||
|
||||
|
||||
def character_woman_body_choices() -> list[str]:
|
||||
return list(CHARACTER_WOMAN_BODY_CHOICES)
|
||||
|
||||
|
||||
def character_man_body_choices() -> list[str]:
|
||||
return list(CHARACTER_MAN_BODY_CHOICES)
|
||||
|
||||
|
||||
def character_ethnicity_choices() -> list[str]:
|
||||
return ["random"] + list(ETHNICITY_FILTER_CHOICES)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user