using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
///
/// HOY Gallery V2 — GalleryManager
///
/// Reads manifest.json (with exact Spatial world coordinates) and places
/// each ArtworkFrame at the precise position/rotation/scale extracted from
/// Carmen Hoyos' Spatial scene-data.json.
///
/// Room geometry: Spatial "Isle Gallery" preset (environment 8)
/// Reconstructed from artwork positions found in the scene data:
///
/// Central hall: X ≈ -9 to +9, Z ≈ -16 to +5 (width ~18 m, depth ~21 m)
/// West wing: X ≈ -22 to -13, Z ≈ -16 to +5 (width ~9 m)
/// East wing: X ≈ +13 to +22, Z ≈ -16 to +5 (width ~9 m)
/// Ceiling height: ~5.5 m (estimated from artwork Y ≈ 2.2 m centre)
///
/// Spawn point: (-0.36, 0, -2.34) facing ~north (from scene JSON)
///
public class GalleryManager : MonoBehaviour
{
[Header("Prefabs")]
public GameObject artworkFramePrefab;
[Header("Materials")]
public Material wallMaterial;
public Material floorMaterial;
public Material ceilingMaterial;
[Header("Lighting")]
public Light mainDirectionalLight;
// ── Room geometry constants (Isle Gallery reconstruction) ─────────────────
// Central hall
const float HALL_W = 18f; // X: -9 to +9
const float HALL_D = 22f; // Z: -17 to +5
const float HALL_X = 0f;
const float HALL_Z = -6f; // centre of Z range
// Side wings (same depth as hall, narrower)
const float WING_W = 9f; // X width of each wing
const float WING_D = 22f; // Z depth matches hall
const float WING_E_X = 18f; // East wing centre X (+13 to +22 → centre ~17.5)
const float WING_W_X = -18f; // West wing centre X (-22 to -13 → centre ~-17.5)
const float WING_Z = -6f; // same Z centre as hall
// Connecting corridors between hall and wings (fill the gap)
const float CORR_W = 4f;
const float CORR_D = HALL_D;
const float CEILING_H = 5.5f;
const float FLOOR_Y = 0f;
void Start()
{
BuildRoom();
SetupLighting();
StartCoroutine(LoadManifest());
}
// ── Room construction ─────────────────────────────────────────────────────
void BuildRoom()
{
var root = new GameObject("Room");
root.transform.SetParent(transform);
// ── Central hall ──────────────────────────────────────────────────────
MakePlane(root, "Floor_Hall", new Vector3(HALL_X, FLOOR_Y, HALL_Z), new Vector3(0,0,0), HALL_W, HALL_D, floorMaterial);
MakePlane(root, "Ceil_Hall", new Vector3(HALL_X, CEILING_H,HALL_Z), new Vector3(180,0,0), HALL_W, HALL_D, ceilingMaterial);
MakePlane(root, "Wall_N_Hall", new Vector3(HALL_X, CEILING_H/2f, -17f),new Vector3(90,180,0), HALL_W, CEILING_H, wallMaterial);
MakePlane(root, "Wall_S_Hall", new Vector3(HALL_X, CEILING_H/2f, 5f), new Vector3(90,0,0), HALL_W, CEILING_H, wallMaterial);
// Inner walls facing the hall (between hall and wings, partial)
MakePlane(root, "Wall_IE_Hall", new Vector3( 9f, CEILING_H/2f, HALL_Z), new Vector3(90,270,0), HALL_D, CEILING_H, wallMaterial);
MakePlane(root, "Wall_IW_Hall", new Vector3(-9f, CEILING_H/2f, HALL_Z), new Vector3(90,90,0), HALL_D, CEILING_H, wallMaterial);
// ── East wing ─────────────────────────────────────────────────────────
MakePlane(root, "Floor_E", new Vector3(WING_E_X, FLOOR_Y, WING_Z), new Vector3(0,0,0), WING_W, WING_D, floorMaterial);
MakePlane(root, "Ceil_E", new Vector3(WING_E_X, CEILING_H,WING_Z), new Vector3(180,0,0), WING_W, WING_D, ceilingMaterial);
MakePlane(root, "Wall_N_E", new Vector3(WING_E_X, CEILING_H/2f,-17f), new Vector3(90,180,0), WING_W, CEILING_H, wallMaterial);
MakePlane(root, "Wall_S_E", new Vector3(WING_E_X, CEILING_H/2f, 5f), new Vector3(90,0,0), WING_W, CEILING_H, wallMaterial);
MakePlane(root, "Wall_Ext_E",new Vector3(22.5f, CEILING_H/2f,WING_Z), new Vector3(90,270,0), WING_D, CEILING_H, wallMaterial);
// ── West wing ─────────────────────────────────────────────────────────
MakePlane(root, "Floor_W", new Vector3(WING_W_X, FLOOR_Y, WING_Z), new Vector3(0,0,0), WING_W, WING_D, floorMaterial);
MakePlane(root, "Ceil_W", new Vector3(WING_W_X, CEILING_H,WING_Z), new Vector3(180,0,0), WING_W, WING_D, ceilingMaterial);
MakePlane(root, "Wall_N_W", new Vector3(WING_W_X, CEILING_H/2f,-17f), new Vector3(90,180,0),WING_W, CEILING_H, wallMaterial);
MakePlane(root, "Wall_S_W", new Vector3(WING_W_X, CEILING_H/2f, 5f), new Vector3(90,0,0), WING_W, CEILING_H, wallMaterial);
MakePlane(root, "Wall_Ext_W",new Vector3(-22.5f,CEILING_H/2f,WING_Z), new Vector3(90,90,0), WING_D, CEILING_H, wallMaterial);
// ── Partial interior walls (X ≈ ±14) facing wings ────────────────────
// These are the inner faces of the wing walls visible from the hall
MakePlane(root, "Wall_IE_Wing", new Vector3(14f, CEILING_H/2f, WING_Z), new Vector3(90,90,0), WING_D, CEILING_H, wallMaterial);
MakePlane(root, "Wall_IW_Wing", new Vector3(-14f,CEILING_H/2f, WING_Z), new Vector3(90,270,0), WING_D, CEILING_H, wallMaterial);
// ── Floor boxing / skirting colliders (invisible, stop player clipping)
AddWallCollider(root, "Col_N", new Vector3(0, 1f, -17.5f), new Vector3(50f, 2f, 0.3f));
AddWallCollider(root, "Col_S", new Vector3(0, 1f, 5.5f), new Vector3(50f, 2f, 0.3f));
AddWallCollider(root, "Col_EE", new Vector3(23f, 1f, WING_Z), new Vector3(0.3f, 2f, WING_D));
AddWallCollider(root, "Col_WW", new Vector3(-23f, 1f, WING_Z), new Vector3(0.3f, 2f, WING_D));
}
void MakePlane(GameObject parent, string name, Vector3 pos, Vector3 euler, float w, float d, Material mat)
{
var go = GameObject.CreatePrimitive(PrimitiveType.Plane);
go.name = name;
go.transform.SetParent(parent.transform);
go.transform.position = pos;
go.transform.eulerAngles = euler;
go.transform.localScale = new Vector3(w * 0.1f, 1f, d * 0.1f);
Destroy(go.GetComponent());
if (mat != null) go.GetComponent().sharedMaterial = mat;
}
void AddWallCollider(GameObject parent, string name, Vector3 pos, Vector3 size)
{
var go = new GameObject(name);
go.transform.SetParent(parent.transform);
go.transform.position = pos;
var col = go.AddComponent();
col.size = size;
}
// ── Lighting ──────────────────────────────────────────────────────────────
void SetupLighting()
{
RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Flat;
RenderSettings.ambientLight = new Color(0.9f, 0.9f, 0.9f);
if (mainDirectionalLight != null)
{
mainDirectionalLight.intensity = 0.3f;
mainDirectionalLight.color = Color.white;
mainDirectionalLight.shadows = LightShadows.None;
mainDirectionalLight.transform.eulerAngles = new Vector3(60, -20, 0);
}
// Track lights grid covering all three zones
SpawnTrackLights();
}
void SpawnTrackLights()
{
// Central hall
float[] hx = { -6f, -2f, 2f, 6f };
float[] hz = { -14f, -10f, -6f, -2f, 2f };
foreach (var x in hx) foreach (var z in hz) AddPointLight(x, CEILING_H - 0.2f, z, 1.0f, 7f);
// East wing
float[] ex = { 15f, 18f, 21f };
float[] ez = { -14f, -8f, -2f, 3f };
foreach (var x in ex) foreach (var z in ez) AddPointLight(x, CEILING_H - 0.2f, z, 0.9f, 6f);
// West wing
float[] wx = { -15f, -18f, -21f };
foreach (var x in wx) foreach (var z in ez) AddPointLight(x, CEILING_H - 0.2f, z, 0.9f, 6f);
}
void AddPointLight(float x, float y, float z, float intensity, float range)
{
var go = new GameObject("TL");
go.transform.SetParent(transform);
go.transform.position = new Vector3(x, y, z);
var l = go.AddComponent();
l.type = LightType.Point;
l.color = new Color(1f, 0.97f, 0.92f);
l.intensity = intensity;
l.range = range;
l.shadows = LightShadows.None;
}
// ── Manifest loading ──────────────────────────────────────────────────────
IEnumerator LoadManifest()
{
string path = System.IO.Path.Combine(Application.streamingAssetsPath, "manifest.json");
#if UNITY_WEBGL && !UNITY_EDITOR
using var req = UnityWebRequest.Get(path);
yield return req.SendWebRequest();
if (req.result != UnityWebRequest.Result.Success)
{
Debug.LogError($"[HOY] Manifest load failed: {req.error}");
yield break;
}
SpawnArtworks(JsonUtility.FromJson(req.downloadHandler.text));
#else
if (!System.IO.File.Exists(path)) { Debug.LogError($"[HOY] manifest.json not found: {path}"); yield break; }
SpawnArtworks(JsonUtility.FromJson(System.IO.File.ReadAllText(path)));
yield return null;
#endif
}
void SpawnArtworks(GalleryManifest manifest)
{
if (manifest?.artworks == null) return;
foreach (var a in manifest.artworks)
{
if (a.file.Contains("NEEDS_MAPPING"))
{
Debug.LogWarning($"[HOY] Skipping unmapped artwork: spatialId={a.spatialId}");
continue;
}
var pos = new Vector3(a.position.x, a.position.y, a.position.z);
var rot = Quaternion.Euler(0, a.rotationY, 0);
var go = Instantiate(artworkFramePrefab, pos, rot, transform);
go.name = $"Frame_{a.spatialId}_{a.title}";
go.transform.localScale = Vector3.one * a.scale;
var frame = go.GetComponent();
frame?.Initialise(a);
}
Debug.Log($"[HOY] Spawned artworks from Spatial coordinates.");
}
}
// ── Data classes ──────────────────────────────────────────────────────────────
[Serializable] public class GalleryManifest
{
public ArtworkData[] artworks;
}
[Serializable] public class ArtworkData
{
public string spatialId;
public string title;
public string artist;
public string type; // "video" | "image"
public string file; // "Videos/xxx.mp4" | "Images/xxx.jpeg"
public SpatialPosition position;
public float rotationY;
public float scale;
public string comment; // "NEEDS_FILE" or ""
}
[Serializable] public class SpatialPosition
{
public float x, y, z;
}