diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ec687d9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "engines/godot/vendor/godot-src"] + path = engines/godot/vendor/godot-src + url = https://a2msystemes-git.duckdns.org/ange/godot.git +[submodule "engines/godot/vendor/godot-cpp"] + path = engines/godot/vendor/godot-cpp + url = https://github.com/godotengine/godot-cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 714852e..bfda6c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ endif() add_subdirectory(core) add_subdirectory(3d) +add_subdirectory(engines/godot/adapter) # adaptateur seul : Godot lui-même n'est pas compilé ici if(SEQUA_BUILD_SERVER) add_subdirectory(studio/host) # dépend d'IXWebSocket et nlohmann/json endif() diff --git a/README.md b/README.md index c870b61..92b93f6 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,14 @@ Documentation de référence : [docs/SEQUA_Engine_resume_complet_v2.md](docs/SEQ | [studio/](studio) | SEQUA Studio : `host/` (exécutable qui gère le Core et sert l'interface) + `ui/` (interface web) | C++20, TypeScript | | [core/](core) | SEQUA Core : projet, simulation déterministe, rejeu, intentions, orchestrateur, confiance | C++20 | | [3d/](3d) | SEQUA 3D : interface vers les moteurs 3D (adaptateurs, capacités, synchronisation) | C++20 | +| [engines/](engines) | Moteurs 3D : `godot/adapter` (adaptateur SEQUA) + `godot/vendor/godot-src` (Godot 4.7.2-stable) et `godot/vendor/godot-cpp` (10.0.0-stable), sous-modules | C++20 | | [schema/](schema) | Contrat de données et protocole Studio↔Core | Protobuf / FlatBuffers | | [docs/](docs) | Documentation et décisions d'architecture (`docs/adr/`) | Markdown | | [artwork/](artwork) | Identité graphique et sources visuelles | PNG | | [prototypes/](prototypes) | Prototypes jetables (ex. échange GPU rendu vers inférence), hors produit | C++ | | [cmake/](cmake), [scripts/](scripts) | Options de compilation, build et vérification locaux | CMake, PowerShell, Bash | -Les adaptateurs de moteurs (Godot, Unreal) vivent dans des dépôts séparés. +Les moteurs eux-mêmes sont des sous-modules git, inutiles pour construire SEQUA : `git submodule update --init engines/godot/vendor/godot-src engines/godot/vendor/godot-cpp` pour travailler sur l'adaptateur Godot ([ADR 0007](docs/adr/0007-adaptateur-godot-dans-le-depot.md)). ## État diff --git a/docs/adr/0007-adaptateur-godot-dans-le-depot.md b/docs/adr/0007-adaptateur-godot-dans-le-depot.md new file mode 100644 index 0000000..7086c14 --- /dev/null +++ b/docs/adr/0007-adaptateur-godot-dans-le-depot.md @@ -0,0 +1,79 @@ +# ADR 0007 : Adaptateur Godot dans le dépôt, Godot hébergé par LibGodot depuis un fork + +- Statut : Acceptée +- Date : 2026-11-07 +- Décideur : Ange-Marie MAURIN - A2M Systèmes +- Références : docs/SEQUA_Engine_resume_complet_v2.md §1, §3, §4.8, §5.5, §5.6, §7, §7.0.1, §7.1, §7.2, §10.2, §10.3, §13 ; ADR 0008 ; prototype `prototypes/gpu_interop` + +## Contexte + +La phase 1 se joue sur Godot (§7.1). SEQUA 3D (`3d/`) définit `I3DEngineAdapter`, la négociation des capacités et la synchronisation de la scène par deltas versionnés, sans dépendre d'aucun moteur. Il faut décider où vit l'adaptateur Godot, comment obtenir et modifier le moteur, comment SEQUA l'héberge, et comment il produit les tampons du contrat (§5.6, §7.2). + +Le README prévoyait des dépôts séparés pour les adaptateurs. La doc (§7) réserve le mot « backend » au calcul GPU (`IComputeBackend`) et parle de « moteurs 3D ». + +Constats faits sur le code de Godot 4.7.2 : + +- `--headless` n'accepte que le pilote de rendu factice (`servers/display/display_server_headless.h`) : aucune image n'est produite, même hors écran. +- Forward+ fournit nativement couleur, profondeur, normales (`normal_roughness`) et vecteurs de mouvement ; il n'a ni albedo séparé ni identifiants d'objets. +- Le `VkDevice` de Godot n'active pas `VK_KHR_external_memory_win32` (seule l'extension `_fd` est demandée, sans usage), et son allocateur n'exporte pas la mémoire (`VMA_EXTERNAL_MEMORY_WIN32=0`). En revanche, `RenderingDevice::texture_create_from_extension()` permet de confier à Godot une image créée hors de lui. +- Godot prend en charge D3D12 sous Windows, mais son pilote par défaut est Vulkan. + +## Options envisagées + +### Emplacement + +1. **Dépôt séparé par adaptateur** : isolation stricte, mais versions à synchroniser entre dépôts alors que le contrat change souvent en phase 0 et 1 (§5.6). +2. **Monorepo, moteur en sous-module** : le contrat et l'adaptateur changent dans le même commit, et la version du moteur est figée par le sous-module. En contrepartie, le clone de Godot est lourd. + +### Modifications de Godot + +1. **Fichiers de correctifs** appliqués à la construction sur le dépôt officiel : le diff reste petit par construction, mais chaque modification oblige à régénérer un `.patch`, et les conflits se règlent à la main à chaque version. +2. **Fork sur le Gitea du projet** : modifications en commits ordinaires, diff visible par `git diff 4.7.2-stable..sequa/4.7.2`, passage de version par `git rebase`, aucune dépendance à GitHub. En contrepartie, le fork pèse environ 1 Go et il faut veiller à ce qu'il ne dérive pas. + +### Hébergement de Godot + +1. **LibGodot** (Godot 4.6 et plus, `core/extension/libgodot.h`, `library_type=shared_library`, Windows, Linux et macOS) : SEQUA charge Godot comme bibliothèque et appelle `GodotInstance::iteration()` à chaque image. Il garde ainsi la maîtrise de la boucle. +2. **Processus Godot séparé + GDExtension** : plantages isolés, mais un transport de plus et un partage de textures GPU entre processus. +3. **Module C++ compilé dans Godot** : accès complet aux internes du rendu, mais lié à une version de Godot. + +### Albedo et identifiants d'objets + +1. **Seconde vue** partageant le monde et la caméra : lumière éteinte (`DEBUG_DRAW_UNSHADED`) pour l'albedo, copies des objets sur un calque dédié avec un matériau qui écrit l'identifiant. Aucune modification de Godot, mais la géométrie est dessinée deux fois. +2. **Sorties supplémentaires dans la pré-passe de profondeur de Forward+** : une seule passe, mais une modification du renderer à maintenir. + +## Décision + +- **Emplacement** : `engines/godot/adapter` (code SEQUA, MPL 2.0) ; sous-modules `engines/godot/vendor/godot-src` (Godot) et `engines/godot/vendor/godot-cpp` (liaisons C++ GDExtension, MIT, tag **10.0.0-stable**, API `4.7`). +- **Fork** : `godot-src` pointe vers le fork du Gitea du projet (`ange/godot`), branche **`sequa/4.7.2`** partant du tag **`4.7.2-stable`**, historique complet conservé. Règles du fork : + - un commit par modification, avec un message qui dit pourquoi ; + - aucune logique de SEQUA dans le fork, seulement des capacités génériques du moteur (§1 : les moteurs ne contiennent aucune logique du produit) ; + - les modifications restent sous licence MIT, celle de Godot ; + - GitHub n'est qu'une source de lecture (`upstream`) pour les versions suivantes. +- **Hébergement** : LibGodot, dans le processus de rendu défini par l'ADR 0008. +- **Pilote graphique** : Vulkan sur Windows et Linux (un seul chemin de partage avec l'inférence, validé par `prototypes/gpu_interop`). D3D12 n'est pas retenu pour l'instant ; macOS (Metal) est reporté. +- **Vrai headless** : le fork ajoute un mode sans fenêtre qui garde le rendu Vulkan (vues dessinées dans des textures, aucune présentation à l'écran), pour les tests, la génération de données et les machines sans écran. +- **Albedo et identifiants** : option 1 (seconde vue) d'abord, pour vérifier que ça marche et mesurer le coût ; l'option 2 seulement si le budget est dépassé. +- **Partage GPU avec l'inférence** : le fork active les extensions de mémoire et de sémaphores externes ; SEQUA alloue lui-même la mémoire partageable sur le `VkDevice` de Godot et la confie à Godot par `texture_create_from_extension()`. + +## Conséquences + +### Positives + +- Le contrat (`3d/`) et l'adaptateur évoluent ensemble, et le test d'isolation (§7.1, phase 2) se fera en ajoutant `engines/unreal/` sans toucher au Core. +- La version de Godot et chacune de nos modifications sont visibles et versionnées sur le Gitea du projet. +- SEQUA maîtrise la boucle d'image, ce qui colle à `render_frame()` et au pas fixe du Core. + +### Négatives et coûts + +- Le fork doit être poussé **avant** SEQUA quand il change, sinon SEQUA référence un commit absent du Gitea (`push.recurseSubmodules=check` à la racine de SEQUA). +- Passer à une nouvelle version de Godot demande de rejouer nos commits et de les revalider. +- Godot se construit avec SCons et Python, en dehors des presets CMake : un script de construction de LibGodot reste à écrire. +- Le vrai headless est estimé à quelques centaines de lignes dans le renderer de Godot, à confirmer par un premier essai. +- La seconde vue double le coût de la géométrie tant que l'option 2 n'est pas faite. +- Godot est sous licence MIT (compatible §10.2) ; ses dépendances tierces (`thirdparty/`) doivent être revues avant toute distribution. + +### Questions ouvertes + +- Formats, résolution et calques partagés avec l'inférence : fixés par le choix du premier modèle neuronal (§17). +- Image affichée quand le rendu IA est actif : le compositeur écrit dans une texture partagée que Godot affiche en dernière passe (voir `engines/godot/adapter/README.md`). +- Interactions dans la fenêtre du moteur (peindre une ambiance sur la scène, §8) : à prévoir tôt, leur chemin vers Studio et le Core reste à définir. diff --git a/docs/adr/0008-processus-de-rendu-et-bibliotheques-chargees.md b/docs/adr/0008-processus-de-rendu-et-bibliotheques-chargees.md new file mode 100644 index 0000000..5827bcc --- /dev/null +++ b/docs/adr/0008-processus-de-rendu-et-bibliotheques-chargees.md @@ -0,0 +1,65 @@ +# ADR 0008 : Processus de rendu séparé du Core, moteur et inférence en bibliothèques chargées + +- Statut : Acceptée +- Date : 2026-11-07 +- Décideur : Ange-Marie MAURIN - A2M Systèmes +- Références : docs/SEQUA_Engine_resume_complet_v2.md §3, §4.8, §5.3, §5.4, §5.6, §7, §7.0.1, §10.2, §15 ; ADR 0005, ADR 0006, ADR 0007 + +## Contexte + +Le Core est déjà un processus à part (`sequa-core`), lancé et supervisé par Studio host (ADR 0005, ADR 0006). Godot sera hébergé par LibGodot (ADR 0007), donc chargé dans un processus. + +Deux contraintes tirent en sens opposés : + +- **Isolation** : un plantage du moteur ne doit pas arrêter la simulation ni perdre la session (§5.3). +- **Partage GPU** : les handles de mémoire GPU partagée ne valent que dans le processus qui les a créés. Mettre le moteur et l'inférence dans deux processus obligerait à les transmettre (`DuplicateHandle` sous Windows, passage de descripteurs sous Linux). + +Le découplage demandé par la doc (§7, §15 décision 6) porte sur le **code** : le Core ne connaît aucun moteur et ne parle qu'au contrat SEQUA 3D. Il ne dit pas que chaque composant doit avoir son processus. + +## Options envisagées + +1. **Moteur dans le Core** : simple et sans transport, mais un plantage de Godot arrête la simulation, et le Core dépend alors à l'exécution d'un moteur. +2. **Un processus par composant** (Core, moteur, inférence) : isolation maximale, mais transmission des handles GPU entre processus à chaque ressource, et une synchronisation GPU entre processus. +3. **Core séparé, plus un processus de rendu qui regroupe moteur et inférence** : la simulation survit à un plantage du rendu, et le partage GPU se fait dans un seul processus. + +## Décision + +Option 3 : trois processus. + +```text +Studio host + interface ──protocole──> Core (sequa-core, ne charge aucun moteur) + │ protocole : capacités, deltas de scène, demandes d'image, mesures + v + Processus de rendu + ├── adaptateur du moteur (I3DEngineAdapter) bibliothèque chargée + ├── moteur (libgodot) bibliothèque chargée + └── inférence (plugin, plus tard) bibliothèque chargée +``` + +- **Chaque composant du processus de rendu est une bibliothèque partagée** (`.dll`, `.so`, `.dylib`), chargée à l'exécution : changer de moteur revient à charger un autre adaptateur, sans recompiler le Core ni Studio. +- **Le Core ne charge jamais de bibliothèque de moteur.** Il pilote le rendu par protocole, à travers le contrat SEQUA 3D. +- **Si le processus de rendu plante**, il est relancé et le Core lui renvoie la scène entière (`SceneState::snapshot()`), puis reprend les deltas. La simulation et la session continuent. +- Le moteur, l'inférence et le compositeur partagent la mémoire GPU dans ce seul processus, sans `DuplicateHandle`. + +## Conséquences + +### Positives + +- La simulation et la session survivent à un plantage du moteur ou de l'inférence. +- Le partage GPU reste dans un seul processus, comme dans `prototypes/gpu_interop`. +- Le test d'isolation (§7.1) se ramène à fournir une autre bibliothèque d'adaptateur. + +### Négatives et coûts + +- Un protocole Core ↔ rendu de plus à spécifier, à côté du protocole Studio ↔ Core 0.2. +- Un processus de plus à lancer, superviser et relancer. +- Les entrées du joueur sont captées par la fenêtre du moteur, donc dans le processus de rendu : elles doivent remonter au Core (comme `session/input`) sans passer par la simulation du moteur. +- Un plantage de l'inférence emporte aussi le moteur, puisqu'ils partagent le processus. + +### Questions ouvertes + +- **Qui lance et supervise le processus de rendu** : Studio host (qui supervise déjà le Core, ADR 0006) ou le Core lui-même. +- **Transport Core ↔ rendu** : WebSocket comme le protocole 0.2 (ADR 0005), ou un canal local plus léger (tube nommé, mémoire partagée) pour les deltas à chaque tick. +- **Frontière binaire des bibliothèques** : une interface C++ entre bibliothèques suppose le même compilateur et la même bibliothèque standard des deux côtés. Piste : un point d'entrée C (`sequa_create_engine_adapter`, avec un numéro de version d'interface vérifié au chargement), tout étant construit ensemble dans le monorepo. +- **Rythme** : le Core simule à pas fixe (60 Hz) et le rendu suit l'affichage ; l'interpolation entre deux ticks se fait côté rendu, à préciser dans le protocole. +- Nom définitif de l'exécutable du processus de rendu. diff --git a/docs/adr/README.md b/docs/adr/README.md index afde7b3..247350a 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -17,6 +17,9 @@ Une ADR (*Architecture Decision Record*) consigne **une** décision structurante | [0003](0003-studio-web-conteneur-remplacable.md) | Studio web, conteneur remplaçable | Acceptée | | [0004](0004-multiplateforme-et-verification-locale.md) | Multiplateforme par conception, vérification locale | Acceptée | | [0005](0005-serveur-websocket-du-core.md) | Serveur WebSocket du Core (IXWebSocket, nlohmann/json) | Acceptée | +| [0006](0006-studio-host-et-cycle-de-vie-du-core.md) | Studio host et cycle de vie du Core | Acceptée | +| [0007](0007-adaptateur-godot-dans-le-depot.md) | Adaptateur Godot dans le dépôt, Godot hébergé par LibGodot depuis un fork | Acceptée | +| [0008](0008-processus-de-rendu-et-bibliotheques-chargees.md) | Processus de rendu séparé du Core, moteur et inférence en bibliothèques chargées | Acceptée | ## Décisions ouvertes (docs, §17) diff --git a/engines/godot/adapter/CMakeLists.txt b/engines/godot/adapter/CMakeLists.txt new file mode 100644 index 0000000..40c3240 --- /dev/null +++ b/engines/godot/adapter/CMakeLists.txt @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# Adaptateur SEQUA 3D vers Godot (côté SEQUA). Ne compile pas encore Godot : le moteur +# (sous-module ../vendor/godot-src, tag 4.7.2-stable) se construit avec SCons en LibGodot ; +# godot-cpp (../vendor/godot-cpp) sera ajouté quand l'hébergement sera écrit (ADR 0007). + +add_library(sequa_godot_adapter src/godot_adapter.cpp) +add_library(sequa::godot_adapter ALIAS sequa_godot_adapter) + +target_include_directories(sequa_godot_adapter PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(sequa_godot_adapter PUBLIC sequa::3d) +sequa_target_defaults(sequa_godot_adapter) + +if(SEQUA_BUILD_TESTS) + add_executable(sequa_godot_adapter_tests tests/test_godot_adapter.cpp) + target_link_libraries(sequa_godot_adapter_tests PRIVATE sequa::godot_adapter doctest::doctest) + sequa_target_defaults(sequa_godot_adapter_tests) + doctest_discover_tests(sequa_godot_adapter_tests) +endif() diff --git a/engines/godot/adapter/README.md b/engines/godot/adapter/README.md new file mode 100644 index 0000000..018496d --- /dev/null +++ b/engines/godot/adapter/README.md @@ -0,0 +1,30 @@ +# Adaptateur Godot + +Implémentation de `sequa::three_d::I3DEngineAdapter` (voir [3d/](../../../3d)) pour le moteur Godot, utilisé comme moteur d'exécution et pas comme éditeur (docs §7.1). Godot est hébergé par LibGodot ([ADR 0007](../../../docs/adr/0007-adaptateur-godot-dans-le-depot.md)), dans le processus de rendu, séparé du Core ; l'adaptateur et Godot y sont des bibliothèques chargées à l'exécution ([ADR 0008](../../../docs/adr/0008-processus-de-rendu-et-bibliotheques-chargees.md)). + +| Élément | Rôle | +|---|---| +| `../vendor/godot-src` | Moteur Godot, sous-module git : fork du Gitea du projet, branche `sequa/4.7.2` partant du tag `4.7.2-stable`. Pas nécessaire pour construire SEQUA | +| `../vendor/godot-cpp` | Liaisons C++ de GDExtension, sous-module figé sur `10.0.0-stable` (API Godot 4.7 : `GODOTCPP_API_VERSION=4.7`, classe `GodotInstance` incluse) | +| `include/sequa/godot/godot_adapter.hpp` | `GodotEngineAdapter` et capacités déclarées pour Forward+ | +| `tests/` | Tests de l'adaptateur sans moteur | + +## État + +**PROVISOIRE** : l'adaptateur déclare ses capacités (couleur, profondeur, normales, vecteurs de mouvement, à vérifier sur la 4.7.2), mais `start()` renvoie `not_implemented` : l'hébergement par LibGodot et la construction de Godot en bibliothèque restent à écrire. + +### À prévoir + +- **Image affichée = sortie du compositeur.** Quand le rendu neuronal ou génératif est actif, la fenêtre de Godot ne doit pas montrer l'image brute de Godot mais celle du compositeur temporel SEQUA (docs §3, §5.4). Le compositeur écrit son résultat dans une texture partagée sur le GPU, que Godot affiche en dernière passe, sans copie CPU. + +Initialiser le moteur (clone lourd) : + +```powershell +git submodule update --init engines/godot/vendor/godot-src engines/godot/vendor/godot-cpp +``` + +## Licences + +- Adaptateur : [MPL 2.0](../../../LICENSE). +- Godot : MIT (`../vendor/godot-src/LICENSE.txt`) ; dépendances tierces dans `../vendor/godot-src/thirdparty/`, à revoir avant distribution. +- godot-cpp : MIT (`../vendor/godot-cpp/LICENSE.md`). diff --git a/engines/godot/adapter/include/sequa/godot/godot_adapter.hpp b/engines/godot/adapter/include/sequa/godot/godot_adapter.hpp new file mode 100644 index 0000000..88324d7 --- /dev/null +++ b/engines/godot/adapter/include/sequa/godot/godot_adapter.hpp @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MPL-2.0 +#pragma once + +#include "sequa/3d/adapter.hpp" + +namespace sequa::godot { + +// Version de Godot visée (sous-module engines/godot/vendor/godot-src). +inline constexpr const char* engine_version = "4.7.2-stable"; + +// Capacités déclarées pour Godot en rendu Forward+ (docs §7.2). À VÉRIFIER sur la 4.7 : +// couleur, profondeur, normales et vecteurs de mouvement existent dans Forward+ ; albedo, +// identifiants d'objets et masque sémantique demandent des passes supplémentaires et ne +// sont pas déclarés tant qu'elles n'existent pas. +[[nodiscard]] three_d::EngineCapabilities godot_capabilities(); + +// Adaptateur SEQUA 3D vers Godot. Seul ce fichier et l'agent côté moteur connaissent +// Godot ; le Core et Studio ne voient que three_d::I3DEngineAdapter. +// +// Godot est hébergé par LibGodot (ADR 0007) : l'adaptateur appellera +// GodotInstance::iteration() dans render_frame(). PROVISOIRE : tant que l'hébergement +// n'est pas écrit, start() renvoie not_implemented et l'adaptateur ne fait que déclarer +// ses capacités. +class GodotEngineAdapter final : public three_d::I3DEngineAdapter { +public: + [[nodiscard]] three_d::EngineCapabilities capabilities() const override { return godot_capabilities(); } + + [[nodiscard]] std::optional start(const three_d::EngineConfig& config) override; + void stop() noexcept override; + [[nodiscard]] bool running() const noexcept override { return running_; } + + [[nodiscard]] std::optional apply(const three_d::SceneDelta& delta) override; + [[nodiscard]] three_d::FrameOutcome render_frame(const three_d::FrameRequest& request) override; + +private: + three_d::SceneState scene_; + bool running_ = false; +}; + +} // namespace sequa::godot diff --git a/engines/godot/adapter/src/godot_adapter.cpp b/engines/godot/adapter/src/godot_adapter.cpp new file mode 100644 index 0000000..9f8f817 --- /dev/null +++ b/engines/godot/adapter/src/godot_adapter.cpp @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "sequa/godot/godot_adapter.hpp" + +#include + +namespace sequa::godot { + +using three_d::BufferSet; +using three_d::Error; +using three_d::FrameBuffer; + +three_d::EngineCapabilities godot_capabilities() +{ + three_d::EngineCapabilities caps; + caps.engine_name = "godot"; + caps.engine_version = engine_version; + caps.buffers = BufferSet{FrameBuffer::color, FrameBuffer::depth, FrameBuffer::normals, + FrameBuffer::motion_vectors}; + caps.windowed = true; + caps.headless = false; // --headless de Godot coupe le rendu : hors écran à étudier + return caps; +} + +std::optional GodotEngineAdapter::start(const three_d::EngineConfig& /*config*/) +{ + if (running_) { + return Error{Error::Code::already_started, "adaptateur Godot déjà démarré"}; + } + return Error{Error::Code::not_implemented, + "hébergement de Godot par LibGodot pas encore écrit (ADR 0007)"}; +} + +void GodotEngineAdapter::stop() noexcept +{ + running_ = false; + scene_.clear(); +} + +std::optional GodotEngineAdapter::apply(const three_d::SceneDelta& delta) +{ + if (!running_) { + return Error{Error::Code::not_started, "adaptateur Godot arrêté"}; + } + return scene_.apply(delta); +} + +three_d::FrameOutcome GodotEngineAdapter::render_frame(const three_d::FrameRequest& request) +{ + if (!running_) { + return Error{Error::Code::not_started, "adaptateur Godot arrêté"}; + } + if (std::optional error = three_d::validate_request(request, capabilities())) { + return *std::move(error); + } + return Error{Error::Code::not_implemented, "rendu Godot pas encore écrit"}; +} + +} // namespace sequa::godot diff --git a/engines/godot/adapter/tests/test_godot_adapter.cpp b/engines/godot/adapter/tests/test_godot_adapter.cpp new file mode 100644 index 0000000..b752722 --- /dev/null +++ b/engines/godot/adapter/tests/test_godot_adapter.cpp @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MPL-2.0 +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "sequa/godot/godot_adapter.hpp" + +#include + +using namespace sequa; + +TEST_CASE("GodotEngineAdapter : capacites declarees sans demarrer le moteur") +{ + godot::GodotEngineAdapter adapter; + const three_d::EngineCapabilities caps = adapter.capabilities(); + CHECK(caps.engine_name == "godot"); + CHECK(caps.buffers.contains(three_d::FrameBuffer::color)); + CHECK(caps.buffers.contains(three_d::FrameBuffer::depth)); + // Forward+ n'a pas de G-buffer classique (docs §7.2) : pas d'albedo ni d'identifiants. + CHECK_FALSE(caps.buffers.contains(three_d::FrameBuffer::albedo)); + CHECK_FALSE(caps.buffers.contains(three_d::FrameBuffer::object_ids)); +} + +TEST_CASE("GodotEngineAdapter : non demarre tant que l'agent n'existe pas") +{ + godot::GodotEngineAdapter adapter; + const auto error = adapter.start({}); + REQUIRE(error.has_value()); + CHECK(error->code == three_d::Error::Code::not_implemented); + CHECK_FALSE(adapter.running()); + CHECK(adapter.apply({1, {}})->code == three_d::Error::Code::not_started); +} diff --git a/engines/godot/vendor/godot-cpp b/engines/godot/vendor/godot-cpp new file mode 160000 index 0000000..507ed9d --- /dev/null +++ b/engines/godot/vendor/godot-cpp @@ -0,0 +1 @@ +Subproject commit 507ed9d840c01a3c5b2a39af8bb4000bfac30bf5 diff --git a/engines/godot/vendor/godot-src b/engines/godot/vendor/godot-src new file mode 160000 index 0000000..ed1daf0 --- /dev/null +++ b/engines/godot/vendor/godot-src @@ -0,0 +1 @@ +Subproject commit ed1daf0bf001b61586d9930840f2f1394092c079