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