Allow inline scene camera profiles

This commit is contained in:
2026-06-27 13:30:59 +02:00
parent f811c02641
commit 17c6d34784
4 changed files with 146 additions and 0 deletions
+90
View File
@@ -118,6 +118,17 @@ THEME_PROFILE_KEYS = {
"classical_library": "classical_library",
}
PROFILE_TEXT_FIELDS = (
"key",
"family",
"layout_label",
"place",
"foreground",
"midground",
"background",
"detail_label",
)
MISMATCHED_COMPOSITION_TERMS = (
"outfit-check",
"outfit check",
@@ -129,6 +140,10 @@ MISMATCHED_COMPOSITION_TERMS = (
)
def _clean_text(value: Any) -> str:
return " ".join(str(value or "").strip().split())
def _profile_by_key(value: Any) -> dict[str, Any]:
key = str(value or "").strip()
if not key:
@@ -141,6 +156,62 @@ def _profile_by_key(value: Any) -> dict[str, Any]:
return {}
def _profile_title(value: str) -> str:
text = _clean_text(value).replace("_", " ").replace("-", " ")
if not text:
return "Scene"
return " ".join(part[:1].upper() + part[1:] for part in text.split())
def _default_composition(profile: dict[str, Any]) -> dict[str, str]:
place = _clean_text(profile.get("place")) or "scene"
foreground = _clean_text(profile.get("foreground")) or "foreground anchor"
background = _clean_text(profile.get("background")) or "environment depth"
return {
"woman": f"{place} frame with the woman near {foreground} and {background} behind her",
"man": f"{place} frame with the man near {foreground} and {background} behind him",
"default": f"{place} frame with the subjects near {foreground} and {background} behind them",
}
def normalize_scene_camera_profile(value: Any) -> dict[str, Any]:
if not isinstance(value, dict):
return {}
base = _profile_by_key(value.get("base_profile_key") or value.get("extends"))
merged = dict(base)
for key, raw_value in value.items():
if key in ("base_profile_key", "extends"):
continue
merged[key] = raw_value
has_profile_fields = any(_clean_text(merged.get(key)) for key in ("layout_label", "place", "foreground", "midground", "background"))
if not has_profile_fields:
return {}
key = _clean_text(merged.get("key") or merged.get("slug") or merged.get("name") or base.get("key") or "custom_scene")
place = _clean_text(merged.get("place") or merged.get("name") or key.replace("_", " "))
profile = {field: _clean_text(merged.get(field)) for field in PROFILE_TEXT_FIELDS}
profile["key"] = key
profile["family"] = profile["family"] or "custom"
profile["place"] = place
profile["layout_label"] = profile["layout_label"] or f"{_profile_title(place)} camera layout"
profile["foreground"] = profile["foreground"] or base.get("foreground", "foreground anchor")
profile["midground"] = profile["midground"] or base.get("midground", "midground environment anchors")
profile["background"] = profile["background"] or base.get("background", "background depth")
profile["detail_label"] = profile["detail_label"] or f"{place} details"
composition = merged.get("composition")
if isinstance(composition, dict):
profile["composition"] = {
str(key): _clean_text(text)
for key, text in composition.items()
if _clean_text(text)
}
else:
base_composition = base.get("composition") if isinstance(base.get("composition"), dict) else {}
profile["composition"] = dict(base_composition) if base_composition else _default_composition(profile)
if not profile["composition"]:
profile["composition"] = _default_composition(profile)
return profile
def _scene_entry_text(scene_entry: Any) -> str:
if not isinstance(scene_entry, dict):
return ""
@@ -165,6 +236,19 @@ def _scene_entry_profile_key(scene_entry: Any) -> str:
).strip()
def _scene_entry_profile(scene_entry: Any) -> dict[str, Any]:
if not isinstance(scene_entry, dict):
return {}
for key in ("scene_camera_profile", "camera_profile"):
profile = normalize_scene_camera_profile(scene_entry.get(key))
if profile:
return profile
profile = normalize_scene_camera_profile(scene_entry.get("profile"))
if profile:
return profile
return normalize_scene_camera_profile(scene_entry)
def scene_camera_profile(
scene_text: Any = "",
*,
@@ -172,9 +256,15 @@ def scene_camera_profile(
theme: Any = "",
profile_key: Any = "",
) -> dict[str, Any]:
inline_explicit_profile = normalize_scene_camera_profile(profile_key)
if inline_explicit_profile:
return inline_explicit_profile
explicit_profile = _profile_by_key(profile_key)
if explicit_profile:
return explicit_profile
inline_entry_profile = _scene_entry_profile(scene_entry)
if inline_entry_profile:
return inline_entry_profile
entry_profile = _profile_by_key(_scene_entry_profile_key(scene_entry))
if entry_profile:
return entry_profile