# ARCHI_APP_FACADE.md : Vers une Architecture Orientée Scène ## 1. Vision et Objectifs Le passage d'une orchestration manuelle à une façade `App` vise à réduire le "boilerplate" tout en conservant la modularité. L'utilisateur utilise désormais une **"Recette par défaut"** basée sur une structure de **Scène**, tout en gardant la liberté de construire son moteur "brique par brique" s'il le souhaite. ### Les piliers : * **Déclaratif** : Toutes les ressources sont déclarées avant le lancement de la boucle. * **Orienté Scène** : L'utilisateur gère des relations (associations) plutôt que des appels de rendu directs. * **Flexible** : L'injection de l'async est gérée via un `Runtime` injecté. * **Transparent** : La "recette" est documentée, permettant une déconstruction totale vers les briques de bas niveau (`Context`, `Renderer`, `PipelineCache`). --- ## 2. Le Workflow de l'utilisateur (Exemple) ```rust // 1. Déclaration : Initialisation asynchrone let mut app = App::builder() .with_runtime(tokio::runtime::Runtime::new().unwrap()) // Injection de l'async .build() .await; // 2. Enregistrement des ressources (Labels identifiants ou références) let shader_id = app.register_shader("basic", "assets/basic.wgsl"); let mat_id = app.create_material("basic_mat", shader_id); let mesh_id = app.create_mesh("my_quad", &vertices, &indices); // 3. Association dans la scène app.scene.add_entity("main_quad", mesh_id, mat_id); // 4. Exécution via un Trait pour la boucle struct MyGame { /* ... */ } impl AppHandler for MyGame { fn render(&mut self, app: &mut App) { // Modification dynamique (ex: transparence, visibilité) app.scene.get_material("basic_mat").set_opacity(0.5); } } app.run(MyGame::new()); ``` ## 3. Gestion des Identifiants (Handles) Pour éviter les problèmes de Borrow Checker, nous utilisons un système de Handles (ou Label) : * **Référencement** : String (label) ou Handle (interne) pour accéder aux ressources. * **Accès** : L'utilisateur manipule ses ressources via `app.scene.get_material("nom")` ou en conservant les IDs retournés lors de la création. * **Sécurité** : Les IDs garantissent que la ressource existe toujours dans le dépôt de la Scene. ## 4. La "Recette" : Comment reproduire manuellement Si App ne convient pas, voici les étapes de la "recette" interne que l'utilisateur peut répliquer : 1. **Init GPU** : `Context::new(window)` → configure(). 2. **Setup PipelineCache** : Instancier le cache et compiler les shaders nécessaires. 3. **Setup Renderer** : Créer le Renderer avec le format de surface. 4. **Boucle winit** : - RedrawRequested → Frame::try_new() - renderer.render() → renderer.present() 5. **Nettoyage** : Gestion propre de la fermeture via elwt.exit(). ## 5. Avantages et Points d'attention ### Avantages * **Performance** : Le moteur peut trier les entités pour minimiser les changements de pipelines. * **Ergonomie** : Suppression des appels manuels à device et format dans le main. * **Sécurité** : Séparation claire entre la phase de déclaration (Init) et la phase d'exécution (Loop). ### Points d'attention (Portes de sortie) * **Accès Bas-Niveau** : App expose ses champs `renderer`, `context` et `cache` en public. Un utilisateur avancé peut toujours bypasser `app.scene` pour des besoins très spécifiques. * **Gestion Async** : Le choix du runtime reste la responsabilité de l'utilisateur. App se contente d'exécuter les futurs fournis. * **Dynamisme** : Si une ressource doit être créée en cours de jeu, l'utilisateur doit l'ajouter dans la Scene via une méthode `app.scene.add_entity(...)` qui est thread-safe. ## 6. Synthèse des responsabilités * **App** : Orchestrateur principal, propriétaire de la Window et de la Surface. * **Scene** : Dépôt de ressources et gestionnaire de visibilité/associations. * **AppHandler** : Trait de logique utilisateur, séparant update et render.