Compare commits
2 Commits
faacfc8853
...
4ca4653e7d
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ca4653e7d | |||
| 3130942caf |
+1
-1
@@ -2280,7 +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"]
|
shared_seed_config = _base_config(soft_scene, "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)),
|
||||||
|
|||||||
+2
-1
@@ -74,6 +74,7 @@ def build_insta_pair_rows_result(
|
|||||||
soft_seed_config = parsed_softcore_seed_config or parsed_seed_config
|
soft_seed_config = parsed_softcore_seed_config or parsed_seed_config
|
||||||
hard_seed_config = parsed_hardcore_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)
|
soft_content_rng = axis_rng(soft_seed_config, "content", seed, row_number + 311)
|
||||||
|
soft_pose_rng = axis_rng(soft_seed_config, "pose", seed, row_number + 313)
|
||||||
hard_content_rng = axis_rng(hard_seed_config, "content", seed, row_number + 317)
|
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_person_rng = axis_rng(soft_seed_config, "person", seed, row_number)
|
||||||
|
|
||||||
@@ -148,7 +149,7 @@ def build_insta_pair_rows_result(
|
|||||||
|
|
||||||
primary_softcore_outfit = slot_softcore_outfit(primary_slot, soft_content_rng)
|
primary_softcore_outfit = slot_softcore_outfit(primary_slot, soft_content_rng)
|
||||||
soft_row["item"] = primary_softcore_outfit or softcore_outfit(soft_content_rng, softcore_level_key)
|
soft_row["item"] = primary_softcore_outfit or softcore_outfit(soft_content_rng, softcore_level_key)
|
||||||
soft_row["pose"] = softcore_pose(soft_content_rng, softcore_level_key)
|
soft_row["pose"] = softcore_pose(soft_pose_rng, softcore_level_key)
|
||||||
soft_row["item_label"] = (
|
soft_row["item_label"] = (
|
||||||
"Insta/OF softcore body exposure"
|
"Insta/OF softcore body exposure"
|
||||||
if softcore_level_key == "explicit_nude"
|
if softcore_level_key == "explicit_nude"
|
||||||
|
|||||||
@@ -1042,10 +1042,11 @@ def scene_camera_directive(
|
|||||||
geometry = pov_camera_geometry_phrase(parsed, compact_labels) if pov_labels else camera_geometry_phrase(parsed, compact_labels)
|
geometry = pov_camera_geometry_phrase(parsed, compact_labels) if pov_labels else camera_geometry_phrase(parsed, compact_labels)
|
||||||
geometry_clause = f" ({geometry})" if geometry else ""
|
geometry_clause = f" ({geometry})" if geometry else ""
|
||||||
if pov_labels:
|
if pov_labels:
|
||||||
|
subject, _pronoun = scene_subject_terms(subject_kind, pov_labels)
|
||||||
return (
|
return (
|
||||||
f"{profile['layout_label']} from POV{geometry_clause}: {direction_detail}. "
|
f"{profile['layout_label']} from POV{geometry_clause}: keep {subject} and the action primary; "
|
||||||
f"{distance_detail}; {elevation_detail}; lower foreground is reserved for POV body or hand cues; "
|
f"{profile['place']} context stays beside or behind the bodies, not in the lower foreground; "
|
||||||
f"use the multiangle camera only as first-person spatial geometry."
|
f"lower foreground is reserved for POV body or hand cues; use the multiangle camera only as first-person spatial geometry."
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
f"{profile['layout_label']}{geometry_clause}: {direction_detail}; "
|
f"{profile['layout_label']}{geometry_clause}: {direction_detail}; "
|
||||||
@@ -1098,6 +1099,35 @@ def composition_subject_text(text: str, subject_kind: str) -> str:
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
ACTION_COMPOSITION_TERMS = (
|
||||||
|
"action geography",
|
||||||
|
"anal",
|
||||||
|
"ass",
|
||||||
|
"body contact",
|
||||||
|
"cowgirl",
|
||||||
|
"doggy",
|
||||||
|
"explicit",
|
||||||
|
"first-person",
|
||||||
|
"foreground hands",
|
||||||
|
"genital",
|
||||||
|
"hips",
|
||||||
|
"kneeling",
|
||||||
|
"mouth",
|
||||||
|
"oral",
|
||||||
|
"penetration",
|
||||||
|
"pov",
|
||||||
|
"rear-entry",
|
||||||
|
"rear entry",
|
||||||
|
"rear-view",
|
||||||
|
"sexual contact",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def is_action_specific_composition(text: Any) -> bool:
|
||||||
|
lower = str(text or "").lower()
|
||||||
|
return any(term in lower for term in ACTION_COMPOSITION_TERMS)
|
||||||
|
|
||||||
|
|
||||||
def contextual_composition_prompt(
|
def contextual_composition_prompt(
|
||||||
scene_text: Any,
|
scene_text: Any,
|
||||||
composition: Any,
|
composition: Any,
|
||||||
@@ -1110,6 +1140,8 @@ def contextual_composition_prompt(
|
|||||||
text = str(composition or "").strip()
|
text = str(composition or "").strip()
|
||||||
if not text:
|
if not text:
|
||||||
return text
|
return text
|
||||||
|
if is_action_specific_composition(text):
|
||||||
|
return text
|
||||||
text = composition_subject_text(text, subject_kind)
|
text = composition_subject_text(text, subject_kind)
|
||||||
profile = scene_camera_profile(scene_text, scene_entry=scene_entry, theme=theme, profile_key=profile_key)
|
profile = scene_camera_profile(scene_text, scene_entry=scene_entry, theme=theme, profile_key=profile_key)
|
||||||
if not profile:
|
if not profile:
|
||||||
|
|||||||
@@ -1258,7 +1258,7 @@ def _pair_seed_pose_reroll_check(seed: int) -> dict[str, Any]:
|
|||||||
seed,
|
seed,
|
||||||
name="pair_seed.pose_reroll",
|
name="pair_seed.pose_reroll",
|
||||||
reroll_axis="pose",
|
reroll_axis="pose",
|
||||||
changed_fields=("hard_position_key", "hard_item", "hard_source_role_graph"),
|
changed_fields=("soft_pose", "hard_position_key", "hard_item", "hard_source_role_graph"),
|
||||||
stable_fields=(
|
stable_fields=(
|
||||||
"shared_cast_descriptors",
|
"shared_cast_descriptors",
|
||||||
"soft_cast_descriptor_text",
|
"soft_cast_descriptor_text",
|
||||||
@@ -1266,7 +1266,6 @@ def _pair_seed_pose_reroll_check(seed: int) -> dict[str, Any]:
|
|||||||
"soft_scene_text",
|
"soft_scene_text",
|
||||||
"hard_scene_text",
|
"hard_scene_text",
|
||||||
"soft_item",
|
"soft_item",
|
||||||
"soft_pose",
|
|
||||||
"soft_composition",
|
"soft_composition",
|
||||||
"hard_composition",
|
"hard_composition",
|
||||||
),
|
),
|
||||||
@@ -1279,13 +1278,14 @@ def _pair_seed_content_reroll_check(seed: int) -> dict[str, Any]:
|
|||||||
seed,
|
seed,
|
||||||
name="pair_seed.content_reroll",
|
name="pair_seed.content_reroll",
|
||||||
reroll_axis="content",
|
reroll_axis="content",
|
||||||
changed_fields=("soft_item", "soft_pose"),
|
changed_fields=("soft_item",),
|
||||||
stable_fields=(
|
stable_fields=(
|
||||||
"shared_cast_descriptors",
|
"shared_cast_descriptors",
|
||||||
"soft_cast_descriptor_text",
|
"soft_cast_descriptor_text",
|
||||||
"hard_cast_descriptor_text",
|
"hard_cast_descriptor_text",
|
||||||
"soft_scene_text",
|
"soft_scene_text",
|
||||||
"hard_scene_text",
|
"hard_scene_text",
|
||||||
|
"soft_pose",
|
||||||
"hard_item",
|
"hard_item",
|
||||||
"hard_position_key",
|
"hard_position_key",
|
||||||
"hard_source_role_graph",
|
"hard_source_role_graph",
|
||||||
|
|||||||
+93
-1
@@ -881,6 +881,36 @@ def smoke_row_camera_policy() -> None:
|
|||||||
"coworking lounge frame with the couple near a desk edge" in updated.get("composition", ""),
|
"coworking lounge frame with the couple near a desk edge" in updated.get("composition", ""),
|
||||||
"row camera policy did not adapt coworking composition for couple rows",
|
"row camera policy did not adapt coworking composition for couple rows",
|
||||||
)
|
)
|
||||||
|
pov_action_row = dict(row)
|
||||||
|
pov_action_row["composition"] = (
|
||||||
|
"first-person rear-view frame looking down at the woman's raised ass, "
|
||||||
|
"with foreground hands and rear-entry contact readable"
|
||||||
|
)
|
||||||
|
pov_action_row["prompt"] = (
|
||||||
|
"A generated adult prompt. Framed as first-person rear-view frame looking down at the woman's raised ass, "
|
||||||
|
"with foreground hands and rear-entry contact readable. Avoid: low quality."
|
||||||
|
)
|
||||||
|
updated_pov_action = row_camera.apply_camera_config(
|
||||||
|
pov_action_row,
|
||||||
|
_orbit_camera(horizontal_angle=180, vertical_angle=-30, zoom=7.5),
|
||||||
|
compact_labels=pb.CAMERA_COMPACT_LABELS,
|
||||||
|
)
|
||||||
|
_expect(
|
||||||
|
"first-person rear-view frame" in updated_pov_action.get("composition", ""),
|
||||||
|
"row camera policy replaced explicit POV action composition with generic location composition",
|
||||||
|
)
|
||||||
|
_expect(
|
||||||
|
"couple's raised ass" not in updated_pov_action.get("composition", ""),
|
||||||
|
"row camera policy rewrote explicit female action anatomy as couple anatomy",
|
||||||
|
)
|
||||||
|
_expect(
|
||||||
|
"coworking lounge frame with the couple near a desk edge" not in updated_pov_action.get("composition", ""),
|
||||||
|
"row camera policy leaked generic coworking composition into explicit POV action frame",
|
||||||
|
)
|
||||||
|
_expect(
|
||||||
|
str(updated_pov_action.get("camera_scene_directive", "")).count(";") <= 3,
|
||||||
|
"POV camera scene directive became too noisy",
|
||||||
|
)
|
||||||
already_matching_row = dict(row)
|
already_matching_row = dict(row)
|
||||||
already_matching_row["pov_character_labels"] = []
|
already_matching_row["pov_character_labels"] = []
|
||||||
already_matching_row["composition"] = "coworking lounge frame with the subjects near a desk edge and tall-window depth behind them"
|
already_matching_row["composition"] = "coworking lounge frame with the subjects near a desk edge and tall-window depth behind them"
|
||||||
@@ -8277,7 +8307,7 @@ def smoke_prompt_route_simulation_policy() -> None:
|
|||||||
)
|
)
|
||||||
_expect(
|
_expect(
|
||||||
pair_seed_checks["pair_seed.pose_reroll"].get("changed") is True,
|
pair_seed_checks["pair_seed.pose_reroll"].get("changed") is True,
|
||||||
"Pair pose reroll should prove hard action can reroll while soft/cast/scene axes stay locked",
|
"Pair pose reroll should prove soft pose or hard action can reroll while cast/scene axes stay locked",
|
||||||
)
|
)
|
||||||
sweep = prompt_route_simulation.run_simulation_sweep(seed=3901, count=3, seed_step=101, include_prompts=False)
|
sweep = prompt_route_simulation.run_simulation_sweep(seed=3901, count=3, seed_step=101, include_prompts=False)
|
||||||
sweep_summary = sweep.get("summary") or {}
|
sweep_summary = sweep.get("summary") or {}
|
||||||
@@ -9263,6 +9293,68 @@ def smoke_node_scene_chain_registration() -> None:
|
|||||||
content_hard_seed_config.get("pose_seed") == 8899 and content_hard_seed_config.get("role_seed") == 8899,
|
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",
|
"Hardcore branch content_pose reroll did not reach hardcore pose and role seeds",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _soft_pose_pair(soft_pose_seed: int) -> dict[str, Any]:
|
||||||
|
soft_pose_seed_options = nodes["SxCPSceneLayerSeedOptions"]().build(
|
||||||
|
"softcore_branch",
|
||||||
|
"fixed",
|
||||||
|
soft_pose_seed,
|
||||||
|
"pose",
|
||||||
|
"same_for_all_rows",
|
||||||
|
"replace_layer",
|
||||||
|
)[0]
|
||||||
|
soft_scene_pose, hard_scene_pose, _summary, _metadata = nodes["SxCPSceneBranchPair"]().build(
|
||||||
|
scene,
|
||||||
|
"same_creator_same_room",
|
||||||
|
"hybrid",
|
||||||
|
branch_options=branch_options,
|
||||||
|
seed_options=soft_pose_seed_options,
|
||||||
|
)
|
||||||
|
soft_scene_pose = nodes["SxCPSoftcoreBranchOptions"]().build(
|
||||||
|
soft_scene_pose,
|
||||||
|
"same_as_hardcore",
|
||||||
|
"lingerie_tease",
|
||||||
|
True,
|
||||||
|
0.45,
|
||||||
|
"from_camera_config",
|
||||||
|
"compact",
|
||||||
|
"",
|
||||||
|
branch_options=branch_options,
|
||||||
|
seed_options=soft_pose_seed_options,
|
||||||
|
)[0]
|
||||||
|
hard_scene_pose = nodes["SxCPHardcoreBranchOptions"]().build(
|
||||||
|
hard_scene_pose,
|
||||||
|
"couple",
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
"hardcore",
|
||||||
|
True,
|
||||||
|
0.85,
|
||||||
|
"explicit_nude",
|
||||||
|
"from_camera_config",
|
||||||
|
"compact",
|
||||||
|
"balanced",
|
||||||
|
"",
|
||||||
|
branch_options=branch_options,
|
||||||
|
)[0]
|
||||||
|
return json.loads(nodes["SxCPScenePairOutput"]().build(soft_scene_pose, hard_scene_pose)[7])
|
||||||
|
|
||||||
|
soft_pose_pairs = [_soft_pose_pair(seed) for seed in (6677, 6678, 6679, 6680)]
|
||||||
|
soft_pose_items = {pair.get("softcore_row", {}).get("item") for pair in soft_pose_pairs}
|
||||||
|
soft_pose_values = {pair.get("softcore_row", {}).get("pose") for pair in soft_pose_pairs}
|
||||||
|
_expect(len(soft_pose_items) == 1, "Softcore branch pose reroll should not change softcore outfit/content")
|
||||||
|
_expect(len(soft_pose_values) > 1, "Softcore branch pose reroll did not change softcore pose")
|
||||||
|
for expected_seed, pose_pair in zip((6677, 6678, 6679, 6680), soft_pose_pairs):
|
||||||
|
soft_seed_config = pose_pair.get("softcore_row", {}).get("seed_config") if isinstance(pose_pair.get("softcore_row"), dict) else {}
|
||||||
|
hard_seed_config = pose_pair.get("hardcore_row", {}).get("seed_config") if isinstance(pose_pair.get("hardcore_row"), dict) else {}
|
||||||
|
_expect(
|
||||||
|
soft_seed_config.get("pose_seed") == expected_seed,
|
||||||
|
"Softcore branch pose seed did not reach softcore generator seed config",
|
||||||
|
)
|
||||||
|
_expect(
|
||||||
|
hard_seed_config.get("pose_seed") != expected_seed,
|
||||||
|
"Softcore branch pose seed leaked into hardcore generator seed config",
|
||||||
|
)
|
||||||
choice_board_node = nodes["SxCPChoiceBoard"]()
|
choice_board_node = nodes["SxCPChoiceBoard"]()
|
||||||
choice_board_output = choice_board_node.build(
|
choice_board_output = choice_board_node.build(
|
||||||
json.dumps(content_pair),
|
json.dumps(content_pair),
|
||||||
|
|||||||
Reference in New Issue
Block a user