Add chainable character characteristics nodes
This commit is contained in:
+218
@@ -11,6 +11,7 @@ except Exception:
|
||||
PromptServer = None
|
||||
|
||||
SXCP_HAIR_CONFIG = "SXCP_HAIR_CONFIG"
|
||||
SXCP_CHARACTERISTICS = "SXCP_CHARACTERISTICS"
|
||||
SXCP_CHARACTER_MANUAL = "SXCP_CHARACTER_MANUAL"
|
||||
SXCP_ETHNICITY_LIST = "SXCP_ETHNICITY_LIST"
|
||||
SXCP_FILTER_CONFIG = "SXCP_FILTER_CONFIG"
|
||||
@@ -35,6 +36,7 @@ try:
|
||||
build_character_slot_json,
|
||||
build_character_manual_config_json,
|
||||
build_character_profile_json,
|
||||
build_characteristics_config_json,
|
||||
build_ethnicity_list_json,
|
||||
build_filter_config_json,
|
||||
build_generation_profile_json,
|
||||
@@ -63,6 +65,7 @@ try:
|
||||
character_body_choices,
|
||||
character_descriptor_detail_choices,
|
||||
character_ethnicity_choices,
|
||||
character_eye_color_choices,
|
||||
character_figure_choices,
|
||||
character_hair_color_choices,
|
||||
character_hair_length_choices,
|
||||
@@ -71,6 +74,10 @@ try:
|
||||
character_man_body_choices,
|
||||
character_presence_choices,
|
||||
character_profile_choices,
|
||||
character_hardcore_clothing_state_choices,
|
||||
character_hardcore_clothing_values,
|
||||
character_softcore_outfit_source_choices,
|
||||
character_softcore_outfit_values,
|
||||
character_woman_body_choices,
|
||||
ethnicity_choices,
|
||||
generation_profile_choices,
|
||||
@@ -93,6 +100,7 @@ except ImportError:
|
||||
build_character_slot_json,
|
||||
build_character_manual_config_json,
|
||||
build_character_profile_json,
|
||||
build_characteristics_config_json,
|
||||
build_ethnicity_list_json,
|
||||
build_filter_config_json,
|
||||
build_generation_profile_json,
|
||||
@@ -121,6 +129,7 @@ except ImportError:
|
||||
character_body_choices,
|
||||
character_descriptor_detail_choices,
|
||||
character_ethnicity_choices,
|
||||
character_eye_color_choices,
|
||||
character_figure_choices,
|
||||
character_hair_color_choices,
|
||||
character_hair_length_choices,
|
||||
@@ -129,6 +138,10 @@ except ImportError:
|
||||
character_man_body_choices,
|
||||
character_presence_choices,
|
||||
character_profile_choices,
|
||||
character_hardcore_clothing_state_choices,
|
||||
character_hardcore_clothing_values,
|
||||
character_softcore_outfit_source_choices,
|
||||
character_softcore_outfit_values,
|
||||
character_woman_body_choices,
|
||||
ethnicity_choices,
|
||||
generation_profile_choices,
|
||||
@@ -880,6 +893,190 @@ class SxCPHairStyle(_SxCPHairAxisNode):
|
||||
AXIS = "style"
|
||||
|
||||
|
||||
def _choice_input_key(prefix, choice):
|
||||
key = "".join(char if char.isalnum() else "_" for char in str(choice).lower()).strip("_")
|
||||
while "__" in key:
|
||||
key = key.replace("__", "_")
|
||||
return f"{prefix}_{key}"
|
||||
|
||||
|
||||
class SxCPCharacterAgeRange:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"combine_mode": (["replace_axis", "add_to_axis"], {"default": "replace_axis"}),
|
||||
"min_age": ("INT", {"default": 21, "min": 21, "max": 85, "step": 1}),
|
||||
"max_age": ("INT", {"default": 35, "min": 21, "max": 85, "step": 1}),
|
||||
},
|
||||
"optional": {
|
||||
"characteristics": (SXCP_CHARACTERISTICS,),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = (SXCP_CHARACTERISTICS, "STRING")
|
||||
RETURN_NAMES = ("characteristics", "summary")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(self, combine_mode, min_age, max_age, characteristics=""):
|
||||
start = max(21, min(85, int(min_age)))
|
||||
end = max(21, min(85, int(max_age)))
|
||||
if end < start:
|
||||
start, end = end, start
|
||||
ages = [f"{age}-year-old adult" for age in range(start, end + 1)]
|
||||
config = build_characteristics_config_json(
|
||||
characteristics=characteristics or "",
|
||||
axis="ages",
|
||||
selected_values=ages,
|
||||
combine_mode=combine_mode,
|
||||
)
|
||||
return config, json.loads(config).get("summary", "")
|
||||
|
||||
|
||||
class _SxCPBodyPoolNode:
|
||||
SUBJECT = "character"
|
||||
|
||||
@classmethod
|
||||
def _choices(cls):
|
||||
if cls.SUBJECT == "woman":
|
||||
return [choice for choice in character_woman_body_choices() if choice not in ("random", "manual")]
|
||||
if cls.SUBJECT == "man":
|
||||
return [choice for choice in character_man_body_choices() if choice not in ("random", "manual")]
|
||||
return [choice for choice in character_body_choices() if choice not in ("random", "manual")]
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
required = {
|
||||
"combine_mode": (["replace_axis", "add_to_axis"], {"default": "replace_axis"}),
|
||||
}
|
||||
for choice in cls._choices():
|
||||
required[_choice_input_key("include", choice)] = ("BOOLEAN", {"default": False})
|
||||
return {
|
||||
"required": required,
|
||||
"optional": {
|
||||
"characteristics": (SXCP_CHARACTERISTICS,),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = (SXCP_CHARACTERISTICS, "STRING")
|
||||
RETURN_NAMES = ("characteristics", "summary")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(self, combine_mode="replace_axis", characteristics="", **kwargs):
|
||||
selected = [
|
||||
choice
|
||||
for choice in self._choices()
|
||||
if bool(kwargs.get(_choice_input_key("include", choice), False))
|
||||
]
|
||||
config = build_characteristics_config_json(
|
||||
characteristics=characteristics or "",
|
||||
axis="bodies",
|
||||
selected_values=selected,
|
||||
combine_mode=combine_mode,
|
||||
)
|
||||
return config, json.loads(config).get("summary", "")
|
||||
|
||||
|
||||
class SxCPCharacterBodyPool(_SxCPBodyPoolNode):
|
||||
SUBJECT = "character"
|
||||
|
||||
|
||||
class SxCPWomanBodyPool(_SxCPBodyPoolNode):
|
||||
SUBJECT = "woman"
|
||||
|
||||
|
||||
class SxCPManBodyPool(_SxCPBodyPoolNode):
|
||||
SUBJECT = "man"
|
||||
|
||||
|
||||
class SxCPEyeColorPool:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
required = {
|
||||
"combine_mode": (["replace_axis", "add_to_axis"], {"default": "replace_axis"}),
|
||||
}
|
||||
for choice in character_eye_color_choices():
|
||||
if choice != "random":
|
||||
required[_choice_input_key("include", choice)] = ("BOOLEAN", {"default": False})
|
||||
return {
|
||||
"required": required,
|
||||
"optional": {
|
||||
"characteristics": (SXCP_CHARACTERISTICS,),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = (SXCP_CHARACTERISTICS, "STRING")
|
||||
RETURN_NAMES = ("characteristics", "summary")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(self, combine_mode="replace_axis", characteristics="", **kwargs):
|
||||
selected = [
|
||||
choice
|
||||
for choice in character_eye_color_choices()
|
||||
if choice != "random" and bool(kwargs.get(_choice_input_key("include", choice), False))
|
||||
]
|
||||
config = build_characteristics_config_json(
|
||||
characteristics=characteristics or "",
|
||||
axis="eyes",
|
||||
selected_values=selected,
|
||||
combine_mode=combine_mode,
|
||||
)
|
||||
return config, json.loads(config).get("summary", "")
|
||||
|
||||
|
||||
class SxCPCharacterClothing:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"combine_mode": (["replace_axis", "add_to_axis"], {"default": "replace_axis"}),
|
||||
"softcore_source": (character_softcore_outfit_source_choices(), {"default": "no_change"}),
|
||||
"hardcore_state": (character_hardcore_clothing_state_choices(), {"default": "no_change"}),
|
||||
"custom_softcore_outfits": ("STRING", {"default": "", "multiline": True}),
|
||||
"custom_hardcore_clothing": ("STRING", {"default": "", "multiline": True}),
|
||||
},
|
||||
"optional": {
|
||||
"characteristics": (SXCP_CHARACTERISTICS,),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = (SXCP_CHARACTERISTICS, "STRING")
|
||||
RETURN_NAMES = ("characteristics", "summary")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(
|
||||
self,
|
||||
combine_mode,
|
||||
softcore_source,
|
||||
hardcore_state,
|
||||
custom_softcore_outfits,
|
||||
custom_hardcore_clothing,
|
||||
characteristics="",
|
||||
):
|
||||
config = characteristics or ""
|
||||
if softcore_source != "no_change":
|
||||
config = build_characteristics_config_json(
|
||||
characteristics=config,
|
||||
axis="softcore_outfits",
|
||||
selected_values=character_softcore_outfit_values(softcore_source, custom_softcore_outfits),
|
||||
combine_mode=combine_mode,
|
||||
)
|
||||
if hardcore_state != "no_change":
|
||||
config = build_characteristics_config_json(
|
||||
characteristics=config,
|
||||
axis="hardcore_clothing",
|
||||
selected_values=character_hardcore_clothing_values(hardcore_state, custom_hardcore_clothing),
|
||||
combine_mode=combine_mode,
|
||||
)
|
||||
if not config:
|
||||
config = build_characteristics_config_json(axis="", selected_values=[])
|
||||
return config, json.loads(config).get("summary", "")
|
||||
|
||||
|
||||
class SxCPCharacterManualDetails:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
@@ -1028,6 +1225,7 @@ class SxCPCharacterSlot:
|
||||
"optional": {
|
||||
"manual": (SXCP_CHARACTER_MANUAL,),
|
||||
"ethnicity_list": (SXCP_ETHNICITY_LIST,),
|
||||
"characteristics": (SXCP_CHARACTERISTICS,),
|
||||
"hair_config": (SXCP_HAIR_CONFIG,),
|
||||
"character_cast": (SXCP_CHARACTER_CAST,),
|
||||
},
|
||||
@@ -1056,6 +1254,7 @@ class SxCPCharacterSlot:
|
||||
hardcore_expression_intensity=-1.0,
|
||||
character_cast="",
|
||||
ethnicity_list="",
|
||||
characteristics="",
|
||||
hair_config="",
|
||||
manual="",
|
||||
):
|
||||
@@ -1072,6 +1271,7 @@ class SxCPCharacterSlot:
|
||||
body_phrase="",
|
||||
skin="",
|
||||
hair="",
|
||||
characteristics=characteristics,
|
||||
hair_config=hair_config,
|
||||
eyes="",
|
||||
descriptor_detail=descriptor_detail,
|
||||
@@ -1109,6 +1309,7 @@ class SxCPWomanSlot:
|
||||
"optional": {
|
||||
"manual": (SXCP_CHARACTER_MANUAL,),
|
||||
"ethnicity_list": (SXCP_ETHNICITY_LIST,),
|
||||
"characteristics": (SXCP_CHARACTERISTICS,),
|
||||
"hair_config": (SXCP_HAIR_CONFIG,),
|
||||
"character_cast": (SXCP_CHARACTER_CAST,),
|
||||
},
|
||||
@@ -1135,6 +1336,7 @@ class SxCPWomanSlot:
|
||||
hardcore_expression_intensity=-1.0,
|
||||
character_cast="",
|
||||
ethnicity_list="",
|
||||
characteristics="",
|
||||
hair_config="",
|
||||
manual="",
|
||||
):
|
||||
@@ -1151,6 +1353,7 @@ class SxCPWomanSlot:
|
||||
body_phrase="",
|
||||
skin="",
|
||||
hair="",
|
||||
characteristics=characteristics,
|
||||
hair_config=hair_config,
|
||||
eyes="",
|
||||
descriptor_detail=descriptor_detail,
|
||||
@@ -1187,6 +1390,7 @@ class SxCPManSlot:
|
||||
"optional": {
|
||||
"manual": (SXCP_CHARACTER_MANUAL,),
|
||||
"ethnicity_list": (SXCP_ETHNICITY_LIST,),
|
||||
"characteristics": (SXCP_CHARACTERISTICS,),
|
||||
"hair_config": (SXCP_HAIR_CONFIG,),
|
||||
"character_cast": (SXCP_CHARACTER_CAST,),
|
||||
},
|
||||
@@ -1213,6 +1417,7 @@ class SxCPManSlot:
|
||||
hardcore_expression_intensity=-1.0,
|
||||
character_cast="",
|
||||
ethnicity_list="",
|
||||
characteristics="",
|
||||
hair_config="",
|
||||
manual="",
|
||||
):
|
||||
@@ -1229,6 +1434,7 @@ class SxCPManSlot:
|
||||
body_phrase="",
|
||||
skin="",
|
||||
hair="",
|
||||
characteristics=characteristics,
|
||||
hair_config=hair_config,
|
||||
eyes="",
|
||||
descriptor_detail=descriptor_detail,
|
||||
@@ -1702,6 +1908,12 @@ NODE_CLASS_MAPPINGS = {
|
||||
"SxCPHairLength": SxCPHairLength,
|
||||
"SxCPHairColor": SxCPHairColor,
|
||||
"SxCPHairStyle": SxCPHairStyle,
|
||||
"SxCPCharacterAgeRange": SxCPCharacterAgeRange,
|
||||
"SxCPCharacterBodyPool": SxCPCharacterBodyPool,
|
||||
"SxCPWomanBodyPool": SxCPWomanBodyPool,
|
||||
"SxCPManBodyPool": SxCPManBodyPool,
|
||||
"SxCPEyeColorPool": SxCPEyeColorPool,
|
||||
"SxCPCharacterClothing": SxCPCharacterClothing,
|
||||
"SxCPCharacterManualDetails": SxCPCharacterManualDetails,
|
||||
"SxCPAdvancedFilters": SxCPAdvancedFilters,
|
||||
"SxCPPromptBuilderFromConfigs": SxCPPromptBuilderFromConfigs,
|
||||
@@ -1732,6 +1944,12 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"SxCPHairLength": "SxCP Hair Length",
|
||||
"SxCPHairColor": "SxCP Hair Color",
|
||||
"SxCPHairStyle": "SxCP Hair Style/Cut",
|
||||
"SxCPCharacterAgeRange": "SxCP Character Age Range",
|
||||
"SxCPCharacterBodyPool": "SxCP Character Body Pool",
|
||||
"SxCPWomanBodyPool": "SxCP Woman Body Pool",
|
||||
"SxCPManBodyPool": "SxCP Man Body Pool",
|
||||
"SxCPEyeColorPool": "SxCP Eye Color Pool",
|
||||
"SxCPCharacterClothing": "SxCP Character Clothing",
|
||||
"SxCPCharacterManualDetails": "SxCP Character Manual Details",
|
||||
"SxCPAdvancedFilters": "SxCP Advanced Filters",
|
||||
"SxCPPromptBuilderFromConfigs": "SxCP Prompt Builder From Configs",
|
||||
|
||||
Reference in New Issue
Block a user