using System.Threading.Tasks;
using MyInfoMate.Vr.Scene;
using UnityEngine;
namespace MyInfoMate.Vr.Boot
{
///
/// Orchestration de l'étape S1 : décor, calibration, personnage, zone de navigation.
///
/// Provisoire par construction. Les chemins sont ici en dur, parce que S1
/// n'a ni manifeste ni réseau — c'est exactement son intérêt : prouver la chaîne
/// technique sans backend. S2 remplace ce script par SceneBuilder, qui lit
/// les mêmes assets depuis un manifeste. Ne rien construire au-dessus de celui-ci.
///
public class S1Bootstrap : MonoBehaviour
{
[Header("Fichiers dans Assets/StreamingAssets")]
[SerializeField] string worldFile = "world.glb";
[SerializeField] string personaFile = "persona.glb";
[Header("Placement du personnage — coordonnées glTF, en mètres")]
[SerializeField] float[] personaPosition = { -1.5f, 0f, -1f };
[Header("Navigation")]
[SerializeField] float navigationRadiusMeters = 3f;
[SerializeField] bool showBoundary = true;
[SerializeField] bool runCalibration = true;
Transform _sceneRoot;
async void Start()
{
_sceneRoot = new GameObject("SceneRoot").transform;
_sceneRoot.SetParent(transform, false);
var head = Camera.main != null ? Camera.main.transform : null;
if (head == null)
Debug.LogError("[S1] Aucune caméra active : le rig VR n'est pas dans la scène. " +
"Meta → Tools → Building Blocks → Camera Rig.");
await LoadWorld();
if (runCalibration)
await gameObject.AddComponent().RunAsync(_sceneRoot);
await LoadPersona(head);
SetUpBounds(head);
}
async Task LoadWorld()
{
var world = await GltfLoader.LoadAsync(
GltfLoader.StreamingAssetsUrl(worldFile), _sceneRoot, "World");
if (world == null)
Debug.LogError($"[S1] {worldFile} absent de StreamingAssets — " +
"exporte un monde Marble en mesh GLB et dépose-le là.");
}
async Task LoadPersona(Transform head)
{
var holder = new GameObject("Persona");
holder.transform.SetParent(_sceneRoot, false);
holder.transform.localPosition = GltfSpace.Position(personaPosition);
var persona = holder.AddComponent();
if (!await persona.LoadAsync(GltfLoader.StreamingAssetsUrl(personaFile), head))
Debug.LogError($"[S1] {personaFile} absent de StreamingAssets.");
}
void SetUpBounds(Transform head)
{
// La zone suit le rig, pas la tête : c'est la position au sol du visiteur
// qui compte, et la tête bouge de 60 cm quand on se penche.
var rig = head != null ? head.root : null;
var bounds = new GameObject("NavigationBounds").AddComponent();
bounds.transform.SetParent(_sceneRoot, false);
bounds.Configure(rig, head, navigationRadiusMeters, showBoundary);
}
}
}