xros-shell / WorldPanelManager.cs
LoveLogicAI's picture
unity world renderer
eb6aba9 verified
Raw History Blame Contribute Delete
3.2 kB
// WorldPanelManager.cs — renders the shared world as spatial panels.
//
// Subscribes to the XrosClient and turns world-state events into GameObjects:
// spawn -> instantiate a panel at the object's pose
// move -> reposition an existing panel
// remove -> destroy a panel
// snapshot -> reconcile the whole scene (on connect)
//
// This is the "spatial computing" element: panels are anchored in the room
// (passthrough) and driven by the shared world model, not by local state.
//
// Setup: attach to a GameObject, assign the XrosClient and a panelPrefab
// (a quad/canvas with a TMP_Text child named "Title"). The prefab's text is
// set from the object's properties.title.
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using TMPro;
using UnityEngine;
public class WorldPanelManager : MonoBehaviour
{
public XrosClient client;
public GameObject panelPrefab;
private readonly Dictionary<string, GameObject> panels = new Dictionary<string, GameObject>();
private void OnEnable()
{
if (client != null) client.OnMessage += HandleMessage;
}
private void OnDisable()
{
if (client != null) client.OnMessage -= HandleMessage;
}
private void HandleMessage(JObject msg)
{
string op = msg["op"]?.ToString();
switch (op)
{
case "spawn":
Spawn(msg["object"] as JObject);
break;
case "move":
Move(msg["object"] as JObject);
break;
case "remove":
Remove(msg["id"]?.ToString());
break;
case "snapshot":
foreach (var o in msg["objects"] ?? new JArray())
Spawn(o as JObject);
break;
}
}
private void Spawn(JObject obj)
{
if (obj == null) return;
string id = obj["id"]?.ToString();
if (id == null || panels.ContainsKey(id)) return;
var go = Instantiate(panelPrefab, transform);
go.name = $"panel_{id}";
ApplyPose(go, obj["pose"] as JObject);
ApplyTitle(go, obj["properties"] as JObject);
panels[id] = go;
}
private void Move(JObject obj)
{
if (obj == null) return;
string id = obj["id"]?.ToString();
if (id == null || !panels.TryGetValue(id, out var go)) return;
ApplyPose(go, obj["pose"] as JObject);
}
private void Remove(string id)
{
if (id == null || !panels.TryGetValue(id, out var go)) return;
Destroy(go);
panels.Remove(id);
}
private void ApplyPose(GameObject go, JObject pose)
{
if (pose == null) return;
var pos = pose["position"] as JArray;
if (pos != null && pos.Count >= 3)
go.transform.localPosition = new Vector3(
(float)pos[0], (float)pos[1], (float)pos[2]);
}
private void ApplyTitle(GameObject go, JObject properties)
{
string title = properties?["title"]?.ToString();
if (string.IsNullOrEmpty(title)) return;
var text = go.GetComponentInChildren<TMP_Text>();
if (text != null) text.text = title;
}
}