Intègre un chat IA capable de manipuler la scène via les mêmes fonctions que l'éditeur manuel (objets, variables, déclencheurs, images générées), avec conversations multiples par écran façon Claude. Corrige au passage le rafraîchissement pjax hors-ordre, l'onglet IA/déclencheurs vide après sélection d'un objet, la comparaison de booléens dans les conditions, et le blocage du glisser-déposer hors du cadre caméra après un redimensionnement de fond par l'IA. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
68 lines
3.6 KiB
Python
68 lines
3.6 KiB
Python
from flask import g, request, redirect, url_for, jsonify, abort
|
|
|
|
import auth
|
|
import screens
|
|
|
|
from core.flask_app import app
|
|
from core.sprite_gate import forbid_admin_only_character, forbid_admin_only_background
|
|
|
|
|
|
@app.route("/game/<slug>/screens/<int:screen_id>/scene-objects/add", methods=["POST"])
|
|
def scene_object_add(slug, screen_id):
|
|
"""Pose un nouvel objet sur la scène — mirror de routes/elements/
|
|
element_add.py, mais pour _scene_objects (voir screens/scenes/
|
|
add_scene_object.py).
|
|
|
|
Appelée en AJAX (voir addSceneObject(), static/js/scenes/scene-editor.js)
|
|
plutôt qu'en soumission de formulaire classique — sans ça, poser un
|
|
objet rechargeait TOUTE la page : perceptible comme un "vidage" de
|
|
l'éditeur de collision/quêtes le temps du rechargement, et perdait tout
|
|
état JS en cours (modale ouverte, etc.). Répond en JSON avec de quoi
|
|
ajouter l'objet au canevas SANS recharger — jamais sélectionné/ouvert
|
|
dans le panneau de propriétés pour autant (ça, voir
|
|
onSceneObjectMouseDown, reste un rechargement pour l'instant). La liste
|
|
"🧩 Collision" n'est PAS incluse ici : addSceneObject() la redemande
|
|
ensuite à routes/scenes/scene_collision_rule_objects.py (même endpoint
|
|
que pour un changement de rôle/nom, ou une suppression) plutôt que de
|
|
dupliquer ici la logique de build_collision_rule_objects()."""
|
|
kind = request.form.get("kind", "personnage")
|
|
forge_character = request.form.get("forge_character")
|
|
background_slug = request.form.get("background_slug")
|
|
asset_id = request.form.get("asset_id", type=int)
|
|
if forge_character:
|
|
forbid_admin_only_character(forge_character)
|
|
if background_slug:
|
|
forbid_admin_only_background(background_slug)
|
|
image_url = None
|
|
if asset_id:
|
|
# "Mes assets" (voir auth/user_assets_dir.py) : isolation stricte
|
|
# par propriétaire, même esprit que les projets (core/auth_guard.py)
|
|
# — jamais poser l'asset d'un autre compte, même en devinant son id.
|
|
asset = auth.get_user_asset(asset_id)
|
|
if not asset or asset["user_id"] != g.current_user["id"]:
|
|
abort(403)
|
|
image_url = url_for("serve_user_asset", user_id=asset["user_id"], filename=asset["filename"])
|
|
new_id = screens.add_scene_object(
|
|
slug, screen_id, kind=kind, forge_character=forge_character,
|
|
background_slug=background_slug, image_url=image_url,
|
|
)
|
|
if request.headers.get("X-Requested-With") == "fetch":
|
|
obj = screens.get_scene_object(slug, new_id)
|
|
return jsonify({
|
|
"id": new_id, "kind": obj["kind"],
|
|
"x": obj["x"], "y": obj["y"], "width": obj["width"], "height": obj["height"],
|
|
"rendered_html": screens.render_scene_object(obj),
|
|
# Relance l'aperçu animé tout de suite (voir personnage-preview.js
|
|
# ::restartPersonnageIdlePreview) — sans ça, un personnage
|
|
# fraîchement posé restait figé sur sa première frame jusqu'au
|
|
# prochain rechargement de page (qui n'arrive plus jamais, voir
|
|
# addSceneObject() côté JS).
|
|
"animations": screens.resolve_personnage_animations(obj) if obj["kind"] == "personnage" else None,
|
|
})
|
|
# Même route que l'éditeur document (/game/<slug>/screens/<id>/edit,
|
|
# endpoint "screen_edit") — c'est CE dispatcher qui bascule vers la
|
|
# vue de scène selon game_type, voir routes/screens/screen_edit.py.
|
|
# Conservé pour tout appelant non-JS (aucun connu actuellement, mais
|
|
# ne coûte rien à garder en secours).
|
|
return redirect(url_for("screen_edit", slug=slug, screen_id=screen_id, selected=new_id))
|