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;
}
}
}