Download WorldPanelManager.cs from LoveLogicAI/xros-shell: direct link, hf CLI and curl.
- Browser
- Download file 3.2 kB
-
https://huggingface.co/LoveLogicAI/xros-shell/resolve/main/WorldPanelManager.cs
- Command line
-
hf download hf://LoveLogicAI/xros-shell/WorldPanelManager.cs
-
curl -L -o WorldPanelManager.cs https://huggingface.co/LoveLogicAI/xros-shell/resolve/main/WorldPanelManager.cs
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; | |
| } | |
| } | |