diff --git a/node_scene.py b/node_scene.py index 28112f2..ac996d6 100644 --- a/node_scene.py +++ b/node_scene.py @@ -2280,6 +2280,7 @@ class SxCPScenePairOutput: hard_scene = _parse_scene(hardcore_scene) base_configs = _compat_configs(soft_scene, "softcore") 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) row = build_insta_of_pair( row_number=int(soft_scene.get("row_number", 1)), @@ -2291,7 +2292,9 @@ class SxCPScenePairOutput: no_black=False, trigger=str(soft_scene.get("trigger") or "sxcpinup_coloredpencil"), 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, filter_config=base_configs["filter_config"] or hard_configs["filter_config"], camera_config=base_configs["camera_config"], diff --git a/pair_builder.py b/pair_builder.py index 0cb4f7a..cdc5793 100644 --- a/pair_builder.py +++ b/pair_builder.py @@ -34,6 +34,8 @@ class InstaPairBuildRequest: trigger: str prepend_trigger_to_prompt: bool 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 filter_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) active_trigger = request.trigger.strip() or deps.default_trigger 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_slot_map = deps.character_slot_label_map(character_slots) 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, active_trigger=active_trigger, parsed_seed_config=parsed_seed_config, + parsed_softcore_seed_config=parsed_softcore_seed_config, + parsed_hardcore_seed_config=parsed_hardcore_seed_config, options=options, ethnicity=ethnicity, figure=figure, @@ -171,6 +185,7 @@ def build_insta_of_pair(request: InstaPairBuildRequest, deps: InstaPairBuildDepe soft_row=soft_row, options=options, parsed_seed_config=parsed_seed_config, + parsed_softcore_seed_config=parsed_softcore_seed_config, seed=request.seed, row_number=request.row_number, ethnicity=ethnicity, diff --git a/pair_cast.py b/pair_cast.py index 73607da..de4afee 100644 --- a/pair_cast.py +++ b/pair_cast.py @@ -222,7 +222,9 @@ def resolve_insta_pair_cast_context( slot_is_pov: SlotIsPov, choose: Choose, slot_softcore_outfit: SlotSoftcoreOutfit, + parsed_softcore_seed_config: dict[str, int] | None = None, ) -> dict[str, Any]: + soft_seed_config = parsed_softcore_seed_config or parsed_seed_config descriptor = insta_descriptor_from_row(soft_row) cast_descriptors, _descriptor_slots = cast_descriptor_entries_from_slots( seed_config=parsed_seed_config, @@ -245,7 +247,7 @@ def resolve_insta_pair_cast_context( 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_partner_styling = softcore_partner_styling( - seed_config=parsed_seed_config, + seed_config=soft_seed_config, seed=seed, row_number=row_number, women_count=hard_women_count if same_softcore_cast else 1, diff --git a/pair_rows.py b/pair_rows.py index a8b94ac..f1b0c51 100644 --- a/pair_rows.py +++ b/pair_rows.py @@ -67,11 +67,15 @@ def build_insta_pair_rows_result( softcore_item_prompt_label: Callable[[str], str], pov_prompt_directive: Callable[[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 = "", ) -> InstaPairRowsRoute: - 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) - soft_person_rng = axis_rng(parsed_seed_config, "person", seed, row_number) + soft_seed_config = parsed_softcore_seed_config or parsed_seed_config + hard_seed_config = parsed_hardcore_seed_config or parsed_seed_config + 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_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, extra_positive="", extra_negative="", - seed_config=parsed_seed_config, + seed_config=soft_seed_config, women_count=1, men_count=0, expression_enabled=soft_expression_enabled, @@ -188,7 +192,7 @@ def build_insta_pair_rows_result( prepend_trigger_to_prompt=False, extra_positive="", extra_negative="", - seed_config=parsed_seed_config, + seed_config=hard_seed_config, women_count=hard_women_count, men_count=hard_men_count, expression_enabled=options["hardcore_expression_enabled"], @@ -251,6 +255,8 @@ def build_insta_pair_rows( softcore_item_prompt_label: Callable[[str], str], pov_prompt_directive: Callable[[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 = "", ) -> dict[str, Any]: return build_insta_pair_rows_result( @@ -259,6 +265,8 @@ def build_insta_pair_rows( seed=seed, active_trigger=active_trigger, parsed_seed_config=parsed_seed_config, + parsed_softcore_seed_config=parsed_softcore_seed_config, + parsed_hardcore_seed_config=parsed_hardcore_seed_config, options=options, ethnicity=ethnicity, figure=figure, diff --git a/prompt_builder.py b/prompt_builder.py index 389a83b..04bb3a2 100644 --- a/prompt_builder.py +++ b/prompt_builder.py @@ -2832,6 +2832,8 @@ def build_insta_of_pair( trigger: str, prepend_trigger_to_prompt: bool, 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, filter_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, prepend_trigger_to_prompt=prepend_trigger_to_prompt, seed_config=seed_config, + softcore_seed_config=softcore_seed_config, + hardcore_seed_config=hardcore_seed_config, options_json=options_json, filter_config=filter_config, camera_config=camera_config, diff --git a/tools/prompt_smoke.py b/tools/prompt_smoke.py index 7243781..7f8afd3 100644 --- a/tools/prompt_smoke.py +++ b/tools/prompt_smoke.py @@ -9180,6 +9180,71 @@ def smoke_node_scene_chain_registration() -> None: hard_trace_axes.get("pose", {}).get("seed") == 7799, "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: