Files
Forge-Engine/screens/elements/delete_element.py
T
williamandClaude Sonnet 5 43abfc9b93
Build and deploy / test-python (push) Successful in 1m40s
Build and deploy / test-js (push) Successful in 7s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Fix éditeur de scène 2D : décalage visuel des objets + crash Timeline
Deux bugs remontés en test manuel sur l'éditeur de scène (Phase A,
commit f0070fa) :

1. Décalage visuel à l'ajout d'un objet de scène (personnage/décor) :
   render_scene_object.py positionne son <img> en absolu (left/top/
   width/height en px), pensé pour être un enfant DIRECT de
   .playScreen.playScene en mode jouable. Dans scene_edit.html, la même
   balise est nichée dans .canvasElementInner, lui-même déjà positionné
   par .canvasElement — l'image se repositionnait donc EN PLUS depuis
   #canvas (son ancêtre positionné le plus proche), en double du
   décalage déjà appliqué par le conteneur. Corrigé par une règle CSS
   scoped à l'éditeur (.canvasElementInner > img) qui neutralise le
   positionnement propre de l'image et la fait simplement remplir son
   conteneur.

2. "FOREIGN KEY constraint failed" à l'ajout d'un clip de Timeline sur
   un objet de scène : _animation_clips.element_id portait une VRAIE
   contrainte FK vers _screen_elements depuis la création de la table.
   animation-timeline.js est réutilisé TEL QUEL entre les deux éditeurs
   (voir le plan "Fondations d'une plateforme multi-éditeurs") et
   n'opère aucune distinction — pour un jeu jeu_2d, element_id désigne
   en réalité un id de _scene_objects, absent de _screen_elements, d'où
   l'échec de l'INSERT sous PRAGMA foreign_keys=ON. ensure_animation_schema
   reconstruit maintenant la table (une fois, migration automatique à la
   volée comme le reste du schéma) sans cette contrainte FK — même
   patron que trigger_element_id/cond_element_a dans ensure_flow_schema.py.
   Comme la suppression en cascade reposait jusqu'ici sur cette FK, un
   nettoyage manuel des clips a été ajouté à la suppression d'un élément
   (delete_element.py) et d'un objet de scène (delete_scene_object.py).

Nouveaux tests (tests/test_scene_edit_view.py, +4 cas) : ajout d'un
clip de Timeline sur un objet de scène via la route, nettoyage des
clips à la suppression d'un objet de scène et d'un élément DOM. Suite
complète : 312 tests passent (aucune régression).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-31 10:22:58 +02:00

51 lines
2.6 KiB
Python

import db
from ..animations.ensure_animation_schema import ensure_animation_schema
from ..flow.ensure_flow_schema import ensure_flow_schema
from .element_descendant_ids import element_descendant_ids
def delete_element(slug, element_id):
ensure_flow_schema(slug)
ensure_animation_schema(slug)
conn = db.connect(slug)
row = conn.execute("SELECT screen_id FROM _screen_elements WHERE id = ?", (element_id,)).fetchone()
if not row:
conn.close()
return
ids = element_descendant_ids(conn, row["screen_id"], element_id)
placeholders = ",".join("?" * len(ids))
# Un nœud de la Logique de la scène (déclencheur "clic sur cet
# élément"/action "Modifier cet élément"/condition de collision — voir
# ci-dessous...) ou une ancienne action du système _actions (conservé
# pour compatibilité) qui référence l'élément supprimé OU L'UN DE SES
# DESCENDANTS n'a plus aucun sens une fois l'élément disparu — et ces
# colonnes (trigger_element_id/target_element_id) n'ont volontairement
# PAS de ON DELETE CASCADE (un élément ne doit pas pouvoir être
# supprimé "par erreur" en cascade depuis un nœud de logique qu'on
# modifie). Sans ce nettoyage préalable, PRAGMA foreign_keys=ON (voir
# db/connection.py) fait échouer la suppression elle-même avec
# "FOREIGN KEY constraint failed". Voir element_delete_impact.py pour
# prévenir l'utilisateur AVANT qu'il confirme, plutôt que de supprimer
# ces nœuds en silence.
#
# cond_element_a/cond_element_b (Phase 5, condition de collision) : ni
# contrainte FK ni ON DELETE CASCADE (voir ensure_flow_schema.py), mais
# un nœud qui compare le rectangle de CET élément à un autre n'a pas
# plus de sens que si c'était trigger_element_id/target_element_id —
# supprimé ici pour la même raison, pas parce que la base l'exigerait.
conn.execute(
f"""DELETE FROM _flow_nodes WHERE trigger_element_id IN ({placeholders})
OR target_element_id IN ({placeholders})
OR cond_element_a IN ({placeholders}) OR cond_element_b IN ({placeholders})""",
ids + ids + ids + ids,
)
conn.execute(f"DELETE FROM _actions WHERE target_element_id IN ({placeholders})", ids)
# _animation_clips.element_id n'a plus de contrainte FK (voir
# ensure_animation_schema.py — réutilisé aussi par les objets de scène
# jeu_2d) : nettoyage manuel, même raison que ci-dessus.
conn.execute(f"DELETE FROM _animation_clips WHERE element_id IN ({placeholders})", ids)
conn.execute("DELETE FROM _screen_elements WHERE id = ?", (element_id,))
conn.commit()
conn.close()