From ea9f91fc192cf6ffa64167edc0fd2c4a7aa5a324 Mon Sep 17 00:00:00 2001 From: william Date: Tue, 25 Aug 2026 11:27:50 +0200 Subject: [PATCH] =?UTF-8?q?=C3=89diteur=20de=20sc=C3=A8ne=20:=20Logique/Ti?= =?UTF-8?q?meline=20en=20onglets=20plein=20=C3=A9cran,=20r=C3=A9glages=20d?= =?UTF-8?q?'=C3=A9cran=20d=C3=A9plac=C3=A9s=20dans=20le=20panneau=20=C3=89?= =?UTF-8?q?l=C3=A9ments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remplace l'ancien panneau du bas rétractable/redimensionnable à la souris (Logique de la scène, Timeline d'animation) par un système d'onglets au centre de l'éditeur - Écran / Logique de la scène / Timeline d'animation - un seul visible à la fois, occupant systématiquement tout l'espace disponible (switchBuilderTab() dans screen_edit.html). Changer d'onglet équivaut à "fermer" celui qu'on quitte ; plus besoin d'une poignée de redimensionnement séparée puisque l'onglet actif prend déjà toute la place. Supprime au passage tout l'ancien mécanisme (toggleFlowPanel/ toggleAnimPanel, poignées flowResizeHandle/animResizeHandle, classe CSS .flowPanel) devenu inutile. Déplace aussi le renommage de l'écran, le bouton "Jouer depuis le début" et le choix du format d'aperçu (Portrait/Paysage/Carré) - jusqu'ici au-dessus du canevas - dans le panneau flottant "Éléments" (celui qui porte déjà ce nom, à gauche) : des réglages qu'on touche rarement une fois l'écran en construction, qui n'ont plus besoin de rester en permanence visibles au-dessus de la zone de travail. Corrige au passage un bug découvert pendant ce tour : sur la page "Nouvel objet" (2 colonnes), le bouton "+ Ajouter un champ" avait disparu - placé APRÈS la zone de liste à défilement (flex-grow:1) dans la colonne de droite, un flex-grow imprévisible dans ce contexte le poussait hors de vue. Déplacé avant la liste (statique, toujours visible), pattern déjà éprouvé ailleurs sur cette même page. Deux tests mis à jour pour refléter intentionnellement la nouvelle structure : la présence de "animTabPanel" (au lieu de l'ancien "animPanel"), et un marqueur plus précis pour distinguer le bloc de propriétés "Onglets" d'une simple occurrence du même texte dans une liste déroulante de la Logique de la scène (qui apparaît désormais plus tôt dans le document, cet éditeur de flow étant maintenant un onglet du centre plutôt qu'un panneau tout en bas de page). Co-Authored-By: Claude Sonnet 5 --- static/style.css | 50 +-- templates/object_form.html | 2 +- templates/screen_edit.html | 736 +++++++++++++++-------------------- tests/test_animations.py | 2 +- tests/test_onglets_widget.py | 11 +- 5 files changed, 351 insertions(+), 450 deletions(-) diff --git a/static/style.css b/static/style.css index 014e4160..9bda1b28 100644 --- a/static/style.css +++ b/static/style.css @@ -114,7 +114,7 @@ body.objectEditBody > main.content{ flex:1 1 auto; min-height:0; overflow:hidden .content-objectEdit .colLeft{ overflow-y:auto; height:100%; } .content-objectEdit .colRight{ display:flex; flex-direction:column; min-height:0; height:100%; } .content-objectEdit .colRight h2{ flex:0 0 auto; } -.content-objectEdit .colRight > .hint{ flex:0 0 auto; } +.content-objectEdit .colRight > .hint, .content-objectEdit .colRight > button{ flex:0 0 auto; } .fieldsTableWrap{ flex:1 1 auto; min-height:0; overflow:auto; border:1px solid var(--border); border-radius:8px; } .fieldsTable{ width:100%; border-collapse:collapse; font-size:12.5px; } @@ -149,7 +149,6 @@ body.builderBody > main.content{ flex:1 1 auto; min-height:0; overflow:hidden; d width:100%; max-width:1600px; } -.content-builder > .fieldRow:first-child{ flex:0 0 auto; } /* 3 colonnes : ajout d'éléments (gauche) / écran en grand (centre) / propriétés (droite) — toutes les trois occupent exactement la même hauteur (celle qui reste @@ -375,37 +374,26 @@ code{ background:var(--panel2); border:1px solid var(--border); border-radius:4p .floatPanelReopenBtn{ display:none !important; } } -/* ---------- Logique de la scène : éditeur de flow à nœuds ---------- */ -/* Panneau du bas, dans le même flux flexbox que .builder3 (pas une - surcouche/overlay) : replié, il ne prend que la hauteur de son en-tête et - .builder3 récupère tout le reste de l'espace ; ouvert, sa hauteur est - fixée en pixels (réglable à la souris via la poignée juste au-dessus) et - .builder3 rétrécit d'autant automatiquement — jamais l'un par-dessus - l'autre. */ -.flowPanel{ - flex:0 0 auto; border:1px solid var(--border); border-radius:10px; background:var(--panel); - margin-top:8px; display:flex; flex-direction:column; overflow:hidden; +/* ---------- Onglets du centre : Écran / Logique de la scène / Timeline + d'animation ---------- */ +/* Un seul onglet visible à la fois (voir switchBuilderTab() dans + screen_edit.html), chacun occupant tout l'espace disponible dans + .builderCanvasArea — remplace l'ancien panneau du bas rétractable/ + redimensionnable à la souris : un onglet "prend toute la place" par + nature, pas besoin d'une poignée de redimensionnement séparée, et en + changer d'onglet équivaut à "fermer" celui qu'on quitte. */ +.builderTabs{ display:flex; gap:2px; flex:0 0 auto; border-bottom:1px solid var(--border); margin-bottom:10px; } +.builderTabBtn{ + background:transparent; border:none; border-bottom:2px solid transparent; border-radius:0; + padding:8px 12px; color:var(--text-dim); font-size:12.5px; cursor:pointer; } -.flowPanelHeader{ - flex:0 0 auto; padding:10px 16px; font-weight:700; cursor:pointer; user-select:none; - display:flex; align-items:center; gap:6px; -} -.flowPanelHeader:hover{ background:var(--panel2); } -.flowToggleIcon{ color:var(--text-dim); font-size:11px; transition:transform .15s; display:inline-block; } -.flowPanel.open .flowToggleIcon{ transform:rotate(90deg); } -.flowPanelBody{ flex:1 1 auto; min-height:0; padding:0 16px 16px; display:none; flex-direction:column; } -.flowPanel.open .flowPanelBody{ display:flex; } -.flowToolbar{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:10px; flex:0 0 auto; } +.builderTabBtn:hover{ color:var(--text); } +.builderTabBtn.active{ color:var(--accent); border-bottom-color:var(--accent); font-weight:600; } -.flowResizeHandle{ - flex:0 0 auto; height:10px; margin-top:6px; cursor:row-resize; position:relative; display:none; -} -.flowResizeHandle.visible{ display:block; } -.flowResizeHandle::before{ - content:""; position:absolute; left:50%; top:3px; width:60px; height:4px; - background:var(--border); border-radius:2px; transform:translateX(-50%); -} -.flowResizeHandle:hover::before{ background:var(--accent); } +.builderTabPanel{ flex:1 1 auto; min-height:0; display:none; flex-direction:column; } +.builderTabPanel.active{ display:flex; } + +.flowToolbar{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:10px; flex:0 0 auto; } .nodeForm{ border:1px solid var(--border); border-radius:8px; padding:12px; margin-bottom:12px; background:var(--panel2); max-width:420px; flex:0 0 auto; } .nodeForm label{ margin-top:8px; } diff --git a/templates/object_form.html b/templates/object_form.html index b86a0075..4d0fa670 100644 --- a/templates/object_form.html +++ b/templates/object_form.html @@ -24,10 +24,10 @@

Champs

+
-
diff --git a/templates/screen_edit.html b/templates/screen_edit.html index 13d69615..a3bfe719 100644 --- a/templates/screen_edit.html +++ b/templates/screen_edit.html @@ -12,16 +12,6 @@
  • {{ screen.name }}
  • {% endblock %} {% block content %} -
    -
    -
    -
    -
    - {% if not screen.is_template %} - ▶️ Jouer depuis le début - {% endif %} -
    - {% if screen.is_template %}

    🧩 Contenu d'un élément de jeu réutilisable. @@ -67,6 +57,25 @@

    + +
    +
    +
    +
    + {% if not screen.is_template %} + ▶️ Jouer depuis le début + {% endif %} + {% set current_aspect = screen.preview_aspect or '9/16' %} +
    + + + +
    +

    Éléments de cet écran

    {% if top_level_elements %}
    @@ -149,27 +158,299 @@
    - +
    {% set current_aspect = screen.preview_aspect or '9/16' %} -
    - Aperçu : - - - + {% if not screen.is_template %} +
    + + +
    -
    -
    - {% for el in top_level_elements %} -
    -
    {{ el.rendered_html|safe }}
    -
    + {% endif %} + +
    +
    +
    + {% for el in top_level_elements %} +
    +
    {{ el.rendered_html|safe }}
    +
    +
    + {% endfor %}
    - {% endfor %} +
    +

    Glisse pour déplacer, tire le coin pour redimensionner, clique pour sélectionner.

    +
    + + {% if not screen.is_template %} +
    +
    + + + + Clique un point de sortie d'un nœud, puis le point d'entrée d'un autre nœud, pour les relier. Reclique une connexion pour la supprimer. +
    + + + +
    + +
    -

    Glisse pour déplacer, tire le coin pour redimensionner, clique pour sélectionner.

    + +
    +
    + + +
    + + + +
    +
    +
    +
    +
    + {% endif %}
    -
    - - -
    -
    - ▸ 🔀 Logique de la scène — nœuds et connexions -
    -
    -
    - - - - Clique un point de sortie d'un nœud, puis le point d'entrée d'un autre nœud, pour les relier. Reclique une connexion pour la supprimer. -
    - - - -
    - -
    -
    -
    -
    - - -
    - - -
    -
    - ▸ 🎬 Timeline d'animation -
    -
    -
    - - -
    - - - -
    -
    -
    -
    -
    -
    -{% endif %} {% endblock %} diff --git a/tests/test_animations.py b/tests/test_animations.py index 6fdde7ee..27e374d0 100644 --- a/tests/test_animations.py +++ b/tests/test_animations.py @@ -89,7 +89,7 @@ def test_clip_delete_removes_it(client, game): def test_screen_edit_exposes_timeline_panel_and_animate_css_cdn(client, game): screen_id = _create_screen(client, game) html = client.get(f"/game/{game}/screens/{screen_id}/edit").data.decode() - assert "animPanel" in html + assert "animTabPanel" in html assert "Timeline d'animation" in html assert "animate.css" in html diff --git a/tests/test_onglets_widget.py b/tests/test_onglets_widget.py index 34b37ecd..ba855b3d 100644 --- a/tests/test_onglets_widget.py +++ b/tests/test_onglets_widget.py @@ -20,10 +20,13 @@ def _create_onglets(client, slug, screen_id): def _tab_rename_ids(html): """Ids des formulaires de renommage DANS le bloc "Onglets" du panneau de - propriétés — pas le premier /elements//rename de la page, qui est le - champ "Nommer" générique de l'élément actuellement sélectionné (pas - forcément un onglet, ex. l'élément Onglets lui-même).""" - block = html.split("Onglets (", 1)[-1] + propriétés — pas le premier /elements//rename de la page (le champ + "Nommer" générique de l'élément actuellement sélectionné), ni une + occurrence de "Onglets (" dans une liste déroulante d'éléments de la + Logique de la scène (ex. ""), qui existe + aussi sur la page — seul l'en-tête du groupe de réglages ("🗂️ + Onglets (") repère sans ambiguïté le bloc de propriétés lui-même.""" + block = html.split(">🗂️ Onglets (", 1)[-1] return [int(x) for x in re.findall(r"/elements/(\d+)/rename", block)]