#if UGX_BRIDGE || UNITY_EDITOR using System; using System.Collections.Generic; using System.IO; using Uigenx.Protocol; namespace Uigenx.Bridge { /// /// Re-opens screens after the editor reimported their assets. The runtime cannot parse UXML or /// USS text itself, so the daemon writes the files, the importer reimports them, and this /// handler rebuilds whatever is on screen. Anything it cannot match is reported as an error /// rather than silently ignored. /// public sealed class UgxHotReloadHandler : IDisposable { readonly UgxBridgeClient _client; readonly List _reloaded = new List(4); readonly List _errors = new List(4); public UgxHotReloadHandler(UgxBridgeClient client) { _client = client ?? throw new ArgumentNullException(nameof(client)); client.Register(UgxMessageTypes.HotReloadRequest, OnRequest); } public void Dispose() => _client.Unregister(UgxMessageTypes.HotReloadRequest); void OnRequest(UgxEnvelope envelope) { var body = envelope.BodyAs(); _reloaded.Clear(); _errors.Clear(); var manager = UgxScreenManager.Instance; var registry = UgxScreenRegistry.Active; foreach (var file in body.Files) { var key = ScreenKeyFor(file.Path); if (registry == null || key == null || !registry.TryGet(key, out _)) { _errors.Add(file.Path + ": no screen matches this file, nothing to reload"); continue; } if (manager == null || !manager.IsOpen(key)) { // Not an error: the next open picks up the reimported asset. _reloaded.Add(key); continue; } // Re-open on the layer it was on, not the registry default: a modal pushed onto // Overlay must not come back above everything on Modal. var layer = LayerOf(manager, key); manager.Close(key); if (manager.Push(key, layer) != null) _reloaded.Add(key); else _errors.Add(key + ": could not be re-opened"); } _client.Send(UgxMessageTypes.HotReloadResult, new UgxHotReloadResult { RequestId = body.RequestId, Reloaded = new List(_reloaded), Errors = new List(_errors), }, re: envelope.Id); } static UgxLayer? LayerOf(UgxScreenManager manager, string key) { var stack = manager.Stack; for (int i = stack.Count - 1; i >= 0; i--) if (stack[i].Key == key) return stack[i].Layer; return null; } /// `.../Screens/Hud/Hud.uxml` becomes `Hud`. Null when the path has no file name. public static string ScreenKeyFor(string path) { if (string.IsNullOrEmpty(path)) return null; var name = Path.GetFileNameWithoutExtension(path); return string.IsNullOrEmpty(name) ? null : name; } } } #endif