using System; using System.IO; using Newtonsoft.Json; using UnityEngine; namespace Uigenx.Editor { /// /// The committed part of the editor configuration. It holds a relative path to the UI Creator /// project and the Unity folder exports land in, and never a token or any other secret. /// [Serializable] public sealed class UgxProjectSettings { /// Path relative to the Unity project root. Committed. public const string FilePath = "ProjectSettings/UgxSettings.json"; public const string DefaultUiFolder = "UI"; /// Relative path from the Unity project root to the UI Creator project folder. [JsonProperty("ugxProject")] public string UgxProject { get; set; } = "../ui"; /// Folder under Assets/ that exports are written to. [JsonProperty("uiFolder")] public string UiFolder { get; set; } = DefaultUiFolder; [JsonProperty("bridgeEnabled")] public bool BridgeEnabled { get; set; } = true; [JsonProperty("streamHz")] public float StreamHz { get; set; } = 20f; static UgxProjectSettings _cached; public static UgxProjectSettings Load() { if (_cached != null) return _cached; if (!File.Exists(FilePath)) { _cached = new UgxProjectSettings(); return _cached; } try { _cached = JsonConvert.DeserializeObject(File.ReadAllText(FilePath)) ?? new UgxProjectSettings(); } catch (Exception e) { Debug.LogError("[ugx] " + FilePath + " could not be read, falling back to defaults: " + e.Message); _cached = new UgxProjectSettings(); } return _cached; } public void Save() { _cached = this; var json = JsonConvert.SerializeObject(this, Formatting.Indented) + "\n"; File.WriteAllText(FilePath, json); } public static void Invalidate() => _cached = null; /// Absolute path to the UI Creator project folder, or null when it does not exist. public string ResolveUicProjectPath() { if (string.IsNullOrEmpty(UgxProject)) return null; var projectRoot = Directory.GetCurrentDirectory(); var combined = Path.GetFullPath(Path.Combine(projectRoot, UgxProject)); return Directory.Exists(combined) ? combined : null; } /// `Assets/<UiFolder>`, with forward slashes as the AssetDatabase expects. public string AssetsUiFolder => "Assets/" + (string.IsNullOrEmpty(UiFolder) ? DefaultUiFolder : UiFolder).Replace('\\', '/').Trim('/'); } /// /// The uncommitted half: `<ugxProject>/.uigenx/daemon.json`, written by the daemon when it starts. /// It carries the port and the pairing token, so it is never read into a committed file and /// the token is never printed. /// public sealed class UgxDaemonInfo { [JsonProperty("url")] public string Url { get; set; } [JsonProperty("port")] public int Port { get; set; } [JsonProperty("token")] public string Token { get; set; } [JsonProperty("pid")] public int Pid { get; set; } [JsonProperty("projectId")] public string ProjectId { get; set; } public const string RelativePath = ".uigenx/daemon.json"; public static UgxDaemonInfo Load(string ugxProjectPath) { if (string.IsNullOrEmpty(ugxProjectPath)) return null; var path = Path.Combine(ugxProjectPath, RelativePath); if (!File.Exists(path)) return null; try { return JsonConvert.DeserializeObject(File.ReadAllText(path)); } catch (Exception e) { Debug.LogWarning("[ugx] " + path + " could not be read: " + e.Message); return null; } } public string ResolveUrl() { if (!string.IsNullOrEmpty(Url)) return Url; return Port > 0 ? "ws://127.0.0.1:" + Port : UgxSettings.DefaultDaemonUrl; } } }