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 Generation Profile`
|
||||||
- `prompt_builder / SxCP Advanced Filters`
|
- `prompt_builder / SxCP Advanced Filters`
|
||||||
- `prompt_builder / SxCP Prompt Builder From Configs`
|
- `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 Slot`
|
||||||
- `prompt_builder / SxCP Character Profile Save`
|
- `prompt_builder / SxCP Character Profile Save`
|
||||||
- `prompt_builder / SxCP Character Profile Load`
|
- `prompt_builder / SxCP Character Profile Load`
|
||||||
@@ -53,7 +55,7 @@ The practical compact workflow is:
|
|||||||
|
|
||||||
`Category Preset` + `Cast Control` + `Generation Profile` + optional
|
`Category Preset` + `Cast Control` + `Generation Profile` + optional
|
||||||
`Advanced Filters`, `Seed Locker` or `Seed Control`, `Camera Control`,
|
`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`.
|
into `Prompt Builder From Configs`.
|
||||||
|
|
||||||
An importable default workflow is included at
|
An importable default workflow is included at
|
||||||
@@ -70,11 +72,18 @@ as one long chain:
|
|||||||
|
|
||||||
## Character Profiles
|
## Character Profiles
|
||||||
|
|
||||||
`SxCP Character Slot` is the scalable per-participant control node. Each slot
|
`SxCP Woman Slot` and `SxCP Man Slot` are the scalable per-participant control
|
||||||
defines one woman or man with optional overrides for age, ethnicity, figure,
|
nodes. `Cast Control` still decides how many women and men are generated; slot
|
||||||
body/body phrase, skin, hair, and eyes. Leave any field on `random` or blank to
|
nodes decide who those people are. Each slot defines one participant with
|
||||||
let the generator fill that part from the normal pools; set exact values only
|
optional overrides for age, ethnicity, body/body phrase, skin, hair, and eyes.
|
||||||
where you want control.
|
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
|
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,
|
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
|
lists the relevant cast descriptors directly and does not depend on the image
|
||||||
model carrying context from another prompt.
|
model carrying context from another prompt.
|
||||||
|
|
||||||
For per-character control, chain `SxCP Character Slot` nodes into the pair
|
For per-character control, chain `SxCP Woman Slot` and `SxCP Man Slot` nodes
|
||||||
node's `character_cast` input. The nearest woman slot controls the shared
|
into the pair node's `character_cast` input. The nearest woman slot controls
|
||||||
primary creator (`Woman A`) in both softcore and hardcore outputs; additional
|
the shared primary creator (`Woman A`) in both softcore and hardcore outputs;
|
||||||
woman/man slots fill partner descriptors before random fallback descriptors are
|
additional woman/man slots fill partner descriptors before random fallback
|
||||||
used.
|
descriptors are used.
|
||||||
|
|
||||||
It outputs:
|
It outputs:
|
||||||
|
|
||||||
|
|||||||
+132
@@ -34,7 +34,9 @@ try:
|
|||||||
character_ethnicity_choices,
|
character_ethnicity_choices,
|
||||||
character_figure_choices,
|
character_figure_choices,
|
||||||
character_label_choices,
|
character_label_choices,
|
||||||
|
character_man_body_choices,
|
||||||
character_profile_choices,
|
character_profile_choices,
|
||||||
|
character_woman_body_choices,
|
||||||
ethnicity_choices,
|
ethnicity_choices,
|
||||||
generation_profile_choices,
|
generation_profile_choices,
|
||||||
load_character_profile_json,
|
load_character_profile_json,
|
||||||
@@ -74,7 +76,9 @@ except ImportError:
|
|||||||
character_ethnicity_choices,
|
character_ethnicity_choices,
|
||||||
character_figure_choices,
|
character_figure_choices,
|
||||||
character_label_choices,
|
character_label_choices,
|
||||||
|
character_man_body_choices,
|
||||||
character_profile_choices,
|
character_profile_choices,
|
||||||
|
character_woman_body_choices,
|
||||||
ethnicity_choices,
|
ethnicity_choices,
|
||||||
generation_profile_choices,
|
generation_profile_choices,
|
||||||
load_character_profile_json,
|
load_character_profile_json,
|
||||||
@@ -606,6 +610,130 @@ class SxCPCharacterSlot:
|
|||||||
return result["character_cast"], result["character_slot"], result["summary"], result["status"]
|
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:
|
class SxCPCharacterProfileSave:
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
@@ -985,6 +1113,8 @@ NODE_CLASS_MAPPINGS = {
|
|||||||
"SxCPGenerationProfile": SxCPGenerationProfile,
|
"SxCPGenerationProfile": SxCPGenerationProfile,
|
||||||
"SxCPAdvancedFilters": SxCPAdvancedFilters,
|
"SxCPAdvancedFilters": SxCPAdvancedFilters,
|
||||||
"SxCPPromptBuilderFromConfigs": SxCPPromptBuilderFromConfigs,
|
"SxCPPromptBuilderFromConfigs": SxCPPromptBuilderFromConfigs,
|
||||||
|
"SxCPWomanSlot": SxCPWomanSlot,
|
||||||
|
"SxCPManSlot": SxCPManSlot,
|
||||||
"SxCPCharacterSlot": SxCPCharacterSlot,
|
"SxCPCharacterSlot": SxCPCharacterSlot,
|
||||||
"SxCPCharacterProfileSave": SxCPCharacterProfileSave,
|
"SxCPCharacterProfileSave": SxCPCharacterProfileSave,
|
||||||
"SxCPCharacterProfileLoad": SxCPCharacterProfileLoad,
|
"SxCPCharacterProfileLoad": SxCPCharacterProfileLoad,
|
||||||
@@ -1004,6 +1134,8 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
|||||||
"SxCPGenerationProfile": "SxCP Generation Profile",
|
"SxCPGenerationProfile": "SxCP Generation Profile",
|
||||||
"SxCPAdvancedFilters": "SxCP Advanced Filters",
|
"SxCPAdvancedFilters": "SxCP Advanced Filters",
|
||||||
"SxCPPromptBuilderFromConfigs": "SxCP Prompt Builder From Configs",
|
"SxCPPromptBuilderFromConfigs": "SxCP Prompt Builder From Configs",
|
||||||
|
"SxCPWomanSlot": "SxCP Woman Slot",
|
||||||
|
"SxCPManSlot": "SxCP Man Slot",
|
||||||
"SxCPCharacterSlot": "SxCP Character Slot",
|
"SxCPCharacterSlot": "SxCP Character Slot",
|
||||||
"SxCPCharacterProfileSave": "SxCP Character Profile Save",
|
"SxCPCharacterProfileSave": "SxCP Character Profile Save",
|
||||||
"SxCPCharacterProfileLoad": "SxCP Character Profile Load",
|
"SxCPCharacterProfileLoad": "SxCP Character Profile Load",
|
||||||
|
|||||||
@@ -137,6 +137,42 @@ CHARACTER_BODY_CHOICES = [
|
|||||||
"broad",
|
"broad",
|
||||||
"muscular",
|
"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"}
|
CHARACTER_RANDOM_TOKENS = {"", "random", "auto", "global", "from_global", "default"}
|
||||||
|
|
||||||
CAMERA_DETAIL_CHOICES = ["off", "compact", "full"]
|
CAMERA_DETAIL_CHOICES = ["off", "compact", "full"]
|
||||||
@@ -1296,6 +1332,14 @@ def character_body_choices() -> list[str]:
|
|||||||
return list(CHARACTER_BODY_CHOICES)
|
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]:
|
def character_ethnicity_choices() -> list[str]:
|
||||||
return ["random"] + list(ETHNICITY_FILTER_CHOICES)
|
return ["random"] + list(ETHNICITY_FILTER_CHOICES)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user