Files
Forge-Engine/screens/rendering/render_overlay.py
T
williamandClaude Sonnet 5 78a373a536 Corrige la vraie cause : la boîte de dialogue restait invisible DANS L'ÉDITEUR (masquée par défaut)
Après vérification serveur, le texte était bel et bien rendu dans le HTML
(couleur correcte incluse) — donc pas un souci de contenu ni de couleur.
La vraie cause : le widget "Superposition / boîte de dialogue" démarre
MASQUÉ par défaut à sa création (display:none, voir
default_style_for_widget.py — pour ne pas couvrir tout l'écran dès qu'on
le pose). Ce display:none est écrit tel quel dans le HTML aussi bien en
mode jouable QUE dans l'éditeur, puisque le rendu de ce widget est
partagé par les deux. Résultat : toute la boîte (et donc son contenu,
peu importe le texte ou sa couleur) restait invisible dans le CANEVAS DE
L'ÉDITEUR dès l'instant de sa création — impossible d'y voir/positionner
visuellement ce qu'on pose dedans tant qu'on n'a pas pensé à basculer
manuellement "Visibilité" sur "Visible" (puis à y repenser pour la
remettre sur "Masqué" avant de tester en jeu).

Correctif (render_overlay.py) : dans l'ÉDITEUR uniquement (détecté via le
ctx "_forge_play_mode" déjà posé par list_elements.py pour le mode
jouable), un "display:flex" est ajouté en dernier dans le style —
gagnant sur le "display:none" par défaut (CSS : la dernière déclaration
de la même propriété l'emporte). Le mode JOUABLE, lui, continue de
respecter ce réglage normalement (masqué tant qu'aucune action ne
l'affiche).

Nouveau test, confirmé en échec sur l'ancien code puis au vert avec le
correctif : vérifie explicitement que le style se termine par
"display:flex;" dans l'éditeur et par "display:none;" en mode jouable.
139 tests au vert au total. Jeu de démo régénéré.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-28 06:30:24 +02:00

99 lines
5.8 KiB
Python

import html as html_lib
from .visible_attrs import _visible_attrs
from .style_string import _style_string
from .render_children import _render_children
def _render_overlay(el, meta, slug, children_map=None, ctx=None, parent_flex_direction=None):
"""3.4 (Confort) — overlay/modale réutilisable : une boîte de dialogue
prête à l'emploi, par-dessus TOUT le reste de l'écran, fermeture
manuelle uniquement (aucun clic-en-dehors-pour-fermer volontairement,
conformément au manque documenté). Contrairement aux autres widgets, sa
position ne dépend PAS de x/y/width/height (glissé-déposé sur le
canevas) : `position:fixed; inset:0` la fait toujours couvrir tout
l'écran, quel que soit l'endroit où elle a été posée dans l'éditeur —
seul un voile semi-transparent + une boîte centrée, contenant les
éléments posés à l'intérieur (comme un conteneur normal).
Ouverture/fermeture : PAS de mécanisme dédié — elle réutilise l'action
existante "Modifier un élément → Visibilité" (masquer/rendre visible),
exactement comme n'importe quel autre élément. C'est pour ça qu'on
fusionne le style de positionnement fixe ci-dessous AVEC le style normal
de l'élément (_style_string) : si l'élément est réglé "Masqué" dans ses
propriétés, ou si une action "Modifier un élément" le cache plus tard,
ce masquage continue de fonctionner normalement.
Classes Bulma ("modal is-active" / "box") posées en PLUS du style
inline existant, jamais à sa place : tout le positionnement/masquage
critique (position:fixed, z-index, display) reste en inline, qui gagne
toujours sur une règle de classe — si Bulma (chargé depuis un CDN, voir
play.html) ne se charge pas (hors-ligne), la boîte de dialogue continue
de fonctionner exactement pareil, ces classes n'ajoutant qu'un habillage
visuel (ombre, base de police) qui se dégrade sans casser quoi que ce
soit. Pas de ".modal-background" séparé : le voile semi-transparent est
déjà posé en inline sur cette même balise (background:rgba(...)) — un
second calque tout aussi transparent par-dessus n'ajouterait rien."""
attrs_raw = el.get("attributes") or {}
box_color = attrs_raw.get("_couleur_boite") or "#1f2430"
radius = attrs_raw.get("_arrondi") or "12"
attrs = _visible_attrs(el, meta, ctx)
base_overlay_style = (
"position:fixed; inset:0; z-index:9999; display:flex; "
"align-items:center; justify-content:center; background:rgba(0,0,0,0.6);"
)
style = base_overlay_style + " " + _style_string(el, parent_flex_direction=parent_flex_direction)
if not (ctx and ctx.get("_forge_play_mode")):
# Dans l'ÉDITEUR (ctx sans _forge_play_mode — voir list_elements.py,
# posé uniquement en mode JOUABLE), ce widget doit rester visible
# quel que soit son réglage de visibilité statique — "Masqué" par
# défaut à SA création (default_style_for_widget.py), pour ne pas
# couvrir tout l'écran dès qu'on le pose. Sans ce forçage, la boîte
# de dialogue reste display:none dans le canevas de l'éditeur, donc
# invisible dès sa création : impossible d'y voir/positionner son
# contenu tant qu'on n'a pas basculé "Visibilité" sur "Visible" à la
# main (puis pensé à la remettre sur "Masqué" avant de tester). Le
# "display:flex;" ajouté ICI, en dernier dans la chaîne de style,
# gagne sur le "display:none" éventuellement posé plus tôt par
# _style_string (CSS : même propriété déclarée deux fois -> la
# dernière l'emporte). Seul le mode JOUABLE respecte réellement ce
# réglage (ou une action "Modifier un élément → Visibilité" qui le
# change en cours de partie)."""
style += " display:flex;"
attr_parts = [f'style="{html_lib.escape(style)}"']
for k, v in attrs.items():
if v in (None, "", False):
continue
attr_parts.append(
html_lib.escape(str(k)) if v is True else f'{html_lib.escape(str(k))}="{html_lib.escape(str(v))}"'
)
box_style = (
f"background:{html_lib.escape(str(box_color))}; border-radius:{html_lib.escape(str(radius))}px; "
# max-width en min(...) plutôt qu'un simple pourcentage : sur un
# écran de jeu large (desktop), "90%" seul donnait une boîte étirée
# bord à bord peu lisible comme dialogue — 560px reste une largeur
# de boîte de dialogue confortable, tout en retombant sur 90% sur un
# écran de jeu étroit (mobile/portrait) pour ne jamais déborder.
# color:#e8eaf0 : la classe Bulma ".box" (ajoutée ci-dessous) impose
# elle-même une couleur de texte SOMBRE (pensée pour un fond blanc
# par défaut) — comme aucun widget ne fige de couleur de texte à sa
# création (default_style_for_widget.py), un titre/texte posé dans
# la boîte SANS couleur personnalisée héritait de ce gris sombre
# imposé par Bulma, invisible sur le fond sombre par défaut de cette
# boîte de dialogue (texte "présent mais invisible", pas de bug côté
# utilisateur). On redonne donc ici une couleur claire par défaut,
# que Bulma ne peut plus écraser (élément le plus proche gagne) —
# un texte/titre qui personnalise sa propre couleur reste bien sûr
# prioritaire sur celle-ci.
"color:#e8eaf0; padding:24px; width:100%; max-width:min(560px, 90%); max-height:90%; overflow:auto; box-sizing:border-box;"
)
child_html = _render_children(el, slug, children_map, ctx)
return (
f'<div class="modal is-active" {" ".join(attr_parts)}>'
f'<div class="box forgeOverlayBox" style="{html_lib.escape(box_style)}">{child_html}</div>'
f"</div>"
)