Ajoute deux mécanismes distincts, à la demande de l'utilisateur qui a précisé qu'un son doit pouvoir être attaché à une SCÈNE (pas seulement joué ponctuellement par une action de flow, comme prévu initialement) : - Musique de fond par écran (nouveau champ background_music_url sur _screens, ALTER TABLE nullable) : réglée dans le panneau gauche de l'éditeur (URL ou envoi de fichier, réutilise la route d'upload générique existante), enregistrée en AJAX au même patron que le format d'aperçu (screen_set_aspect.py). Démarrée en boucle à l'affichage de l'écran et arrêtée au changement d'écran (runScreenBackgroundMusic(), appelée depuis showScreen() dans static/js/play/screens.js) — un seul Audio actif à la fois, jamais cumulé avec une musique restée d'un écran précédent. - Action de flow "jouer_son" (aux côtés des actions existantes) : effet sonore ponctuel, non bouclé, déclenchable sur n'importe quel nœud Déclencheur. Réutilise data_value (déjà un champ texte générique sur le nœud action, comme pour "attendre") plutôt qu'une nouvelle colonne dédiée — fire-and-forget côté client (runActionNode), ne bloque jamais la suite du graphe. Les deux réutilisent le même mécanisme d'upload de fichier déjà en place ailleurs dans l'éditeur (ex. source d'une vidéo), sans nouvelle route. Ceci complète les 6 phases du plan d'extension du moteur (état par joueur, hasard/maths, clavier/minuteur, ajout de ligne, position/ collision, son) : Forge Engine peut désormais couvrir des jeux bien au-delà du narratif/puzzle/quiz (action, arcade, jeux à contrainte de temps). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
135 lines
6.9 KiB
Python
135 lines
6.9 KiB
Python
"""
|
|
screens.py — écrans de jeu : éléments posés en glisser-déposer sur un
|
|
écran, sans jamais toucher à un fichier HTML/CSS, enchaînement des écrans,
|
|
et actions déclenchées par clic ou soumission de formulaire.
|
|
|
|
Version 3 — inspirée d'Elementor / Bricks Builder : un catalogue fermé de
|
|
WIDGETS (Texte, Titre, Image, Bouton, Case à cocher, Répéteur de
|
|
données...), chacun avec ses propres réglages ("controls") : un réglage =
|
|
un champ, une case à cocher, un bouton radio ou un curseur — jamais de nom
|
|
de balise ni de nom de propriété CSS à taper. En coulisses, chaque widget
|
|
correspond à une vraie balise HTML avec de vrais attributs et un vrai
|
|
style CSS ; l'utilisateur ne les manipule jamais directement.
|
|
|
|
Tout est stocké dans la même base SQLite que le reste du jeu
|
|
(projects/<slug>/game.db) :
|
|
- _screens : un écran du jeu (accueil, formulaire, scène...)
|
|
- _element_types : le "catalogue" des éléments de jeu réutilisables
|
|
(Personnage, Outil, IA...) que l'utilisateur crée
|
|
- _screen_elements : chaque élément posé sur un écran (widget, position
|
|
et taille en POURCENTAGE de l'écran, contenu,
|
|
attributs et style — dérivés des réglages du
|
|
widget, jamais saisis en texte libre)
|
|
- _actions : ce qui se passe au clic / à la soumission d'un
|
|
élément (écran suivant, écran précédent, aller à
|
|
un écran précis, ne rien faire)
|
|
|
|
Un élément peut aussi être un "Répéteur de données" : au lieu d'un contenu
|
|
fixe, il est relié à un objet défini dans ce jeu (voir db.py) et affiche
|
|
automatiquement une ligne par donnée existante — par exemple, tous les
|
|
niveaux d'un parcours — à partir d'un modèle de texte avec des
|
|
{{nom_de_champ}}.
|
|
|
|
Ce fichier est désormais un package (voir les sous-dossiers) organisé
|
|
selon "un fichier = une fonction, un dossier = une responsabilité" ; ce
|
|
module se contente de ré-exporter l'intégralité de l'API publique
|
|
utilisée par app.py et les templates, afin que `import screens` continue
|
|
de fonctionner à l'identique.
|
|
"""
|
|
|
|
from .widgets.registry import WIDGETS
|
|
from .widgets.container_widgets import CONTAINER_WIDGETS
|
|
from .widgets.layout_capable_widgets import LAYOUT_CAPABLE_WIDGETS
|
|
from .widgets.fontawesome_icons import FONTAWESOME_ICONS
|
|
from .widgets.widget_meta import widget_meta
|
|
from .widgets.controls_with_values import controls_with_values
|
|
from .widgets.data_definition_options import data_definition_options
|
|
|
|
from .labels.trigger_labels import TRIGGER_LABELS
|
|
from .labels.action_type_labels import ACTION_TYPE_LABELS
|
|
from .labels.element_action_properties import (
|
|
ELEMENT_ACTION_PROPERTIES, ELEMENT_ACTION_PROPERTY_LABELS,
|
|
ELEMENT_SURBRILLANCE_VALUES, ELEMENT_SURBRILLANCE_LABELS,
|
|
ELEMENT_DESACTIVE_VALUES, ELEMENT_DESACTIVE_LABELS,
|
|
)
|
|
from .labels.element_visibility import ELEMENT_VISIBILITY_VALUES, ELEMENT_VISIBILITY_LABELS
|
|
from .labels.data_operations import DATA_OPERATIONS, DATA_OPERATION_LABELS
|
|
|
|
from .flow.constants import (
|
|
TRIGGER_EVENTS, CONDITION_OPERATORS, CONDITION_OPERATOR_LABELS, CLICKED_ROW_ID, LAST_INSERTED_ROW_ID,
|
|
)
|
|
|
|
from .rendering.render_element_html import render_element_html
|
|
from .rendering.trigger_for import _trigger_for
|
|
|
|
from .screens_repo.ensure_schema import ensure_schema
|
|
from .screens_repo.list_screens import list_screens
|
|
from .screens_repo.get_screen import get_screen
|
|
from .screens_repo.create_screen import create_screen
|
|
from .screens_repo.rename_screen import rename_screen
|
|
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_screen_background_music import set_screen_background_music
|
|
|
|
from .elements.list_elements import list_elements
|
|
from .elements.get_element import get_element
|
|
from .elements.add_element import add_element
|
|
from .elements.add_tab import add_tab
|
|
from .elements.update_element_geometry import update_element_geometry
|
|
from .elements.reorder_element import reorder_element
|
|
from .elements.move_element_to_container import move_element_to_container
|
|
from .elements.save_element_controls import save_element_controls
|
|
from .elements.delete_element import delete_element
|
|
from .elements.flow_nodes_referencing_element import flow_nodes_referencing_element
|
|
from .elements.duplicate_element import duplicate_element
|
|
from .elements.rename_element import rename_element
|
|
from .elements.element_label import element_label
|
|
|
|
from .element_types.list_element_types import list_element_types
|
|
from .element_types.get_element_type_by_template_screen import get_element_type_by_template_screen
|
|
from .element_types.create_element_type import create_element_type
|
|
from .element_types.update_element_type import update_element_type
|
|
from .element_types.element_type_usage_count import element_type_usage_count
|
|
from .element_types.delete_element_type import delete_element_type
|
|
|
|
from .legacy_actions.list_actions import list_actions
|
|
from .legacy_actions.add_action import add_action
|
|
from .legacy_actions.get_action import get_action
|
|
from .legacy_actions.delete_action import delete_action
|
|
|
|
from .flow.ensure_flow_schema import ensure_flow_schema
|
|
from .flow.list_flow_nodes import list_flow_nodes
|
|
from .flow.list_flow_edges import list_flow_edges
|
|
from .flow.get_flow_node import get_flow_node
|
|
from .flow.add_flow_node import add_flow_node
|
|
from .flow.move_flow_node import move_flow_node
|
|
from .flow.delete_flow_node import delete_flow_node
|
|
from .flow.add_flow_edge import add_flow_edge
|
|
from .flow.delete_flow_edge import delete_flow_edge
|
|
|
|
from .flow.blocks.list_flow_blocks import list_flow_blocks
|
|
from .flow.blocks.get_flow_block import get_flow_block
|
|
from .flow.blocks.create_flow_block import create_flow_block
|
|
from .flow.blocks.update_flow_block import update_flow_block
|
|
from .flow.blocks.delete_flow_block import delete_flow_block
|
|
from .flow.blocks.blocks_view import blocks_view
|
|
|
|
from .data_actions.apply_data_action import apply_data_action
|
|
from .data_actions.apply_variable_action import apply_variable_action
|
|
from .data_actions.apply_add_row_action import apply_add_row_action
|
|
|
|
from .animations.ensure_animation_schema import ensure_animation_schema
|
|
from .animations.list_animation_clips import list_animation_clips
|
|
from .animations.get_animation_clip import get_animation_clip
|
|
from .animations.add_animation_clip import add_animation_clip
|
|
from .animations.update_animation_clip import update_animation_clip
|
|
from .animations.delete_animation_clip import delete_animation_clip
|
|
from .animations.animate_css_catalog import ANIMATE_CSS_CATALOG, ANIMATE_CSS_LABELS
|
|
|
|
from .custom_events.list_custom_event_usages import list_custom_event_usages
|
|
from .custom_events.delete_custom_event import delete_custom_event
|
|
|
|
from .payload.full_game_payload import full_game_payload
|