Fusion des deux moteurs : type d'écran par écran, plus par projet
Build and deploy / test-python (push) Failing after 6m10s
Build and deploy / test-js (push) Successful in 58s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped

"document" (écrans %) et "jeu_2d" (scène pixels) devient une propriété
PAR ÉCRAN (_screens.kind, migration automatique idempotente dans
ensure_schema.py, source = l'ancien game_type au niveau projet) plutôt
qu'un choix figé pour tout le jeu — un même projet peut désormais
mélanger écrans classiques et scènes 2D librement.

- routes/screens/screen_edit.py : dispatch vers l'éditeur de scène selon
  screen["kind"] (l'écran demandé), plus game["game_type"].
- screens/payload/full_game_payload.py, templates/play.html,
  static/js/play/screens.js : le rendu jouable (payload, markup, bascule
  du mode plein-écran #playFrame) décide écran par écran, y compris en
  cours de partie (changer d'écran ne recharge pas la page).
- screens/screens_repo/create_screen.py : nouveau paramètre kind.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
william
2026-09-02 06:21:13 +02:00
co-authored by Claude Sonnet 5
parent f767ed4fab
commit d5a59bdbd8
12 changed files with 132 additions and 80 deletions
+8
View File
@@ -34,6 +34,13 @@
</div>
<form method="post" action="{{ url_for('screens_new', slug=game.slug) }}" class="dashCreateBar" id="dashCreate-screens" style="display:none;">
<input type="text" name="name" placeholder="Nom du nouvel écran (ex. Accueil, Scène 1...)" required autocomplete="off">
<!-- Fusion des moteurs (voir screens/screens_repo/ensure_schema.py) :
chaque écran choisit son propre type à la création, librement,
plus le jeu entier. -->
<select name="kind">
<option value="document">Écran classique (%, quiz/formulaire/contenu)</option>
<option value="jeu_2d">Scène 2D (pixels, RPG/serious game)</option>
</select>
<button type="submit" class="primary">Créer</button>
</form>
{% if screen_list %}
@@ -45,6 +52,7 @@
<tr>
<td>{{ loop.index }}</td>
<td>
{{ '🧩' if s.kind == 'jeu_2d' else '📄' }}
<a href="{{ url_for('screen_edit', slug=game.slug, screen_id=s.id) }}">{{ s.name }}</a>
{% if loop.first %} <span class="tag is-info is-light">★ Départ</span>{% endif %}
</td>
+19 -18
View File
@@ -27,18 +27,19 @@
}
#playFrame{
position:relative; overflow:hidden; background:#0b0d12;
{% if game.game_type == 'jeu_2d' %}
/* Fondations multi-éditeurs — une scène jeu_2d a une taille FIXE en
pixels (voir scene_width/scene_height, ensure_schema.py), pas un
ratio fluide : #playFrame remplit simplement tout le viewport, la
scène elle-même se centre dedans (voir .playScreen ci-dessous et
la boucle d'écrans jeu_2d plus bas). */
width:100vw; height:100vh;
{% else %}
width: min(100vw, calc(100vh * var(--ratio-w, 9) / var(--ratio-h, 16)));
height: min(100vh, calc(100vw * var(--ratio-h, 16) / var(--ratio-w, 9)));
{% endif %}
}
/* Fusion des moteurs (voir screens/screens_repo/ensure_schema.py) : le
type d'écran ("document"/"jeu_2d") est désormais choisi PAR ÉCRAN, pas
figé pour toute la page au chargement — changer d'écran ne recharge
pas la page (voir showScreen() dans static/js/play/screens.js), donc
la taille de #playFrame doit pouvoir basculer EN COURS DE PARTIE.
.sceneMode (posée/enlevée par showScreen() selon screen.kind) donne à
une scène jeu_2d sa taille FIXE en pixels (scene_width/scene_height) —
elle-même se centre dedans (voir .playScreen.playScene ci-dessous) —
au lieu du ratio fluide par défaut ci-dessus. */
#playFrame.sceneMode{ width:100vw; height:100vh; }
.playScreen{ position:absolute; inset:0; display:none; }
.playScreen.playScene{ inset:auto; top:50%; left:50%; transform:translate(-50%, -50%); background:#1a1d24; }
.playElement{
@@ -70,27 +71,25 @@
<body>
<div id="playRoot">
<div id="playFrame">
{% if game.game_type == 'jeu_2d' %}
<!-- Fondations multi-éditeurs — scène jeu_2d : objets déjà entièrement
{% for s in screens_data %}
{% if s.kind == 'jeu_2d' %}
<!-- Fusion des moteurs — écran "jeu_2d" : objets déjà entièrement
positionnés en pixels absolus par render_scene_object.py (voir
screens/scenes/), pas de wrapper .playElement/elstyle (spécifiques
au %/DOM de l'éditeur document) : juste le HTML tel quel. -->
{% for s in screens_data %}
<div class="playScreen playScene" data-screen-id="{{ s.id }}" style="width:{{ s.scene_width }}px; height:{{ s.scene_height }}px;">
au %/DOM d'un écran "document") : juste le HTML tel quel. -->
<div class="playScreen playScene" data-screen-id="{{ s.id }}" data-kind="jeu_2d" style="width:{{ s.scene_width }}px; height:{{ s.scene_height }}px;">
{% for obj in s.elements %}{{ obj.rendered_html|safe }}{% endfor %}
</div>
{% endfor %}
{% else %}
{% for s in screens_data %}
<div class="playScreen" data-screen-id="{{ s.id }}" data-aspect="{{ s.preview_aspect or '9/16' }}">
<div class="playScreen" data-screen-id="{{ s.id }}" data-kind="document" data-aspect="{{ s.preview_aspect or '9/16' }}">
{% for el in s.elements if not el.parent_id %}
<div class="playElement" data-el-id="{{ el.id }}" data-anim-target="{{ el.id }}" style="{{ el|elstyle }}">
<div class="playElementInner" style="{{ el|eltransform }}">{{ el.rendered_html|safe }}</div>
</div>
{% endfor %}
</div>
{% endfor %}
{% endif %}
{% endfor %}
{% if not screens_data %}
<div id="emptyState">Aucun écran défini pour l'instant — retourne dans l'éditeur pour en créer un.</div>
{% endif %}
@@ -118,6 +117,8 @@
runtimePayload: {{ runtime_payload_url|tojson }},
flowNodeRunData: {{ flow_node_run_data_url|tojson }},
flowNodeRunVariable: {{ flow_node_run_variable_url|tojson }},
flowNodeRunScore: {{ flow_node_run_score_url|tojson }},
flowNodeRunStatus: {{ flow_node_run_status_url|tojson }},
flowNodeRunAddRow: {{ flow_node_run_add_row_url|tojson }},
};
</script>