Keep softcore clothing stable during hard rerolls

This commit is contained in:
2026-06-28 01:49:10 +02:00
parent ab8abc07e6
commit 509960a699
6 changed files with 104 additions and 7 deletions
+4 -1
View File
@@ -2280,6 +2280,7 @@ class SxCPScenePairOutput:
hard_scene = _parse_scene(hardcore_scene) hard_scene = _parse_scene(hardcore_scene)
base_configs = _compat_configs(soft_scene, "softcore") base_configs = _compat_configs(soft_scene, "softcore")
hard_configs = _compat_configs(hard_scene, "hardcore") hard_configs = _compat_configs(hard_scene, "hardcore")
shared_seed_config = _base_config(soft_scene, "seed_config") or base_configs["seed_config"]
options_json = _pair_options(soft_scene, hard_scene) options_json = _pair_options(soft_scene, hard_scene)
row = build_insta_of_pair( row = build_insta_of_pair(
row_number=int(soft_scene.get("row_number", 1)), row_number=int(soft_scene.get("row_number", 1)),
@@ -2291,7 +2292,9 @@ class SxCPScenePairOutput:
no_black=False, no_black=False,
trigger=str(soft_scene.get("trigger") or "sxcpinup_coloredpencil"), trigger=str(soft_scene.get("trigger") or "sxcpinup_coloredpencil"),
prepend_trigger_to_prompt=bool(soft_scene.get("prepend_trigger_to_prompt", True)), prepend_trigger_to_prompt=bool(soft_scene.get("prepend_trigger_to_prompt", True)),
seed_config=_combined_seed_config(base_configs["seed_config"], hard_configs["seed_config"]), seed_config=shared_seed_config,
softcore_seed_config=base_configs["seed_config"],
hardcore_seed_config=hard_configs["seed_config"],
options_json=options_json, options_json=options_json,
filter_config=base_configs["filter_config"] or hard_configs["filter_config"], filter_config=base_configs["filter_config"] or hard_configs["filter_config"],
camera_config=base_configs["camera_config"], camera_config=base_configs["camera_config"],
+15
View File
@@ -34,6 +34,8 @@ class InstaPairBuildRequest:
trigger: str trigger: str
prepend_trigger_to_prompt: bool prepend_trigger_to_prompt: bool
seed_config: str | dict[str, Any] | None = None seed_config: str | dict[str, Any] | None = None
softcore_seed_config: str | dict[str, Any] | None = None
hardcore_seed_config: str | dict[str, Any] | None = None
options_json: str | dict[str, Any] | None = None options_json: str | dict[str, Any] | None = None
filter_config: str | dict[str, Any] | None = None filter_config: str | dict[str, Any] | None = None
camera_config: str | dict[str, Any] | None = None camera_config: str | dict[str, Any] | None = None
@@ -119,6 +121,16 @@ def build_insta_of_pair(request: InstaPairBuildRequest, deps: InstaPairBuildDepe
hard_women_count, hard_men_count = deps.hardcore_counts(options) hard_women_count, hard_men_count = deps.hardcore_counts(options)
active_trigger = request.trigger.strip() or deps.default_trigger active_trigger = request.trigger.strip() or deps.default_trigger
parsed_seed_config = deps.parse_seed_config(request.seed_config) parsed_seed_config = deps.parse_seed_config(request.seed_config)
parsed_softcore_seed_config = (
deps.parse_seed_config(request.softcore_seed_config)
if request.softcore_seed_config
else parsed_seed_config
)
parsed_hardcore_seed_config = (
deps.parse_seed_config(request.hardcore_seed_config)
if request.hardcore_seed_config
else parsed_seed_config
)
character_slots = deps.parse_character_cast(request.character_cast) character_slots = deps.parse_character_cast(request.character_cast)
character_slot_map = deps.character_slot_label_map(character_slots) character_slot_map = deps.character_slot_label_map(character_slots)
pov_character_labels = deps.pov_character_labels(character_slot_map, hard_men_count) pov_character_labels = deps.pov_character_labels(character_slot_map, hard_men_count)
@@ -131,6 +143,8 @@ def build_insta_of_pair(request: InstaPairBuildRequest, deps: InstaPairBuildDepe
seed=request.seed, seed=request.seed,
active_trigger=active_trigger, active_trigger=active_trigger,
parsed_seed_config=parsed_seed_config, parsed_seed_config=parsed_seed_config,
parsed_softcore_seed_config=parsed_softcore_seed_config,
parsed_hardcore_seed_config=parsed_hardcore_seed_config,
options=options, options=options,
ethnicity=ethnicity, ethnicity=ethnicity,
figure=figure, figure=figure,
@@ -171,6 +185,7 @@ def build_insta_of_pair(request: InstaPairBuildRequest, deps: InstaPairBuildDepe
soft_row=soft_row, soft_row=soft_row,
options=options, options=options,
parsed_seed_config=parsed_seed_config, parsed_seed_config=parsed_seed_config,
parsed_softcore_seed_config=parsed_softcore_seed_config,
seed=request.seed, seed=request.seed,
row_number=request.row_number, row_number=request.row_number,
ethnicity=ethnicity, ethnicity=ethnicity,
+3 -1
View File
@@ -222,7 +222,9 @@ def resolve_insta_pair_cast_context(
slot_is_pov: SlotIsPov, slot_is_pov: SlotIsPov,
choose: Choose, choose: Choose,
slot_softcore_outfit: SlotSoftcoreOutfit, slot_softcore_outfit: SlotSoftcoreOutfit,
parsed_softcore_seed_config: dict[str, int] | None = None,
) -> dict[str, Any]: ) -> dict[str, Any]:
soft_seed_config = parsed_softcore_seed_config or parsed_seed_config
descriptor = insta_descriptor_from_row(soft_row) descriptor = insta_descriptor_from_row(soft_row)
cast_descriptors, _descriptor_slots = cast_descriptor_entries_from_slots( cast_descriptors, _descriptor_slots = cast_descriptor_entries_from_slots(
seed_config=parsed_seed_config, seed_config=parsed_seed_config,
@@ -245,7 +247,7 @@ def resolve_insta_pair_cast_context(
same_softcore_cast = options["softcore_cast"] == "same_as_hardcore" same_softcore_cast = options["softcore_cast"] == "same_as_hardcore"
soft_cast_descriptor_text = cast_descriptor_text if same_softcore_cast else f"Woman A: {descriptor}" soft_cast_descriptor_text = cast_descriptor_text if same_softcore_cast else f"Woman A: {descriptor}"
soft_partner_styling = softcore_partner_styling( soft_partner_styling = softcore_partner_styling(
seed_config=parsed_seed_config, seed_config=soft_seed_config,
seed=seed, seed=seed,
row_number=row_number, row_number=row_number,
women_count=hard_women_count if same_softcore_cast else 1, women_count=hard_women_count if same_softcore_cast else 1,
+13 -5
View File
@@ -67,11 +67,15 @@ 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],
parsed_softcore_seed_config: dict[str, int] | None = None,
parsed_hardcore_seed_config: dict[str, int] | None = None,
style_config: str | dict[str, Any] | None = "", style_config: str | dict[str, Any] | None = "",
) -> InstaPairRowsRoute: ) -> InstaPairRowsRoute:
soft_content_rng = axis_rng(parsed_seed_config, "content", seed, row_number + 311) soft_seed_config = parsed_softcore_seed_config or parsed_seed_config
hard_content_rng = axis_rng(parsed_seed_config, "content", seed, row_number + 317) hard_seed_config = parsed_hardcore_seed_config or parsed_seed_config
soft_person_rng = axis_rng(parsed_seed_config, "person", seed, row_number) soft_content_rng = axis_rng(soft_seed_config, "content", seed, row_number + 311)
hard_content_rng = axis_rng(hard_seed_config, "content", seed, row_number + 317)
soft_person_rng = axis_rng(soft_seed_config, "person", seed, row_number)
soft_expression_women_count = hard_women_count if options["softcore_cast"] == "same_as_hardcore" else 1 soft_expression_women_count = hard_women_count if options["softcore_cast"] == "same_as_hardcore" else 1
soft_expression_men_count = hard_men_count if options["softcore_cast"] == "same_as_hardcore" else 0 soft_expression_men_count = hard_men_count if options["softcore_cast"] == "same_as_hardcore" else 0
@@ -123,7 +127,7 @@ def build_insta_pair_rows_result(
prepend_trigger_to_prompt=False, prepend_trigger_to_prompt=False,
extra_positive="", extra_positive="",
extra_negative="", extra_negative="",
seed_config=parsed_seed_config, seed_config=soft_seed_config,
women_count=1, women_count=1,
men_count=0, men_count=0,
expression_enabled=soft_expression_enabled, expression_enabled=soft_expression_enabled,
@@ -188,7 +192,7 @@ def build_insta_pair_rows_result(
prepend_trigger_to_prompt=False, prepend_trigger_to_prompt=False,
extra_positive="", extra_positive="",
extra_negative="", extra_negative="",
seed_config=parsed_seed_config, seed_config=hard_seed_config,
women_count=hard_women_count, women_count=hard_women_count,
men_count=hard_men_count, men_count=hard_men_count,
expression_enabled=options["hardcore_expression_enabled"], expression_enabled=options["hardcore_expression_enabled"],
@@ -251,6 +255,8 @@ 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],
parsed_softcore_seed_config: dict[str, int] | None = None,
parsed_hardcore_seed_config: dict[str, int] | None = None,
style_config: str | dict[str, Any] | None = "", 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(
@@ -259,6 +265,8 @@ def build_insta_pair_rows(
seed=seed, seed=seed,
active_trigger=active_trigger, active_trigger=active_trigger,
parsed_seed_config=parsed_seed_config, parsed_seed_config=parsed_seed_config,
parsed_softcore_seed_config=parsed_softcore_seed_config,
parsed_hardcore_seed_config=parsed_hardcore_seed_config,
options=options, options=options,
ethnicity=ethnicity, ethnicity=ethnicity,
figure=figure, figure=figure,
+4
View File
@@ -2832,6 +2832,8 @@ def build_insta_of_pair(
trigger: str, trigger: str,
prepend_trigger_to_prompt: bool, prepend_trigger_to_prompt: bool,
seed_config: str | dict[str, Any] | None = None, seed_config: str | dict[str, Any] | None = None,
softcore_seed_config: str | dict[str, Any] | None = None,
hardcore_seed_config: str | dict[str, Any] | None = None,
options_json: str | dict[str, Any] | None = None, options_json: str | dict[str, Any] | None = None,
filter_config: str | dict[str, Any] | None = None, filter_config: str | dict[str, Any] | None = None,
camera_config: str | dict[str, Any] | None = None, camera_config: str | dict[str, Any] | None = None,
@@ -2857,6 +2859,8 @@ def build_insta_of_pair(
trigger=trigger, trigger=trigger,
prepend_trigger_to_prompt=prepend_trigger_to_prompt, prepend_trigger_to_prompt=prepend_trigger_to_prompt,
seed_config=seed_config, seed_config=seed_config,
softcore_seed_config=softcore_seed_config,
hardcore_seed_config=hardcore_seed_config,
options_json=options_json, options_json=options_json,
filter_config=filter_config, filter_config=filter_config,
camera_config=camera_config, camera_config=camera_config,
+65
View File
@@ -9180,6 +9180,71 @@ def smoke_node_scene_chain_registration() -> None:
hard_trace_axes.get("pose", {}).get("seed") == 7799, hard_trace_axes.get("pose", {}).get("seed") == 7799,
"Scene Pair Output generation trace did not use hardcore branch pose seed", "Scene Pair Output generation trace did not use hardcore branch pose seed",
) )
content_pose_seed_options = nodes["SxCPSceneLayerSeedOptions"]().build(
"hardcore_branch",
"fixed",
8899,
"content_pose",
"same_for_all_rows",
"replace_layer",
)[0]
soft_scene_content, hard_scene_content, _branch_summary, _branch_metadata = nodes["SxCPSceneBranchPair"]().build(
scene,
"same_creator_same_room",
"hybrid",
branch_options=branch_options,
seed_options=content_pose_seed_options,
)
soft_scene_content = nodes["SxCPSoftcoreBranchOptions"]().build(
soft_scene_content,
"same_as_hardcore",
"lingerie_tease",
True,
0.45,
"from_camera_config",
"compact",
"",
branch_options=branch_options,
)[0]
hard_scene_content = nodes["SxCPHardcoreBranchOptions"]().build(
hard_scene_content,
"couple",
1,
1,
"hardcore",
True,
0.85,
"explicit_nude",
"from_camera_config",
"compact",
"balanced",
"",
branch_options=branch_options,
seed_options=content_pose_seed_options,
)[0]
content_pair = json.loads(nodes["SxCPScenePairOutput"]().build(soft_scene_content, hard_scene_content)[7])
content_soft_seed_config = (
content_pair.get("softcore_row", {}).get("seed_config")
if isinstance(content_pair.get("softcore_row"), dict)
else {}
)
content_hard_seed_config = (
content_pair.get("hardcore_row", {}).get("seed_config")
if isinstance(content_pair.get("hardcore_row"), dict)
else {}
)
_expect(
content_soft_seed_config.get("content_seed") != 8899,
"Hardcore branch content_pose reroll leaked into softcore clothing seed",
)
_expect(
content_hard_seed_config.get("content_seed") == 8899,
"Hardcore branch content_pose reroll did not reach hardcore content seed",
)
_expect(
content_hard_seed_config.get("pose_seed") == 8899 and content_hard_seed_config.get("role_seed") == 8899,
"Hardcore branch content_pose reroll did not reach hardcore pose and role seeds",
)
def smoke_node_builder_registration() -> None: def smoke_node_builder_registration() -> None: