using System.Collections.Generic;
using System.Linq;
using Manager.DTOs;
using ManagerService.DTOs;
using static ManagerService.Data.SectionText;
namespace ManagerService.Data.SubSection
{
/// Objet manipulé ou décor habité — voir .
public enum Scene3DMode
{
// ⚠️ Persisté en int : toute valeur nouvelle s'ajoute à la fin.
Asset = 0,
Scene = 1
}
///
/// Une scène 3D : un modèle glTF et ses points d'intérêt — lot XR-4,
/// items E5 (le décor) et E7 (l'objet).
///
/// Nommé « Scene3D » et pas « Model3D » alors qu'il ne porte aujourd'hui qu'un
/// modèle et des points : le discriminateur TPH est une chaîne persistée en base.
/// Le renommer tant que rien n'est en production coûte zéro ; le renommer après la
/// première maquette livrée coûte une migration de données. Les objets posés, les
/// personnages et la navigation prévus au §S4 de la conception viendront ici, en
/// colonnes nullables — pas dans un second type à faire cohabiter.
///
/// Pourquoi un type à part et pas une augmentée : une
/// maquette n'est pas une carte. Les deux se ressemblent parce qu'elles portent des
/// points d'intérêt, mais une carte a un fond cartographique, un zoom, un fournisseur
/// et des coordonnées terrestres — dont une maquette n'a que faire. Tordre la Map
/// aurait donné un type qui ment sur la moitié de ses champs.
///
/// Ce qu'on réutilise en revanche : le . Il portait déjà
/// deux rattachements (SectionMapId, SectionEventId) ; un troisième suit
/// le même patron. Un point garde ainsi son titre, sa description, son image, ses
/// contenus audio et son multilingue — et l'éditeur de points du back-office avec.
/// Seule sa change de nature.
///
public class SectionScene3D : Section
{
/// Ressource Model3D (glTF binaire) affichée par cette section.
public string Model3DResourceId { get; set; }
///
/// Ce que le visiteur fait de cette scène — et c'est une opposition franche
/// (§4bis de DOCS/v2/immersif-frontiere-plan.md, arrêté le 11/09) :
///
///
/// - Asset — un objet posé devant lui, qu'il manipule : caméra
/// orbitale, on tourne autour, les points tournent avec l'objet. L'épée du
/// roi, une pièce de collection.
/// - Scene — un décor dans lequel il est : caméra fixe, on
/// regarde autour, les points restent où ils sont. Une salle reconstituée.
///
///
/// Même GLB, même modèle de point, même éditeur : ce qui change, c'est où l'on met
/// le visiteur — et aucun fichier ne peut le deviner, d'où ce champ.
///
public Scene3DMode Mode { get; set; } = Scene3DMode.Asset;
///
/// URL du modèle, dupliquée comme l'est à côté
/// de . Ce n'est pas de la redondance gratuite : le
/// viewer et le casque ont besoin de l'URL sans faire de jointure, et l'export
/// hors ligne la réécrit en chemin local.
///
public string Model3DSource { get; set; }
///
/// Points posés sur le modèle. Même collection que celle d'une Map, même éditeur,
/// même contenu — seule la position diffère.
///
public List Points { get; set; }
public override string GetEmbeddableText(string language) =>
JoinText(new[] { BaseText(language) }
.Concat((Points ?? new List())
.Select(p => p.GetEmbeddableText(language)))
.ToArray());
///
/// Le modèle compte parmi les ressources de la visite : sans lui, un téléchargement
/// hors ligne rapporterait les points d'une maquette absente.
///
public override IEnumerable GetReferencedResourceIds(string language = null) =>
BaseResourceIds()
.Concat(ResourceId(Model3DResourceId))
.Concat((Points ?? new List())
.SelectMany(p => p.GetReferencedResourceIds()));
public Scene3DDTO ToDTO()
{
return new Scene3DDTO()
{
id = Id,
label = Label,
title = Title.ToList(),
description = Description.ToList(),
order = Order,
type = Type,
imageId = ImageId,
imageSource = ImageSource,
configurationId = ConfigurationId,
isSubSection = IsSubSection,
parentId = ParentId,
isActive = IsActive,
dateCreation = DateCreation,
instanceId = InstanceId,
latitude = Latitude,
longitude = Longitude,
meterZoneGPS = MeterZoneGPS,
isBeacon = IsBeacon,
beaconId = BeaconId,
model3DResourceId = Model3DResourceId,
model3DSource = Model3DSource,
mode = Mode,
points = (Points ?? new List()).Select(p => p.ToDTO()).ToList()
};
}
}
}