Files
Forge-Engine/screens/rendering/dialogue_box_style.py
T
williamandClaude Sonnet 5 2347a70c45
Build and deploy / test-python (push) Successful in 11m32s
Build and deploy / test-js (push) Successful in 1m12s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Quêtes/collision : personnages nommés, dialogues qui parlent, boîte de dialogue en jeu
- "ℹ️ Informations" (propriétés d'un personnage) : nom éditable, réutilisé
  comme "qui parle" dans l'éditeur de dialogue de quête (menu déroulant,
  plus "Joueur" toujours disponible) — remplace l'ancien choix binaire
  joueur/pnj. db.sanitize_quest_dialogues accepte maintenant un nom libre.

- Nouveau menu "🖥️ Interface" (palette d'objets) avec le premier widget :
  "💬 Boîte de dialogue" (kind="dialogue_box", screens/rendering/
  dialogue_box_style.py) — position/taille comme tout objet de scène,
  panneau "🎨 Style" dédié (police, taille, épaisseur, couleur du texte,
  couleur header/body/footer). Rendu en <div> à 3 zones, jamais soumis à
  la collision ni à l'éditeur de collision (exclu partout : obstacles,
  liste des règles, payload). Rendu côté jeu dans .sceneUI, une couche
  FIXE au viewport (jamais .sceneWorld, qui défile avec la caméra).

- static/js/play/dialogue-box-controller.js : fait le lien moteur entre
  l'action "quete" de l'éditeur de collision et ce widget — affiche la
  réplique en cours du dialogue correspondant au STATUT ACTUEL de la
  quête (gameData.quests, désormais exposé game-wide par
  full_game_payload.py), avance au clic sur "Suivant" (header = qui
  parle, body = texte, footer = bouton), se masque à la dernière réplique.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-03 11:20:58 +02:00

51 lines
1.8 KiB
Python

import json
# Widget d'interface "💬 Boîte de dialogue" (voir "🖥️ Interface",
# templates/scene_edit.html, screens/scenes/add_scene_object.py kind=
# "dialogue_box") : affiche AUTOMATIQUEMENT, en jeu, la réplique en cours
# d'une quête déclenchée par une règle de collision "quete" (voir
# static/js/play/dialogue-box-controller.js) — header (nom du
# personnage qui parle), corps (texte), pied (bouton "Suivant"),
# entièrement stylisable par l'auteur.
DEFAULT_DIALOGUE_BOX_STYLE = {
"font_family": "inherit",
"font_size": 14,
"font_weight": "normal",
"text_color": "#ffffff",
"header_bg": "#2f6fed",
"body_bg": "#1a1d24",
"footer_bg": "#11141b",
}
FONT_WEIGHT_CHOICES = ["normal", "bold"]
def sanitize_dialogue_box_style(raw_style):
style = dict(DEFAULT_DIALOGUE_BOX_STYLE)
if not isinstance(raw_style, dict):
return style
if isinstance(raw_style.get("font_family"), str) and raw_style["font_family"].strip():
style["font_family"] = raw_style["font_family"].strip()[:60]
try:
style["font_size"] = max(8, min(48, int(raw_style.get("font_size"))))
except (TypeError, ValueError):
pass
if raw_style.get("font_weight") in FONT_WEIGHT_CHOICES:
style["font_weight"] = raw_style["font_weight"]
for key in ("text_color", "header_bg", "body_bg", "footer_bg"):
value = raw_style.get(key)
if isinstance(value, str) and value.strip():
style[key] = value.strip()[:20]
return style
def resolve_dialogue_box_style(obj):
raw = (obj.get("attributes") or {}).get("_dialogue_box_style")
if not raw:
return dict(DEFAULT_DIALOGUE_BOX_STYLE)
try:
parsed = json.loads(raw)
except (TypeError, ValueError):
return dict(DEFAULT_DIALOGUE_BOX_STYLE)
return sanitize_dialogue_box_style(parsed)