818 lines
30 KiB
Python
818 lines
30 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
try:
|
|
from .character_config import (
|
|
build_characteristics_config_json,
|
|
build_hair_config_json,
|
|
character_age_choices,
|
|
character_body_choices,
|
|
character_descriptor_detail_choices,
|
|
character_eye_color_choices,
|
|
character_figure_choices,
|
|
character_hair_color_choices,
|
|
character_hair_length_choices,
|
|
character_hair_style_choices,
|
|
character_label_choices,
|
|
character_man_body_choices,
|
|
character_presence_choices,
|
|
character_woman_body_choices,
|
|
)
|
|
from .character_profile import (
|
|
build_character_manual_config_json,
|
|
character_profile_choices,
|
|
load_character_profile_json,
|
|
)
|
|
from .character_slot import build_character_slot_json
|
|
from .prompt_builder import (
|
|
build_character_profile_json,
|
|
character_ethnicity_choices,
|
|
character_hardcore_clothing_state_choices,
|
|
character_hardcore_clothing_values,
|
|
character_softcore_outfit_source_choices,
|
|
character_softcore_outfit_values,
|
|
)
|
|
except ImportError: # Allows local smoke tests from the repository root.
|
|
from character_config import (
|
|
build_characteristics_config_json,
|
|
build_hair_config_json,
|
|
character_age_choices,
|
|
character_body_choices,
|
|
character_descriptor_detail_choices,
|
|
character_eye_color_choices,
|
|
character_figure_choices,
|
|
character_hair_color_choices,
|
|
character_hair_length_choices,
|
|
character_hair_style_choices,
|
|
character_label_choices,
|
|
character_man_body_choices,
|
|
character_presence_choices,
|
|
character_woman_body_choices,
|
|
)
|
|
from character_profile import (
|
|
build_character_manual_config_json,
|
|
character_profile_choices,
|
|
load_character_profile_json,
|
|
)
|
|
from character_slot import build_character_slot_json
|
|
from prompt_builder import (
|
|
build_character_profile_json,
|
|
character_ethnicity_choices,
|
|
character_hardcore_clothing_state_choices,
|
|
character_hardcore_clothing_values,
|
|
character_softcore_outfit_source_choices,
|
|
character_softcore_outfit_values,
|
|
)
|
|
|
|
|
|
SXCP_HAIR_CONFIG = "SXCP_HAIR_CONFIG"
|
|
SXCP_CHARACTERISTICS = "SXCP_CHARACTERISTICS"
|
|
SXCP_CHARACTER_MANUAL = "SXCP_CHARACTER_MANUAL"
|
|
SXCP_ETHNICITY_LIST = "SXCP_ETHNICITY_LIST"
|
|
SXCP_CHARACTER_CAST = "SXCP_CHARACTER_CAST"
|
|
SXCP_CHARACTER_SLOT = "SXCP_CHARACTER_SLOT"
|
|
SXCP_CHARACTER_PROFILE = "SXCP_CHARACTER_PROFILE"
|
|
|
|
|
|
class _SxCPHairAxisNode:
|
|
AXIS = "color"
|
|
PREFIX = "include"
|
|
|
|
@classmethod
|
|
def _choices(cls):
|
|
if cls.AXIS == "color":
|
|
return [choice for choice in character_hair_color_choices() if choice != "random"]
|
|
if cls.AXIS == "length":
|
|
return [choice for choice in character_hair_length_choices() if choice != "random"]
|
|
return [choice for choice in character_hair_style_choices() if choice != "random"]
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
required = {
|
|
"combine_mode": (["replace_axis", "add_to_axis"], {"default": "replace_axis"}),
|
|
}
|
|
for choice in cls._choices():
|
|
required[f"{cls.PREFIX}_{choice}"] = ("BOOLEAN", {"default": False})
|
|
return {
|
|
"required": required,
|
|
"optional": {
|
|
"hair_config": (SXCP_HAIR_CONFIG,),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (SXCP_HAIR_CONFIG, "STRING")
|
|
RETURN_NAMES = ("hair_config", "summary")
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt_builder"
|
|
|
|
def build(self, combine_mode="replace_axis", hair_config="", **kwargs):
|
|
selected = [
|
|
choice
|
|
for choice in self._choices()
|
|
if bool(kwargs.get(f"{self.PREFIX}_{choice}", False))
|
|
]
|
|
config = build_hair_config_json(
|
|
hair_config=hair_config or "",
|
|
axis=self.AXIS,
|
|
selected_values=selected,
|
|
combine_mode=combine_mode,
|
|
)
|
|
parsed = json.loads(config)
|
|
return config, parsed.get("summary", "")
|
|
|
|
|
|
class SxCPHairColor(_SxCPHairAxisNode):
|
|
AXIS = "color"
|
|
|
|
|
|
class SxCPHairLength(_SxCPHairAxisNode):
|
|
AXIS = "length"
|
|
|
|
|
|
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):
|
|
return {
|
|
"required": {
|
|
"combine_mode": (["merge_nonempty", "replace_all"], {"default": "merge_nonempty"}),
|
|
"manual_age": ("STRING", {"default": ""}),
|
|
"manual_body": ("STRING", {"default": ""}),
|
|
"body_phrase": ("STRING", {"default": ""}),
|
|
"skin": ("STRING", {"default": ""}),
|
|
"hair": ("STRING", {"default": ""}),
|
|
"eyes": ("STRING", {"default": ""}),
|
|
"softcore_outfit": ("STRING", {"default": ""}),
|
|
"hardcore_clothing": ("STRING", {"default": ""}),
|
|
},
|
|
"optional": {
|
|
"manual": (SXCP_CHARACTER_MANUAL,),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (SXCP_CHARACTER_MANUAL, "STRING")
|
|
RETURN_NAMES = ("manual", "summary")
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt_builder"
|
|
|
|
def build(
|
|
self,
|
|
combine_mode,
|
|
manual_age,
|
|
manual_body,
|
|
body_phrase,
|
|
skin,
|
|
hair,
|
|
eyes,
|
|
softcore_outfit,
|
|
hardcore_clothing,
|
|
manual="",
|
|
):
|
|
config = build_character_manual_config_json(
|
|
manual=manual or "",
|
|
combine_mode=combine_mode,
|
|
manual_age=manual_age,
|
|
manual_body=manual_body,
|
|
body_phrase=body_phrase,
|
|
skin=skin,
|
|
hair=hair,
|
|
eyes=eyes,
|
|
softcore_outfit=softcore_outfit,
|
|
hardcore_clothing=hardcore_clothing,
|
|
)
|
|
parsed = json.loads(config)
|
|
return config, parsed.get("summary", "")
|
|
|
|
|
|
class SxCPCharacterSlot:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"enabled": ("BOOLEAN", {"default": True}),
|
|
"subject_type": (["woman", "man"], {"default": "woman"}),
|
|
"label": (character_label_choices(), {"default": "auto_chain"}),
|
|
"slot_seed": ("INT", {"default": -1, "min": -1, "max": 0xFFFFFFFF}),
|
|
"age": ([choice for choice in character_age_choices() if choice != "manual"], {"default": "random"}),
|
|
"ethnicity": (character_ethnicity_choices(), {"default": "random"}),
|
|
"figure": (character_figure_choices(), {"default": "random"}),
|
|
"body": ([choice for choice in character_body_choices() if choice != "manual"], {"default": "random"}),
|
|
"descriptor_detail": (character_descriptor_detail_choices(), {"default": "auto"}),
|
|
"expression_enabled": ("BOOLEAN", {"default": True}),
|
|
"expression_intensity": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
|
"presence_mode": (character_presence_choices(), {"default": "visible"}),
|
|
"softcore_expression_intensity": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
|
"hardcore_expression_intensity": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
|
},
|
|
"optional": {
|
|
"manual": (SXCP_CHARACTER_MANUAL,),
|
|
"ethnicity_list": (SXCP_ETHNICITY_LIST,),
|
|
"characteristics": (SXCP_CHARACTERISTICS,),
|
|
"hair_config": (SXCP_HAIR_CONFIG,),
|
|
"character_cast": (SXCP_CHARACTER_CAST,),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (SXCP_CHARACTER_CAST, SXCP_CHARACTER_SLOT, "STRING", "STRING")
|
|
RETURN_NAMES = ("character_cast", "character_slot", "summary", "status")
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt_builder"
|
|
|
|
def build(
|
|
self,
|
|
enabled,
|
|
subject_type,
|
|
label,
|
|
slot_seed,
|
|
age,
|
|
ethnicity,
|
|
figure,
|
|
body,
|
|
descriptor_detail="auto",
|
|
expression_enabled=True,
|
|
expression_intensity=-1.0,
|
|
presence_mode="visible",
|
|
softcore_expression_intensity=-1.0,
|
|
hardcore_expression_intensity=-1.0,
|
|
character_cast="",
|
|
ethnicity_list="",
|
|
characteristics="",
|
|
hair_config="",
|
|
manual="",
|
|
):
|
|
result = build_character_slot_json(
|
|
subject_type=subject_type,
|
|
label=label,
|
|
slot_seed=slot_seed,
|
|
age=age,
|
|
manual=manual,
|
|
ethnicity=ethnicity_list or ethnicity,
|
|
figure=figure,
|
|
body=body,
|
|
manual_body="",
|
|
body_phrase="",
|
|
skin="",
|
|
hair="",
|
|
characteristics=characteristics,
|
|
hair_config=hair_config,
|
|
eyes="",
|
|
descriptor_detail=descriptor_detail,
|
|
expression_enabled=expression_enabled,
|
|
expression_intensity=expression_intensity,
|
|
presence_mode=presence_mode,
|
|
softcore_expression_intensity=softcore_expression_intensity,
|
|
hardcore_expression_intensity=hardcore_expression_intensity,
|
|
softcore_outfit="",
|
|
hardcore_clothing="",
|
|
enabled=enabled,
|
|
character_cast=character_cast or "",
|
|
)
|
|
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"}),
|
|
"slot_seed": ("INT", {"default": -1, "min": -1, "max": 0xFFFFFFFF}),
|
|
"age": ([choice for choice in character_age_choices() if choice != "manual"], {"default": "random"}),
|
|
"ethnicity": (character_ethnicity_choices(), {"default": "random"}),
|
|
"figure_bias": (character_figure_choices(), {"default": "random"}),
|
|
"body": ([choice for choice in character_woman_body_choices() if choice != "manual"], {"default": "random"}),
|
|
"descriptor_detail": (character_descriptor_detail_choices(), {"default": "auto"}),
|
|
"expression_enabled": ("BOOLEAN", {"default": True}),
|
|
"expression_intensity": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
|
"softcore_expression_intensity": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
|
"hardcore_expression_intensity": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
|
},
|
|
"optional": {
|
|
"manual": (SXCP_CHARACTER_MANUAL,),
|
|
"ethnicity_list": (SXCP_ETHNICITY_LIST,),
|
|
"characteristics": (SXCP_CHARACTERISTICS,),
|
|
"hair_config": (SXCP_HAIR_CONFIG,),
|
|
"character_cast": (SXCP_CHARACTER_CAST,),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (SXCP_CHARACTER_CAST, SXCP_CHARACTER_SLOT, "STRING", "STRING")
|
|
RETURN_NAMES = ("character_cast", "character_slot", "summary", "status")
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt_builder"
|
|
|
|
def build(
|
|
self,
|
|
enabled,
|
|
label,
|
|
slot_seed,
|
|
age,
|
|
ethnicity,
|
|
figure_bias,
|
|
body,
|
|
descriptor_detail="auto",
|
|
expression_enabled=True,
|
|
expression_intensity=-1.0,
|
|
softcore_expression_intensity=-1.0,
|
|
hardcore_expression_intensity=-1.0,
|
|
character_cast="",
|
|
ethnicity_list="",
|
|
characteristics="",
|
|
hair_config="",
|
|
manual="",
|
|
):
|
|
result = build_character_slot_json(
|
|
subject_type="woman",
|
|
label=label,
|
|
slot_seed=slot_seed,
|
|
age=age,
|
|
manual=manual,
|
|
ethnicity=ethnicity_list or ethnicity,
|
|
figure=figure_bias,
|
|
body=body,
|
|
manual_body="",
|
|
body_phrase="",
|
|
skin="",
|
|
hair="",
|
|
characteristics=characteristics,
|
|
hair_config=hair_config,
|
|
eyes="",
|
|
descriptor_detail=descriptor_detail,
|
|
expression_enabled=expression_enabled,
|
|
expression_intensity=expression_intensity,
|
|
softcore_expression_intensity=softcore_expression_intensity,
|
|
hardcore_expression_intensity=hardcore_expression_intensity,
|
|
softcore_outfit="",
|
|
hardcore_clothing="",
|
|
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"}),
|
|
"slot_seed": ("INT", {"default": -1, "min": -1, "max": 0xFFFFFFFF}),
|
|
"age": ([choice for choice in character_age_choices() if choice != "manual"], {"default": "random"}),
|
|
"ethnicity": (character_ethnicity_choices(), {"default": "random"}),
|
|
"body": ([choice for choice in character_man_body_choices() if choice != "manual"], {"default": "random"}),
|
|
"descriptor_detail": (character_descriptor_detail_choices(), {"default": "compact"}),
|
|
"expression_enabled": ("BOOLEAN", {"default": True}),
|
|
"expression_intensity": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
|
"presence_mode": (character_presence_choices(), {"default": "visible"}),
|
|
"softcore_expression_intensity": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
|
"hardcore_expression_intensity": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
|
},
|
|
"optional": {
|
|
"manual": (SXCP_CHARACTER_MANUAL,),
|
|
"ethnicity_list": (SXCP_ETHNICITY_LIST,),
|
|
"characteristics": (SXCP_CHARACTERISTICS,),
|
|
"hair_config": (SXCP_HAIR_CONFIG,),
|
|
"character_cast": (SXCP_CHARACTER_CAST,),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (SXCP_CHARACTER_CAST, SXCP_CHARACTER_SLOT, "STRING", "STRING")
|
|
RETURN_NAMES = ("character_cast", "character_slot", "summary", "status")
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt_builder"
|
|
|
|
def build(
|
|
self,
|
|
enabled,
|
|
label,
|
|
slot_seed,
|
|
age,
|
|
ethnicity,
|
|
body,
|
|
descriptor_detail="compact",
|
|
expression_enabled=True,
|
|
expression_intensity=-1.0,
|
|
presence_mode="visible",
|
|
softcore_expression_intensity=-1.0,
|
|
hardcore_expression_intensity=-1.0,
|
|
character_cast="",
|
|
ethnicity_list="",
|
|
characteristics="",
|
|
hair_config="",
|
|
manual="",
|
|
):
|
|
result = build_character_slot_json(
|
|
subject_type="man",
|
|
label=label,
|
|
slot_seed=slot_seed,
|
|
age=age,
|
|
manual=manual,
|
|
ethnicity=ethnicity_list or ethnicity,
|
|
figure="random",
|
|
body=body,
|
|
manual_body="",
|
|
body_phrase="",
|
|
skin="",
|
|
hair="",
|
|
characteristics=characteristics,
|
|
hair_config=hair_config,
|
|
eyes="",
|
|
descriptor_detail=descriptor_detail,
|
|
expression_enabled=expression_enabled,
|
|
expression_intensity=expression_intensity,
|
|
presence_mode=presence_mode,
|
|
softcore_expression_intensity=softcore_expression_intensity,
|
|
hardcore_expression_intensity=hardcore_expression_intensity,
|
|
softcore_outfit="",
|
|
hardcore_clothing="",
|
|
enabled=enabled,
|
|
character_cast=character_cast or "",
|
|
)
|
|
return result["character_cast"], result["character_slot"], result["summary"], result["status"]
|
|
|
|
|
|
class SxCPCharacterProfileSave:
|
|
OUTPUT_NODE = True
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"profile_name": ("STRING", {"default": "saved_character"}),
|
|
"source": (["metadata_json", "character_slot", "manual"], {"default": "metadata_json"}),
|
|
"subject_type": (["woman", "man"], {"default": "woman"}),
|
|
"age": ("STRING", {"default": ""}),
|
|
"body": ("STRING", {"default": ""}),
|
|
"body_phrase": ("STRING", {"default": ""}),
|
|
"skin": ("STRING", {"default": ""}),
|
|
"hair": ("STRING", {"default": ""}),
|
|
"eyes": ("STRING", {"default": ""}),
|
|
"figure": ("STRING", {"default": ""}),
|
|
"save_now": ("BOOLEAN", {"default": False}),
|
|
},
|
|
"optional": {
|
|
"metadata_json": ("STRING", {"default": "", "multiline": True}),
|
|
"character_slot": (SXCP_CHARACTER_SLOT,),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (SXCP_CHARACTER_PROFILE, "STRING", "STRING", "STRING", "STRING", SXCP_CHARACTER_PROFILE)
|
|
RETURN_NAMES = ("character_profile", "descriptor", "profile_name", "saved_path", "status", "profile_json")
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt_builder"
|
|
|
|
def build(
|
|
self,
|
|
profile_name,
|
|
source,
|
|
subject_type,
|
|
age,
|
|
body,
|
|
body_phrase,
|
|
skin,
|
|
hair,
|
|
eyes,
|
|
figure,
|
|
save_now,
|
|
metadata_json="",
|
|
character_slot="",
|
|
):
|
|
profile = build_character_profile_json(
|
|
profile_name=profile_name,
|
|
source=source,
|
|
metadata_json=metadata_json or "",
|
|
character_slot=character_slot or "",
|
|
subject_type=subject_type,
|
|
age=age,
|
|
body=body,
|
|
body_phrase=body_phrase,
|
|
skin=skin,
|
|
hair=hair,
|
|
eyes=eyes,
|
|
figure=figure,
|
|
save_now=save_now,
|
|
)
|
|
result = (
|
|
profile["profile_json"],
|
|
profile["descriptor"],
|
|
profile["profile_name"],
|
|
profile["saved_path"],
|
|
profile["status"],
|
|
profile["profile_json"],
|
|
)
|
|
return {
|
|
"ui": {
|
|
"profile_json": [profile["profile_json"]],
|
|
"descriptor": [profile["descriptor"]],
|
|
"profile_name": [profile["profile_name"]],
|
|
"saved_path": [profile["saved_path"]],
|
|
"status": [profile["status"]],
|
|
},
|
|
"result": result,
|
|
}
|
|
|
|
|
|
class SxCPCharacterProfileLoad:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"enabled": ("BOOLEAN", {"default": True}),
|
|
"profile_name": (character_profile_choices(), {"default": "manual"}),
|
|
"rename_to": ("STRING", {"default": ""}),
|
|
"delete_now": ("BOOLEAN", {"default": False}),
|
|
"rename_now": ("BOOLEAN", {"default": False}),
|
|
},
|
|
"optional": {
|
|
"manual_profile_name": ("STRING", {"default": ""}),
|
|
"fallback_profile_json": (SXCP_CHARACTER_PROFILE,),
|
|
"override_subject_type": (["keep_profile", "woman", "man"], {"default": "keep_profile"}),
|
|
"override_age": ("STRING", {"default": ""}),
|
|
"override_body": ("STRING", {"default": ""}),
|
|
"override_body_phrase": ("STRING", {"default": ""}),
|
|
"override_skin": ("STRING", {"default": ""}),
|
|
"override_hair": ("STRING", {"default": ""}),
|
|
"override_eyes": ("STRING", {"default": ""}),
|
|
"override_figure": ("STRING", {"default": ""}),
|
|
"override_descriptor_detail": (["keep_profile"] + character_descriptor_detail_choices(), {"default": "keep_profile"}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (SXCP_CHARACTER_PROFILE, "STRING", "STRING", "STRING", "STRING", SXCP_CHARACTER_PROFILE)
|
|
RETURN_NAMES = ("character_profile", "descriptor", "profile_name", "saved_path", "status", "profile_json")
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt_builder"
|
|
|
|
def build(
|
|
self,
|
|
enabled,
|
|
profile_name,
|
|
rename_to,
|
|
delete_now,
|
|
rename_now,
|
|
manual_profile_name="",
|
|
fallback_profile_json="",
|
|
override_subject_type="keep_profile",
|
|
override_age="",
|
|
override_body="",
|
|
override_body_phrase="",
|
|
override_skin="",
|
|
override_hair="",
|
|
override_eyes="",
|
|
override_figure="",
|
|
override_descriptor_detail="keep_profile",
|
|
):
|
|
chosen_name = manual_profile_name.strip() if profile_name == "manual" and manual_profile_name.strip() else profile_name
|
|
profile = load_character_profile_json(
|
|
profile_name=chosen_name,
|
|
fallback_profile_json=fallback_profile_json or "",
|
|
enabled=enabled,
|
|
delete_now=delete_now,
|
|
rename_now=rename_now,
|
|
rename_to=rename_to,
|
|
override_subject_type=override_subject_type,
|
|
override_age=override_age,
|
|
override_body=override_body,
|
|
override_body_phrase=override_body_phrase,
|
|
override_skin=override_skin,
|
|
override_hair=override_hair,
|
|
override_eyes=override_eyes,
|
|
override_figure=override_figure,
|
|
override_descriptor_detail=override_descriptor_detail,
|
|
)
|
|
return (
|
|
profile["profile_json"],
|
|
profile["descriptor"],
|
|
profile["profile_name"],
|
|
profile["saved_path"],
|
|
profile["status"],
|
|
profile["profile_json"],
|
|
)
|
|
|
|
|
|
NODE_CLASS_MAPPINGS = {
|
|
"SxCPHairLength": SxCPHairLength,
|
|
"SxCPHairColor": SxCPHairColor,
|
|
"SxCPHairStyle": SxCPHairStyle,
|
|
"SxCPCharacterAgeRange": SxCPCharacterAgeRange,
|
|
"SxCPCharacterBodyPool": SxCPCharacterBodyPool,
|
|
"SxCPWomanBodyPool": SxCPWomanBodyPool,
|
|
"SxCPManBodyPool": SxCPManBodyPool,
|
|
"SxCPEyeColorPool": SxCPEyeColorPool,
|
|
"SxCPCharacterClothing": SxCPCharacterClothing,
|
|
"SxCPCharacterManualDetails": SxCPCharacterManualDetails,
|
|
"SxCPWomanSlot": SxCPWomanSlot,
|
|
"SxCPManSlot": SxCPManSlot,
|
|
"SxCPCharacterSlot": SxCPCharacterSlot,
|
|
"SxCPCharacterProfileSave": SxCPCharacterProfileSave,
|
|
"SxCPCharacterProfileLoad": SxCPCharacterProfileLoad,
|
|
}
|
|
|
|
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",
|
|
"SxCPWomanSlot": "SxCP Woman Slot",
|
|
"SxCPManSlot": "SxCP Man Slot",
|
|
"SxCPCharacterSlot": "SxCP Character Slot",
|
|
"SxCPCharacterProfileSave": "SxCP Character Profile Save",
|
|
"SxCPCharacterProfileLoad": "SxCP Character Profile Load",
|
|
}
|