Connect character profiles to slots
This commit is contained in:
@@ -181,12 +181,15 @@ nodes remain useful for one reusable primary character, but slots are better
|
||||
when you need different settings for each participant.
|
||||
|
||||
`SxCP Character Profile Save` extracts a reusable woman/man profile from
|
||||
`metadata_json` or from manual fields. The profile stores age, body/body phrase,
|
||||
skin, hair, eyes, figure, and subject type. It only writes a file when
|
||||
the `Save Profile Now` button is clicked; otherwise it just outputs profile JSON
|
||||
for direct wiring. Saved files are written under `profiles/<profile_name>.json`;
|
||||
saved profile files are ignored by git. The button is backed by the hidden
|
||||
`save_now` trigger and queues the workflow once.
|
||||
`metadata_json`, a `character_slot`, or from manual fields. The profile stores
|
||||
age, body/body phrase, skin, hair, eyes, figure, and subject type. To save a
|
||||
Woman Slot, connect `Woman Slot.character_slot` to
|
||||
`Character Profile Save.character_slot`, set `source=character_slot`, enter a
|
||||
name, then click `Save Profile Now`. It only writes a file when the button is
|
||||
clicked; otherwise it just outputs profile JSON for direct wiring. Saved files
|
||||
are written under `profiles/<profile_name>.json`; saved profile files are
|
||||
ignored by git. The button is backed by the hidden `save_now` trigger and queues
|
||||
the workflow once.
|
||||
|
||||
`SxCP Character Profile Load` has an `enabled` switch. When disabled, it returns
|
||||
an empty profile so connected prompt builders ignore it. When enabled, it loads
|
||||
@@ -202,12 +205,16 @@ buttons are backed by hidden `delete_now` and `rename_now` triggers and queue
|
||||
the workflow once.
|
||||
|
||||
Connect the loader's `character_profile` output to `SxCP Prompt Builder`,
|
||||
`SxCP Prompt Builder From Configs`, or `SxCP Insta/OF Prompt Pair`.
|
||||
`SxCP Prompt Builder From Configs`, or `SxCP Insta/OF Prompt Pair` for the
|
||||
older single-primary-character path. Connect `character_cast` instead when you
|
||||
want the loaded profile to act like a slot in a cast chain.
|
||||
|
||||
Profile reuse currently applies to structured JSON-category single woman/man
|
||||
rows and to the primary creator in Insta/OF pair mode. The outfit, scene, pose,
|
||||
expression, and composition can still change while the saved character
|
||||
appearance remains stable.
|
||||
When loaded through `character_profile`, profile reuse applies to structured
|
||||
JSON-category single woman/man rows and to the primary creator in Insta/OF pair
|
||||
mode. When loaded through `character_cast`, the same saved appearance behaves
|
||||
like an auto-labeled slot and can participate in couple/group casts. The outfit,
|
||||
scene, pose, expression, and composition can still change while the saved
|
||||
character appearance remains stable.
|
||||
|
||||
`SxCP Seed Control` outputs `seed_config`, which can be connected to the prompt
|
||||
builder's optional `seed_config` input. When an axis is set to `random`, the
|
||||
|
||||
+24
-7
@@ -989,7 +989,7 @@ class SxCPCharacterProfileSave:
|
||||
return {
|
||||
"required": {
|
||||
"profile_name": ("STRING", {"default": "saved_character"}),
|
||||
"source": (["metadata_json", "manual"], {"default": "metadata_json"}),
|
||||
"source": (["metadata_json", "character_slot", "manual"], {"default": "metadata_json"}),
|
||||
"subject_type": (["woman", "man"], {"default": "woman"}),
|
||||
"age": ("STRING", {"default": ""}),
|
||||
"body": ("STRING", {"default": ""}),
|
||||
@@ -1002,11 +1002,12 @@ class SxCPCharacterProfileSave:
|
||||
},
|
||||
"optional": {
|
||||
"metadata_json": ("STRING", {"default": "", "multiline": True}),
|
||||
"character_slot": ("STRING", {"default": "", "multiline": True}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING")
|
||||
RETURN_NAMES = ("character_profile", "descriptor", "profile_name", "saved_path", "status")
|
||||
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING", "STRING")
|
||||
RETURN_NAMES = ("character_profile", "descriptor", "profile_name", "saved_path", "status", "character_cast")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
@@ -1024,11 +1025,13 @@ class SxCPCharacterProfileSave:
|
||||
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,
|
||||
@@ -1039,7 +1042,14 @@ class SxCPCharacterProfileSave:
|
||||
figure=figure,
|
||||
save_now=save_now,
|
||||
)
|
||||
return profile["profile_json"], profile["descriptor"], profile["profile_name"], profile["saved_path"], profile["status"]
|
||||
return (
|
||||
profile["profile_json"],
|
||||
profile["descriptor"],
|
||||
profile["profile_name"],
|
||||
profile["saved_path"],
|
||||
profile["status"],
|
||||
profile["profile_json"],
|
||||
)
|
||||
|
||||
|
||||
class SxCPCharacterProfileLoad:
|
||||
@@ -1059,8 +1069,8 @@ class SxCPCharacterProfileLoad:
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING")
|
||||
RETURN_NAMES = ("character_profile", "descriptor", "profile_name", "saved_path", "status")
|
||||
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING", "STRING")
|
||||
RETURN_NAMES = ("character_profile", "descriptor", "profile_name", "saved_path", "status", "character_cast")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
@@ -1083,7 +1093,14 @@ class SxCPCharacterProfileLoad:
|
||||
rename_now=rename_now,
|
||||
rename_to=rename_to,
|
||||
)
|
||||
return profile["profile_json"], profile["descriptor"], profile["profile_name"], profile["saved_path"], profile["status"]
|
||||
return (
|
||||
profile["profile_json"],
|
||||
profile["descriptor"],
|
||||
profile["profile_name"],
|
||||
profile["saved_path"],
|
||||
profile["status"],
|
||||
profile["profile_json"],
|
||||
)
|
||||
|
||||
|
||||
class SxCPCaptionNaturalizer:
|
||||
|
||||
+23
-1
@@ -2847,6 +2847,13 @@ def _row_from_profile_metadata(metadata_json: str | dict[str, Any] | None) -> di
|
||||
return row
|
||||
|
||||
|
||||
def _row_from_character_slot(character_slot: str | dict[str, Any] | None) -> dict[str, Any]:
|
||||
slots = _parse_character_cast(character_slot)
|
||||
if not slots:
|
||||
return {}
|
||||
return slots[-1]
|
||||
|
||||
|
||||
def _character_profile_descriptor(profile: dict[str, Any]) -> str:
|
||||
subject = str(profile.get("subject_type") or profile.get("subject") or "person").strip()
|
||||
return _descriptor_from_parts(
|
||||
@@ -2890,6 +2897,7 @@ def build_character_profile_json(
|
||||
profile_name: str = "",
|
||||
source: str = "metadata_json",
|
||||
metadata_json: str | dict[str, Any] | None = "",
|
||||
character_slot: str | dict[str, Any] | None = "",
|
||||
subject_type: str = "woman",
|
||||
age: str = "",
|
||||
body: str = "",
|
||||
@@ -2900,7 +2908,21 @@ def build_character_profile_json(
|
||||
figure: str = "",
|
||||
save_now: bool = False,
|
||||
) -> dict[str, str]:
|
||||
if source == "metadata_json":
|
||||
if source == "character_slot":
|
||||
row = _row_from_character_slot(character_slot or metadata_json)
|
||||
raw_profile = {
|
||||
"profile_name": profile_name,
|
||||
"subject_type": row.get("subject_type") or subject_type,
|
||||
"age": row.get("age") or age,
|
||||
"body": row.get("body") or body,
|
||||
"body_phrase": row.get("body_phrase") or body_phrase,
|
||||
"skin": row.get("skin") or skin,
|
||||
"hair": row.get("hair") or hair,
|
||||
"eyes": row.get("eyes") or eyes,
|
||||
"figure": row.get("figure") or figure,
|
||||
"descriptor_detail": row.get("descriptor_detail") or "auto",
|
||||
}
|
||||
elif source == "metadata_json":
|
||||
row = _row_from_profile_metadata(metadata_json)
|
||||
raw_profile = {
|
||||
"profile_name": profile_name,
|
||||
|
||||
Reference in New Issue
Block a user