Files
2026-06-07 16:58:24 +01:00

161 lines
5.9 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using System.IO;
using FileInfo = System.IO.FileInfo;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UdonSharp.Updater
{
internal class UdonSharpDataLocator : ScriptableObject
{
private const string DEFAULT_DATA_PATH = "Assets/UdonSharp/UdonSharpDataLocator.asset";
private const string PROJECT_LOADED_KEY = "UdonSharpDataLocator_HasPostProcessedAssets";
private static string _cachedDataLocation;
#if UNITY_EDITOR
internal static bool HasEverPostProcessedAssets
{
get => SessionState.GetBool(PROJECT_LOADED_KEY, false);
set => SessionState.SetBool(PROJECT_LOADED_KEY, value);
}
#endif
public static string DataPath
{
get
{
#if UNITY_EDITOR
if (_cachedDataLocation != null)
return _cachedDataLocation;
string[] foundLocatorGuids = AssetDatabase.FindAssets($"t:{nameof(UdonSharpDataLocator)}");
List<UdonSharpDataLocator> foundLocators = new List<UdonSharpDataLocator>();
foreach (string locatorGuid in foundLocatorGuids)
{
UdonSharpDataLocator locator =
AssetDatabase.LoadAssetAtPath<UdonSharpDataLocator>(AssetDatabase.GUIDToAssetPath(locatorGuid));
if (locator)
foundLocators.Add(locator);
}
if (foundLocators.Count > 1)
throw new System.Exception(
"Multiple UdonSharp data locators found, make sure you do not have multiple installations of UdonSharp and have not duplicated any UdonSharp directories");
if (foundLocators.Count == 0)
{
if (!HasEverPostProcessedAssets)
{
// We can't trust this result, the asset database may be invalid if the Library folder was cleared.
// This may be running too early.
// Best effort, give back the default path without caching.
return Path.GetDirectoryName(DEFAULT_DATA_PATH);
}
foundLocators.Add(InitializeUdonSharpData());
}
_cachedDataLocation = Path.GetDirectoryName(AssetDatabase.GetAssetPath(foundLocators[0]));
return _cachedDataLocation;
#else
throw new System.PlatformNotSupportedException("Cannot get UdonSharp data path outside of the Editor runtime");
#endif
}
}
#if UNITY_EDITOR
private static string GetUtilitiesPath(string locatorPath)
{
return Path.Combine(Path.GetDirectoryName(locatorPath), "UtilityScripts");
}
private static UdonSharpDataLocator InitializeUdonSharpData()
{
if (!AssetDatabase.IsValidFolder(Path.GetDirectoryName(DEFAULT_DATA_PATH)))
AssetDatabase.CreateFolder("Assets", "UdonSharp");
string utilsTargetPath = GetUtilitiesPath(DEFAULT_DATA_PATH);
string utilsSourcePath = Path.Combine(UdonSharpLocator.SamplesPath, "Utilities");
if (Directory.Exists(utilsSourcePath))
DeepCopyDirectory(utilsSourcePath, utilsTargetPath);
else
Debug.LogWarning("No utilities directory found to copy from for UdonSharp utility scripts");
UdonSharpDataLocator locator = CreateInstance<UdonSharpDataLocator>();
AssetDatabase.CreateAsset(locator, DEFAULT_DATA_PATH);
Debug.Log("Created UdonSharp data directory", locator);
AssetDatabase.Refresh();
return locator;
}
#endif
private static void DeepCopyDirectory(string sourcePath, string destinationPath)
{
string[] sourceDirs = Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories);
foreach (string sourceDir in sourceDirs)
{
Directory.CreateDirectory(sourceDir.Replace(sourcePath, destinationPath));
}
string[] sourceFiles = Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories);
foreach (string sourceFile in sourceFiles)
{
string targetFilePath = sourceFile.Replace(sourcePath, destinationPath);
File.Copy(sourceFile, targetFilePath, true);
new FileInfo(targetFilePath).IsReadOnly = false;
}
}
}
#if UNITY_EDITOR
[CustomEditor(typeof(UdonSharpDataLocator))]
internal class UdonSharpDataLocatorEditor : Editor
{
public override void OnInspectorGUI()
{
EditorGUILayout.HelpBox("Do not delete this file! This is used by UdonSharp to locate its data directory.", MessageType.Error);
}
}
internal class InitUSharpDataOnImport : AssetPostprocessor
{
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
UdonSharpDataLocator.HasEverPostProcessedAssets = true;
if (importedAssets.Length <= 0) return;
try
{
foreach (string importedAsset in importedAssets)
{
if (Path.GetFileName(importedAsset) == "UdonSharpLocator.asset" &&
AssetDatabase.LoadAssetAtPath<UdonSharpLocator>(importedAsset))
{
string _ = UdonSharpDataLocator.DataPath; // Implicitly initializes the data asset if it doesn't exist
}
}
}
catch (System.Exception e)
{
Debug.LogError(e);
}
}
}
#endif
}