Bouton "📐 Agrandir la caméra à la zone visible"
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 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
14ec76dddd
commit
b9d3c46087
@@ -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
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
from flask import request, jsonify
|
||||
|
||||
import screens
|
||||
|
||||
from core.flask_app import app
|
||||
|
||||
|
||||
@app.route("/game/<slug>/screens/<int:screen_id>/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})
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
@@ -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' },
|
||||
|
||||
@@ -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. -->
|
||||
<p class="hint" style="background:var(--panel); border:1px solid var(--border); border-radius:8px; padding:10px 14px; margin:10px 0;">
|
||||
🎮 Jeu 2D — scène à taille fixe ({{ screen.scene_width }}×{{ screen.scene_height }} px).
|
||||
<p class="hint" style="background:var(--panel); border:1px solid var(--border); border-radius:8px; padding:10px 14px; margin:10px 0; display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;">
|
||||
<span>🎮 Jeu 2D — scène à taille fixe ({{ screen.scene_width }}×{{ screen.scene_height }} px).</span>
|
||||
{% if world_width > screen.scene_width or world_height > screen.scene_height %}
|
||||
<!-- "📐 Agrandir la caméra à la zone visible" : fait de tout le
|
||||
"monde" affiché (voir world_width/world_height, routes/scenes/
|
||||
scene_edit_view.py) la scène/caméra elle-même — n'apparaît que si
|
||||
un fond dépasse encore la scène nominale (voir "🎥 Champ de la
|
||||
caméra" plus bas), inutile sinon. -->
|
||||
<button type="button" class="button is-small" onclick="expandCameraToWorld({{ world_width }}, {{ world_height }})">📐 Agrandir la caméra à la zone visible ({{ world_width }}×{{ world_height }} px)</button>
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
<div class="builder3" id="builder3">
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user