Premier commit du cinquième front. Trois parties : - `unity/MyInfoMateVR/` : le projet Unity (6000.0.83f1, URP, Meta XR SDK 205), un APK unique pour tous les clients. Menu flottant à sélection au regard, appairage, chargement de scène GLB, POI, cache de contenu, télémétrie. - `unity-overlay/` : les mêmes scripts à recopier sur un projet Unity neuf, avec les pièges rencontrés consignés dans son README. - `viewer/` : viewer et éditeur de scène web autonome (Vite, TypeScript, three.js), partagé avec les autres fronts. - `docs/` : état des lieux, setup Unity, décisions d'architecture et plan d'exécution en 9 étapes. La scène est décrite par un `scene.json` poussé par `adb push` : l'app le préfère à celui embarqué dans l'APK. Les binaires (GLB, textures de l'échantillon Sponza, DLL Meta XR) passent par Git LFS dès ce premier commit — les y faire entrer après coup demanderait de réécrire l'historique. Les artefacts régénérés par l'éditeur et par CMake (`Library/`, `.utmp/`, Burst debug) sont ignorés. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
88 lines
4.2 KiB
C#
88 lines
4.2 KiB
C#
using MyInfoMate.Vr.Boot;
|
|
using UnityEditor;
|
|
using UnityEditor.SceneManagement;
|
|
using UnityEngine;
|
|
|
|
namespace MyInfoMate.Vr.EditorTools
|
|
{
|
|
/// <summary>
|
|
/// Construit Boot.unity <b>par code</b> 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 <i>en silence</i>. 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 :
|
|
/// <b>S1</b> prouve la chaîne technique avec des chemins en dur, <b>S2</b> prouve
|
|
/// le contrat de données en lisant <c>scene.json</c>. 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.
|
|
/// </summary>
|
|
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<S1Bootstrap>(),
|
|
"S1 (chemins en dur)");
|
|
|
|
[MenuItem("MyInfoMate/Construire la scène Boot (S2 — depuis scene.json)")]
|
|
public static void BuildS2() =>
|
|
Build(() => new GameObject("Bootstrap").AddComponent<S2Bootstrap>(),
|
|
"S2 (manifeste scene.json)");
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[MenuItem("MyInfoMate/Construire la scène Boot (E2-E3 — appairage et export)")]
|
|
public static void BuildPairing() =>
|
|
Build(() => new GameObject("Bootstrap").AddComponent<PairingBootstrap>(),
|
|
"E2-E3 (appairage et export)");
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[MenuItem("MyInfoMate/Construire la scène Boot (E5 — menu flottant)")]
|
|
public static void BuildMenu() =>
|
|
Build(() => new GameObject("Bootstrap").AddComponent<MenuBootstrap>(),
|
|
"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>();
|
|
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).");
|
|
}
|
|
}
|
|
}
|