using MyInfoMate.Vr.Boot; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; namespace MyInfoMate.Vr.EditorTools { /// /// Construit Boot.unity par code plutôt que de versionner un .unity écrit à /// la main. Le YAML d'une scène Unity est plein de GUID et de fileID internes : /// écrit à la main il produit une scène qui s'ouvre mais dont un réglage sur deux /// est faux en silence. Ceci est lisible, rejouable et diffable. /// /// Ce que ce script ne fait pas : ajouter le rig VR. Le Camera Rig vient du SDK /// Meta et se pose par les Building Blocks — le référencer ici créerait une /// dépendance de compilation sur un package importé à la main. /// /// Deux variantes, et elles coexistent volontairement le temps de la validation : /// S1 prouve la chaîne technique avec des chemins en dur, S2 prouve /// le contrat de données en lisant scene.json. Tant que S1 n'est pas validé /// au casque, pouvoir revenir à la scène minimale en un clic évite de confondre /// un bug de rendu avec un bug de manifeste. /// public static class BuildBootScene { const string ScenePath = "Assets/Scenes/Boot.unity"; [MenuItem("MyInfoMate/Construire la scène Boot (S1 — chemins en dur)")] public static void BuildS1() => Build(() => new GameObject("Bootstrap").AddComponent(), "S1 (chemins en dur)"); [MenuItem("MyInfoMate/Construire la scène Boot (S2 — depuis scene.json)")] public static void BuildS2() => Build(() => new GameObject("Bootstrap").AddComponent(), "S2 (manifeste scene.json)"); /// /// La troisième variante appartient à l'autre plan : le canal VR (E2/E3), pas la /// piste Scène 3D. Elle ne charge aucun décor — elle appaire le casque et affiche /// ce que le serveur renvoie. Le code PIN se pose dans l'inspecteur du Bootstrap /// avant le build, tant que E1 n'a pas donné de pointeur. /// [MenuItem("MyInfoMate/Construire la scène Boot (E2-E3 — appairage et export)")] public static void BuildPairing() => Build(() => new GameObject("Bootstrap").AddComponent(), "E2-E3 (appairage et export)"); /// /// L'app du canal VR telle qu'elle tient : appairage, cache, menu flottant au /// regard, télémétrie. La variante précédente reste là pour isoler un problème /// de réseau d'un problème de rendu. /// [MenuItem("MyInfoMate/Construire la scène Boot (E5 — menu flottant)")] public static void BuildMenu() => Build(() => new GameObject("Bootstrap").AddComponent(), "E5 (menu flottant)"); static void Build(System.Action addBootstrap, string label) { var scene = EditorSceneManager.NewScene( NewSceneSetup.EmptyScene, NewSceneMode.Single); var light = new GameObject("Directional Light").AddComponent(); light.type = LightType.Directional; light.transform.rotation = Quaternion.Euler(50f, -30f, 0f); light.intensity = 1f; addBootstrap(); System.IO.Directory.CreateDirectory("Assets/Scenes"); EditorSceneManager.SaveScene(scene, ScenePath); EditorBuildSettings.scenes = new[] { new EditorBuildSettingsScene(ScenePath, true) }; // Enchaîné ici plutôt que laissé à ta mémoire : une scène reconstruite // puis buildée sans ses shaders embarqués donne un casque magenta, et // l'erreur se diagnostique mal parce que l'éditeur, lui, va bien. IncludeRuntimeShaders.Include(); Debug.Log($"Boot.unity construite sur {label}. Reste à faire à la main : " + "Meta → Tools → Building Blocks → Camera Rig, puis Hand Tracking " + "si on veut le pincement (AimSelector le détecte tout seul, et " + "retombe sur la visée à la tête s'il est absent)."); } } }