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>
124 lines
3.8 KiB
C#
124 lines
3.8 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace MyInfoMate.Vr.Menu
|
|
{
|
|
/// <summary>
|
|
/// Placement « bento » dense sur une grille de colonnes — le socle du menu flottant.
|
|
///
|
|
/// <b>Port C# de <c>myinfomate_layout</c></b> (Dart), qui sert au manager et à
|
|
/// mymuseum-visitapp ; le web refait le même placement en CSS Grid. Trois
|
|
/// implémentations, une seule règle : chaque item va à la première cellule libre,
|
|
/// parcours ligne par ligne, qui l'accueille — soit <c>grid-auto-flow: dense</c>.
|
|
///
|
|
/// <b>Porté plutôt que calculé par le serveur</b> : l'export reste une description du
|
|
/// contenu, pas une mise en page. Un placement calculé à distance ferait qu'un vieux
|
|
/// contenu en cache porterait une vieille mise en page.
|
|
/// </summary>
|
|
public static class BentoLayout
|
|
{
|
|
public struct Item
|
|
{
|
|
public string Id;
|
|
public int ColSpan;
|
|
public int RowSpan;
|
|
|
|
public Item(string id, int colSpan = 1, int rowSpan = 1)
|
|
{
|
|
Id = id;
|
|
ColSpan = colSpan;
|
|
RowSpan = rowSpan;
|
|
}
|
|
}
|
|
|
|
public struct Placement
|
|
{
|
|
public string Id;
|
|
public int Col;
|
|
public int Row;
|
|
public int ColSpan;
|
|
public int RowSpan;
|
|
}
|
|
|
|
public struct Result
|
|
{
|
|
public List<Placement> Placements;
|
|
public int RowCount;
|
|
}
|
|
|
|
public static Result Compute(IList<Item> items, int columns)
|
|
{
|
|
var cols = columns < 1 ? 1 : columns;
|
|
var occupied = new List<bool[]>();
|
|
|
|
void EnsureRow(int r)
|
|
{
|
|
while (occupied.Count <= r) occupied.Add(new bool[cols]);
|
|
}
|
|
|
|
bool Fits(int r, int c, int cs, int rs)
|
|
{
|
|
if (c + cs > cols) return false;
|
|
for (var rr = r; rr < r + rs; rr++)
|
|
{
|
|
EnsureRow(rr);
|
|
for (var cc = c; cc < c + cs; cc++)
|
|
if (occupied[rr][cc]) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Fill(int r, int c, int cs, int rs)
|
|
{
|
|
for (var rr = r; rr < r + rs; rr++)
|
|
{
|
|
EnsureRow(rr);
|
|
for (var cc = c; cc < c + cs; cc++) occupied[rr][cc] = true;
|
|
}
|
|
}
|
|
|
|
var placements = new List<Placement>();
|
|
|
|
foreach (var item in items)
|
|
{
|
|
var cs = item.ColSpan < 1 ? 1 : (item.ColSpan > cols ? cols : item.ColSpan);
|
|
var rs = item.RowSpan < 1 ? 1 : item.RowSpan;
|
|
|
|
var placed = false;
|
|
var r = 0;
|
|
while (!placed)
|
|
{
|
|
for (var c = 0; c + cs <= cols; c++)
|
|
{
|
|
if (!Fits(r, c, cs, rs)) continue;
|
|
|
|
Fill(r, c, cs, rs);
|
|
placements.Add(new Placement
|
|
{
|
|
Id = item.Id,
|
|
Col = c,
|
|
Row = r,
|
|
ColSpan = cs,
|
|
RowSpan = rs,
|
|
});
|
|
placed = true;
|
|
break;
|
|
}
|
|
if (!placed) r++;
|
|
}
|
|
}
|
|
|
|
var rowCount = occupied.Count;
|
|
while (rowCount > 0 && IsEmpty(occupied[rowCount - 1])) rowCount--;
|
|
|
|
return new Result { Placements = placements, RowCount = rowCount };
|
|
}
|
|
|
|
static bool IsEmpty(bool[] row)
|
|
{
|
|
foreach (var cell in row)
|
|
if (cell) return false;
|
|
return true;
|
|
}
|
|
}
|
|
}
|