Files
Forge-Engine/screens/scenes/add_scene_object.py
T
william 50835a18e2
Build and deploy / test-python (push) Successful in 9m41s
Build and deploy / test-js (push) Successful in 1m0s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Supprime le type d'écran "document" et recentre le produit sur le jeu 2D
Le document de cadrage produit cible des formateurs non techniques créant
des serious games/quiz gamifiés — l'éditeur générique "document" (blocs de
logique en nœuds, timeline d'animation, définitions d'objets/relations,
templates réutilisables) est une complexité hors cible que l'effort
d'ingénierie récent avait déjà abandonnée au profit du jeu_2d.

- Onboarding : ne garde que le parcours "RPG" (jeu_2d), retire
  Quiz/Embranchement/Créer mon jeu de A à Z (tous document-only)
- Suppression en bloc des modules exclusifs au document : routes/elements,
  routes/element_types, routes/objects, routes/legacy_actions,
  screens/elements, screens/element_types, screens/widgets,
  screens/legacy_actions, le rendu render_element_html.py et son cluster,
  templates/screen_edit.html, templates/game_dashboard.html,
  flow-editor.js/tabs-and-blocks.js/animation-timeline.js
- Dashboard toujours simplifié (un seul mode possible désormais)
- Tests document-only supprimés, tests de logique partagée (flow,
  événements personnalisés, animations) retargetés sur des écrans jeu_2d
- Aucune régression jeu_2d : 299 tests passent

Carte d'onboarding retravaillée : argumentaire RH non technique (liste à
coche, badge "Compatible LMS"), taille et interaction de retournement
ajustées.
2026-09-04 20:56:32 +02:00

88 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import json
import db
from .ensure_scene_schema import ensure_scene_schema
_DEFAULT_PERSONNAGE_DATA = {"source": "forge", "forge_character": "male-adventurer"}
_KINDS = {"personnage", "decor", "fond", "dialogue_box", "quiz_box", "score_widget"}
# Widgets d'interface (voir "🖥️ Interface", screens/rendering/dialogue_box_style.py) :
# assez grands pour lire une réplique/question sans redimensionner,
# jamais confondus visuellement avec un personnage/décor (128×128 par
# défaut). "score_widget" reste petit — juste un nombre.
_DIALOGUE_BOX_DEFAULT_SIZE = (320, 150)
_QUIZ_BOX_DEFAULT_SIZE = (340, 240)
_SCORE_WIDGET_DEFAULT_SIZE = (140, 50)
def add_scene_object(slug, scene_id, kind="personnage", forge_character=None, background_slug=None):
"""Pose un nouvel objet sur une scène (voir ensure_scene_schema.py).
kind="personnage" : attributes._personnage_data, MÊME structure/mêmes
fonctions resolve_personnage_* que le widget "personnage" de l'éditeur
document (screens/rendering/personnage_data.py) — un objet de scène
"personnage" partage donc directement la bibliothèque Forge et le
système d'animation déjà écrits. kind="decor" : une simple image fixe
(attributes.src), pas d'animation. kind="fond" : même image fixe que
"decor" (render_scene_object.py ne les distingue pas au rendu), mais
posée en dessous de tout le reste (z_index très négatif, voir
static/style.css .sceneBackground) et à la taille RÉELLE de l'image
choisie (voir screens/labels/background_library.py) par défaut — une
image plus grande que la scène devient alors le "monde" que la caméra
suit en défilant (voir static/js/play/personnage-controller.js)."""
ensure_scene_schema(slug)
kind = kind if kind in _KINDS else "personnage"
attributes = {}
width = height = None
conn = db.connect(slug)
if kind == "personnage":
data = dict(_DEFAULT_PERSONNAGE_DATA)
if forge_character:
from ..labels.sprite_library import PUBLIC_SPRITE_LIBRARY
from ..labels.animal_sprite_library import ADMIN_SPRITE_LIBRARY
if forge_character in PUBLIC_SPRITE_LIBRARY or forge_character in ADMIN_SPRITE_LIBRARY:
data["forge_character"] = forge_character
attributes["_personnage_data"] = json.dumps(data)
# Rôle "pnj" explicite (demande explicite : un personnage fraîchement
# posé n'est JAMAIS le joueur par défaut, même le premier de la
# scène — voir screens/rendering/personnage_role.py, "🏷️ Rôle" dans
# le panneau de propriétés pour le passer en "Joueur" à la main).
# Un rôle non défini retomberait sur "joueur" par défaut (voir
# resolve_personnage_role) : sans cette affectation explicite, un
# personnage fraîchement posé se ferait donc passer pour le joueur
# et disparaîtrait à tort de "🧩 Collision" (voir scene_edit_view.py,
# qui exclut toujours le joueur).
attributes["_personnage_role"] = "pnj"
elif kind == "fond" and background_slug:
from ..labels.background_library import BACKGROUND_LIBRARY
background = BACKGROUND_LIBRARY.get(background_slug)
if background:
attributes["src"] = background["url"]
width, height = background["width"], background["height"]
elif kind == "dialogue_box":
width, height = _DIALOGUE_BOX_DEFAULT_SIZE
elif kind == "quiz_box":
width, height = _QUIZ_BOX_DEFAULT_SIZE
elif kind == "score_widget":
width, height = _SCORE_WIDGET_DEFAULT_SIZE
if kind == "fond":
z_index = -1000
else:
max_z = conn.execute(
"SELECT MAX(z_index) AS m FROM _scene_objects WHERE scene_id = ?", (scene_id,)
).fetchone()["m"]
z_index = (max_z or 0) + 1
cols = ["scene_id", "kind", "attributes", "z_index"]
values = [scene_id, kind, json.dumps(attributes), z_index]
if width is not None:
# x=0/y=0 (jamais le défaut 100/100, voir ensure_scene_schema.py) :
# un fond commence au coin haut-gauche de la scène/du monde, pas
# décalé arbitrairement comme un objet ordinaire.
cols += ["width", "height", "x", "y"]
values += [width, height, 0, 0]
placeholders = ", ".join(["?"] * len(values))
conn.execute(f"INSERT INTO _scene_objects ({', '.join(cols)}) VALUES ({placeholders})", values)
object_id = conn.execute("SELECT last_insert_rowid() AS id").fetchone()["id"]
conn.commit()
conn.close()
return object_id