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.
|
when you need different settings for each participant.
|
||||||
|
|
||||||
`SxCP Character Profile Save` extracts a reusable woman/man profile from
|
`SxCP Character Profile Save` extracts a reusable woman/man profile from
|
||||||
`metadata_json` or from manual fields. The profile stores age, body/body phrase,
|
`metadata_json`, a `character_slot`, or from manual fields. The profile stores
|
||||||
skin, hair, eyes, figure, and subject type. It only writes a file when
|
age, body/body phrase, skin, hair, eyes, figure, and subject type. To save a
|
||||||
the `Save Profile Now` button is clicked; otherwise it just outputs profile JSON
|
Woman Slot, connect `Woman Slot.character_slot` to
|
||||||
for direct wiring. Saved files are written under `profiles/<profile_name>.json`;
|
`Character Profile Save.character_slot`, set `source=character_slot`, enter a
|
||||||
saved profile files are ignored by git. The button is backed by the hidden
|
name, then click `Save Profile Now`. It only writes a file when the button is
|
||||||
`save_now` trigger and queues the workflow once.
|
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
|
`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
|
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.
|
the workflow once.
|
||||||
|
|
||||||
Connect the loader's `character_profile` output to `SxCP Prompt Builder`,
|
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
|
When loaded through `character_profile`, profile reuse applies to structured
|
||||||
rows and to the primary creator in Insta/OF pair mode. The outfit, scene, pose,
|
JSON-category single woman/man rows and to the primary creator in Insta/OF pair
|
||||||
expression, and composition can still change while the saved character
|
mode. When loaded through `character_cast`, the same saved appearance behaves
|
||||||
appearance remains stable.
|
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
|
`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
|
builder's optional `seed_config` input. When an axis is set to `random`, the
|
||||||
|
|||||||
+24
-7
@@ -989,7 +989,7 @@ class SxCPCharacterProfileSave:
|
|||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"profile_name": ("STRING", {"default": "saved_character"}),
|
"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"}),
|
"subject_type": (["woman", "man"], {"default": "woman"}),
|
||||||
"age": ("STRING", {"default": ""}),
|
"age": ("STRING", {"default": ""}),
|
||||||
"body": ("STRING", {"default": ""}),
|
"body": ("STRING", {"default": ""}),
|
||||||
@@ -1002,11 +1002,12 @@ class SxCPCharacterProfileSave:
|
|||||||
},
|
},
|
||||||
"optional": {
|
"optional": {
|
||||||
"metadata_json": ("STRING", {"default": "", "multiline": True}),
|
"metadata_json": ("STRING", {"default": "", "multiline": True}),
|
||||||
|
"character_slot": ("STRING", {"default": "", "multiline": True}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING")
|
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING", "STRING")
|
||||||
RETURN_NAMES = ("character_profile", "descriptor", "profile_name", "saved_path", "status")
|
RETURN_NAMES = ("character_profile", "descriptor", "profile_name", "saved_path", "status", "character_cast")
|
||||||
FUNCTION = "build"
|
FUNCTION = "build"
|
||||||
CATEGORY = "prompt_builder"
|
CATEGORY = "prompt_builder"
|
||||||
|
|
||||||
@@ -1024,11 +1025,13 @@ class SxCPCharacterProfileSave:
|
|||||||
figure,
|
figure,
|
||||||
save_now,
|
save_now,
|
||||||
metadata_json="",
|
metadata_json="",
|
||||||
|
character_slot="",
|
||||||
):
|
):
|
||||||
profile = build_character_profile_json(
|
profile = build_character_profile_json(
|
||||||
profile_name=profile_name,
|
profile_name=profile_name,
|
||||||
source=source,
|
source=source,
|
||||||
metadata_json=metadata_json or "",
|
metadata_json=metadata_json or "",
|
||||||
|
character_slot=character_slot or "",
|
||||||
subject_type=subject_type,
|
subject_type=subject_type,
|
||||||
age=age,
|
age=age,
|
||||||
body=body,
|
body=body,
|
||||||
@@ -1039,7 +1042,14 @@ class SxCPCharacterProfileSave:
|
|||||||
figure=figure,
|
figure=figure,
|
||||||
save_now=save_now,
|
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:
|
class SxCPCharacterProfileLoad:
|
||||||
@@ -1059,8 +1069,8 @@ class SxCPCharacterProfileLoad:
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING")
|
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING", "STRING")
|
||||||
RETURN_NAMES = ("character_profile", "descriptor", "profile_name", "saved_path", "status")
|
RETURN_NAMES = ("character_profile", "descriptor", "profile_name", "saved_path", "status", "character_cast")
|
||||||
FUNCTION = "build"
|
FUNCTION = "build"
|
||||||
CATEGORY = "prompt_builder"
|
CATEGORY = "prompt_builder"
|
||||||
|
|
||||||
@@ -1083,7 +1093,14 @@ class SxCPCharacterProfileLoad:
|
|||||||
rename_now=rename_now,
|
rename_now=rename_now,
|
||||||
rename_to=rename_to,
|
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:
|
class SxCPCaptionNaturalizer:
|
||||||
|
|||||||
+23
-1
@@ -2847,6 +2847,13 @@ def _row_from_profile_metadata(metadata_json: str | dict[str, Any] | None) -> di
|
|||||||
return row
|
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:
|
def _character_profile_descriptor(profile: dict[str, Any]) -> str:
|
||||||
subject = str(profile.get("subject_type") or profile.get("subject") or "person").strip()
|
subject = str(profile.get("subject_type") or profile.get("subject") or "person").strip()
|
||||||
return _descriptor_from_parts(
|
return _descriptor_from_parts(
|
||||||
@@ -2890,6 +2897,7 @@ def build_character_profile_json(
|
|||||||
profile_name: str = "",
|
profile_name: str = "",
|
||||||
source: str = "metadata_json",
|
source: str = "metadata_json",
|
||||||
metadata_json: str | dict[str, Any] | None = "",
|
metadata_json: str | dict[str, Any] | None = "",
|
||||||
|
character_slot: str | dict[str, Any] | None = "",
|
||||||
subject_type: str = "woman",
|
subject_type: str = "woman",
|
||||||
age: str = "",
|
age: str = "",
|
||||||
body: str = "",
|
body: str = "",
|
||||||
@@ -2900,7 +2908,21 @@ def build_character_profile_json(
|
|||||||
figure: str = "",
|
figure: str = "",
|
||||||
save_now: bool = False,
|
save_now: bool = False,
|
||||||
) -> dict[str, str]:
|
) -> 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)
|
row = _row_from_profile_metadata(metadata_json)
|
||||||
raw_profile = {
|
raw_profile = {
|
||||||
"profile_name": profile_name,
|
"profile_name": profile_name,
|
||||||
|
|||||||
Reference in New Issue
Block a user