Allow inline scene camera profiles
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user