// ---------- Affichage des écrans, timeline d'animation ---------- // Extrait de templates/play.html (voir plan de modularisation — un // fichier = une responsabilité, aussi pour le JS) : navigation entre // écrans, proportion de la zone de jeu, lecture des clips d'animation // posés dans l'éditeur ("Timeline d'animation"). // Élément à onglets (voir render_onglets.py) : bascule le panneau visible // sans aller-retour serveur — même fonction que dans screen_edit.html, // pour un comportement identique éditeur/jeu. function forgeShowTab(btn) { var groupId = btn.dataset.tabBtn; var targetId = btn.dataset.tabTarget; document.querySelectorAll('[data-tab-btn="' + groupId + '"]').forEach(function (b) { b.classList.toggle('is-active', b === btn); }); document.querySelectorAll('[data-tab-group="' + groupId + '"]').forEach(function (p) { p.style.display = (p.id === targetId) ? '' : 'none'; }); } function showScreen(id) { // Déjà l'écran affiché : rien à refaire. Sans ce garde-fou, l'action // "Ouvrir la ligne cliquée" (voir plus bas) — pensée pour révéler un // détail SUR LE MÊME écran qu'un Répéteur, en la combinant avec une // action "Modifier un élément → Visibilité" sur le même clic — rejouait // à chaque clic sur une ligne les déclencheurs "À l'affichage de // l'écran" et relançait la timeline d'animation depuis le début, ce qui // donnait l'impression trompeuse d'un rechargement de page (éléments // qui rejouent leur animation d'entrée, visibilité qu'un déclencheur // "affichage" repasse à son état initial en écrasant l'action "Rendre // visible" du même clic...). Aller vers un écran DIFFÉRENT continue de // tout rejouer normalement, comme un vrai premier affichage. if (id === window.currentScreenId) return; document.querySelectorAll('.playScreen').forEach(s => s.style.display = 'none'); const el = document.querySelector('.playScreen[data-screen-id="' + id + '"]'); if (el) { el.style.display = 'block'; window.currentScreenId = id; applyScreenAspect(el.dataset.aspect || '9/16'); } // Phase 7 — nettoie les animations de sprites de l'écran quitté (sinon // une boucle setInterval reste active sur un élément désormais caché, // mirroring le nettoyage déjà fait pour activeTimerTriggerIntervals // dans triggers.js). stopAllSpriteAnimations(); runScreenShowTriggers(id); runScreenTimerTriggers(id); runScreenHeldKeyTriggers(id); runAnimationTimeline(id); runScreenBackgroundMusic(id); } // Phase 6 — musique de fond par écran (voir screen-bg-music-url dans // screen_edit.html) : démarrée en boucle à l'affichage de l'écran, // arrêtée au changement d'écran — un seul Audio actif à la fois (pas un // tableau comme activeTimerTriggerIntervals dans triggers.js, une // musique de fond ne se cumule jamais avec une autre). var currentBackgroundAudio = null; function runScreenBackgroundMusic(screenId) { if (currentBackgroundAudio) { currentBackgroundAudio.pause(); currentBackgroundAudio = null; } var screenData = screensData.find(function(s) { return String(s.id) === String(screenId); }); var url = screenData && screenData.background_music_url; if (!url) return; currentBackgroundAudio = new Audio(url); currentBackgroundAudio.loop = true; currentBackgroundAudio.play().catch(function() {}); } // Voir le commentaire sur #playFrame dans le