From b9d3c460874f5c27affed75bb31156e0ed87c884 Mon Sep 17 00:00:00 2001 From: william Date: Thu, 3 Sep 2026 17:07:24 +0200 Subject: [PATCH] =?UTF-8?q?Bouton=20"=F0=9F=93=90=20Agrandir=20la=20cam?= =?UTF-8?q?=C3=A9ra=20=C3=A0=20la=20zone=20visible"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fait de tout le "monde" affiché par l'éditeur (la taille réelle d'un "fond" plus grand que la scène nominale, voir routes/scenes/ scene_edit_view.py::world_width/world_height) la scène/caméra ELLE-MÊME — jusqu'ici scene_width/scene_height n'étaient fixées qu'à la création de l'écran, jamais modifiables ensuite. Le bouton n'apparaît que quand un fond dépasse encore la scène nominale (même condition que le repère "🎥 Champ de la caméra"), affiche la taille cible, recharge la page une fois appliqué. La caméra ne recadre alors plus rien en jeu (monde == scène == viewport, voir personnage-controller.js::forgeUpdateSceneCamera). Co-Authored-By: Claude Sonnet 5 --- routes/screens/__init__.py | 2 +- routes/screens/screen_set_scene_size.py | 20 ++++++++++++++ screens/__init__.py | 1 + screens/screens_repo/set_scene_size.py | 19 ++++++++++++++ static/js/scenes/scene-editor.js | 14 ++++++++++ templates/scene_edit.html | 12 +++++++-- tests/test_scene_edit_view.py | 35 +++++++++++++++++++++++++ 7 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 routes/screens/screen_set_scene_size.py create mode 100644 screens/screens_repo/set_scene_size.py diff --git a/routes/screens/__init__.py b/routes/screens/__init__.py index 6912fe9e..8fd2d9f4 100644 --- a/routes/screens/__init__.py +++ b/routes/screens/__init__.py @@ -1 +1 @@ -from . import screens_new, screen_rename, screen_move, screen_delete, screen_edit, screen_set_aspect, screen_set_background_music +from . import screens_new, screen_rename, screen_move, screen_delete, screen_edit, screen_set_aspect, screen_set_background_music, screen_set_scene_size diff --git a/routes/screens/screen_set_scene_size.py b/routes/screens/screen_set_scene_size.py new file mode 100644 index 00000000..3466ccf1 --- /dev/null +++ b/routes/screens/screen_set_scene_size.py @@ -0,0 +1,20 @@ +from flask import request, jsonify + +import screens + +from core.flask_app import app + + +@app.route("/game//screens//scene-size", methods=["POST"]) +def screen_set_scene_size(slug, screen_id): + """"📐 Agrandir la caméra à la zone visible" (voir templates/ + scene_edit.html) — redimensionne la scène/caméra elle-même à la + taille du "monde" affiché (world_width/world_height, voir + routes/scenes/scene_edit_view.py), calculée et postée par le client.""" + body = request.get_json(silent=True) or {} + try: + width, height = int(body.get("width")), int(body.get("height")) + except (TypeError, ValueError): + return jsonify({"error": "largeur/hauteur invalides"}), 400 + screens.set_scene_size(slug, screen_id, width, height) + return jsonify({"ok": True}) diff --git a/screens/__init__.py b/screens/__init__.py index 246e62a0..fb9463d1 100644 --- a/screens/__init__.py +++ b/screens/__init__.py @@ -100,6 +100,7 @@ from .screens_repo.delete_screen import delete_screen from .screens_repo.move_screen import move_screen from .screens_repo.screens_referencing import screens_referencing from .screens_repo.set_screen_aspect import set_screen_aspect +from .screens_repo.set_scene_size import set_scene_size from .screens_repo.set_screen_background_music import set_screen_background_music from .elements.list_elements import list_elements diff --git a/screens/screens_repo/set_scene_size.py b/screens/screens_repo/set_scene_size.py new file mode 100644 index 00000000..4096dad9 --- /dev/null +++ b/screens/screens_repo/set_scene_size.py @@ -0,0 +1,19 @@ +import db + + +def set_scene_size(slug, screen_id, width, height): + """Redimensionne la scène/caméra elle-même (colonnes scene_width/ + scene_height, voir ensure_schema.py) — jusqu'ici fixées à la création + et jamais modifiables ensuite. Utilisé par "📐 Agrandir la caméra à la + zone visible" (templates/scene_edit.html) : quand un "fond" plus + grand que la scène nominale l'a fait déborder dans le "monde" affiché + par l'éditeur (voir routes/scenes/scene_edit_view.py::world_width/ + world_height), ce bouton fait de CE monde la scène elle-même — la + caméra ne recadre alors plus rien (voir personnage-controller.js:: + forgeUpdateSceneCamera, sans effet dès que monde == scène).""" + width = max(1, int(width)) + height = max(1, int(height)) + conn = db.connect(slug) + conn.execute("UPDATE _screens SET scene_width = ?, scene_height = ? WHERE id = ?", (width, height, screen_id)) + conn.commit() + conn.close() diff --git a/static/js/scenes/scene-editor.js b/static/js/scenes/scene-editor.js index c14a1c28..9fe057dc 100644 --- a/static/js/scenes/scene-editor.js +++ b/static/js/scenes/scene-editor.js @@ -20,6 +20,20 @@ function addSceneObject(kind, forgeCharacter, backgroundSlug) { form.requestSubmit(); } +// "📐 Agrandir la caméra à la zone visible" (voir templates/scene_edit.html) : +// fait de tout le "monde" affiché par l'éditeur (voir world_width/ +// world_height, routes/scenes/scene_edit_view.py — la taille réelle +// d'un "fond" plus grand que la scène nominale) la scène/caméra +// elle-même — recharge la page ensuite, SCENE_WIDTH/SCENE_HEIGHT et le +// cadre "🎥 Champ de la caméra" doivent tous deux refléter la nouvelle +// taille, plus simple qu'une mise à jour partielle en JS. +function expandCameraToWorld(width, height) { + fetch("/game/" + GAME_SLUG + "/screens/" + SCREEN_ID + "/scene-size", { + method: 'POST', headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ width: width, height: height }), + }).then(function () { window.location.reload(); }); +} + function saveSceneObjectGeometry(id, x, y, width, height) { return fetch("/game/" + GAME_SLUG + "/scene-objects/" + id + "/geometry", { method: 'POST', headers: { 'Content-Type': 'application/json' }, diff --git a/templates/scene_edit.html b/templates/scene_edit.html index 270308d1..fefc770c 100644 --- a/templates/scene_edit.html +++ b/templates/scene_edit.html @@ -29,8 +29,16 @@ tel quel pour l'éditeur document) a été retiré de CET éditeur à la demande de l'utilisateur, en prévision d'un éditeur dédié aux scènes 2D (collision/périmètre -> action), pas encore construit. --> -

- 🎮 Jeu 2D — scène à taille fixe ({{ screen.scene_width }}×{{ screen.scene_height }} px). +

+ 🎮 Jeu 2D — scène à taille fixe ({{ screen.scene_width }}×{{ screen.scene_height }} px). + {% if world_width > screen.scene_width or world_height > screen.scene_height %} + + + {% endif %}

diff --git a/tests/test_scene_edit_view.py b/tests/test_scene_edit_view.py index f355f82f..b653fd93 100644 --- a/tests/test_scene_edit_view.py +++ b/tests/test_scene_edit_view.py @@ -239,3 +239,38 @@ def test_scene_edit_view_world_bounds_are_used_for_drag_clamping(client, tmp_gam html = client.get(f"/game/{slug}/screens/{screen_id}/edit").get_data(as_text=True) assert "var SCENE_WIDTH = 1920;" in html assert "var SCENE_HEIGHT = 1080;" in html + + +def test_set_scene_size_updates_screen_dimensions(tmp_game_slug_cleanup): + """"📐 Agrandir la caméra à la zone visible" (voir templates/ + scene_edit.html) : fait du "monde" affiché la scène/caméra + elle-même — jusqu'ici fixée à la création et jamais modifiable.""" + slug = tmp_game_slug_cleanup(db.create_game("pytest_scene_size")) + screen_id = screens.create_screen(slug, "Scène 1", kind="jeu_2d") + screens.set_scene_size(slug, screen_id, 1920, 1080) + screen = screens.get_screen(slug, screen_id) + assert screen["scene_width"] == 1920 + assert screen["scene_height"] == 1080 + + +def test_screen_set_scene_size_route_persists_and_reflects_in_editor(client, tmp_game_slug_cleanup): + slug, screen_id = _create_jeu2d_game(client, tmp_game_slug_cleanup) + resp = client.post( + f"/game/{slug}/screens/{screen_id}/scene-size", + data=json.dumps({"width": 1920, "height": 1080}), content_type="application/json", + ) + assert resp.get_json() == {"ok": True} + html = client.get(f"/game/{slug}/screens/{screen_id}/edit").get_data(as_text=True) + assert 'id="canvas" style="width:1920px; height:1080px;' in html + # La scène nominale == le monde désormais -> plus de repère caméra ni de bouton. + assert "sceneCameraFrame" not in html + assert "Agrandir la caméra" not in html + + +def test_screen_set_scene_size_route_rejects_invalid_dimensions(client, tmp_game_slug_cleanup): + slug, screen_id = _create_jeu2d_game(client, tmp_game_slug_cleanup) + resp = client.post( + f"/game/{slug}/screens/{screen_id}/scene-size", + data=json.dumps({"width": "oops", "height": 540}), content_type="application/json", + ) + assert resp.status_code == 400