Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 78e39734b5 | |||
| 4c8edc0d3e | |||
| e2c4ecb853 | |||
| 3c54bb4bbe |
@@ -22,6 +22,7 @@ The node is registered as:
|
|||||||
- `prompt_builder / SxCP Cast Control`
|
- `prompt_builder / SxCP Cast Control`
|
||||||
- `prompt_builder / SxCP Cast Bias`
|
- `prompt_builder / SxCP Cast Bias`
|
||||||
- `prompt_builder / SxCP Generation Profile`
|
- `prompt_builder / SxCP Generation Profile`
|
||||||
|
- `prompt_builder / SxCP Style Pool`
|
||||||
- `prompt_builder / SxCP Ethnicity List`
|
- `prompt_builder / SxCP Ethnicity List`
|
||||||
- `prompt_builder / SxCP Hair Length`
|
- `prompt_builder / SxCP Hair Length`
|
||||||
- `prompt_builder / SxCP Hair Color`
|
- `prompt_builder / SxCP Hair Color`
|
||||||
@@ -93,6 +94,11 @@ node. For cleaner workflows, use the split nodes:
|
|||||||
`composition_config`. Themes such as `classical_library`,
|
`composition_config`. Themes such as `classical_library`,
|
||||||
`semi_public_affair`, `hotel_corridor`, `parking_garage`, and
|
`semi_public_affair`, `hotel_corridor`, `parking_garage`, and
|
||||||
`theater_backstage` keep scene and framing compatible.
|
`theater_backstage` keep scene and framing compatible.
|
||||||
|
- `SxCP Style Pool` outputs `style_config` for visual rendering style only.
|
||||||
|
It can force realistic/photo/cinematic/comic output independently from
|
||||||
|
category, action, pose, location, and camera. The previous colored-pencil
|
||||||
|
comic wording is available as the `comic_pinup_colored_pencil` preset instead
|
||||||
|
of being baked into hardcore pose prompts.
|
||||||
- `SxCP Generation Profile` outputs `generation_profile` for common behavior
|
- `SxCP Generation Profile` outputs `generation_profile` for common behavior
|
||||||
presets such as casual-clean, evocative-softcore, hardcore-intense,
|
presets such as casual-clean, evocative-softcore, hardcore-intense,
|
||||||
Krea2-friendly, or Flux-original. Its clothing and pose overrides can be
|
Krea2-friendly, or Flux-original. Its clothing and pose overrides can be
|
||||||
@@ -115,7 +121,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` or
|
`Advanced Filters`, `Seed Locker` or `Seed Control`, `Camera Control` or
|
||||||
`Camera Orbit Control`, `Location Theme` or `Location Pool` + `Composition Pool`,
|
`Camera Orbit Control`, `Location Theme` or `Location Pool` + `Composition Pool`,
|
||||||
`Woman Slot` / `Man Slot`, and `Character Profile`
|
`Style Pool`, `Woman Slot` / `Man Slot`, and `Character Profile`
|
||||||
into `Prompt Builder From Configs`.
|
into `Prompt Builder From Configs`.
|
||||||
|
|
||||||
## Scene-Chain v2 Nodes
|
## Scene-Chain v2 Nodes
|
||||||
@@ -128,6 +134,16 @@ blocking, action, performance, camera, composition, and lighting layers. Use
|
|||||||
`SxCP Hardcore Branch Options`, then render both sides through
|
`SxCP Hardcore Branch Options`, then render both sides through
|
||||||
`SxCP Scene Pair Output`.
|
`SxCP Scene Pair Output`.
|
||||||
|
|
||||||
|
Each layer can stay light on the main chain and take optional side-node inputs:
|
||||||
|
`SxCP Scene Layer Seed Options`, `SxCP Scene Cast Options`,
|
||||||
|
`SxCP Scene Character Options`, `SxCP Scene Wardrobe Options`,
|
||||||
|
`SxCP Scene Location Layout Options`, `SxCP Scene Set Dressing Options`,
|
||||||
|
`SxCP Scene Blocking Options`, `SxCP Scene Action Options`,
|
||||||
|
`SxCP Scene Performance Options`, `SxCP Scene Camera Options`,
|
||||||
|
`SxCP Scene Composition Options`, `SxCP Scene Lighting Options`, and
|
||||||
|
`SxCP Scene Branch Options`. These side nodes are chainable and only override
|
||||||
|
the layer they are connected to.
|
||||||
|
|
||||||
The current v2 output nodes intentionally reuse the existing builder,
|
The current v2 output nodes intentionally reuse the existing builder,
|
||||||
Insta/OF pair, and formatter metadata routes. This keeps old workflows working
|
Insta/OF pair, and formatter metadata routes. This keeps old workflows working
|
||||||
while giving new workflows a cleaner movie-scene structure.
|
while giving new workflows a cleaner movie-scene structure.
|
||||||
@@ -147,6 +163,11 @@ as one long chain:
|
|||||||
A dedicated v2 scene-chain Insta/OF branching demo is available at
|
A dedicated v2 scene-chain Insta/OF branching demo is available at
|
||||||
`examples/scene_chain_insta_of_branching_workflow.json`.
|
`examples/scene_chain_insta_of_branching_workflow.json`.
|
||||||
|
|
||||||
|
A proposed adapter-style v2 layout is available at
|
||||||
|
`examples/scene_chain_adapter_layout_workflow.json`. It keeps the main scene
|
||||||
|
chain in one center lane and parks layer-specific option nodes beside the layer
|
||||||
|
they override.
|
||||||
|
|
||||||
## Loop Nodes
|
## Loop Nodes
|
||||||
|
|
||||||
`SxCP For Loop Start` and `SxCP For Loop End` provide a lightweight replacement
|
`SxCP For Loop Start` and `SxCP For Loop End` provide a lightweight replacement
|
||||||
@@ -719,7 +740,7 @@ Example:
|
|||||||
"slug": "casual_clothes",
|
"slug": "casual_clothes",
|
||||||
"subject_type": "woman",
|
"subject_type": "woman",
|
||||||
"item_label": "Clothing",
|
"item_label": "Clothing",
|
||||||
"style": "tasteful adult fashion-editorial coloured-pencil comic illustration",
|
"style": "tasteful adult fashion-editorial scene",
|
||||||
"subcategories": [
|
"subcategories": [
|
||||||
{
|
{
|
||||||
"name": "Streetwear",
|
"name": "Streetwear",
|
||||||
|
|||||||
+14
@@ -20,11 +20,25 @@ SXCP_CATEGORY_CONFIG = "SXCP_CATEGORY_CONFIG"
|
|||||||
SXCP_CAST_CONFIG = "SXCP_CAST_CONFIG"
|
SXCP_CAST_CONFIG = "SXCP_CAST_CONFIG"
|
||||||
SXCP_GENERATION_PROFILE = "SXCP_GENERATION_PROFILE"
|
SXCP_GENERATION_PROFILE = "SXCP_GENERATION_PROFILE"
|
||||||
SXCP_INSTA_OF_OPTIONS = "SXCP_INSTA_OF_OPTIONS"
|
SXCP_INSTA_OF_OPTIONS = "SXCP_INSTA_OF_OPTIONS"
|
||||||
|
SXCP_STYLE_CONFIG = "SXCP_STYLE_CONFIG"
|
||||||
SXCP_HARDCORE_POSITION_CONFIG = "SXCP_HARDCORE_POSITION_CONFIG"
|
SXCP_HARDCORE_POSITION_CONFIG = "SXCP_HARDCORE_POSITION_CONFIG"
|
||||||
SXCP_CHARACTER_CAST = "SXCP_CHARACTER_CAST"
|
SXCP_CHARACTER_CAST = "SXCP_CHARACTER_CAST"
|
||||||
SXCP_CHARACTER_SLOT = "SXCP_CHARACTER_SLOT"
|
SXCP_CHARACTER_SLOT = "SXCP_CHARACTER_SLOT"
|
||||||
SXCP_CHARACTER_PROFILE = "SXCP_CHARACTER_PROFILE"
|
SXCP_CHARACTER_PROFILE = "SXCP_CHARACTER_PROFILE"
|
||||||
SXCP_SCENE = "SXCP_SCENE"
|
SXCP_SCENE = "SXCP_SCENE"
|
||||||
|
SXCP_SCENE_LAYER_SEED = "SXCP_SCENE_LAYER_SEED"
|
||||||
|
SXCP_SCENE_CAST_OPTIONS = "SXCP_SCENE_CAST_OPTIONS"
|
||||||
|
SXCP_SCENE_CHARACTER_OPTIONS = "SXCP_SCENE_CHARACTER_OPTIONS"
|
||||||
|
SXCP_SCENE_WARDROBE_OPTIONS = "SXCP_SCENE_WARDROBE_OPTIONS"
|
||||||
|
SXCP_SCENE_LOCATION_OPTIONS = "SXCP_SCENE_LOCATION_OPTIONS"
|
||||||
|
SXCP_SCENE_SET_OPTIONS = "SXCP_SCENE_SET_OPTIONS"
|
||||||
|
SXCP_SCENE_BLOCKING_OPTIONS = "SXCP_SCENE_BLOCKING_OPTIONS"
|
||||||
|
SXCP_SCENE_ACTION_OPTIONS = "SXCP_SCENE_ACTION_OPTIONS"
|
||||||
|
SXCP_SCENE_PERFORMANCE_OPTIONS = "SXCP_SCENE_PERFORMANCE_OPTIONS"
|
||||||
|
SXCP_SCENE_CAMERA_OPTIONS = "SXCP_SCENE_CAMERA_OPTIONS"
|
||||||
|
SXCP_SCENE_COMPOSITION_OPTIONS = "SXCP_SCENE_COMPOSITION_OPTIONS"
|
||||||
|
SXCP_SCENE_LIGHTING_OPTIONS = "SXCP_SCENE_LIGHTING_OPTIONS"
|
||||||
|
SXCP_SCENE_BRANCH_OPTIONS = "SXCP_SCENE_BRANCH_OPTIONS"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from .node_tooltips import install_input_tooltips as _install_input_tooltips
|
from .node_tooltips import install_input_tooltips as _install_input_tooltips
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class PromptFromConfigsRequest:
|
|||||||
hardcore_position_config: str | dict[str, Any] | None = ""
|
hardcore_position_config: str | dict[str, Any] | None = ""
|
||||||
location_config: str | dict[str, Any] | None = ""
|
location_config: str | dict[str, Any] | None = ""
|
||||||
composition_config: str | dict[str, Any] | None = ""
|
composition_config: str | dict[str, Any] | None = ""
|
||||||
|
style_config: str | dict[str, Any] | None = ""
|
||||||
extra_positive: str = ""
|
extra_positive: str = ""
|
||||||
extra_negative: str = ""
|
extra_negative: str = ""
|
||||||
|
|
||||||
@@ -82,6 +83,7 @@ def build_prompt_from_configs_result(
|
|||||||
"hardcore_position_config": request.hardcore_position_config or "",
|
"hardcore_position_config": request.hardcore_position_config or "",
|
||||||
"location_config": request.location_config or "",
|
"location_config": request.location_config or "",
|
||||||
"composition_config": request.composition_config or "",
|
"composition_config": request.composition_config or "",
|
||||||
|
"style_config": request.style_config or "",
|
||||||
}
|
}
|
||||||
return PromptFromConfigsRoute(
|
return PromptFromConfigsRoute(
|
||||||
row=deps.build_prompt(**build_kwargs),
|
row=deps.build_prompt(**build_kwargs),
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ class PromptBuildRequest:
|
|||||||
hardcore_position_config: str | dict[str, Any] | None = None
|
hardcore_position_config: str | dict[str, Any] | None = None
|
||||||
location_config: str | dict[str, Any] | None = None
|
location_config: str | dict[str, Any] | None = None
|
||||||
composition_config: str | dict[str, Any] | None = None
|
composition_config: str | dict[str, Any] | None = None
|
||||||
|
style_config: str | dict[str, Any] | None = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
@@ -226,6 +227,7 @@ def build_prompt_result(request: PromptBuildRequest, deps: PromptBuildDependenci
|
|||||||
request.hardcore_position_config,
|
request.hardcore_position_config,
|
||||||
parsed_location_config,
|
parsed_location_config,
|
||||||
parsed_composition_config,
|
parsed_composition_config,
|
||||||
|
request.style_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
if row.get("source") == "built_in_generator":
|
if row.get("source") == "built_in_generator":
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"subject_type": "woman",
|
"subject_type": "woman",
|
||||||
"item_label": "Clothing",
|
"item_label": "Clothing",
|
||||||
"style": "tasteful adult fashion-editorial coloured-pencil comic illustration with casual everyday styling",
|
"style": "tasteful adult fashion-editorial scene with casual everyday styling",
|
||||||
"positive_suffix": "Use crisp clean comic linework, soft fabric texture, detailed hatching, warm natural light, and tactile textured paper.",
|
"positive_suffix": "Use readable full outfits, clear fabric texture, natural light, coherent anatomy, and polished styling detail.",
|
||||||
"expression_pools": ["casual_observational_expressions"],
|
"expression_pools": ["casual_observational_expressions"],
|
||||||
"composition_pools": ["casual_fashion_compositions"],
|
"composition_pools": ["casual_fashion_compositions"],
|
||||||
"subcategories": [
|
"subcategories": [
|
||||||
@@ -833,8 +833,8 @@
|
|||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"subject_type": "man",
|
"subject_type": "man",
|
||||||
"item_label": "Clothing",
|
"item_label": "Clothing",
|
||||||
"style": "tasteful adult menswear fashion-editorial coloured-pencil comic illustration with casual everyday styling",
|
"style": "tasteful adult menswear fashion-editorial scene with casual everyday styling",
|
||||||
"positive_suffix": "Use crisp clean comic linework, structured fabric texture, detailed hatching, natural light, and tactile textured paper.",
|
"positive_suffix": "Use readable full outfits, structured fabric texture, natural light, coherent anatomy, and polished styling detail.",
|
||||||
"expression_pools": ["men_casual_expressions"],
|
"expression_pools": ["men_casual_expressions"],
|
||||||
"composition_pools": ["men_casual_compositions"],
|
"composition_pools": ["men_casual_compositions"],
|
||||||
"subcategories": [
|
"subcategories": [
|
||||||
@@ -1285,8 +1285,8 @@
|
|||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"subject_type": "couple",
|
"subject_type": "couple",
|
||||||
"item_label": "Clothing",
|
"item_label": "Clothing",
|
||||||
"style": "tasteful adult couple fashion-editorial coloured-pencil comic illustration with coordinated casual styling",
|
"style": "tasteful adult couple fashion-editorial scene with coordinated casual styling",
|
||||||
"positive_suffix": "Use crisp clean comic linework, readable full outfits, detailed hatching, warm natural light, and tactile textured paper.",
|
"positive_suffix": "Use readable coordinated outfits, clear fabric texture, warm natural light, coherent body placement, and polished styling detail.",
|
||||||
"expression_pools": ["couple_casual_expressions"],
|
"expression_pools": ["couple_casual_expressions"],
|
||||||
"composition_pools": ["couple_casual_compositions"],
|
"composition_pools": ["couple_casual_compositions"],
|
||||||
"subcategories": [
|
"subcategories": [
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"subject_type": "woman",
|
"subject_type": "woman",
|
||||||
"item_label": "Erotic outfit",
|
"item_label": "Erotic outfit",
|
||||||
"style": "explicit adult erotic fashion illustration, sensual pin-up coloured-pencil comic style, adults only",
|
"style": "explicit adult erotic fashion scene with sensual pin-up styling, adults only",
|
||||||
"positive_suffix": "Use crisp clean comic linework, detailed hatching, soft skin shading, tactile fabric texture, warm intimate lighting, and textured paper.",
|
"positive_suffix": "Use clear adult anatomy, readable erotic outfit construction, tactile fabric texture, warm intimate lighting, coherent body placement, and polished detail.",
|
||||||
"negative_prompt": "minors, childlike appearance, schoolgirl, childlike costume, non-consensual, coercion, violence, injury, watermark",
|
"negative_prompt": "minors, childlike appearance, schoolgirl, childlike costume, non-consensual, coercion, violence, injury, watermark",
|
||||||
"scene_pools": ["softcore_creator_scenes", "mirror_scenes"],
|
"scene_pools": ["softcore_creator_scenes", "mirror_scenes"],
|
||||||
"expression_pools": ["softcore_creator_expressions", "erotic_inviting_expressions"],
|
"expression_pools": ["softcore_creator_expressions", "erotic_inviting_expressions"],
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"subject_type": "configured_cast",
|
"subject_type": "configured_cast",
|
||||||
"item_label": "Sexual pose",
|
"item_label": "Sexual pose",
|
||||||
"style": "explicit consensual adult hardcore sex illustration, anatomically clear erotic comic pin-up style, adults only",
|
"style": "explicit consensual adult hardcore sex scene, anatomically clear body positioning, adults only",
|
||||||
"positive_suffix": "Use clear adult anatomy, visible sexual contact, intense body language, crisp comic linework, detailed hatching, warm erotic lighting, and tactile textured paper.",
|
"positive_suffix": "Use clear adult anatomy, visible sexual contact, readable limb placement, precise body orientation, coherent spatial depth, and intense body language.",
|
||||||
"negative_prompt": "minors, childlike appearance, teen, schoolgirl, incest, bestiality, non-consensual, coercion, rape, violence, injury, blood, gore, watermark",
|
"negative_prompt": "minors, childlike appearance, teen, schoolgirl, incest, bestiality, non-consensual, coercion, rape, violence, injury, blood, gore, watermark",
|
||||||
"scene_pools": ["hardcore_private_scenes"],
|
"scene_pools": ["hardcore_private_scenes"],
|
||||||
"expression_pools": ["hardcore_orgasm_expressions", "hardcore_messy_expressions"],
|
"expression_pools": ["hardcore_orgasm_expressions", "hardcore_messy_expressions"],
|
||||||
"composition_pools": ["hardcore_explicit_compositions"],
|
"composition_pools": ["hardcore_explicit_compositions"],
|
||||||
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Sexual pose: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit, hardcore, and anatomically clear, with visible genital contact and adult bodies only. {positive_suffix} Avoid: {negative_prompt}.",
|
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Sexual pose: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit, hardcore, and anatomically clear, with visible genital contact and adult bodies only. {positive_suffix} Avoid: {negative_prompt}.",
|
||||||
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, {item}, {scene}, {composition}, explicit consensual adult hardcore sex illustration",
|
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, {item}, {scene}, {composition}, explicit consensual adult hardcore sex scene",
|
||||||
"expressions": [
|
"expressions": [
|
||||||
"adult ahegao-style orgasm face",
|
"adult ahegao-style orgasm face",
|
||||||
"eyes rolled back with tongue out",
|
"eyes rolled back with tongue out",
|
||||||
@@ -97,9 +97,9 @@
|
|||||||
"position_family": "foreplay"
|
"position_family": "foreplay"
|
||||||
},
|
},
|
||||||
"item_label": "Foreplay action",
|
"item_label": "Foreplay action",
|
||||||
"positive_suffix": "Use clear adult body contact, readable hands and faces, visible undressing, exposed skin, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.",
|
"positive_suffix": "Use clear adult body contact, readable hands and faces, visible undressing, exposed skin, precise body orientation, and coherent spatial depth.",
|
||||||
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Foreplay action: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult body contact, kissing, caressing, undressing, visible arousal, exposed skin, and readable hand placement. {positive_suffix} Avoid: {negative_prompt}.",
|
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Foreplay action: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult body contact, kissing, caressing, undressing, visible arousal, exposed skin, and readable hand placement. {positive_suffix} Avoid: {negative_prompt}.",
|
||||||
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, foreplay teasing action: {item}, {scene}, {composition}, explicit consensual adult erotic foreplay illustration",
|
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, foreplay teasing action: {item}, {scene}, {composition}, explicit consensual adult erotic foreplay scene",
|
||||||
"scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
"scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||||
"expression_pools": ["hardcore_foreplay_expressions"],
|
"expression_pools": ["hardcore_foreplay_expressions"],
|
||||||
"composition_pools": ["foreplay_compositions"],
|
"composition_pools": ["foreplay_compositions"],
|
||||||
@@ -220,9 +220,9 @@
|
|||||||
"position_family": "manual"
|
"position_family": "manual"
|
||||||
},
|
},
|
||||||
"item_label": "Manual action",
|
"item_label": "Manual action",
|
||||||
"positive_suffix": "Use clear adult manual contact, readable hands, explicit body positioning, exposed skin, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.",
|
"positive_suffix": "Use clear adult manual contact, readable hands, explicit body positioning, exposed skin, precise hand placement, and coherent body orientation.",
|
||||||
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Manual action: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult manual stimulation, visible hands, exposed skin, clear body positioning, and readable reaction. {positive_suffix} Avoid: {negative_prompt}.",
|
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Manual action: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult manual stimulation, visible hands, exposed skin, clear body positioning, and readable reaction. {positive_suffix} Avoid: {negative_prompt}.",
|
||||||
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, manual stimulation action: {item}, {scene}, {composition}, explicit consensual adult manual stimulation illustration",
|
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, manual stimulation action: {item}, {scene}, {composition}, explicit consensual adult manual stimulation scene",
|
||||||
"scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
"scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||||
"expression_pools": ["hardcore_manual_expressions"],
|
"expression_pools": ["hardcore_manual_expressions"],
|
||||||
"composition_pools": ["manual_stimulation_compositions"],
|
"composition_pools": ["manual_stimulation_compositions"],
|
||||||
@@ -329,9 +329,9 @@
|
|||||||
"position_family": "interaction"
|
"position_family": "interaction"
|
||||||
},
|
},
|
||||||
"item_label": "Body interaction",
|
"item_label": "Body interaction",
|
||||||
"positive_suffix": "Use readable adult body contact, hands and mouth on skin, exposed skin, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.",
|
"positive_suffix": "Use readable adult body contact, hands and mouth on skin, exposed skin, clear head position, precise limb placement, and coherent body orientation.",
|
||||||
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Body interaction: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult body worship, close skin contact, mouth and hand placement, exposed skin, and readable body positioning. {positive_suffix} Avoid: {negative_prompt}.",
|
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Body interaction: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult body worship, close skin contact, mouth and hand placement, exposed skin, and readable body positioning. {positive_suffix} Avoid: {negative_prompt}.",
|
||||||
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, body worship action: {item}, {scene}, {composition}, explicit consensual adult body-contact illustration",
|
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, body worship action: {item}, {scene}, {composition}, explicit consensual adult body-contact scene",
|
||||||
"scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
"scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||||
"expression_pools": ["hardcore_interaction_expressions"],
|
"expression_pools": ["hardcore_interaction_expressions"],
|
||||||
"composition_pools": ["interaction_compositions"],
|
"composition_pools": ["interaction_compositions"],
|
||||||
@@ -442,9 +442,9 @@
|
|||||||
"position_family": "interaction"
|
"position_family": "interaction"
|
||||||
},
|
},
|
||||||
"item_label": "Transition action",
|
"item_label": "Transition action",
|
||||||
"positive_suffix": "Use readable adult movement, clothing being moved, hands guiding bodies, exposed skin, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.",
|
"positive_suffix": "Use readable adult movement, clothing being moved, hands guiding bodies, exposed skin, clear before-and-after body placement, and coherent spatial depth.",
|
||||||
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Transition action: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult undressing, position changes, visible hands, exposed skin, and clear movement from one sexual beat to the next. {positive_suffix} Avoid: {negative_prompt}.",
|
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Transition action: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult undressing, position changes, visible hands, exposed skin, and clear movement from one sexual beat to the next. {positive_suffix} Avoid: {negative_prompt}.",
|
||||||
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, clothing and position transition: {item}, {scene}, {composition}, explicit consensual adult transition illustration",
|
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, clothing and position transition: {item}, {scene}, {composition}, explicit consensual adult transition scene",
|
||||||
"scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
"scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||||
"expression_pools": ["hardcore_interaction_expressions"],
|
"expression_pools": ["hardcore_interaction_expressions"],
|
||||||
"composition_pools": ["interaction_compositions"],
|
"composition_pools": ["interaction_compositions"],
|
||||||
@@ -551,9 +551,9 @@
|
|||||||
"position_family": "interaction"
|
"position_family": "interaction"
|
||||||
},
|
},
|
||||||
"item_label": "Guidance action",
|
"item_label": "Guidance action",
|
||||||
"positive_suffix": "Use consensual adult control, readable hand placement, clear body positioning, exposed skin, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.",
|
"positive_suffix": "Use consensual adult control, readable hand placement, clear body positioning, exposed skin, precise contact points, and coherent body orientation.",
|
||||||
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Guidance action: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through consensual adult guidance, hair or wrist control, body positioning, visible hands, exposed skin, and clear power dynamic. {positive_suffix} Avoid: {negative_prompt}.",
|
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Guidance action: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through consensual adult guidance, hair or wrist control, body positioning, visible hands, exposed skin, and clear power dynamic. {positive_suffix} Avoid: {negative_prompt}.",
|
||||||
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, dominant guidance action: {item}, {scene}, {composition}, explicit consensual adult power-dynamic illustration",
|
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, dominant guidance action: {item}, {scene}, {composition}, explicit consensual adult power-dynamic scene",
|
||||||
"scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
"scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||||
"expression_pools": ["hardcore_interaction_expressions"],
|
"expression_pools": ["hardcore_interaction_expressions"],
|
||||||
"composition_pools": ["interaction_compositions"],
|
"composition_pools": ["interaction_compositions"],
|
||||||
@@ -665,9 +665,9 @@
|
|||||||
"position_family": "interaction"
|
"position_family": "interaction"
|
||||||
},
|
},
|
||||||
"item_label": "Camera performance",
|
"item_label": "Camera performance",
|
||||||
"positive_suffix": "Use creator-shot adult presentation, readable camera-facing pose, exposed skin, clear hand placement, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.",
|
"positive_suffix": "Use creator-shot adult presentation, readable camera-facing pose, exposed skin, clear hand placement, stable camera geography, and coherent subject framing.",
|
||||||
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Camera performance: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through camera-aware adult presentation, body opened or displayed to the viewer, visible hands, exposed skin, and clean creator-shot framing. {positive_suffix} Avoid: {negative_prompt}.",
|
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Camera performance: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through camera-aware adult presentation, body opened or displayed to the viewer, visible hands, exposed skin, and clean creator-shot framing. {positive_suffix} Avoid: {negative_prompt}.",
|
||||||
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, camera performance action: {item}, {scene}, {composition}, explicit consensual adult creator-performance illustration",
|
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, camera performance action: {item}, {scene}, {composition}, explicit consensual adult creator-performance scene",
|
||||||
"scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
"scene_pools": ["hardcore_private_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||||
"expression_pools": ["hardcore_interaction_expressions"],
|
"expression_pools": ["hardcore_interaction_expressions"],
|
||||||
"composition_pools": ["camera_performance_compositions"],
|
"composition_pools": ["camera_performance_compositions"],
|
||||||
@@ -773,9 +773,9 @@
|
|||||||
"position_family": "interaction"
|
"position_family": "interaction"
|
||||||
},
|
},
|
||||||
"item_label": "Group interaction",
|
"item_label": "Group interaction",
|
||||||
"positive_suffix": "Use readable adult group coordination, clear body spacing, visible watching/touching roles, exposed skin, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.",
|
"positive_suffix": "Use readable adult group coordination, clear body spacing, visible watching/touching roles, exposed skin, precise role placement, and coherent spatial depth.",
|
||||||
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Group interaction: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult group coordination, watching, guiding hands, body presentation, exposed skin, and clear role spacing. {positive_suffix} Avoid: {negative_prompt}.",
|
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Group interaction: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult group coordination, watching, guiding hands, body presentation, exposed skin, and clear role spacing. {positive_suffix} Avoid: {negative_prompt}.",
|
||||||
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, group coordination action: {item}, {scene}, {composition}, explicit consensual adult group-interaction illustration",
|
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, group coordination action: {item}, {scene}, {composition}, explicit consensual adult group-interaction scene",
|
||||||
"scene_pools": ["hardcore_group_scenes", "hardcore_private_scenes"],
|
"scene_pools": ["hardcore_group_scenes", "hardcore_private_scenes"],
|
||||||
"expression_pools": ["hardcore_group_expressions"],
|
"expression_pools": ["hardcore_group_expressions"],
|
||||||
"composition_pools": ["group_coordination_compositions"],
|
"composition_pools": ["group_coordination_compositions"],
|
||||||
@@ -879,9 +879,9 @@
|
|||||||
"position_family": "interaction"
|
"position_family": "interaction"
|
||||||
},
|
},
|
||||||
"item_label": "Aftermath interaction",
|
"item_label": "Aftermath interaction",
|
||||||
"positive_suffix": "Use adult post-sex intimacy, readable bodies and hands, visible aftermath details, warm erotic lighting, crisp comic linework, detailed hatching, and tactile textured paper.",
|
"positive_suffix": "Use adult post-sex intimacy, readable bodies and hands, visible aftermath details, clear body placement, and coherent spatial depth.",
|
||||||
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Aftermath interaction: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult post-sex closeness, cleanup, visible skin, relaxed body contact, aftermath details, and readable hands and faces. {positive_suffix} Avoid: {negative_prompt}.",
|
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Aftermath interaction: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit through adult post-sex closeness, cleanup, visible skin, relaxed body contact, aftermath details, and readable hands and faces. {positive_suffix} Avoid: {negative_prompt}.",
|
||||||
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, aftercare and cleanup action: {item}, {scene}, {composition}, explicit consensual adult post-sex aftermath illustration",
|
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, aftercare and cleanup action: {item}, {scene}, {composition}, explicit consensual adult post-sex aftermath scene",
|
||||||
"scene_pools": ["hardcore_climax_scenes", "hardcore_bed_scenes", "hardcore_private_scenes"],
|
"scene_pools": ["hardcore_climax_scenes", "hardcore_bed_scenes", "hardcore_private_scenes"],
|
||||||
"expression_pools": ["hardcore_aftercare_expressions"],
|
"expression_pools": ["hardcore_aftercare_expressions"],
|
||||||
"composition_pools": ["aftercare_compositions"],
|
"composition_pools": ["aftercare_compositions"],
|
||||||
|
|||||||
@@ -80,6 +80,16 @@ V2 scene-chain display nodes: `SxCP Scene Cast`, `SxCP Scene Character`,
|
|||||||
`SxCP Scene Branch Pair`, `SxCP Softcore Branch Options`, and
|
`SxCP Scene Branch Pair`, `SxCP Softcore Branch Options`, and
|
||||||
`SxCP Hardcore Branch Options`.
|
`SxCP Hardcore Branch Options`.
|
||||||
|
|
||||||
|
V2 scene-chain side option nodes: `SxCP Scene Layer Seed Options`,
|
||||||
|
`SxCP Scene Cast Options`, `SxCP Scene Character Options`,
|
||||||
|
`SxCP Scene Wardrobe Options`, `SxCP Scene Location Layout Options`,
|
||||||
|
`SxCP Scene Set Dressing Options`, `SxCP Scene Blocking Options`,
|
||||||
|
`SxCP Scene Action Options`, `SxCP Scene Performance Options`,
|
||||||
|
`SxCP Scene Camera Options`, `SxCP Scene Composition Options`,
|
||||||
|
`SxCP Scene Lighting Options`, and `SxCP Scene Branch Options`. These nodes
|
||||||
|
feed typed option sockets into the main scene chain so the visible chain can
|
||||||
|
stay organized by movie-scene layer while deeper knobs remain adjacent.
|
||||||
|
|
||||||
Core helper ownership:
|
Core helper ownership:
|
||||||
|
|
||||||
| Python module | What it owns |
|
| Python module | What it owns |
|
||||||
@@ -110,6 +120,7 @@ Core helper ownership:
|
|||||||
| `subject_context.py` | Row subject-context routing for single, couple, configured-cast, group, and layout subjects, combining appearance policy, cast metadata, and generator subject pools. |
|
| `subject_context.py` | Row subject-context routing for single, couple, configured-cast, group, and layout subjects, combining appearance policy, cast metadata, and generator subject pools. |
|
||||||
| `row_subject_route.py` | Row subject route orchestration, character slot/profile precedence, configured-cast POV labels, visible cast descriptor collection, and descriptor prompt cleanup. |
|
| `row_subject_route.py` | Row subject route orchestration, character slot/profile precedence, configured-cast POV labels, visible cast descriptor collection, and descriptor prompt cleanup. |
|
||||||
| `location_config.py` | Location/composition preset schemas, themed location packs, custom location/composition parsing, pool merge behavior, and location/composition config parsing. |
|
| `location_config.py` | Location/composition preset schemas, themed location packs, custom location/composition parsing, pool merge behavior, and location/composition config parsing. |
|
||||||
|
| `style_config.py` | Visual style preset schemas, style-pool merge behavior, positive style suffixes, and style negative-prompt merging. |
|
||||||
| `row_location.py` | Built-in row location/composition config application, deterministic scene/composition choice, source metadata, and legacy prompt/caption rewrites. |
|
| `row_location.py` | Built-in row location/composition config application, deterministic scene/composition choice, source metadata, and legacy prompt/caption rewrites. |
|
||||||
| `row_expression.py` | Row expression cleanup, expression route resolution, expression intensity weighting, character-slot/cast expression override resolution, per-character expression selection, and action-aware character-expression sanitizing. |
|
| `row_expression.py` | Row expression cleanup, expression route resolution, expression intensity weighting, character-slot/cast expression override resolution, per-character expression selection, and action-aware character-expression sanitizing. |
|
||||||
| `row_pools.py` | Row scene/expression/pose/composition pool routing, category inheritance handling, runtime location/composition pool overrides, and generator fallback pools. |
|
| `row_pools.py` | Row scene/expression/pose/composition pool routing, category inheritance handling, runtime location/composition pool overrides, and generator fallback pools. |
|
||||||
@@ -163,9 +174,9 @@ recoverable.
|
|||||||
|
|
||||||
| Node | Important inputs | Important outputs |
|
| Node | Important inputs | Important outputs |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `SxCP Prompt Builder` | category, subcategory, seed, optional config nodes | `prompt`, `negative_prompt`, `caption`, `metadata_json`, `category`, `subcategory` |
|
| `SxCP Prompt Builder` | category, subcategory, seed, optional config nodes including location/composition/style | `prompt`, `negative_prompt`, `caption`, `metadata_json`, `category`, `subcategory` |
|
||||||
| `SxCP Prompt Builder From Configs` | category/cast/profile/filter/config node outputs | Same as `SxCP Prompt Builder` |
|
| `SxCP Prompt Builder From Configs` | category/cast/profile/filter/config node outputs including style_config | Same as `SxCP Prompt Builder` |
|
||||||
| `SxCP Insta/OF Prompt Pair` | options, seed_config, character_cast, location/composition/camera, hardcore_position_config | `softcore_prompt`, `hardcore_prompt`, both negatives, both captions, `shared_descriptor`, `metadata_json` |
|
| `SxCP Insta/OF Prompt Pair` | options, seed_config, character_cast, location/composition/style/camera, hardcore_position_config | `softcore_prompt`, `hardcore_prompt`, both negatives, both captions, `shared_descriptor`, `metadata_json` |
|
||||||
| `SxCP Krea2 Formatter` | `source_text`, connectable `metadata_json`, target | `krea_prompt`, both pair prompts if pair metadata exists, negative outputs, method, `route_trace_json` |
|
| `SxCP Krea2 Formatter` | `source_text`, connectable `metadata_json`, target | `krea_prompt`, both pair prompts if pair metadata exists, negative outputs, method, `route_trace_json` |
|
||||||
| `SxCP SDXL Formatter` | `source_text`, connectable `metadata_json`, target, style/quality preset | `sdxl_prompt`, both pair prompts if pair metadata exists, negative outputs, method, `route_trace_json` |
|
| `SxCP SDXL Formatter` | `source_text`, connectable `metadata_json`, target, style/quality preset | `sdxl_prompt`, both pair prompts if pair metadata exists, negative outputs, method, `route_trace_json` |
|
||||||
| `SxCP Caption Naturalizer` | `source_text`, connectable `metadata_json`, target | `natural_caption`, method, `route_trace_json` |
|
| `SxCP Caption Naturalizer` | `source_text`, connectable `metadata_json`, target | `natural_caption`, method, `route_trace_json` |
|
||||||
@@ -185,6 +196,7 @@ These recipes identify the intended road before editing prompt text.
|
|||||||
| Change only outfit/clothing | Character clothing or category content route | Keep `person_seed`, `scene_seed`, `pose_seed`; change `content_seed`; slot `softcore_outfit` overrides Insta/OF outfit | `SxCP Character Clothing`, `pair_options.py`, category item templates |
|
| Change only outfit/clothing | Character clothing or category content route | Keep `person_seed`, `scene_seed`, `pose_seed`; change `content_seed`; slot `softcore_outfit` overrides Insta/OF outfit | `SxCP Character Clothing`, `pair_options.py`, category item templates |
|
||||||
| Force a custom location | `SxCP Location Pool` or `SxCP Location Theme` -> builder/pair | `combine_mode=replace` to force; `add` to mix with category scenes | `_scene_pool`, `row_location.apply_location_config_to_legacy_row`, camera scene adapter |
|
| Force a custom location | `SxCP Location Pool` or `SxCP Location Theme` -> builder/pair | `combine_mode=replace` to force; `add` to mix with category scenes | `_scene_pool`, `row_location.apply_location_config_to_legacy_row`, camera scene adapter |
|
||||||
| Force a custom frame/composition | `SxCP Composition Pool` or `SxCP Location Theme` -> builder/pair | `combine_mode=replace` to force; `add` to mix | `_composition_pool`, `row_location.apply_composition_config_to_legacy_row`, Krea composition phrase |
|
| Force a custom frame/composition | `SxCP Composition Pool` or `SxCP Location Theme` -> builder/pair | `combine_mode=replace` to force; `add` to mix | `_composition_pool`, `row_location.apply_composition_config_to_legacy_row`, Krea composition phrase |
|
||||||
|
| Force realistic/photo/comic style | `SxCP Style Pool` -> builder/pair/Scene Start | `combine_mode=replace` to override category style; `add` to append; choose realistic/photo/comic preset | `style_config.py`, `row_rendering.resolve_row_text_fields`, row `style` / `positive_suffix` metadata |
|
||||||
| Use Qwen/orbit camera geometry | Qwen/orbit node -> camera_config -> builder/pair | For pair, use `softcore_camera_config` and/or `hardcore_camera_config`; set mode from config in options | `_camera_config_with_mode`, `_camera_directive`, `_camera_scene_directive_for_context` |
|
| Use Qwen/orbit camera geometry | Qwen/orbit node -> camera_config -> builder/pair | For pair, use `softcore_camera_config` and/or `hardcore_camera_config`; set mode from config in options | `_camera_config_with_mode`, `_camera_directive`, `_camera_scene_directive_for_context` |
|
||||||
| Use Krea2 for only hard prompt from a pair | Pair `metadata_json` -> Krea2 Formatter | `target=hardcore`, `input_hint=metadata_json` or auto with metadata connected | `_insta_pair_to_krea`, hard row fields |
|
| Use Krea2 for only hard prompt from a pair | Pair `metadata_json` -> Krea2 Formatter | `target=hardcore`, `input_hint=metadata_json` or auto with metadata connected | `_insta_pair_to_krea`, hard row fields |
|
||||||
| Convert builder output to SDXL tags | Builder/pair metadata -> SDXL Formatter | Use metadata input; set `target`; select style and quality preset | `sdxl_tag_routes.py`, `sdxl_tag_policy.py`, compatibility wrappers `_row_core_tags` / `_soft_tags` / `_hard_tags` |
|
| Convert builder output to SDXL tags | Builder/pair metadata -> SDXL Formatter | Use metadata input; set `target`; select style and quality preset | `sdxl_tag_routes.py`, `sdxl_tag_policy.py`, compatibility wrappers `_row_core_tags` / `_soft_tags` / `_hard_tags` |
|
||||||
|
|||||||
@@ -0,0 +1,960 @@
|
|||||||
|
{
|
||||||
|
"last_node_id": 45,
|
||||||
|
"last_link_id": 56,
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"type": "SxCPGlobalSeed",
|
||||||
|
"pos": [-1900, -1040],
|
||||||
|
"size": [300, 90],
|
||||||
|
"flags": {},
|
||||||
|
"order": 0,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "seed", "type": "INT", "links": null, "slot_index": 0},
|
||||||
|
{"name": "seed_config", "type": "STRING", "links": [1], "slot_index": 1},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPGlobalSeed"},
|
||||||
|
"widgets_values": [20260821]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"type": "SxCPSceneStart",
|
||||||
|
"pos": [-1260, -600],
|
||||||
|
"size": [360, 250],
|
||||||
|
"flags": {},
|
||||||
|
"order": 1,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "seed_config", "type": "STRING", "link": 1}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [2], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneStart"},
|
||||||
|
"widgets_values": [1, 41, 20260821, "raw", "provocative_erotic", "random", "balanced", "sxcppnl7", true]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"type": "SxCPSceneCastOptions",
|
||||||
|
"pos": [-840, -1040],
|
||||||
|
"size": [340, 180],
|
||||||
|
"flags": {},
|
||||||
|
"order": 2,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "cast_options", "type": "STRING", "links": [11], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneCastOptions"},
|
||||||
|
"widgets_values": ["replace", "mixed_couple", 1, 1, "woman_a", "none"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"type": "SxCPSceneCast",
|
||||||
|
"pos": [-840, -600],
|
||||||
|
"size": [360, 150],
|
||||||
|
"flags": {},
|
||||||
|
"order": 3,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 2},
|
||||||
|
{"name": "cast_options", "type": "STRING", "link": 11}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [12], "slot_index": 0},
|
||||||
|
{"name": "cast_config", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 2},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 3}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneCast"},
|
||||||
|
"widgets_values": ["mixed_couple", 1, 1, "woman_a", "none"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"type": "SxCPSceneCharacterOptions",
|
||||||
|
"pos": [-420, -1040],
|
||||||
|
"size": [390, 260],
|
||||||
|
"flags": {},
|
||||||
|
"order": 4,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "character_options", "type": "STRING", "links": [14], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneCharacterOptions"},
|
||||||
|
"widgets_values": ["replace", "medium", "visible", "enabled", 0.45, 0.35, 0.85, "creator remains visually central"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"type": "SxCPSceneCharacter",
|
||||||
|
"pos": [-420, -760],
|
||||||
|
"size": [390, 360],
|
||||||
|
"flags": {},
|
||||||
|
"order": 5,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 12},
|
||||||
|
{"name": "character_options", "type": "STRING", "link": 14},
|
||||||
|
{"name": "seed_options", "type": "STRING", "link": 9}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [15], "slot_index": 0},
|
||||||
|
{"name": "character_cast", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "character_slot", "type": "STRING", "links": null, "slot_index": 2},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 3},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 4}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneCharacter"},
|
||||||
|
"widgets_values": [true, "woman", "A", -1, "25-year-old adult", "random", "random", "random", "medium", true, 0.45, "visible", -1.0, -1.0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"type": "SxCPSceneCharacter",
|
||||||
|
"pos": [-420, -310],
|
||||||
|
"size": [390, 360],
|
||||||
|
"flags": {},
|
||||||
|
"order": 6,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 15},
|
||||||
|
{"name": "seed_options", "type": "STRING", "link": 13}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [16], "slot_index": 0},
|
||||||
|
{"name": "character_cast", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "character_slot", "type": "STRING", "links": null, "slot_index": 2},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 3},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 4}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneCharacter"},
|
||||||
|
"widgets_values": [true, "man", "A", -1, "40-year-old adult", "random", "random", "average", "compact", true, 0.35, "visible", -1.0, -1.0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"type": "SxCPSceneWardrobeOptions",
|
||||||
|
"pos": [40, -1040],
|
||||||
|
"size": [410, 320],
|
||||||
|
"flags": {},
|
||||||
|
"order": 7,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "wardrobe_options", "type": "STRING", "links": [18], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneWardrobeOptions"},
|
||||||
|
"widgets_values": ["replace", "woman", "A", "minimal", "explicit_nude", true, "black lace lingerie set with stockings and garter details", "", "thin necklace, small earrings", "softcore outfit only; hardcore branch should not repeat outfit tokens"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"type": "SxCPSceneWardrobe",
|
||||||
|
"pos": [40, -760],
|
||||||
|
"size": [390, 250],
|
||||||
|
"flags": {},
|
||||||
|
"order": 8,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 16},
|
||||||
|
{"name": "wardrobe_options", "type": "STRING", "link": 18},
|
||||||
|
{"name": "seed_options", "type": "STRING", "link": 17}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [19], "slot_index": 0},
|
||||||
|
{"name": "character_cast", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 2},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 3}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneWardrobe"},
|
||||||
|
"widgets_values": [true, "woman", "A", "minimal", "black lace lingerie set with stockings and garter details", "fully nude", ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"type": "SxCPSceneWardrobeOptions",
|
||||||
|
"pos": [40, 10],
|
||||||
|
"size": [410, 290],
|
||||||
|
"flags": {},
|
||||||
|
"order": 9,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "wardrobe_options", "type": "STRING", "links": [20], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneWardrobeOptions"},
|
||||||
|
"widgets_values": ["replace", "man", "A", "full", "dressed", true, "half-open black shirt with dark trousers", "shirt open, lower body mostly off-camera when explicit action is framed", "", "partner outfit stays simpler than creator outfit"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 11,
|
||||||
|
"type": "SxCPSceneWardrobe",
|
||||||
|
"pos": [40, -360],
|
||||||
|
"size": [390, 250],
|
||||||
|
"flags": {},
|
||||||
|
"order": 10,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 19},
|
||||||
|
{"name": "wardrobe_options", "type": "STRING", "link": 20},
|
||||||
|
{"name": "seed_options", "type": "STRING", "link": 21}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [22], "slot_index": 0},
|
||||||
|
{"name": "character_cast", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 2},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 3}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneWardrobe"},
|
||||||
|
"widgets_values": [true, "man", "A", "full", "half-open black shirt with dark trousers", "shirt open, lower body mostly off-camera when explicit action is framed", ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"type": "SxCPSceneLocationLayoutOptions",
|
||||||
|
"pos": [500, -1040],
|
||||||
|
"size": [410, 250],
|
||||||
|
"flags": {},
|
||||||
|
"order": 11,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "location_options", "type": "STRING", "links": [23], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneLocationLayoutOptions"},
|
||||||
|
"widgets_values": ["replace", "near desk edge, laptop corner, chair back", "warm work desks, laptop tables, glass partition seams", "repeated desk rows, plants, tall windows", "semi_public", "semi_public", "coworking lounge layout that survives camera rerolls"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13,
|
||||||
|
"type": "SxCPSceneLocation",
|
||||||
|
"pos": [500, -760],
|
||||||
|
"size": [410, 210],
|
||||||
|
"flags": {},
|
||||||
|
"order": 12,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 22},
|
||||||
|
{"name": "location_options", "type": "STRING", "link": 23},
|
||||||
|
{"name": "seed_options", "type": "STRING", "link": 24}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [25], "slot_index": 0},
|
||||||
|
{"name": "location_config", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 2},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 3}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneLocation"},
|
||||||
|
"widgets_values": [true, "replace", "custom_only", "coworking lounge with tall windows, warm desks, glass partitions, plants, and polished office-lounge surfaces", "shared location base"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 14,
|
||||||
|
"type": "SxCPSceneSetDressingOptions",
|
||||||
|
"pos": [500, -170],
|
||||||
|
"size": [410, 230],
|
||||||
|
"flags": {},
|
||||||
|
"order": 13,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "set_options", "type": "STRING", "links": [26], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneSetDressingOptions"},
|
||||||
|
"widgets_values": ["replace", "laptop corner and polished tabletop line", "desks, chairs, glass seams, plant rows", "phone, coffee cup, folded jacket", "warm wood, glass reflections, muted office light", "keep props beside or behind the action, not blocking the subject"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"type": "SxCPSceneSetDressing",
|
||||||
|
"pos": [500, -470],
|
||||||
|
"size": [410, 250],
|
||||||
|
"flags": {},
|
||||||
|
"order": 14,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 25},
|
||||||
|
{"name": "set_options", "type": "STRING", "link": 26}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [27], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneSetDressing"},
|
||||||
|
"widgets_values": [true, "", "", "", ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 16,
|
||||||
|
"type": "SxCPSceneBlockingOptions",
|
||||||
|
"pos": [960, -1040],
|
||||||
|
"size": [410, 270],
|
||||||
|
"flags": {},
|
||||||
|
"order": 15,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "blocking_options", "type": "STRING", "links": [28], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneBlockingOptions"},
|
||||||
|
"widgets_values": ["replace", "custom", "woman close to the desk edge with room depth behind her", "man close enough for the hardcore branch but not forced into the softcore pose", "three_quarter", "foreground", "subjects dominate the frame while the coworking pattern remains visible", "shared blocking base before branch-specific action"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 17,
|
||||||
|
"type": "SxCPSceneBlocking",
|
||||||
|
"pos": [960, -760],
|
||||||
|
"size": [410, 250],
|
||||||
|
"flags": {},
|
||||||
|
"order": 16,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 27},
|
||||||
|
{"name": "blocking_options", "type": "STRING", "link": 28}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [29], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneBlocking"},
|
||||||
|
"widgets_values": [true, "custom", "", "", ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 18,
|
||||||
|
"type": "SxCPSceneActionOptions",
|
||||||
|
"pos": [960, -170],
|
||||||
|
"size": [410, 190],
|
||||||
|
"flags": {},
|
||||||
|
"order": 17,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "action_options", "type": "STRING", "links": [30], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneActionOptions"},
|
||||||
|
"widgets_values": ["replace", "softcore", "softcore_tease", "no_change", "soft branch starts as an outfit tease; hardcore branch replaces action through the action filter"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 19,
|
||||||
|
"type": "SxCPSceneAction",
|
||||||
|
"pos": [960, -470],
|
||||||
|
"size": [410, 210],
|
||||||
|
"flags": {},
|
||||||
|
"order": 18,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 29},
|
||||||
|
{"name": "action_options", "type": "STRING", "link": 30},
|
||||||
|
{"name": "seed_options", "type": "STRING", "link": 31}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [32], "slot_index": 0},
|
||||||
|
{"name": "hardcore_position_config", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 2},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 3}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneAction"},
|
||||||
|
"widgets_values": [true, "regular", "no_change", ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 20,
|
||||||
|
"type": "SxCPScenePerformanceOptions",
|
||||||
|
"pos": [1420, -1040],
|
||||||
|
"size": [410, 250],
|
||||||
|
"flags": {},
|
||||||
|
"order": 19,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "performance_options", "type": "STRING", "links": [33], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPScenePerformanceOptions"},
|
||||||
|
"widgets_values": ["replace", "enabled", "fixed", 0.55, "camera", "on_body", "posed", "controlled creator-camera expression"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 21,
|
||||||
|
"type": "SxCPScenePerformance",
|
||||||
|
"pos": [1420, -760],
|
||||||
|
"size": [410, 180],
|
||||||
|
"flags": {},
|
||||||
|
"order": 20,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 32},
|
||||||
|
{"name": "performance_options", "type": "STRING", "link": 33}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [34], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPScenePerformance"},
|
||||||
|
"widgets_values": [true, "fixed", 0.55, ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 22,
|
||||||
|
"type": "SxCPSceneCameraOptions",
|
||||||
|
"pos": [1420, -150],
|
||||||
|
"size": [410, 170],
|
||||||
|
"flags": {},
|
||||||
|
"order": 21,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "camera_options", "type": "STRING", "links": [35], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneCameraOptions"},
|
||||||
|
"widgets_values": ["replace", "from_camera_config", true, "camera should adapt to the location layout instead of replacing it"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23,
|
||||||
|
"type": "SxCPSceneCamera",
|
||||||
|
"pos": [1420, -530],
|
||||||
|
"size": [410, 330],
|
||||||
|
"flags": {},
|
||||||
|
"order": 22,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 34},
|
||||||
|
{"name": "camera_options", "type": "STRING", "link": 35}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [36], "slot_index": 0},
|
||||||
|
{"name": "camera_config", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 2},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 3}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneCamera"},
|
||||||
|
"widgets_values": [true, "standard", "three_quarter", "eye_level", "auto", "auto", "vertical_story", "auto", "strong", "compact", ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 24,
|
||||||
|
"type": "SxCPSceneCompositionOptions",
|
||||||
|
"pos": [1880, -1040],
|
||||||
|
"size": [410, 200],
|
||||||
|
"flags": {},
|
||||||
|
"order": 23,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "composition_options", "type": "STRING", "links": [37], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneCompositionOptions"},
|
||||||
|
"widgets_values": ["replace", "body", "three_quarter", "clear", "subject remains dominant while desk rows and glass seams prove the location"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 25,
|
||||||
|
"type": "SxCPSceneComposition",
|
||||||
|
"pos": [1880, -760],
|
||||||
|
"size": [410, 210],
|
||||||
|
"flags": {},
|
||||||
|
"order": 24,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 36},
|
||||||
|
{"name": "composition_options", "type": "STRING", "link": 37}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [38], "slot_index": 0},
|
||||||
|
{"name": "composition_config", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 2},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 3}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneComposition"},
|
||||||
|
"widgets_values": [true, "replace", "no_outfit_check", "", ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 26,
|
||||||
|
"type": "SxCPSceneLightingOptions",
|
||||||
|
"pos": [1880, -150],
|
||||||
|
"size": [410, 220],
|
||||||
|
"flags": {},
|
||||||
|
"order": 25,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "lighting_options", "type": "STRING", "links": [39], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneLightingOptions"},
|
||||||
|
"widgets_values": ["replace", "window_light", "soft", "medium", "warm", "evening", "soft office-window light with practical lamps in the background"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 27,
|
||||||
|
"type": "SxCPSceneLighting",
|
||||||
|
"pos": [1880, -470],
|
||||||
|
"size": [410, 210],
|
||||||
|
"flags": {},
|
||||||
|
"order": 26,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 38},
|
||||||
|
{"name": "lighting_options", "type": "STRING", "link": 39}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [40], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneLighting"},
|
||||||
|
"widgets_values": [true, "auto", "auto", "auto", "auto", ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 28,
|
||||||
|
"type": "SxCPSceneBranchOptions",
|
||||||
|
"pos": [2340, -1040],
|
||||||
|
"size": [390, 180],
|
||||||
|
"flags": {},
|
||||||
|
"order": 27,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "branch_options", "type": "STRING", "links": [41, 44, 47], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneBranchOptions"},
|
||||||
|
"widgets_values": ["replace", "both", "same_creator_same_room", "hybrid", "same cast, same coworking room, different explicitness"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 29,
|
||||||
|
"type": "SxCPSceneBranchPair",
|
||||||
|
"pos": [2340, -600],
|
||||||
|
"size": [340, 130],
|
||||||
|
"flags": {},
|
||||||
|
"order": 28,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 40},
|
||||||
|
{"name": "branch_options", "type": "STRING", "link": 41},
|
||||||
|
{"name": "seed_options", "type": "STRING", "link": 42}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "softcore_scene", "type": "STRING", "links": [43], "slot_index": 0},
|
||||||
|
{"name": "hardcore_scene", "type": "STRING", "links": [45], "slot_index": 1},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 2},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 3}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneBranchPair"},
|
||||||
|
"widgets_values": ["same_creator_same_room", "hybrid"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 30,
|
||||||
|
"type": "SxCPSoftcoreBranchOptions",
|
||||||
|
"pos": [2760, -760],
|
||||||
|
"size": [390, 260],
|
||||||
|
"flags": {},
|
||||||
|
"order": 29,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 43},
|
||||||
|
{"name": "branch_options", "type": "STRING", "link": 44}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [49], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSoftcoreBranchOptions"},
|
||||||
|
"widgets_values": ["same_as_hardcore", "lingerie_tease", true, 0.45, "from_camera_config", "compact", ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 31,
|
||||||
|
"type": "SxCPHardcoreActionFilter",
|
||||||
|
"pos": [2340, -310],
|
||||||
|
"size": [360, 300],
|
||||||
|
"flags": {},
|
||||||
|
"order": 30,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "hardcore_position_config", "type": "STRING", "links": [46], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPHardcoreActionFilter"},
|
||||||
|
"widgets_values": ["penetration_only", false, false, true, false, false, false, false, false, false, false]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 32,
|
||||||
|
"type": "SxCPHardcoreBranchOptions",
|
||||||
|
"pos": [2760, -350],
|
||||||
|
"size": [390, 360],
|
||||||
|
"flags": {},
|
||||||
|
"order": 31,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "link": 45},
|
||||||
|
{"name": "hardcore_position_config", "type": "STRING", "link": 46},
|
||||||
|
{"name": "branch_options", "type": "STRING", "link": 47},
|
||||||
|
{"name": "seed_options", "type": "STRING", "link": 48}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "scene", "type": "STRING", "links": [50], "slot_index": 0},
|
||||||
|
{"name": "hardcore_position_config", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 2},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 3}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPHardcoreBranchOptions"},
|
||||||
|
"widgets_values": ["couple", 1, 1, "hardcore", true, 0.85, "explicit_nude", "from_camera_config", "compact", "balanced", ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 33,
|
||||||
|
"type": "SxCPScenePairOutput",
|
||||||
|
"pos": [3220, -600],
|
||||||
|
"size": [430, 290],
|
||||||
|
"flags": {},
|
||||||
|
"order": 32,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "softcore_scene", "type": "STRING", "link": 49},
|
||||||
|
{"name": "hardcore_scene", "type": "STRING", "link": 50}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "softcore_prompt", "type": "STRING", "links": [53], "slot_index": 0},
|
||||||
|
{"name": "hardcore_prompt", "type": "STRING", "links": [54], "slot_index": 1},
|
||||||
|
{"name": "softcore_negative_prompt", "type": "STRING", "links": null, "slot_index": 2},
|
||||||
|
{"name": "hardcore_negative_prompt", "type": "STRING", "links": null, "slot_index": 3},
|
||||||
|
{"name": "softcore_caption", "type": "STRING", "links": null, "slot_index": 4},
|
||||||
|
{"name": "hardcore_caption", "type": "STRING", "links": null, "slot_index": 5},
|
||||||
|
{"name": "shared_descriptor", "type": "STRING", "links": null, "slot_index": 6},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": [51, 52], "slot_index": 7},
|
||||||
|
{"name": "scene_metadata_json", "type": "STRING", "links": null, "slot_index": 8}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPScenePairOutput"},
|
||||||
|
"widgets_values": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 34,
|
||||||
|
"type": "SxCPKrea2Formatter",
|
||||||
|
"pos": [3720, -760],
|
||||||
|
"size": [390, 270],
|
||||||
|
"flags": {},
|
||||||
|
"order": 33,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "metadata_json", "type": "STRING", "link": 51}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "krea_prompt", "type": "STRING", "links": null, "slot_index": 0},
|
||||||
|
{"name": "negative_prompt", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "krea_softcore_prompt", "type": "STRING", "links": [55], "slot_index": 2},
|
||||||
|
{"name": "krea_hardcore_prompt", "type": "STRING", "links": [56], "slot_index": 3},
|
||||||
|
{"name": "softcore_negative_prompt", "type": "STRING", "links": null, "slot_index": 4},
|
||||||
|
{"name": "hardcore_negative_prompt", "type": "STRING", "links": null, "slot_index": 5},
|
||||||
|
{"name": "method", "type": "STRING", "links": null, "slot_index": 6},
|
||||||
|
{"name": "route_trace_json", "type": "STRING", "links": null, "slot_index": 7}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPKrea2Formatter"},
|
||||||
|
"widgets_values": ["", "metadata_json", "auto", "balanced", "preserve", false, "", ""]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 35,
|
||||||
|
"type": "SxCPCaptionNaturalizer",
|
||||||
|
"pos": [3720, -370],
|
||||||
|
"size": [390, 240],
|
||||||
|
"flags": {},
|
||||||
|
"order": 34,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "metadata_json", "type": "STRING", "link": 52}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "natural_caption", "type": "STRING", "links": null, "slot_index": 0},
|
||||||
|
{"name": "method", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "route_trace_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPCaptionNaturalizer"},
|
||||||
|
"widgets_values": ["", "metadata_json", "training_dense", "balanced", "drop_style_tail", "sxcppnl7", true, "auto"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 36,
|
||||||
|
"type": "SxCPPreviewAnyAsText",
|
||||||
|
"pos": [4200, -900],
|
||||||
|
"size": [420, 180],
|
||||||
|
"flags": {},
|
||||||
|
"order": 35,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "value", "type": "*", "link": 53}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "text", "type": "STRING", "links": null, "slot_index": 0}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPPreviewAnyAsText"},
|
||||||
|
"widgets_values": ["Raw softcore prompt preview", "auto", 30000]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 37,
|
||||||
|
"type": "SxCPPreviewAnyAsText",
|
||||||
|
"pos": [4200, -690],
|
||||||
|
"size": [420, 180],
|
||||||
|
"flags": {},
|
||||||
|
"order": 36,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "value", "type": "*", "link": 54}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "text", "type": "STRING", "links": null, "slot_index": 0}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPPreviewAnyAsText"},
|
||||||
|
"widgets_values": ["Raw hardcore prompt preview", "auto", 30000]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 38,
|
||||||
|
"type": "SxCPPreviewAnyAsText",
|
||||||
|
"pos": [4200, -480],
|
||||||
|
"size": [420, 180],
|
||||||
|
"flags": {},
|
||||||
|
"order": 37,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "value", "type": "*", "link": 55}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "text", "type": "STRING", "links": null, "slot_index": 0}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPPreviewAnyAsText"},
|
||||||
|
"widgets_values": ["Krea softcore prompt preview", "auto", 30000]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 39,
|
||||||
|
"type": "SxCPPreviewAnyAsText",
|
||||||
|
"pos": [4200, -270],
|
||||||
|
"size": [420, 180],
|
||||||
|
"flags": {},
|
||||||
|
"order": 38,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "value", "type": "*", "link": 56}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "text", "type": "STRING", "links": null, "slot_index": 0}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPPreviewAnyAsText"},
|
||||||
|
"widgets_values": ["Krea hardcore prompt preview", "auto", 30000]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 40,
|
||||||
|
"type": "Note",
|
||||||
|
"pos": [-1900, -470],
|
||||||
|
"size": [560, 260],
|
||||||
|
"flags": {},
|
||||||
|
"order": 39,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [],
|
||||||
|
"properties": {},
|
||||||
|
"widgets_values": [
|
||||||
|
"Proposed adapter layout: the center row is the mental-model chain (scene start -> cast -> characters -> wardrobe -> location -> set -> blocking -> action -> performance -> camera -> composition -> lighting -> branch). Adapter nodes sit above/below the layer they override. The seed adapter bus on the left is chained once and reused by character, wardrobe, location, action, and hardcore branch nodes."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 41,
|
||||||
|
"type": "SxCPSceneLayerSeedOptions",
|
||||||
|
"pos": [-1900, -900],
|
||||||
|
"size": [340, 170],
|
||||||
|
"flags": {},
|
||||||
|
"order": 40,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "seed_options", "type": "STRING", "links": [3], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneLayerSeedOptions"},
|
||||||
|
"widgets_values": ["character", "fixed", 20260831, "person", "same_for_all_rows", "replace_layer"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 42,
|
||||||
|
"type": "SxCPSceneLayerSeedOptions",
|
||||||
|
"pos": [-1900, -710],
|
||||||
|
"size": [340, 170],
|
||||||
|
"flags": {},
|
||||||
|
"order": 41,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "seed_options", "type": "STRING", "link": 3}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "seed_options", "type": "STRING", "links": [4], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneLayerSeedOptions"},
|
||||||
|
"widgets_values": ["wardrobe", "fixed", 20260832, "content", "same_for_all_rows", "add"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 43,
|
||||||
|
"type": "SxCPSceneLayerSeedOptions",
|
||||||
|
"pos": [-1540, -900],
|
||||||
|
"size": [340, 170],
|
||||||
|
"flags": {},
|
||||||
|
"order": 42,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "seed_options", "type": "STRING", "link": 4}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "seed_options", "type": "STRING", "links": [5], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneLayerSeedOptions"},
|
||||||
|
"widgets_values": ["location", "fixed", 20260833, "scene", "same_for_all_rows", "add"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 44,
|
||||||
|
"type": "SxCPSceneLayerSeedOptions",
|
||||||
|
"pos": [-1540, -710],
|
||||||
|
"size": [340, 170],
|
||||||
|
"flags": {},
|
||||||
|
"order": 43,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "seed_options", "type": "STRING", "link": 5}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "seed_options", "type": "STRING", "links": [6], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneLayerSeedOptions"},
|
||||||
|
"widgets_values": ["action", "fixed", 20260834, "pose", "same_for_all_rows", "add"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 45,
|
||||||
|
"type": "SxCPSceneLayerSeedOptions",
|
||||||
|
"pos": [-1540, -520],
|
||||||
|
"size": [340, 170],
|
||||||
|
"flags": {},
|
||||||
|
"order": 44,
|
||||||
|
"mode": 0,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "seed_options", "type": "STRING", "link": 6}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{"name": "seed_options", "type": "STRING", "links": [9, 13, 17, 21, 24, 31, 42, 48], "slot_index": 0},
|
||||||
|
{"name": "summary", "type": "STRING", "links": null, "slot_index": 1},
|
||||||
|
{"name": "metadata_json", "type": "STRING", "links": null, "slot_index": 2}
|
||||||
|
],
|
||||||
|
"properties": {"Node name for S&R": "SxCPSceneLayerSeedOptions"},
|
||||||
|
"widgets_values": ["hardcore_branch", "fixed", 20260835, "pose", "same_for_all_rows", "add"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"links": [
|
||||||
|
[1, 1, 1, 2, 0, "STRING"],
|
||||||
|
[2, 2, 0, 4, 0, "STRING"],
|
||||||
|
[3, 41, 0, 42, 0, "STRING"],
|
||||||
|
[4, 42, 0, 43, 0, "STRING"],
|
||||||
|
[5, 43, 0, 44, 0, "STRING"],
|
||||||
|
[6, 44, 0, 45, 0, "STRING"],
|
||||||
|
[9, 45, 0, 6, 2, "STRING"],
|
||||||
|
[11, 3, 0, 4, 1, "STRING"],
|
||||||
|
[12, 4, 0, 6, 0, "STRING"],
|
||||||
|
[13, 45, 0, 7, 1, "STRING"],
|
||||||
|
[14, 5, 0, 6, 1, "STRING"],
|
||||||
|
[15, 6, 0, 7, 0, "STRING"],
|
||||||
|
[16, 7, 0, 9, 0, "STRING"],
|
||||||
|
[17, 45, 0, 9, 2, "STRING"],
|
||||||
|
[18, 8, 0, 9, 1, "STRING"],
|
||||||
|
[19, 9, 0, 11, 0, "STRING"],
|
||||||
|
[20, 10, 0, 11, 1, "STRING"],
|
||||||
|
[21, 45, 0, 11, 2, "STRING"],
|
||||||
|
[22, 11, 0, 13, 0, "STRING"],
|
||||||
|
[23, 12, 0, 13, 1, "STRING"],
|
||||||
|
[24, 45, 0, 13, 2, "STRING"],
|
||||||
|
[25, 13, 0, 15, 0, "STRING"],
|
||||||
|
[26, 14, 0, 15, 1, "STRING"],
|
||||||
|
[27, 15, 0, 17, 0, "STRING"],
|
||||||
|
[28, 16, 0, 17, 1, "STRING"],
|
||||||
|
[29, 17, 0, 19, 0, "STRING"],
|
||||||
|
[30, 18, 0, 19, 1, "STRING"],
|
||||||
|
[31, 45, 0, 19, 2, "STRING"],
|
||||||
|
[32, 19, 0, 21, 0, "STRING"],
|
||||||
|
[33, 20, 0, 21, 1, "STRING"],
|
||||||
|
[34, 21, 0, 23, 0, "STRING"],
|
||||||
|
[35, 22, 0, 23, 1, "STRING"],
|
||||||
|
[36, 23, 0, 25, 0, "STRING"],
|
||||||
|
[37, 24, 0, 25, 1, "STRING"],
|
||||||
|
[38, 25, 0, 27, 0, "STRING"],
|
||||||
|
[39, 26, 0, 27, 1, "STRING"],
|
||||||
|
[40, 27, 0, 29, 0, "STRING"],
|
||||||
|
[41, 28, 0, 29, 1, "STRING"],
|
||||||
|
[42, 45, 0, 29, 2, "STRING"],
|
||||||
|
[43, 29, 0, 30, 0, "STRING"],
|
||||||
|
[44, 28, 0, 30, 1, "STRING"],
|
||||||
|
[45, 29, 1, 32, 0, "STRING"],
|
||||||
|
[46, 31, 0, 32, 1, "STRING"],
|
||||||
|
[47, 28, 0, 32, 2, "STRING"],
|
||||||
|
[48, 45, 0, 32, 3, "STRING"],
|
||||||
|
[49, 30, 0, 33, 0, "STRING"],
|
||||||
|
[50, 32, 0, 33, 1, "STRING"],
|
||||||
|
[51, 33, 7, 34, 0, "STRING"],
|
||||||
|
[52, 33, 7, 35, 0, "STRING"],
|
||||||
|
[53, 33, 0, 36, 0, "STRING"],
|
||||||
|
[54, 33, 1, 37, 0, "STRING"],
|
||||||
|
[55, 34, 2, 38, 0, "STRING"],
|
||||||
|
[56, 34, 3, 39, 0, "STRING"]
|
||||||
|
],
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"title": "Seed Adapter Bus",
|
||||||
|
"bounding": [-1930, -1090, 760, 780],
|
||||||
|
"color": "#4d6b8f",
|
||||||
|
"font_size": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Main Scene Chain",
|
||||||
|
"bounding": [-1290, -810, 3610, 900],
|
||||||
|
"color": "#3f789e",
|
||||||
|
"font_size": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Layer Option Adapters",
|
||||||
|
"bounding": [-870, -1090, 3220, 1180],
|
||||||
|
"color": "#6b5a8f",
|
||||||
|
"font_size": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Softcore/Hardcore Branch Adapters",
|
||||||
|
"bounding": [2310, -1090, 880, 1160],
|
||||||
|
"color": "#8a5a5a",
|
||||||
|
"font_size": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Pair Output, Formatters, Persistent Text Previews",
|
||||||
|
"bounding": [3190, -950, 1470, 900],
|
||||||
|
"color": "#4d7f45",
|
||||||
|
"font_size": 24
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"config": {},
|
||||||
|
"extra": {
|
||||||
|
"ds": {
|
||||||
|
"scale": 0.52,
|
||||||
|
"offset": [1290, 665]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": 0.4
|
||||||
|
}
|
||||||
@@ -29,6 +29,7 @@ SXCP_COMPOSITION_CONFIG = "SXCP_COMPOSITION_CONFIG"
|
|||||||
SXCP_CATEGORY_CONFIG = "SXCP_CATEGORY_CONFIG"
|
SXCP_CATEGORY_CONFIG = "SXCP_CATEGORY_CONFIG"
|
||||||
SXCP_CAST_CONFIG = "SXCP_CAST_CONFIG"
|
SXCP_CAST_CONFIG = "SXCP_CAST_CONFIG"
|
||||||
SXCP_GENERATION_PROFILE = "SXCP_GENERATION_PROFILE"
|
SXCP_GENERATION_PROFILE = "SXCP_GENERATION_PROFILE"
|
||||||
|
SXCP_STYLE_CONFIG = "SXCP_STYLE_CONFIG"
|
||||||
SXCP_HARDCORE_POSITION_CONFIG = "SXCP_HARDCORE_POSITION_CONFIG"
|
SXCP_HARDCORE_POSITION_CONFIG = "SXCP_HARDCORE_POSITION_CONFIG"
|
||||||
SXCP_CHARACTER_CAST = "SXCP_CHARACTER_CAST"
|
SXCP_CHARACTER_CAST = "SXCP_CHARACTER_CAST"
|
||||||
SXCP_CHARACTER_PROFILE = "SXCP_CHARACTER_PROFILE"
|
SXCP_CHARACTER_PROFILE = "SXCP_CHARACTER_PROFILE"
|
||||||
@@ -64,6 +65,7 @@ class SxCPPromptBuilder:
|
|||||||
"camera_config": (SXCP_CAMERA_CONFIG,),
|
"camera_config": (SXCP_CAMERA_CONFIG,),
|
||||||
"location_config": (SXCP_LOCATION_CONFIG,),
|
"location_config": (SXCP_LOCATION_CONFIG,),
|
||||||
"composition_config": (SXCP_COMPOSITION_CONFIG,),
|
"composition_config": (SXCP_COMPOSITION_CONFIG,),
|
||||||
|
"style_config": (SXCP_STYLE_CONFIG,),
|
||||||
"character_profile": (SXCP_CHARACTER_PROFILE,),
|
"character_profile": (SXCP_CHARACTER_PROFILE,),
|
||||||
"character_cast": (SXCP_CHARACTER_CAST,),
|
"character_cast": (SXCP_CHARACTER_CAST,),
|
||||||
"hardcore_position_config": (SXCP_HARDCORE_POSITION_CONFIG,),
|
"hardcore_position_config": (SXCP_HARDCORE_POSITION_CONFIG,),
|
||||||
@@ -101,6 +103,7 @@ class SxCPPromptBuilder:
|
|||||||
camera_config="",
|
camera_config="",
|
||||||
location_config="",
|
location_config="",
|
||||||
composition_config="",
|
composition_config="",
|
||||||
|
style_config="",
|
||||||
character_profile="",
|
character_profile="",
|
||||||
character_cast="",
|
character_cast="",
|
||||||
hardcore_position_config="",
|
hardcore_position_config="",
|
||||||
@@ -137,6 +140,7 @@ class SxCPPromptBuilder:
|
|||||||
camera_config=camera_config or "",
|
camera_config=camera_config or "",
|
||||||
location_config=location_config or "",
|
location_config=location_config or "",
|
||||||
composition_config=composition_config or "",
|
composition_config=composition_config or "",
|
||||||
|
style_config=style_config or "",
|
||||||
character_profile=character_profile or "",
|
character_profile=character_profile or "",
|
||||||
character_cast=character_cast or "",
|
character_cast=character_cast or "",
|
||||||
hardcore_position_config=hardcore_position_config or "",
|
hardcore_position_config=hardcore_position_config or "",
|
||||||
@@ -170,6 +174,7 @@ class SxCPPromptBuilderFromConfigs:
|
|||||||
"camera_config": (SXCP_CAMERA_CONFIG,),
|
"camera_config": (SXCP_CAMERA_CONFIG,),
|
||||||
"location_config": (SXCP_LOCATION_CONFIG,),
|
"location_config": (SXCP_LOCATION_CONFIG,),
|
||||||
"composition_config": (SXCP_COMPOSITION_CONFIG,),
|
"composition_config": (SXCP_COMPOSITION_CONFIG,),
|
||||||
|
"style_config": (SXCP_STYLE_CONFIG,),
|
||||||
"character_profile": (SXCP_CHARACTER_PROFILE,),
|
"character_profile": (SXCP_CHARACTER_PROFILE,),
|
||||||
"character_cast": (SXCP_CHARACTER_CAST,),
|
"character_cast": (SXCP_CHARACTER_CAST,),
|
||||||
"hardcore_position_config": (SXCP_HARDCORE_POSITION_CONFIG,),
|
"hardcore_position_config": (SXCP_HARDCORE_POSITION_CONFIG,),
|
||||||
@@ -197,6 +202,7 @@ class SxCPPromptBuilderFromConfigs:
|
|||||||
camera_config="",
|
camera_config="",
|
||||||
location_config="",
|
location_config="",
|
||||||
composition_config="",
|
composition_config="",
|
||||||
|
style_config="",
|
||||||
character_profile="",
|
character_profile="",
|
||||||
character_cast="",
|
character_cast="",
|
||||||
hardcore_position_config="",
|
hardcore_position_config="",
|
||||||
@@ -215,6 +221,7 @@ class SxCPPromptBuilderFromConfigs:
|
|||||||
camera_config=camera_config or "",
|
camera_config=camera_config or "",
|
||||||
location_config=location_config or "",
|
location_config=location_config or "",
|
||||||
composition_config=composition_config or "",
|
composition_config=composition_config or "",
|
||||||
|
style_config=style_config or "",
|
||||||
character_profile=character_profile or "",
|
character_profile=character_profile or "",
|
||||||
character_cast=character_cast or "",
|
character_cast=character_cast or "",
|
||||||
hardcore_position_config=hardcore_position_config or "",
|
hardcore_position_config=hardcore_position_config or "",
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ SXCP_CHARACTER_CAST = "SXCP_CHARACTER_CAST"
|
|||||||
SXCP_CHARACTER_PROFILE = "SXCP_CHARACTER_PROFILE"
|
SXCP_CHARACTER_PROFILE = "SXCP_CHARACTER_PROFILE"
|
||||||
SXCP_ETHNICITY_LIST = "SXCP_ETHNICITY_LIST"
|
SXCP_ETHNICITY_LIST = "SXCP_ETHNICITY_LIST"
|
||||||
SXCP_FILTER_CONFIG = "SXCP_FILTER_CONFIG"
|
SXCP_FILTER_CONFIG = "SXCP_FILTER_CONFIG"
|
||||||
|
SXCP_STYLE_CONFIG = "SXCP_STYLE_CONFIG"
|
||||||
|
|
||||||
|
|
||||||
class SxCPInstaOFOptions:
|
class SxCPInstaOFOptions:
|
||||||
@@ -130,6 +131,7 @@ class SxCPInstaOFPromptPair:
|
|||||||
"hardcore_camera_config": (SXCP_CAMERA_CONFIG,),
|
"hardcore_camera_config": (SXCP_CAMERA_CONFIG,),
|
||||||
"location_config": (SXCP_LOCATION_CONFIG,),
|
"location_config": (SXCP_LOCATION_CONFIG,),
|
||||||
"composition_config": (SXCP_COMPOSITION_CONFIG,),
|
"composition_config": (SXCP_COMPOSITION_CONFIG,),
|
||||||
|
"style_config": (SXCP_STYLE_CONFIG,),
|
||||||
"character_profile": (SXCP_CHARACTER_PROFILE,),
|
"character_profile": (SXCP_CHARACTER_PROFILE,),
|
||||||
"character_cast": (SXCP_CHARACTER_CAST,),
|
"character_cast": (SXCP_CHARACTER_CAST,),
|
||||||
"hardcore_position_config": (SXCP_HARDCORE_POSITION_CONFIG,),
|
"hardcore_position_config": (SXCP_HARDCORE_POSITION_CONFIG,),
|
||||||
@@ -170,6 +172,7 @@ class SxCPInstaOFPromptPair:
|
|||||||
hardcore_camera_config="",
|
hardcore_camera_config="",
|
||||||
location_config="",
|
location_config="",
|
||||||
composition_config="",
|
composition_config="",
|
||||||
|
style_config="",
|
||||||
character_profile="",
|
character_profile="",
|
||||||
character_cast="",
|
character_cast="",
|
||||||
hardcore_position_config="",
|
hardcore_position_config="",
|
||||||
@@ -196,6 +199,7 @@ class SxCPInstaOFPromptPair:
|
|||||||
hardcore_camera_config=hardcore_camera_config or "",
|
hardcore_camera_config=hardcore_camera_config or "",
|
||||||
location_config=location_config or "",
|
location_config=location_config or "",
|
||||||
composition_config=composition_config or "",
|
composition_config=composition_config or "",
|
||||||
|
style_config=style_config or "",
|
||||||
character_profile=character_profile or "",
|
character_profile=character_profile or "",
|
||||||
character_cast=character_cast or "",
|
character_cast=character_cast or "",
|
||||||
hardcore_position_config=hardcore_position_config or "",
|
hardcore_position_config=hardcore_position_config or "",
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ try:
|
|||||||
location_pool_preset_choices,
|
location_pool_preset_choices,
|
||||||
location_theme_choices,
|
location_theme_choices,
|
||||||
)
|
)
|
||||||
|
from .style_config import (
|
||||||
|
build_style_config_json,
|
||||||
|
style_combine_mode_choices,
|
||||||
|
style_pool_preset_choices,
|
||||||
|
)
|
||||||
except ImportError: # Allows local smoke tests from the repository root.
|
except ImportError: # Allows local smoke tests from the repository root.
|
||||||
from category_cast_config import (
|
from category_cast_config import (
|
||||||
build_cast_config_json,
|
build_cast_config_json,
|
||||||
@@ -41,6 +46,11 @@ except ImportError: # Allows local smoke tests from the repository root.
|
|||||||
location_pool_preset_choices,
|
location_pool_preset_choices,
|
||||||
location_theme_choices,
|
location_theme_choices,
|
||||||
)
|
)
|
||||||
|
from style_config import (
|
||||||
|
build_style_config_json,
|
||||||
|
style_combine_mode_choices,
|
||||||
|
style_pool_preset_choices,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
SXCP_CATEGORY_CONFIG = "SXCP_CATEGORY_CONFIG"
|
SXCP_CATEGORY_CONFIG = "SXCP_CATEGORY_CONFIG"
|
||||||
@@ -48,6 +58,7 @@ SXCP_LOCATION_CONFIG = "SXCP_LOCATION_CONFIG"
|
|||||||
SXCP_COMPOSITION_CONFIG = "SXCP_COMPOSITION_CONFIG"
|
SXCP_COMPOSITION_CONFIG = "SXCP_COMPOSITION_CONFIG"
|
||||||
SXCP_CAST_CONFIG = "SXCP_CAST_CONFIG"
|
SXCP_CAST_CONFIG = "SXCP_CAST_CONFIG"
|
||||||
SXCP_SEED_CONFIG = "SXCP_SEED_CONFIG"
|
SXCP_SEED_CONFIG = "SXCP_SEED_CONFIG"
|
||||||
|
SXCP_STYLE_CONFIG = "SXCP_STYLE_CONFIG"
|
||||||
|
|
||||||
|
|
||||||
class SxCPCategoryPreset:
|
class SxCPCategoryPreset:
|
||||||
@@ -178,6 +189,51 @@ class SxCPLocationTheme:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SxCPStylePool:
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"enabled": ("BOOLEAN", {"default": True}),
|
||||||
|
"combine_mode": (style_combine_mode_choices(), {"default": "replace"}),
|
||||||
|
"preset": (style_pool_preset_choices(), {"default": "realistic_photo"}),
|
||||||
|
"custom_style": ("STRING", {"default": "", "multiline": True}),
|
||||||
|
"custom_positive_suffix": ("STRING", {"default": "", "multiline": True}),
|
||||||
|
"custom_negative": ("STRING", {"default": "", "multiline": True}),
|
||||||
|
},
|
||||||
|
"optional": {
|
||||||
|
"style_config": (SXCP_STYLE_CONFIG,),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = (SXCP_STYLE_CONFIG, "STRING")
|
||||||
|
RETURN_NAMES = ("style_config", "summary")
|
||||||
|
FUNCTION = "build"
|
||||||
|
CATEGORY = "prompt_builder"
|
||||||
|
|
||||||
|
def build(
|
||||||
|
self,
|
||||||
|
enabled,
|
||||||
|
combine_mode,
|
||||||
|
preset,
|
||||||
|
custom_style,
|
||||||
|
custom_positive_suffix,
|
||||||
|
custom_negative,
|
||||||
|
style_config="",
|
||||||
|
):
|
||||||
|
config = build_style_config_json(
|
||||||
|
enabled=enabled,
|
||||||
|
combine_mode=combine_mode,
|
||||||
|
preset=preset,
|
||||||
|
custom_style=custom_style or "",
|
||||||
|
custom_positive_suffix=custom_positive_suffix or "",
|
||||||
|
custom_negative=custom_negative or "",
|
||||||
|
style_config=style_config or "",
|
||||||
|
)
|
||||||
|
parsed = json.loads(config)
|
||||||
|
return config, parsed.get("summary", "")
|
||||||
|
|
||||||
|
|
||||||
class SxCPCastControl:
|
class SxCPCastControl:
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
@@ -313,6 +369,7 @@ NODE_CLASS_MAPPINGS = {
|
|||||||
"SxCPLocationPool": SxCPLocationPool,
|
"SxCPLocationPool": SxCPLocationPool,
|
||||||
"SxCPCompositionPool": SxCPCompositionPool,
|
"SxCPCompositionPool": SxCPCompositionPool,
|
||||||
"SxCPLocationTheme": SxCPLocationTheme,
|
"SxCPLocationTheme": SxCPLocationTheme,
|
||||||
|
"SxCPStylePool": SxCPStylePool,
|
||||||
"SxCPCastControl": SxCPCastControl,
|
"SxCPCastControl": SxCPCastControl,
|
||||||
"SxCPCastBias": SxCPCastBias,
|
"SxCPCastBias": SxCPCastBias,
|
||||||
}
|
}
|
||||||
@@ -322,6 +379,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
|||||||
"SxCPLocationPool": "SxCP Location Pool",
|
"SxCPLocationPool": "SxCP Location Pool",
|
||||||
"SxCPCompositionPool": "SxCP Composition Pool",
|
"SxCPCompositionPool": "SxCP Composition Pool",
|
||||||
"SxCPLocationTheme": "SxCP Location Theme",
|
"SxCPLocationTheme": "SxCP Location Theme",
|
||||||
|
"SxCPStylePool": "SxCP Style Pool",
|
||||||
"SxCPCastControl": "SxCP Cast Control",
|
"SxCPCastControl": "SxCP Cast Control",
|
||||||
"SxCPCastBias": "SxCP Cast Bias",
|
"SxCPCastBias": "SxCP Cast Bias",
|
||||||
}
|
}
|
||||||
|
|||||||
+1117
-18
File diff suppressed because it is too large
Load Diff
@@ -17,9 +17,14 @@ COMMON_INPUT_TOOLTIPS = {
|
|||||||
"filter_config": "Ethnicity/body filter config. Ethnicity List can feed this too.",
|
"filter_config": "Ethnicity/body filter config. Ethnicity List can feed this too.",
|
||||||
"ethnicity_list": "Optional ethnicity pool. When connected, it overrides the slot or generator ethnicity picker.",
|
"ethnicity_list": "Optional ethnicity pool. When connected, it overrides the slot or generator ethnicity picker.",
|
||||||
"seed_config": "Per-axis seed config. Use Global Seed for full reproducibility, Seed Locker to reroll one axis, or Seed Control for manual axis seeds.",
|
"seed_config": "Per-axis seed config. Use Global Seed for full reproducibility, Seed Locker to reroll one axis, or Seed Control for manual axis seeds.",
|
||||||
|
"layer": "Scene layer affected by this side node. all applies to every compatible scene node that receives the options.",
|
||||||
|
"seed_mode": "follow_global uses the scene seed, fixed uses the seed field, random resolves a fresh seed at queue time, disabled does nothing.",
|
||||||
|
"row_behavior": "same_for_all_rows keeps the option seed as-is; vary_by_row offsets it by row number before writing axis seeds.",
|
||||||
|
"reroll_axis": "Specific generator axis group to reroll. none uses the default axes for the selected scene layer.",
|
||||||
"camera_config": "Camera config consumed only by nodes/options set to from_camera_config.",
|
"camera_config": "Camera config consumed only by nodes/options set to from_camera_config.",
|
||||||
"location_config": "Location config from SxCP Location Pool. It can replace or add to the category scene pool.",
|
"location_config": "Location config from SxCP Location Pool. It can replace or add to the category scene pool.",
|
||||||
"composition_config": "Composition config from SxCP Composition Pool or Location Theme. It can replace or add framing options.",
|
"composition_config": "Composition config from SxCP Composition Pool or Location Theme. It can replace or add framing options.",
|
||||||
|
"style_config": "Visual style config from SxCP Style Pool. It controls realistic/photo/comic rendering separately from category, action, and pose logic.",
|
||||||
"softcore_camera_config": "Camera config used only for the softcore Insta/OF prompt. Falls back to camera_config if empty.",
|
"softcore_camera_config": "Camera config used only for the softcore Insta/OF prompt. Falls back to camera_config if empty.",
|
||||||
"hardcore_camera_config": "Camera config used only for the hardcore Insta/OF prompt. Falls back to camera_config if empty.",
|
"hardcore_camera_config": "Camera config used only for the hardcore Insta/OF prompt. Falls back to camera_config if empty.",
|
||||||
"character_profile": "Saved or loaded single-character profile. Character slots override this for configured casts.",
|
"character_profile": "Saved or loaded single-character profile. Character slots override this for configured casts.",
|
||||||
@@ -28,11 +33,28 @@ COMMON_INPUT_TOOLTIPS = {
|
|||||||
"hardcore_position_config": "Hardcore action/position config. Chain Position Pool into Action Filter, then into the generator.",
|
"hardcore_position_config": "Hardcore action/position config. Chain Position Pool into Action Filter, then into the generator.",
|
||||||
"custom_locations": "One custom location per line. Use plain text, or slug: location text.",
|
"custom_locations": "One custom location per line. Use plain text, or slug: location text.",
|
||||||
"custom_compositions": "One custom composition/framing phrase per line.",
|
"custom_compositions": "One custom composition/framing phrase per line.",
|
||||||
|
"custom_style": "Manual visual style phrase. Use this when the preset list is not specific enough.",
|
||||||
|
"custom_positive_suffix": "Manual style/quality suffix merged with the selected style preset.",
|
||||||
|
"custom_negative": "Negative style terms added by the style pool.",
|
||||||
"theme": "Matched location and composition theme, useful when the place needs compatible framing.",
|
"theme": "Matched location and composition theme, useful when the place needs compatible framing.",
|
||||||
"metadata_json": "Structured metadata from an SxCP generator. Prefer this over raw prompt text for formatters and profile save.",
|
"metadata_json": "Structured metadata from an SxCP generator. Prefer this over raw prompt text for formatters and profile save.",
|
||||||
"scene": "Structured v2 scene context. Chain Scene nodes in order, then connect to Scene Output or Scene Pair Output.",
|
"scene": "Structured v2 scene context. Chain Scene nodes in order, then connect to Scene Output or Scene Pair Output.",
|
||||||
"softcore_scene": "Softcore branch scene from Scene Branch Pair, optionally refined by Softcore Branch Options.",
|
"softcore_scene": "Softcore branch scene from Scene Branch Pair, optionally refined by Softcore Branch Options.",
|
||||||
"hardcore_scene": "Hardcore branch scene from Scene Branch Pair, optionally refined by Hardcore Branch Options.",
|
"hardcore_scene": "Hardcore branch scene from Scene Branch Pair, optionally refined by Hardcore Branch Options.",
|
||||||
|
"options": "Incoming options of the same type. Chain option nodes with combine_mode=add when multiple side knobs should contribute.",
|
||||||
|
"seed_options": "Scene layer seed options. Connect Scene Layer Seed Options to reroll one layer without changing the whole scene.",
|
||||||
|
"cast_options": "Optional cast side-node settings that override the Cast node widgets only when connected.",
|
||||||
|
"character_options": "Optional character side-node settings that override descriptor, presence, and expression controls.",
|
||||||
|
"wardrobe_options": "Optional wardrobe side-node settings for subject-specific clothing, nudity state, and wardrobe prompt text.",
|
||||||
|
"location_options": "Optional location layout settings such as foreground anchors, midground, repetition, and public/private context.",
|
||||||
|
"set_options": "Optional set-dressing settings for props, repeated background, foreground anchors, and sensory details.",
|
||||||
|
"blocking_options": "Optional blocking settings for subject placement, orientation, depth plane, and exact body geography.",
|
||||||
|
"action_options": "Optional action settings for scene kind, action family, category preset, and manual action text.",
|
||||||
|
"performance_options": "Optional performance settings for expression, gaze, hands, body tension, and actor notes.",
|
||||||
|
"camera_options": "Optional camera side-node settings that describe camera source and freeform camera text.",
|
||||||
|
"composition_options": "Optional composition side-node settings for readability target, crop, occlusion, and framing text.",
|
||||||
|
"lighting_options": "Optional lighting side-node settings for source, softness, contrast, color, and time of day.",
|
||||||
|
"branch_options": "Optional branch settings that apply to softcore, hardcore, or both Insta/OF branches.",
|
||||||
"target_formatter": "Intended downstream formatter target. The scene stores this as metadata; use formatter nodes for final rewriting.",
|
"target_formatter": "Intended downstream formatter target. The scene stores this as metadata; use formatter nodes for final rewriting.",
|
||||||
"category_preset": "Category preset this scene should render through when no explicit category config overrides it.",
|
"category_preset": "Category preset this scene should render through when no explicit category config overrides it.",
|
||||||
"central_subject": "Who should be visually central in this scene metadata.",
|
"central_subject": "Who should be visually central in this scene metadata.",
|
||||||
@@ -42,24 +64,43 @@ COMMON_INPUT_TOOLTIPS = {
|
|||||||
"custom_location": "Exact location text for this scene. One line or JSON entry is enough.",
|
"custom_location": "Exact location text for this scene. One line or JSON entry is enough.",
|
||||||
"location_note": "Additional location wording merged into the location pool entry.",
|
"location_note": "Additional location wording merged into the location pool entry.",
|
||||||
"foreground_anchors": "Objects or surfaces that should stay near the camera or lower frame.",
|
"foreground_anchors": "Objects or surfaces that should stay near the camera or lower frame.",
|
||||||
|
"midground_layer": "Readable middle-distance scene elements between the subject and background.",
|
||||||
|
"background_repetition": "Repeated environmental structure that helps the model keep a location coherent across rerolls.",
|
||||||
|
"visibility_level": "How visible or hidden the scene should feel inside the location.",
|
||||||
|
"public_level": "Private, semi-public, or public context for the location layer.",
|
||||||
"repeated_background": "Repeating background structure such as desks, doors, shelves, pillars, or windows.",
|
"repeated_background": "Repeating background structure such as desks, doors, shelves, pillars, or windows.",
|
||||||
"props": "Scene props or set dressing objects that make the location readable.",
|
"props": "Scene props or set dressing objects that make the location readable.",
|
||||||
|
"sensory_details": "Small material/light/surface details that make the set dressing feel specific.",
|
||||||
"set_prompt": "Freeform set-dressing sentence appended to the scene layer.",
|
"set_prompt": "Freeform set-dressing sentence appended to the scene layer.",
|
||||||
"blocking_mode": "Broad body-placement mode. custom lets custom_blocking carry the exact placement.",
|
"blocking_mode": "Broad body-placement mode. custom lets custom_blocking carry the exact placement.",
|
||||||
"subject_placement": "Where the subject or cast sits in the space: foreground, near desk edge, on bed, in aisle, etc.",
|
"subject_placement": "Where the subject or cast sits in the space: foreground, near desk edge, on bed, in aisle, etc.",
|
||||||
"body_relation": "Spatial relationship between participants, separate from the action itself.",
|
"body_relation": "Spatial relationship between participants, separate from the action itself.",
|
||||||
|
"body_orientation": "Front, side, back, three-quarter, or POV-facing body orientation.",
|
||||||
|
"depth_plane": "Whether the subjects sit in foreground, midground, background, or a layered composition.",
|
||||||
|
"distance_note": "Extra spatial distance wording, such as close together, across the table, or partly hidden behind a shelf.",
|
||||||
"custom_blocking": "Exact blocking/positioning sentence for the scene layer.",
|
"custom_blocking": "Exact blocking/positioning sentence for the scene layer.",
|
||||||
"scene_kind": "Regular, softcore, or hardcore intent for this action layer.",
|
"scene_kind": "Regular, softcore, or hardcore intent for this action layer.",
|
||||||
|
"action_family": "Broad action family such as softcore tease, oral, penetration, climax, group, or custom.",
|
||||||
"action_prompt": "Action text stored separately from blocking and camera. Use position pools for hardcore randomization when possible.",
|
"action_prompt": "Action text stored separately from blocking and camera. Use position pools for hardcore randomization when possible.",
|
||||||
|
"gaze": "Where the character looks: camera, partner, down, away, over shoulder, or eyes closed.",
|
||||||
|
"hand_placement": "What hands are doing: relaxed, on body, on partner, holding camera, pulling clothing, or braced.",
|
||||||
|
"body_tension": "Body performance cue: relaxed, posed, arched, braced, or active motion.",
|
||||||
"performance_prompt": "Expression, gaze, hand, and body-performance note stored separately from the action.",
|
"performance_prompt": "Expression, gaze, hand, and body-performance note stored separately from the action.",
|
||||||
|
"camera_source": "Where camera text comes from conceptually: config, qwen orbit, POV, phone, external, or manual.",
|
||||||
|
"preserve_location_layout": "Keep location layout wording compatible with the camera instead of letting camera text replace the space.",
|
||||||
"camera_prompt": "Optional freeform camera note kept as scene metadata. Camera config still controls existing formatter behavior.",
|
"camera_prompt": "Optional freeform camera note kept as scene metadata. Camera config still controls existing formatter behavior.",
|
||||||
"custom_composition": "Exact composition/framing entry to add to the composition pool.",
|
"custom_composition": "Exact composition/framing entry to add to the composition pool.",
|
||||||
|
"readability_target": "What the composition should keep most readable: face, body, action, room, anchor objects, or contact points.",
|
||||||
|
"crop": "Composition crop intent such as full body, three-quarter, close-up, or extreme close-up.",
|
||||||
|
"occlusion": "How much foreground or hidden-sightline occlusion the composition should allow.",
|
||||||
"composition_prompt": "Additional composition wording merged into the composition layer.",
|
"composition_prompt": "Additional composition wording merged into the composition layer.",
|
||||||
"lighting_source": "Main light source family for the scene.",
|
"lighting_source": "Main light source family for the scene.",
|
||||||
"lighting_softness": "Softness of the light: soft, balanced, or hard.",
|
"lighting_softness": "Softness of the light: soft, balanced, or hard.",
|
||||||
"lighting_contrast": "Overall contrast level for the lighting layer.",
|
"lighting_contrast": "Overall contrast level for the lighting layer.",
|
||||||
"color_temperature": "Warm, neutral, cool, or mixed color temperature.",
|
"color_temperature": "Warm, neutral, cool, or mixed color temperature.",
|
||||||
|
"time_of_day": "Optional time-of-day lighting context.",
|
||||||
"custom_lighting": "Exact lighting sentence for the scene layer.",
|
"custom_lighting": "Exact lighting sentence for the scene layer.",
|
||||||
|
"branch_target": "Whether branch options affect both Insta/OF branches, softcore only, or hardcore only.",
|
||||||
"continuity": "How branch outputs share cast/location setup between softcore and hardcore scenes.",
|
"continuity": "How branch outputs share cast/location setup between softcore and hardcore scenes.",
|
||||||
"platform_style": "Instagram/OnlyFans styling bias for Scene Pair Output.",
|
"platform_style": "Instagram/OnlyFans styling bias for Scene Pair Output.",
|
||||||
"softcore_cast": "Whether the softcore branch uses a solo creator or the same cast as the hardcore branch.",
|
"softcore_cast": "Whether the softcore branch uses a solo creator or the same cast as the hardcore branch.",
|
||||||
@@ -126,6 +167,9 @@ COMMON_INPUT_TOOLTIPS = {
|
|||||||
"presence_mode": "Controls whether the character is visible or acts as the male POV participant.",
|
"presence_mode": "Controls whether the character is visible or acts as the male POV participant.",
|
||||||
"softcore_outfit": "Manual softcore outfit text for this character. Prefer Character Clothing for reusable outfit pools.",
|
"softcore_outfit": "Manual softcore outfit text for this character. Prefer Character Clothing for reusable outfit pools.",
|
||||||
"hardcore_clothing": "Manual hardcore exposure text for this character. Use explicit nude states when you do not want clothing words repeated.",
|
"hardcore_clothing": "Manual hardcore exposure text for this character. Use explicit nude states when you do not want clothing words repeated.",
|
||||||
|
"wardrobe_state": "High-level clothing/body-exposure state. explicit_nude avoids conflicting outfit text in hardcore prompts.",
|
||||||
|
"accessories": "Accessories that can remain visible without forcing full outfit wording.",
|
||||||
|
"avoid_clothing_when_nude": "When nude states are selected, avoid reintroducing clothing words that make the image model dress the subject.",
|
||||||
"custom_softcore_outfits": "One custom softcore outfit per line. Used when softcore_source is custom.",
|
"custom_softcore_outfits": "One custom softcore outfit per line. Used when softcore_source is custom.",
|
||||||
"custom_hardcore_clothing": "One custom hardcore clothing/body exposure state per line.",
|
"custom_hardcore_clothing": "One custom hardcore clothing/body exposure state per line.",
|
||||||
"condition": "Loop condition. When false, the loop stops and passes current values through.",
|
"condition": "Loop condition. When false, the loop stops and passes current values through.",
|
||||||
@@ -264,6 +308,15 @@ NODE_INPUT_TOOLTIPS = {
|
|||||||
"phone_visibility": "Leave auto when using Qwen/Orbit camera prompts unless you explicitly want phone visibility text.",
|
"phone_visibility": "Leave auto when using Qwen/Orbit camera prompts unless you explicitly want phone visibility text.",
|
||||||
"suppress_phone_visibility": "Avoid adding phone visibility text unless you explicitly set a phone option.",
|
"suppress_phone_visibility": "Avoid adding phone visibility text unless you explicitly set a phone option.",
|
||||||
},
|
},
|
||||||
|
"SxCPStylePool": {
|
||||||
|
"enabled": "Disable to keep the node wired while preserving category/default style behavior.",
|
||||||
|
"combine_mode": "replace overrides category style; add appends this visual style to incoming/category style; disabled emits no style override.",
|
||||||
|
"preset": "Visual rendering preset only. It does not select content, pose, exposure, or camera.",
|
||||||
|
"style_config": "Optional incoming style config. Use combine_mode=add to chain multiple style nodes.",
|
||||||
|
"custom_style": "Manual visual style phrase, for example realistic phone photo or colored-pencil pin-up.",
|
||||||
|
"custom_positive_suffix": "Extra rendering/detail sentence added to the prompt when the style is active.",
|
||||||
|
"custom_negative": "Negative style terms merged into the generated negative prompt.",
|
||||||
|
},
|
||||||
"SxCPHardcorePositionPool": {
|
"SxCPHardcorePositionPool": {
|
||||||
"family": "Restrict the broad hardcore family. Use any when you want oral and penetration to both be possible.",
|
"family": "Restrict the broad hardcore family. Use any when you want oral and penetration to both be possible.",
|
||||||
"combine_mode": "replace discards incoming position choices; add merges these choices with the incoming config.",
|
"combine_mode": "replace discards incoming position choices; add merges these choices with the incoming config.",
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class InstaPairBuildRequest:
|
|||||||
hardcore_position_config: str | dict[str, Any] | None = ""
|
hardcore_position_config: str | dict[str, Any] | None = ""
|
||||||
location_config: str | dict[str, Any] | None = ""
|
location_config: str | dict[str, Any] | None = ""
|
||||||
composition_config: str | dict[str, Any] | None = ""
|
composition_config: str | dict[str, Any] | None = ""
|
||||||
|
style_config: str | dict[str, Any] | None = ""
|
||||||
extra_positive: str = ""
|
extra_positive: str = ""
|
||||||
extra_negative: str = ""
|
extra_negative: str = ""
|
||||||
|
|
||||||
@@ -148,6 +149,7 @@ def build_insta_of_pair(request: InstaPairBuildRequest, deps: InstaPairBuildDepe
|
|||||||
hardcore_position_config=request.hardcore_position_config,
|
hardcore_position_config=request.hardcore_position_config,
|
||||||
location_config=request.location_config or "",
|
location_config=request.location_config or "",
|
||||||
composition_config=request.composition_config or "",
|
composition_config=request.composition_config or "",
|
||||||
|
style_config=request.style_config or "",
|
||||||
build_prompt=deps.build_prompt,
|
build_prompt=deps.build_prompt,
|
||||||
axis_rng=deps.axis_rng,
|
axis_rng=deps.axis_rng,
|
||||||
cast_expression_intensity_override=deps.cast_expression_intensity_override,
|
cast_expression_intensity_override=deps.cast_expression_intensity_override,
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ def build_insta_pair_rows_result(
|
|||||||
softcore_item_prompt_label: Callable[[str], str],
|
softcore_item_prompt_label: Callable[[str], str],
|
||||||
pov_prompt_directive: Callable[[list[str]], str],
|
pov_prompt_directive: Callable[[list[str]], str],
|
||||||
pov_composition_prompt: Callable[[Any, list[str]], str],
|
pov_composition_prompt: Callable[[Any, list[str]], str],
|
||||||
|
style_config: str | dict[str, Any] | None = "",
|
||||||
) -> InstaPairRowsRoute:
|
) -> InstaPairRowsRoute:
|
||||||
soft_content_rng = axis_rng(parsed_seed_config, "content", seed, row_number + 311)
|
soft_content_rng = axis_rng(parsed_seed_config, "content", seed, row_number + 311)
|
||||||
hard_content_rng = axis_rng(parsed_seed_config, "content", seed, row_number + 317)
|
hard_content_rng = axis_rng(parsed_seed_config, "content", seed, row_number + 317)
|
||||||
@@ -131,6 +132,7 @@ def build_insta_pair_rows_result(
|
|||||||
character_cast="",
|
character_cast="",
|
||||||
location_config=location_config or "",
|
location_config=location_config or "",
|
||||||
composition_config=composition_config or "",
|
composition_config=composition_config or "",
|
||||||
|
style_config=style_config or "",
|
||||||
)
|
)
|
||||||
soft_row["expression_intensity_source"] = soft_expression_intensity_source
|
soft_row["expression_intensity_source"] = soft_expression_intensity_source
|
||||||
if primary_slot_context:
|
if primary_slot_context:
|
||||||
@@ -196,6 +198,7 @@ def build_insta_pair_rows_result(
|
|||||||
hardcore_position_config=hardcore_position_config or "",
|
hardcore_position_config=hardcore_position_config or "",
|
||||||
location_config=location_config or "",
|
location_config=location_config or "",
|
||||||
composition_config=composition_config or "",
|
composition_config=composition_config or "",
|
||||||
|
style_config=style_config or "",
|
||||||
)
|
)
|
||||||
hard_row["hardcore_detail_density"] = options["hardcore_detail_density"]
|
hard_row["hardcore_detail_density"] = options["hardcore_detail_density"]
|
||||||
hard_row["pov_character_labels"] = pov_character_labels
|
hard_row["pov_character_labels"] = pov_character_labels
|
||||||
@@ -248,6 +251,7 @@ def build_insta_pair_rows(
|
|||||||
softcore_item_prompt_label: Callable[[str], str],
|
softcore_item_prompt_label: Callable[[str], str],
|
||||||
pov_prompt_directive: Callable[[list[str]], str],
|
pov_prompt_directive: Callable[[list[str]], str],
|
||||||
pov_composition_prompt: Callable[[Any, list[str]], str],
|
pov_composition_prompt: Callable[[Any, list[str]], str],
|
||||||
|
style_config: str | dict[str, Any] | None = "",
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
return build_insta_pair_rows_result(
|
return build_insta_pair_rows_result(
|
||||||
row_number=row_number,
|
row_number=row_number,
|
||||||
@@ -273,6 +277,7 @@ def build_insta_pair_rows(
|
|||||||
hardcore_position_config=hardcore_position_config,
|
hardcore_position_config=hardcore_position_config,
|
||||||
location_config=location_config,
|
location_config=location_config,
|
||||||
composition_config=composition_config,
|
composition_config=composition_config,
|
||||||
|
style_config=style_config,
|
||||||
build_prompt=build_prompt,
|
build_prompt=build_prompt,
|
||||||
axis_rng=axis_rng,
|
axis_rng=axis_rng,
|
||||||
cast_expression_intensity_override=cast_expression_intensity_override,
|
cast_expression_intensity_override=cast_expression_intensity_override,
|
||||||
|
|||||||
+45
-2
@@ -47,6 +47,7 @@ try:
|
|||||||
from . import row_route_metadata as row_route_policy
|
from . import row_route_metadata as row_route_policy
|
||||||
from . import row_subject_route as row_subject_route_policy
|
from . import row_subject_route as row_subject_route_policy
|
||||||
from . import seed_config as seed_policy
|
from . import seed_config as seed_policy
|
||||||
|
from . import style_config as style_policy
|
||||||
from . import subject_context as subject_context_policy
|
from . import subject_context as subject_context_policy
|
||||||
from .hardcore_text_cleanup import (
|
from .hardcore_text_cleanup import (
|
||||||
sanitize_hardcore_axis_values as _sanitize_hardcore_axis_values,
|
sanitize_hardcore_axis_values as _sanitize_hardcore_axis_values,
|
||||||
@@ -95,6 +96,7 @@ except ImportError: # Allows local smoke tests with `python -c`.
|
|||||||
import row_route_metadata as row_route_policy
|
import row_route_metadata as row_route_policy
|
||||||
import row_subject_route as row_subject_route_policy
|
import row_subject_route as row_subject_route_policy
|
||||||
import seed_config as seed_policy
|
import seed_config as seed_policy
|
||||||
|
import style_config as style_policy
|
||||||
import subject_context as subject_context_policy
|
import subject_context as subject_context_policy
|
||||||
from hardcore_text_cleanup import (
|
from hardcore_text_cleanup import (
|
||||||
sanitize_hardcore_axis_values as _sanitize_hardcore_axis_values,
|
sanitize_hardcore_axis_values as _sanitize_hardcore_axis_values,
|
||||||
@@ -376,6 +378,7 @@ CATEGORY_PRESETS = category_cast_policy.CATEGORY_PRESETS
|
|||||||
CAST_PRESETS = category_cast_policy.CAST_PRESETS
|
CAST_PRESETS = category_cast_policy.CAST_PRESETS
|
||||||
|
|
||||||
GENERATION_PROFILE_PRESETS = generation_profile_policy.GENERATION_PROFILE_PRESETS
|
GENERATION_PROFILE_PRESETS = generation_profile_policy.GENERATION_PROFILE_PRESETS
|
||||||
|
STYLE_PRESETS = style_policy.STYLE_PRESETS
|
||||||
|
|
||||||
|
|
||||||
def category_preset_choices() -> list[str]:
|
def category_preset_choices() -> list[str]:
|
||||||
@@ -390,6 +393,14 @@ def generation_profile_choices() -> list[str]:
|
|||||||
return generation_profile_policy.generation_profile_choices()
|
return generation_profile_policy.generation_profile_choices()
|
||||||
|
|
||||||
|
|
||||||
|
def style_pool_preset_choices() -> list[str]:
|
||||||
|
return style_policy.style_pool_preset_choices()
|
||||||
|
|
||||||
|
|
||||||
|
def style_combine_mode_choices() -> list[str]:
|
||||||
|
return style_policy.style_combine_mode_choices()
|
||||||
|
|
||||||
|
|
||||||
def build_category_config_json(preset: str = "auto_weighted", subcategory: str = RANDOM_SUBCATEGORY) -> str:
|
def build_category_config_json(preset: str = "auto_weighted", subcategory: str = RANDOM_SUBCATEGORY) -> str:
|
||||||
return category_cast_policy.build_category_config_json(preset=preset, subcategory=subcategory)
|
return category_cast_policy.build_category_config_json(preset=preset, subcategory=subcategory)
|
||||||
|
|
||||||
@@ -436,6 +447,30 @@ def _parse_generation_profile(profile_config: str | dict[str, Any] | None) -> di
|
|||||||
return generation_profile_policy.parse_generation_profile(profile_config)
|
return generation_profile_policy.parse_generation_profile(profile_config)
|
||||||
|
|
||||||
|
|
||||||
|
def build_style_config_json(
|
||||||
|
enabled: bool = True,
|
||||||
|
combine_mode: str = "replace",
|
||||||
|
preset: str = "category_default",
|
||||||
|
custom_style: str = "",
|
||||||
|
custom_positive_suffix: str = "",
|
||||||
|
custom_negative: str = "",
|
||||||
|
style_config: str | dict[str, Any] | None = "",
|
||||||
|
) -> str:
|
||||||
|
return style_policy.build_style_config_json(
|
||||||
|
enabled=enabled,
|
||||||
|
combine_mode=combine_mode,
|
||||||
|
preset=preset,
|
||||||
|
custom_style=custom_style,
|
||||||
|
custom_positive_suffix=custom_positive_suffix,
|
||||||
|
custom_negative=custom_negative,
|
||||||
|
style_config=style_config,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_style_config(style_config: str | dict[str, Any] | None) -> dict[str, Any]:
|
||||||
|
return style_policy.parse_style_config(style_config)
|
||||||
|
|
||||||
|
|
||||||
def build_filter_config_json(
|
def build_filter_config_json(
|
||||||
ethnicity: str = "any",
|
ethnicity: str = "any",
|
||||||
figure: str = "curvy",
|
figure: str = "curvy",
|
||||||
@@ -880,8 +915,9 @@ def _row_text_fields(
|
|||||||
category: dict[str, Any],
|
category: dict[str, Any],
|
||||||
subcategory: dict[str, Any],
|
subcategory: dict[str, Any],
|
||||||
item: Any,
|
item: Any,
|
||||||
|
style_config: str | dict[str, Any] | None = None,
|
||||||
) -> row_rendering_policy.RowTextFields:
|
) -> row_rendering_policy.RowTextFields:
|
||||||
return row_rendering_policy.resolve_row_text_fields(category, subcategory, item)
|
return row_rendering_policy.resolve_row_text_fields(category, subcategory, item, style_config)
|
||||||
|
|
||||||
|
|
||||||
def _clean_prompt_punctuation(text: str) -> str:
|
def _clean_prompt_punctuation(text: str) -> str:
|
||||||
@@ -2284,6 +2320,7 @@ def _build_custom_row(
|
|||||||
hardcore_position_config: str | dict[str, Any] | None = None,
|
hardcore_position_config: str | dict[str, Any] | None = None,
|
||||||
location_config: str | dict[str, Any] | None = None,
|
location_config: str | dict[str, Any] | None = None,
|
||||||
composition_config: str | dict[str, Any] | None = None,
|
composition_config: str | dict[str, Any] | None = None,
|
||||||
|
style_config: str | dict[str, Any] | None = None,
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
scene_rng = _axis_rng(seed_config, "scene", seed, row_number)
|
scene_rng = _axis_rng(seed_config, "scene", seed, row_number)
|
||||||
pose_rng = _axis_rng(seed_config, "pose", seed, row_number)
|
pose_rng = _axis_rng(seed_config, "pose", seed, row_number)
|
||||||
@@ -2421,7 +2458,7 @@ def _build_custom_row(
|
|||||||
position_key = action_route.position_key
|
position_key = action_route.position_key
|
||||||
action_family = action_route.action_family
|
action_family = action_route.action_family
|
||||||
|
|
||||||
text_fields = _row_text_fields(category, subcategory, item)
|
text_fields = _row_text_fields(category, subcategory, item, style_config)
|
||||||
|
|
||||||
assembly_request = row_assembly_policy.CustomRowAssemblyRequest(
|
assembly_request = row_assembly_policy.CustomRowAssemblyRequest(
|
||||||
row_number=row_number,
|
row_number=row_number,
|
||||||
@@ -2542,6 +2579,7 @@ def build_prompt(
|
|||||||
hardcore_position_config: str | dict[str, Any] | None = None,
|
hardcore_position_config: str | dict[str, Any] | None = None,
|
||||||
location_config: str | dict[str, Any] | None = None,
|
location_config: str | dict[str, Any] | None = None,
|
||||||
composition_config: str | dict[str, Any] | None = None,
|
composition_config: str | dict[str, Any] | None = None,
|
||||||
|
style_config: str | dict[str, Any] | None = None,
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
return builder_prompt_route_policy.build_prompt(
|
return builder_prompt_route_policy.build_prompt(
|
||||||
builder_prompt_route_policy.PromptBuildRequest(
|
builder_prompt_route_policy.PromptBuildRequest(
|
||||||
@@ -2575,6 +2613,7 @@ def build_prompt(
|
|||||||
hardcore_position_config=hardcore_position_config,
|
hardcore_position_config=hardcore_position_config,
|
||||||
location_config=location_config,
|
location_config=location_config,
|
||||||
composition_config=composition_config,
|
composition_config=composition_config,
|
||||||
|
style_config=style_config,
|
||||||
),
|
),
|
||||||
_prompt_build_dependencies(),
|
_prompt_build_dependencies(),
|
||||||
)
|
)
|
||||||
@@ -2605,6 +2644,7 @@ def build_prompt_from_configs(
|
|||||||
hardcore_position_config: str | dict[str, Any] | None = "",
|
hardcore_position_config: str | dict[str, Any] | None = "",
|
||||||
location_config: str | dict[str, Any] | None = "",
|
location_config: str | dict[str, Any] | None = "",
|
||||||
composition_config: str | dict[str, Any] | None = "",
|
composition_config: str | dict[str, Any] | None = "",
|
||||||
|
style_config: str | dict[str, Any] | None = "",
|
||||||
extra_positive: str = "",
|
extra_positive: str = "",
|
||||||
extra_negative: str = "",
|
extra_negative: str = "",
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
@@ -2624,6 +2664,7 @@ def build_prompt_from_configs(
|
|||||||
hardcore_position_config=hardcore_position_config,
|
hardcore_position_config=hardcore_position_config,
|
||||||
location_config=location_config,
|
location_config=location_config,
|
||||||
composition_config=composition_config,
|
composition_config=composition_config,
|
||||||
|
style_config=style_config,
|
||||||
extra_positive=extra_positive,
|
extra_positive=extra_positive,
|
||||||
extra_negative=extra_negative,
|
extra_negative=extra_negative,
|
||||||
),
|
),
|
||||||
@@ -2801,6 +2842,7 @@ def build_insta_of_pair(
|
|||||||
hardcore_position_config: str | dict[str, Any] | None = "",
|
hardcore_position_config: str | dict[str, Any] | None = "",
|
||||||
location_config: str | dict[str, Any] | None = "",
|
location_config: str | dict[str, Any] | None = "",
|
||||||
composition_config: str | dict[str, Any] | None = "",
|
composition_config: str | dict[str, Any] | None = "",
|
||||||
|
style_config: str | dict[str, Any] | None = "",
|
||||||
extra_positive: str = "",
|
extra_positive: str = "",
|
||||||
extra_negative: str = "",
|
extra_negative: str = "",
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
@@ -2825,6 +2867,7 @@ def build_insta_of_pair(
|
|||||||
hardcore_position_config=hardcore_position_config,
|
hardcore_position_config=hardcore_position_config,
|
||||||
location_config=location_config,
|
location_config=location_config,
|
||||||
composition_config=composition_config,
|
composition_config=composition_config,
|
||||||
|
style_config=style_config,
|
||||||
extra_positive=extra_positive,
|
extra_positive=extra_positive,
|
||||||
extra_negative=extra_negative,
|
extra_negative=extra_negative,
|
||||||
)
|
)
|
||||||
|
|||||||
+19
-12
@@ -8,18 +8,20 @@ try:
|
|||||||
from . import category_library as category_policy
|
from . import category_library as category_policy
|
||||||
from . import generate_prompt_batches as g
|
from . import generate_prompt_batches as g
|
||||||
from . import row_camera as row_camera_policy
|
from . import row_camera as row_camera_policy
|
||||||
|
from . import style_config as style_config_policy
|
||||||
except ImportError: # Allows local smoke tests from the repository root.
|
except ImportError: # Allows local smoke tests from the repository root.
|
||||||
import category_library as category_policy
|
import category_library as category_policy
|
||||||
import generate_prompt_batches as g
|
import generate_prompt_batches as g
|
||||||
import row_camera as row_camera_policy
|
import row_camera as row_camera_policy
|
||||||
|
import style_config as style_config_policy
|
||||||
|
|
||||||
|
|
||||||
GENERIC_POSITIVE_SUFFIX = (
|
GENERIC_POSITIVE_SUFFIX = (
|
||||||
"Use crisp clean comic linework, detailed hatching, soft blended shading, "
|
"Use coherent anatomy, readable body placement, natural light response, "
|
||||||
"pastel skin tones, muted blues and pinks, warm sensual lighting, and tactile textured paper."
|
"clear material texture, stable spatial depth, and polished visual detail."
|
||||||
)
|
)
|
||||||
|
|
||||||
DEFAULT_STYLE = "sexy but tasteful adult pin-up coloured-pencil comic illustration"
|
DEFAULT_STYLE = "realistic adult scene with natural camera realism"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
@@ -55,7 +57,7 @@ LAYOUT_TEMPLATE = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
DEFAULT_CAPTION_TEMPLATE = (
|
DEFAULT_CAPTION_TEMPLATE = (
|
||||||
"{trigger}, {subject_phrase}, {age}, {item}, {scene}, {composition}, coloured pencil comic illustration"
|
"{trigger}, {subject_phrase}, {age}, {item}, {scene}, {composition}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -72,15 +74,20 @@ def format_template(template: str, context: dict[str, Any]) -> str:
|
|||||||
return template.format_map(safe_context)
|
return template.format_map(safe_context)
|
||||||
|
|
||||||
|
|
||||||
def resolve_row_text_fields(category: dict[str, Any], subcategory: dict[str, Any], item: Any) -> RowTextFields:
|
def resolve_row_text_fields(
|
||||||
|
category: dict[str, Any],
|
||||||
|
subcategory: dict[str, Any],
|
||||||
|
item: Any,
|
||||||
|
style_config: str | dict[str, Any] | None = None,
|
||||||
|
) -> RowTextFields:
|
||||||
|
base_negative = str(category_policy.merged_field(category, subcategory, item, "negative_prompt", g.NEGATIVE_PROMPT))
|
||||||
|
base_suffix = str(category_policy.merged_field(category, subcategory, item, "positive_suffix", GENERIC_POSITIVE_SUFFIX))
|
||||||
|
base_style = str(category_policy.merged_field(category, subcategory, item, "style", DEFAULT_STYLE))
|
||||||
|
style, positive_suffix = style_config_policy.resolve_style_fields(base_style, base_suffix, style_config)
|
||||||
return RowTextFields(
|
return RowTextFields(
|
||||||
negative_prompt=str(
|
negative_prompt=style_config_policy.merge_negative_prompt(base_negative, style_config),
|
||||||
category_policy.merged_field(category, subcategory, item, "negative_prompt", g.NEGATIVE_PROMPT)
|
positive_suffix=positive_suffix,
|
||||||
),
|
style=style,
|
||||||
positive_suffix=str(
|
|
||||||
category_policy.merged_field(category, subcategory, item, "positive_suffix", GENERIC_POSITIVE_SUFFIX)
|
|
||||||
),
|
|
||||||
style=str(category_policy.merged_field(category, subcategory, item, "style", DEFAULT_STYLE)),
|
|
||||||
item_label=str(category_policy.merged_field(category, subcategory, item, "item_label", category["name"])),
|
item_label=str(category_policy.merged_field(category, subcategory, item, "item_label", category["name"])),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+148
@@ -0,0 +1,148 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
STYLE_CONFIG_SCHEMA = "sxcp_style_config_v1"
|
||||||
|
STYLE_COMBINE_MODES = ("replace", "add", "disabled")
|
||||||
|
STYLE_PRESETS = {
|
||||||
|
"category_default": {
|
||||||
|
"style": "",
|
||||||
|
"positive_suffix": "",
|
||||||
|
"summary": "category default style",
|
||||||
|
},
|
||||||
|
"realistic_photo": {
|
||||||
|
"style": "realistic adult photographic scene, natural camera capture",
|
||||||
|
"positive_suffix": "Use realistic skin texture, natural light response, coherent anatomy, readable contact points, and believable spatial depth.",
|
||||||
|
"summary": "realistic photographic style",
|
||||||
|
},
|
||||||
|
"creator_phone_photo": {
|
||||||
|
"style": "realistic creator-shot phone photo, natural adult social-media image",
|
||||||
|
"positive_suffix": "Use handheld camera realism, natural skin texture, readable body positioning, and believable room depth.",
|
||||||
|
"summary": "creator phone photo style",
|
||||||
|
},
|
||||||
|
"documentary_flash": {
|
||||||
|
"style": "realistic direct-flash documentary photo, raw adult snapshot",
|
||||||
|
"positive_suffix": "Use direct flash, natural skin texture, sharp foreground detail, visible contact points, and unpolished camera realism.",
|
||||||
|
"summary": "direct flash documentary style",
|
||||||
|
},
|
||||||
|
"cinematic_realism": {
|
||||||
|
"style": "cinematic realistic adult scene, natural lens perspective",
|
||||||
|
"positive_suffix": "Use realistic anatomy, readable blocking, natural depth, motivated lighting, and coherent camera perspective.",
|
||||||
|
"summary": "cinematic realism style",
|
||||||
|
},
|
||||||
|
"comic_pinup_colored_pencil": {
|
||||||
|
"style": "adult erotic coloured-pencil comic pin-up style",
|
||||||
|
"positive_suffix": "Use crisp comic linework, detailed hatching, warm erotic lighting, soft skin shading, and tactile textured paper.",
|
||||||
|
"summary": "colored-pencil comic pin-up style",
|
||||||
|
},
|
||||||
|
"flat_vector_comic": {
|
||||||
|
"style": "flat vector adult comic illustration",
|
||||||
|
"positive_suffix": "Use flat color, clean graphic shapes, crisp outlines, simplified shadows, and readable adult body positioning.",
|
||||||
|
"summary": "flat vector comic style",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def style_pool_preset_choices() -> list[str]:
|
||||||
|
return list(STYLE_PRESETS)
|
||||||
|
|
||||||
|
|
||||||
|
def style_combine_mode_choices() -> list[str]:
|
||||||
|
return list(STYLE_COMBINE_MODES)
|
||||||
|
|
||||||
|
|
||||||
|
def _clean_text(value: Any) -> str:
|
||||||
|
return str(value or "").strip()
|
||||||
|
|
||||||
|
|
||||||
|
def _join_text(*values: Any) -> str:
|
||||||
|
parts: list[str] = []
|
||||||
|
for value in values:
|
||||||
|
text = _clean_text(value)
|
||||||
|
if text and text not in parts:
|
||||||
|
parts.append(text.rstrip("."))
|
||||||
|
return ". ".join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_style_config(style_config: str | dict[str, Any] | None) -> dict[str, Any]:
|
||||||
|
if not style_config:
|
||||||
|
return {"enabled": False, "combine_mode": "disabled", "style": "", "positive_suffix": "", "negative_prompt": ""}
|
||||||
|
if isinstance(style_config, dict):
|
||||||
|
raw = dict(style_config)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
raw = json.loads(str(style_config))
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
return {"enabled": False, "combine_mode": "disabled", "style": "", "positive_suffix": "", "negative_prompt": ""}
|
||||||
|
if raw.get("schema") != STYLE_CONFIG_SCHEMA:
|
||||||
|
return {"enabled": False, "combine_mode": "disabled", "style": "", "positive_suffix": "", "negative_prompt": ""}
|
||||||
|
combine_mode = _clean_text(raw.get("combine_mode")) or "replace"
|
||||||
|
if combine_mode not in STYLE_COMBINE_MODES:
|
||||||
|
combine_mode = "replace"
|
||||||
|
return {
|
||||||
|
"schema": STYLE_CONFIG_SCHEMA,
|
||||||
|
"version": 1,
|
||||||
|
"enabled": bool(raw.get("enabled", True)) and combine_mode != "disabled",
|
||||||
|
"combine_mode": combine_mode,
|
||||||
|
"preset": _clean_text(raw.get("preset")) or "category_default",
|
||||||
|
"style": _clean_text(raw.get("style")),
|
||||||
|
"positive_suffix": _clean_text(raw.get("positive_suffix")),
|
||||||
|
"negative_prompt": _clean_text(raw.get("negative_prompt")),
|
||||||
|
"summary": _clean_text(raw.get("summary")) or "style config",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def build_style_config_json(
|
||||||
|
*,
|
||||||
|
enabled: bool = True,
|
||||||
|
combine_mode: str = "replace",
|
||||||
|
preset: str = "category_default",
|
||||||
|
custom_style: str = "",
|
||||||
|
custom_positive_suffix: str = "",
|
||||||
|
custom_negative: str = "",
|
||||||
|
style_config: str | dict[str, Any] | None = "",
|
||||||
|
) -> str:
|
||||||
|
if combine_mode not in STYLE_COMBINE_MODES:
|
||||||
|
combine_mode = "replace"
|
||||||
|
base = parse_style_config(style_config)
|
||||||
|
preset_entry = STYLE_PRESETS.get(preset, STYLE_PRESETS["category_default"])
|
||||||
|
style = _clean_text(custom_style) or preset_entry["style"]
|
||||||
|
positive_suffix = _clean_text(custom_positive_suffix) or preset_entry["positive_suffix"]
|
||||||
|
negative_prompt = _clean_text(custom_negative)
|
||||||
|
if combine_mode == "add" and base.get("enabled"):
|
||||||
|
style = _join_text(base.get("style"), style)
|
||||||
|
positive_suffix = _join_text(base.get("positive_suffix"), positive_suffix)
|
||||||
|
negative_prompt = _join_text(base.get("negative_prompt"), negative_prompt)
|
||||||
|
payload = {
|
||||||
|
"schema": STYLE_CONFIG_SCHEMA,
|
||||||
|
"version": 1,
|
||||||
|
"enabled": bool(enabled) and combine_mode != "disabled",
|
||||||
|
"combine_mode": combine_mode,
|
||||||
|
"preset": preset,
|
||||||
|
"style": style,
|
||||||
|
"positive_suffix": positive_suffix,
|
||||||
|
"negative_prompt": negative_prompt,
|
||||||
|
"summary": "style disabled" if not enabled or combine_mode == "disabled" else preset_entry["summary"],
|
||||||
|
}
|
||||||
|
return json.dumps(payload, ensure_ascii=True, sort_keys=True)
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_style_fields(base_style: str, base_positive_suffix: str, style_config: str | dict[str, Any] | None) -> tuple[str, str]:
|
||||||
|
config = parse_style_config(style_config)
|
||||||
|
if not config.get("enabled"):
|
||||||
|
return base_style, base_positive_suffix
|
||||||
|
if config["combine_mode"] == "add":
|
||||||
|
return (
|
||||||
|
_join_text(base_style, config.get("style")),
|
||||||
|
_join_text(base_positive_suffix, config.get("positive_suffix")),
|
||||||
|
)
|
||||||
|
return config.get("style", "") or base_style, config.get("positive_suffix", "") or base_positive_suffix
|
||||||
|
|
||||||
|
|
||||||
|
def merge_negative_prompt(base_negative: str, style_config: str | dict[str, Any] | None) -> str:
|
||||||
|
config = parse_style_config(style_config)
|
||||||
|
if not config.get("enabled"):
|
||||||
|
return base_negative
|
||||||
|
return _join_text(base_negative, config.get("negative_prompt"))
|
||||||
+130
-5
@@ -477,6 +477,7 @@ def _prompt_row(
|
|||||||
camera_config: str | dict[str, Any] | None = "",
|
camera_config: str | dict[str, Any] | None = "",
|
||||||
location_config: str | dict[str, Any] | None = "",
|
location_config: str | dict[str, Any] | None = "",
|
||||||
composition_config: str | dict[str, Any] | None = "",
|
composition_config: str | dict[str, Any] | None = "",
|
||||||
|
style_config: str | dict[str, Any] | None = "",
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
row = pb.build_prompt(
|
row = pb.build_prompt(
|
||||||
category=category,
|
category=category,
|
||||||
@@ -507,6 +508,7 @@ def _prompt_row(
|
|||||||
camera_config=camera_config,
|
camera_config=camera_config,
|
||||||
location_config=location_config,
|
location_config=location_config,
|
||||||
composition_config=composition_config,
|
composition_config=composition_config,
|
||||||
|
style_config=style_config,
|
||||||
)
|
)
|
||||||
_expect_row_base(row, name)
|
_expect_row_base(row, name)
|
||||||
return row
|
return row
|
||||||
@@ -3385,6 +3387,16 @@ def smoke_row_rendering_policy() -> None:
|
|||||||
_expect(default_text_fields.positive_suffix == row_rendering.GENERIC_POSITIVE_SUFFIX, "Row text fields lost suffix default")
|
_expect(default_text_fields.positive_suffix == row_rendering.GENERIC_POSITIVE_SUFFIX, "Row text fields lost suffix default")
|
||||||
_expect(default_text_fields.style == row_rendering.DEFAULT_STYLE, "Row text fields lost style default")
|
_expect(default_text_fields.style == row_rendering.DEFAULT_STYLE, "Row text fields lost style default")
|
||||||
_expect(default_text_fields.item_label == "Default Category", "Row text fields lost category-name label default")
|
_expect(default_text_fields.item_label == "Default Category", "Row text fields lost category-name label default")
|
||||||
|
style_config = pb.build_style_config_json(preset="comic_pinup_colored_pencil")
|
||||||
|
styled_fields = row_rendering.resolve_row_text_fields(category_text, subcategory_text, item_text, style_config)
|
||||||
|
_expect("comic pin-up" in styled_fields.style, "Style Pool did not override row style")
|
||||||
|
_expect("comic linework" in styled_fields.positive_suffix, "Style Pool did not override row style suffix")
|
||||||
|
negative_style_config = pb.build_style_config_json(
|
||||||
|
preset="realistic_photo",
|
||||||
|
custom_negative="flat vector, comic paper texture",
|
||||||
|
)
|
||||||
|
negative_fields = row_rendering.resolve_row_text_fields(category_text, subcategory_text, item_text, negative_style_config)
|
||||||
|
_expect("comic paper texture" in negative_fields.negative_prompt, "Style Pool did not merge style negatives")
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"trigger": Trigger,
|
"trigger": Trigger,
|
||||||
@@ -5713,6 +5725,20 @@ def smoke_hardcore_category_routes() -> None:
|
|||||||
_expect(sdxl_tag in (sdxl.get("sdxl_prompt") or "").lower(), f"{name} SDXL prompt did not include family tag {sdxl_tag!r}")
|
_expect(sdxl_tag in (sdxl.get("sdxl_prompt") or "").lower(), f"{name} SDXL prompt did not include family tag {sdxl_tag!r}")
|
||||||
caption, _method = caption_naturalizer.naturalize_caption("", metadata_json=_json(row), trigger=Trigger, include_trigger=True)
|
caption, _method = caption_naturalizer.naturalize_caption("", metadata_json=_json(row), trigger=Trigger, include_trigger=True)
|
||||||
_expect(caption_label in caption.lower(), f"{name} caption did not include family label {caption_label!r}")
|
_expect(caption_label in caption.lower(), f"{name} caption did not include family label {caption_label!r}")
|
||||||
|
styled_row = _prompt_row(
|
||||||
|
name="hardcore_style_pool_override",
|
||||||
|
category="Hardcore sexual poses",
|
||||||
|
subcategory="Penetrative sex",
|
||||||
|
seed=1181,
|
||||||
|
character_cast=cast,
|
||||||
|
women_count=1,
|
||||||
|
men_count=1,
|
||||||
|
hardcore_position_config=_action_filter("penetration_only"),
|
||||||
|
style_config=pb.build_style_config_json(preset="comic_pinup_colored_pencil"),
|
||||||
|
)
|
||||||
|
_expect("comic pin-up" in styled_row.get("style", ""), "Style Pool did not reach generated hardcore row style")
|
||||||
|
_expect("comic linework" in styled_row.get("positive_suffix", ""), "Style Pool did not reach generated hardcore row suffix")
|
||||||
|
_expect("comic pin-up" in styled_row.get("prompt", ""), "Style Pool style was not rendered into hardcore prompt")
|
||||||
multi_cases = [
|
multi_cases = [
|
||||||
("hardcore_threesome", "Threesomes", "threesome_only", "threesome", {"threesome", "toy_double"}, "threesome", "three-person action", 1, 2),
|
("hardcore_threesome", "Threesomes", "threesome_only", "threesome", {"threesome", "toy_double"}, "threesome", "three-person action", 1, 2),
|
||||||
("hardcore_group", "Group sex and orgy", "group_only", "group", {"group", "toy_double"}, "group sex", "group action", 2, 2),
|
("hardcore_group", "Group sex and orgy", "group_only", "group", {"group", "toy_double"}, "group sex", "group action", 2, 2),
|
||||||
@@ -8239,6 +8265,7 @@ def smoke_node_route_config_registration() -> None:
|
|||||||
"SxCPLocationPool",
|
"SxCPLocationPool",
|
||||||
"SxCPCompositionPool",
|
"SxCPCompositionPool",
|
||||||
"SxCPLocationTheme",
|
"SxCPLocationTheme",
|
||||||
|
"SxCPStylePool",
|
||||||
"SxCPCastControl",
|
"SxCPCastControl",
|
||||||
"SxCPCastBias",
|
"SxCPCastBias",
|
||||||
]
|
]
|
||||||
@@ -8286,6 +8313,23 @@ def smoke_node_route_config_registration() -> None:
|
|||||||
_expect(json.loads(theme_composition).get("composition_entries"), "Location Theme did not output compositions")
|
_expect(json.loads(theme_composition).get("composition_entries"), "Location Theme did not output compositions")
|
||||||
_expect("semi_public_affair" in theme_summary, "Location Theme summary lost theme name")
|
_expect("semi_public_affair" in theme_summary, "Location Theme summary lost theme name")
|
||||||
|
|
||||||
|
style_node = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPStylePool"]
|
||||||
|
style_inputs = style_node.INPUT_TYPES().get("required") or {}
|
||||||
|
_expect("preset" in style_inputs, "Style Pool lost preset input")
|
||||||
|
_expect("tooltip" in style_inputs["preset"][1], "Style Pool tooltip injection missing")
|
||||||
|
style_config, style_summary = style_node().build(
|
||||||
|
True,
|
||||||
|
"replace",
|
||||||
|
"comic_pinup_colored_pencil",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
parsed_style = json.loads(style_config)
|
||||||
|
_expect(parsed_style.get("schema") == "sxcp_style_config_v1", "Style Pool emitted wrong schema")
|
||||||
|
_expect("comic pin-up" in parsed_style.get("style", ""), "Style Pool lost comic preset style")
|
||||||
|
_expect("comic pin-up" in style_summary, "Style Pool summary lost preset label")
|
||||||
|
|
||||||
cast_config, women_count, men_count, cast_summary = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPCastControl"]().build(
|
cast_config, women_count, men_count, cast_summary = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPCastControl"]().build(
|
||||||
"mixed_couple",
|
"mixed_couple",
|
||||||
1,
|
1,
|
||||||
@@ -8792,6 +8836,19 @@ def smoke_node_insta_registration() -> None:
|
|||||||
|
|
||||||
def smoke_node_scene_chain_registration() -> None:
|
def smoke_node_scene_chain_registration() -> None:
|
||||||
required_nodes = [
|
required_nodes = [
|
||||||
|
"SxCPSceneLayerSeedOptions",
|
||||||
|
"SxCPSceneCastOptions",
|
||||||
|
"SxCPSceneCharacterOptions",
|
||||||
|
"SxCPSceneWardrobeOptions",
|
||||||
|
"SxCPSceneLocationLayoutOptions",
|
||||||
|
"SxCPSceneSetDressingOptions",
|
||||||
|
"SxCPSceneBlockingOptions",
|
||||||
|
"SxCPSceneActionOptions",
|
||||||
|
"SxCPScenePerformanceOptions",
|
||||||
|
"SxCPSceneCameraOptions",
|
||||||
|
"SxCPSceneCompositionOptions",
|
||||||
|
"SxCPSceneLightingOptions",
|
||||||
|
"SxCPSceneBranchOptions",
|
||||||
"SxCPSceneStart",
|
"SxCPSceneStart",
|
||||||
"SxCPSceneCast",
|
"SxCPSceneCast",
|
||||||
"SxCPSceneCharacter",
|
"SxCPSceneCharacter",
|
||||||
@@ -8830,6 +8887,7 @@ def smoke_node_scene_chain_registration() -> None:
|
|||||||
parsed_scene = json.loads(scene)
|
parsed_scene = json.loads(scene)
|
||||||
_expect(parsed_scene.get("schema") == "sxcp_scene_v2", "Scene Start did not emit v2 schema")
|
_expect(parsed_scene.get("schema") == "sxcp_scene_v2", "Scene Start did not emit v2 schema")
|
||||||
|
|
||||||
|
cast_options = nodes["SxCPSceneCastOptions"]().build("replace", "mixed_couple", 1, 1, "woman_a", "none")[0]
|
||||||
scene, _cast_config, _cast_summary, _cast_metadata = nodes["SxCPSceneCast"]().build(
|
scene, _cast_config, _cast_summary, _cast_metadata = nodes["SxCPSceneCast"]().build(
|
||||||
scene,
|
scene,
|
||||||
"mixed_couple",
|
"mixed_couple",
|
||||||
@@ -8837,7 +8895,18 @@ def smoke_node_scene_chain_registration() -> None:
|
|||||||
1,
|
1,
|
||||||
"woman_a",
|
"woman_a",
|
||||||
"none",
|
"none",
|
||||||
|
cast_options=cast_options,
|
||||||
)
|
)
|
||||||
|
character_options = nodes["SxCPSceneCharacterOptions"]().build(
|
||||||
|
"replace",
|
||||||
|
"medium",
|
||||||
|
"visible",
|
||||||
|
"enabled",
|
||||||
|
0.5,
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
"controlled slot performance note",
|
||||||
|
)[0]
|
||||||
scene, character_cast, _slot, _summary, _metadata = nodes["SxCPSceneCharacter"]().build(
|
scene, character_cast, _slot, _summary, _metadata = nodes["SxCPSceneCharacter"]().build(
|
||||||
scene,
|
scene,
|
||||||
True,
|
True,
|
||||||
@@ -8854,6 +8923,7 @@ def smoke_node_scene_chain_registration() -> None:
|
|||||||
"visible",
|
"visible",
|
||||||
-1,
|
-1,
|
||||||
-1,
|
-1,
|
||||||
|
character_options=character_options,
|
||||||
)
|
)
|
||||||
scene, character_cast, _slot, _summary, _metadata = nodes["SxCPSceneCharacter"]().build(
|
scene, character_cast, _slot, _summary, _metadata = nodes["SxCPSceneCharacter"]().build(
|
||||||
scene,
|
scene,
|
||||||
@@ -8872,6 +8942,19 @@ def smoke_node_scene_chain_registration() -> None:
|
|||||||
-1,
|
-1,
|
||||||
-1,
|
-1,
|
||||||
)
|
)
|
||||||
|
wardrobe_seed_options = nodes["SxCPSceneLayerSeedOptions"]().build("wardrobe", "fixed", 9981, "content", "same_for_all_rows", "replace_layer")[0]
|
||||||
|
wardrobe_options = nodes["SxCPSceneWardrobeOptions"]().build(
|
||||||
|
"replace",
|
||||||
|
"woman",
|
||||||
|
"A",
|
||||||
|
"full",
|
||||||
|
"explicit_nude",
|
||||||
|
True,
|
||||||
|
"simple black dress",
|
||||||
|
"",
|
||||||
|
"thin necklace",
|
||||||
|
"",
|
||||||
|
)[0]
|
||||||
scene, character_cast, _wardrobe_summary, _wardrobe_metadata = nodes["SxCPSceneWardrobe"]().build(
|
scene, character_cast, _wardrobe_summary, _wardrobe_metadata = nodes["SxCPSceneWardrobe"]().build(
|
||||||
scene,
|
scene,
|
||||||
True,
|
True,
|
||||||
@@ -8881,12 +8964,24 @@ def smoke_node_scene_chain_registration() -> None:
|
|||||||
"simple black dress",
|
"simple black dress",
|
||||||
"fully nude",
|
"fully nude",
|
||||||
"",
|
"",
|
||||||
|
wardrobe_options=wardrobe_options,
|
||||||
|
seed_options=wardrobe_seed_options,
|
||||||
)
|
)
|
||||||
slots = json.loads(character_cast).get("slots") or []
|
slots = json.loads(character_cast).get("slots") or []
|
||||||
woman_slot = next(slot for slot in slots if slot.get("subject_type") == "woman")
|
woman_slot = next(slot for slot in slots if slot.get("subject_type") == "woman")
|
||||||
_expect(woman_slot.get("softcore_outfit") == "simple black dress", "Scene Wardrobe did not update softcore outfit")
|
_expect(woman_slot.get("softcore_outfit") == "simple black dress", "Scene Wardrobe did not update softcore outfit")
|
||||||
_expect(woman_slot.get("hardcore_clothing") == "fully nude", "Scene Wardrobe did not update hardcore clothing")
|
_expect(woman_slot.get("hardcore_clothing") == "fully nude", "Scene Wardrobe did not update hardcore clothing")
|
||||||
|
_expect(json.loads(scene).get("seed_trace", {}).get("wardrobe", {}).get("seed") == 9981, "Scene Wardrobe seed options did not write seed trace")
|
||||||
|
|
||||||
|
location_options = nodes["SxCPSceneLocationLayoutOptions"]().build(
|
||||||
|
"replace",
|
||||||
|
"mirror edge",
|
||||||
|
"soft curtain layer",
|
||||||
|
"repeating lamp reflections",
|
||||||
|
"private",
|
||||||
|
"private",
|
||||||
|
"warm mirror-room geometry",
|
||||||
|
)[0]
|
||||||
scene = nodes["SxCPSceneLocation"]().build(
|
scene = nodes["SxCPSceneLocation"]().build(
|
||||||
scene,
|
scene,
|
||||||
True,
|
True,
|
||||||
@@ -8894,10 +8989,26 @@ def smoke_node_scene_chain_registration() -> None:
|
|||||||
"custom_only",
|
"custom_only",
|
||||||
"quiet studio room with a large mirror",
|
"quiet studio room with a large mirror",
|
||||||
"",
|
"",
|
||||||
|
location_options=location_options,
|
||||||
)[0]
|
)[0]
|
||||||
scene = nodes["SxCPSceneSetDressing"]().build(scene, True, "mirror edge", "soft curtains", "small lamp", "")[0]
|
set_options = nodes["SxCPSceneSetDressingOptions"]().build("replace", "mirror edge", "soft curtains", "small lamp", "warm fabric texture", "")[0]
|
||||||
scene = nodes["SxCPSceneBlocking"]().build(scene, True, "standing", "woman near mirror", "man behind her", "")[0]
|
scene = nodes["SxCPSceneSetDressing"]().build(scene, True, "mirror edge", "soft curtains", "small lamp", "", set_options=set_options)[0]
|
||||||
scene = nodes["SxCPScenePerformance"]().build(scene, True, "fixed", 0.4, "controlled eye contact")[0]
|
blocking_options = nodes["SxCPSceneBlockingOptions"]().build(
|
||||||
|
"replace",
|
||||||
|
"standing",
|
||||||
|
"woman near mirror",
|
||||||
|
"man behind her",
|
||||||
|
"three_quarter",
|
||||||
|
"foreground",
|
||||||
|
"standing close",
|
||||||
|
"",
|
||||||
|
)[0]
|
||||||
|
scene = nodes["SxCPSceneBlocking"]().build(scene, True, "standing", "woman near mirror", "man behind her", "", blocking_options=blocking_options)[0]
|
||||||
|
action_options = nodes["SxCPSceneActionOptions"]().build("replace", "softcore", "softcore_tease", "no_change", "quiet pose transition")[0]
|
||||||
|
scene = nodes["SxCPSceneAction"]().build(scene, True, "regular", "no_change", "", action_options=action_options)[0]
|
||||||
|
performance_options = nodes["SxCPScenePerformanceOptions"]().build("replace", "enabled", "fixed", 0.4, "camera", "on_body", "posed", "controlled eye contact")[0]
|
||||||
|
scene = nodes["SxCPScenePerformance"]().build(scene, True, "fixed", 0.4, "controlled eye contact", performance_options=performance_options)[0]
|
||||||
|
camera_options = nodes["SxCPSceneCameraOptions"]().build("replace", "from_camera_config", True, "mirror-aware camera note")[0]
|
||||||
scene = nodes["SxCPSceneCamera"]().build(
|
scene = nodes["SxCPSceneCamera"]().build(
|
||||||
scene,
|
scene,
|
||||||
True,
|
True,
|
||||||
@@ -8911,9 +9022,12 @@ def smoke_node_scene_chain_registration() -> None:
|
|||||||
"strong",
|
"strong",
|
||||||
"compact",
|
"compact",
|
||||||
"",
|
"",
|
||||||
|
camera_options=camera_options,
|
||||||
)[0]
|
)[0]
|
||||||
scene = nodes["SxCPSceneComposition"]().build(scene, True, "replace", "no_outfit_check", "mirror-aware three-quarter frame", "")[0]
|
composition_options = nodes["SxCPSceneCompositionOptions"]().build("replace", "body", "three_quarter", "clear", "mirror-aware three-quarter frame")[0]
|
||||||
scene = nodes["SxCPSceneLighting"]().build(scene, True, "practical_lamps", "soft", "medium", "warm", "")[0]
|
scene = nodes["SxCPSceneComposition"]().build(scene, True, "replace", "no_outfit_check", "", "", composition_options=composition_options)[0]
|
||||||
|
lighting_options = nodes["SxCPSceneLightingOptions"]().build("replace", "practical_lamps", "soft", "medium", "warm", "evening", "")[0]
|
||||||
|
scene = nodes["SxCPSceneLighting"]().build(scene, True, "practical_lamps", "soft", "medium", "warm", "", lighting_options=lighting_options)[0]
|
||||||
|
|
||||||
output = nodes["SxCPSceneOutput"]().build(scene)
|
output = nodes["SxCPSceneOutput"]().build(scene)
|
||||||
_expect_text("node_scene_chain.prompt", output[0], 40)
|
_expect_text("node_scene_chain.prompt", output[0], 40)
|
||||||
@@ -8921,10 +9035,14 @@ def smoke_node_scene_chain_registration() -> None:
|
|||||||
row = json.loads(output[3])
|
row = json.loads(output[3])
|
||||||
_expect(row.get("scene_chain", {}).get("schema") == "sxcp_scene_v2", "Scene Output lost scene_chain metadata")
|
_expect(row.get("scene_chain", {}).get("schema") == "sxcp_scene_v2", "Scene Output lost scene_chain metadata")
|
||||||
|
|
||||||
|
branch_options = nodes["SxCPSceneBranchOptions"]().build("replace", "both", "same_creator_same_room", "hybrid", "shared branch note")[0]
|
||||||
|
branch_seed_options = nodes["SxCPSceneLayerSeedOptions"]().build("hardcore_branch", "fixed", 7799, "pose", "same_for_all_rows", "replace_layer")[0]
|
||||||
soft_scene, hard_scene, _branch_summary, _branch_metadata = nodes["SxCPSceneBranchPair"]().build(
|
soft_scene, hard_scene, _branch_summary, _branch_metadata = nodes["SxCPSceneBranchPair"]().build(
|
||||||
scene,
|
scene,
|
||||||
"same_creator_same_room",
|
"same_creator_same_room",
|
||||||
"hybrid",
|
"hybrid",
|
||||||
|
branch_options=branch_options,
|
||||||
|
seed_options=branch_seed_options,
|
||||||
)
|
)
|
||||||
soft_scene = nodes["SxCPSoftcoreBranchOptions"]().build(
|
soft_scene = nodes["SxCPSoftcoreBranchOptions"]().build(
|
||||||
soft_scene,
|
soft_scene,
|
||||||
@@ -8935,6 +9053,7 @@ def smoke_node_scene_chain_registration() -> None:
|
|||||||
"from_camera_config",
|
"from_camera_config",
|
||||||
"compact",
|
"compact",
|
||||||
"",
|
"",
|
||||||
|
branch_options=branch_options,
|
||||||
)[0]
|
)[0]
|
||||||
hard_scene = nodes["SxCPHardcoreBranchOptions"]().build(
|
hard_scene = nodes["SxCPHardcoreBranchOptions"]().build(
|
||||||
hard_scene,
|
hard_scene,
|
||||||
@@ -8949,6 +9068,8 @@ def smoke_node_scene_chain_registration() -> None:
|
|||||||
"compact",
|
"compact",
|
||||||
"balanced",
|
"balanced",
|
||||||
"",
|
"",
|
||||||
|
branch_options=branch_options,
|
||||||
|
seed_options=branch_seed_options,
|
||||||
)[0]
|
)[0]
|
||||||
pair_output = nodes["SxCPScenePairOutput"]().build(soft_scene, hard_scene)
|
pair_output = nodes["SxCPScenePairOutput"]().build(soft_scene, hard_scene)
|
||||||
_expect_text("node_scene_chain.softcore_prompt", pair_output[0], 40)
|
_expect_text("node_scene_chain.softcore_prompt", pair_output[0], 40)
|
||||||
@@ -8957,6 +9078,10 @@ def smoke_node_scene_chain_registration() -> None:
|
|||||||
_expect_pair(pair, "node_scene_chain_pair")
|
_expect_pair(pair, "node_scene_chain_pair")
|
||||||
_expect(pair.get("options", {}).get("hardcore_cast") == "couple", "Scene Pair Output lost hardcore branch options")
|
_expect(pair.get("options", {}).get("hardcore_cast") == "couple", "Scene Pair Output lost hardcore branch options")
|
||||||
_expect("scene_chain" in pair, "Scene Pair Output lost scene_chain metadata")
|
_expect("scene_chain" in pair, "Scene Pair Output lost scene_chain metadata")
|
||||||
|
_expect(
|
||||||
|
pair.get("scene_chain", {}).get("hardcore", {}).get("seed_trace", {}).get("hardcore.hardcore_branch", {}).get("seed") == 7799,
|
||||||
|
"Scene branch seed options did not write hardcore branch seed trace",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def smoke_node_builder_registration() -> None:
|
def smoke_node_builder_registration() -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user