using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; namespace Uigenx { [Serializable] public sealed class UgxScreenEntry { [SerializeField] string key; [SerializeField] VisualTreeAsset uxml; [SerializeField] StyleSheet[] styles = Array.Empty(); [SerializeField] string className; [SerializeField] UgxLayer layer = UgxLayer.Hud; [SerializeField] PanelSettings panel; public UgxScreenEntry() { } public UgxScreenEntry(string key, VisualTreeAsset uxml, string className, UgxLayer layer, StyleSheet[] styles = null, PanelSettings panel = null) { this.key = key; this.uxml = uxml; this.className = className; this.layer = layer; this.styles = styles ?? Array.Empty(); this.panel = panel; } public string Key => key; public VisualTreeAsset Uxml => uxml; public StyleSheet[] Styles => styles; /// Full name of the generated screen class. Diagnostics only, never used to reflect. public string ClassName => className; public UgxLayer Layer => layer; /// Optional panel override. Null means the layer's default panel. public PanelSettings Panel => panel; } /// /// Everything the runtime needs to open a screen by key. Rebuilt by the editor after every /// import; never hand edited. /// [CreateAssetMenu(menuName = "UI Creator/Screen Registry", fileName = "UgxScreenRegistry")] public sealed class UgxScreenRegistry : ScriptableObject { /// Resources path the editor writes the registry to, so a build can always find it. public const string ResourcePath = "UgxScreenRegistry"; [SerializeField] UgxScreenEntry[] entries = Array.Empty(); readonly Dictionary _byKey = new Dictionary(StringComparer.Ordinal); bool _built; static UgxScreenRegistry _active; public IReadOnlyList Entries => entries; /// The registry the settings asset points at, or the one in Resources. public static UgxScreenRegistry Active { get { if (_active != null) return _active; var settings = UgxSettings.InstanceOrNull; if (settings != null && settings.ScreenRegistry != null) _active = settings.ScreenRegistry; if (_active == null) _active = Resources.Load(ResourcePath); return _active; } set => _active = value; } void OnEnable() => Rebuild(); public void Rebuild() { _byKey.Clear(); _built = true; if (entries == null) return; foreach (var entry in entries) { if (entry == null || string.IsNullOrEmpty(entry.Key)) continue; if (_byKey.ContainsKey(entry.Key)) { Debug.LogWarning("[ugx] screen registry has two entries for key '" + entry.Key + "', the first one wins", this); continue; } _byKey[entry.Key] = entry; } } public bool TryGet(string key, out UgxScreenEntry entry) { if (!_built) Rebuild(); entry = null; return !string.IsNullOrEmpty(key) && _byKey.TryGetValue(key, out entry); } public UgxScreenEntry GetOrThrow(string key) { if (TryGet(key, out var entry)) return entry; throw new InvalidOperationException( "screen '" + key + "' is not in the UI Creator screen registry. Re-export from the studio, " + "or rebuild the registry with Tools > UI Creator > Sync now."); } /// Replaces every entry. Editor only in practice, public so tests can build one. public void SetEntries(UgxScreenEntry[] value) { entries = value ?? Array.Empty(); Rebuild(); } } }