unity world renderer
Browse files- WorldPanelManager.cs +103 -0
WorldPanelManager.cs
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// WorldPanelManager.cs — renders the shared world as spatial panels.
|
| 2 |
+
//
|
| 3 |
+
// Subscribes to the XrosClient and turns world-state events into GameObjects:
|
| 4 |
+
// spawn -> instantiate a panel at the object's pose
|
| 5 |
+
// move -> reposition an existing panel
|
| 6 |
+
// remove -> destroy a panel
|
| 7 |
+
// snapshot -> reconcile the whole scene (on connect)
|
| 8 |
+
//
|
| 9 |
+
// This is the "spatial computing" element: panels are anchored in the room
|
| 10 |
+
// (passthrough) and driven by the shared world model, not by local state.
|
| 11 |
+
//
|
| 12 |
+
// Setup: attach to a GameObject, assign the XrosClient and a panelPrefab
|
| 13 |
+
// (a quad/canvas with a TMP_Text child named "Title"). The prefab's text is
|
| 14 |
+
// set from the object's properties.title.
|
| 15 |
+
|
| 16 |
+
using System.Collections.Generic;
|
| 17 |
+
using Newtonsoft.Json.Linq;
|
| 18 |
+
using TMPro;
|
| 19 |
+
using UnityEngine;
|
| 20 |
+
|
| 21 |
+
public class WorldPanelManager : MonoBehaviour
|
| 22 |
+
{
|
| 23 |
+
public XrosClient client;
|
| 24 |
+
public GameObject panelPrefab;
|
| 25 |
+
|
| 26 |
+
private readonly Dictionary<string, GameObject> panels = new Dictionary<string, GameObject>();
|
| 27 |
+
|
| 28 |
+
private void OnEnable()
|
| 29 |
+
{
|
| 30 |
+
if (client != null) client.OnMessage += HandleMessage;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
private void OnDisable()
|
| 34 |
+
{
|
| 35 |
+
if (client != null) client.OnMessage -= HandleMessage;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
private void HandleMessage(JObject msg)
|
| 39 |
+
{
|
| 40 |
+
string op = msg["op"]?.ToString();
|
| 41 |
+
switch (op)
|
| 42 |
+
{
|
| 43 |
+
case "spawn":
|
| 44 |
+
Spawn(msg["object"] as JObject);
|
| 45 |
+
break;
|
| 46 |
+
case "move":
|
| 47 |
+
Move(msg["object"] as JObject);
|
| 48 |
+
break;
|
| 49 |
+
case "remove":
|
| 50 |
+
Remove(msg["id"]?.ToString());
|
| 51 |
+
break;
|
| 52 |
+
case "snapshot":
|
| 53 |
+
foreach (var o in msg["objects"] ?? new JArray())
|
| 54 |
+
Spawn(o as JObject);
|
| 55 |
+
break;
|
| 56 |
+
}
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
private void Spawn(JObject obj)
|
| 60 |
+
{
|
| 61 |
+
if (obj == null) return;
|
| 62 |
+
string id = obj["id"]?.ToString();
|
| 63 |
+
if (id == null || panels.ContainsKey(id)) return;
|
| 64 |
+
|
| 65 |
+
var go = Instantiate(panelPrefab, transform);
|
| 66 |
+
go.name = $"panel_{id}";
|
| 67 |
+
ApplyPose(go, obj["pose"] as JObject);
|
| 68 |
+
ApplyTitle(go, obj["properties"] as JObject);
|
| 69 |
+
panels[id] = go;
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
private void Move(JObject obj)
|
| 73 |
+
{
|
| 74 |
+
if (obj == null) return;
|
| 75 |
+
string id = obj["id"]?.ToString();
|
| 76 |
+
if (id == null || !panels.TryGetValue(id, out var go)) return;
|
| 77 |
+
ApplyPose(go, obj["pose"] as JObject);
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
private void Remove(string id)
|
| 81 |
+
{
|
| 82 |
+
if (id == null || !panels.TryGetValue(id, out var go)) return;
|
| 83 |
+
Destroy(go);
|
| 84 |
+
panels.Remove(id);
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
private void ApplyPose(GameObject go, JObject pose)
|
| 88 |
+
{
|
| 89 |
+
if (pose == null) return;
|
| 90 |
+
var pos = pose["position"] as JArray;
|
| 91 |
+
if (pos != null && pos.Count >= 3)
|
| 92 |
+
go.transform.localPosition = new Vector3(
|
| 93 |
+
(float)pos[0], (float)pos[1], (float)pos[2]);
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
private void ApplyTitle(GameObject go, JObject properties)
|
| 97 |
+
{
|
| 98 |
+
string title = properties?["title"]?.ToString();
|
| 99 |
+
if (string.IsNullOrEmpty(title)) return;
|
| 100 |
+
var text = go.GetComponentInChildren<TMP_Text>();
|
| 101 |
+
if (text != null) text.text = title;
|
| 102 |
+
}
|
| 103 |
+
}
|