190 lines
7.5 KiB
C#
190 lines
7.5 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Needle.Engine.Utils;
|
|
using Newtonsoft.Json.Linq;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace Needle.Engine
|
|
{
|
|
internal class HiddenProject
|
|
{
|
|
private static readonly string InstallDirectory = Path.GetFullPath("Temp/@needle-tools-npm-tools");
|
|
|
|
private static readonly string PackageJsonPath = InstallDirectory + "/package.json";
|
|
|
|
internal static string BuildPipelinePath { get; } =
|
|
$"{InstallDirectory}/node_modules/{Constants.GltfBuildPipelineNpmPackageName}";
|
|
|
|
internal static string ComponentCompilerPath { get; } =
|
|
$"{InstallDirectory}/node_modules/{Constants.ComponentCompilerNpmPackageName}";
|
|
|
|
internal static string ToolsPath { get; } =
|
|
$"{InstallDirectory}/node_modules/{Constants.ToolsNpmPackageName}";
|
|
|
|
|
|
// #if UNITY_EDITOR
|
|
// [InitializeOnLoadMethod]
|
|
// private static async void Init()
|
|
// {
|
|
// while (EditorApplication.isCompiling || EditorApplication.isUpdating) await Task.Delay(1000);
|
|
// await Task.Delay(1000);
|
|
// await Initialize(true);
|
|
// }
|
|
// #endif
|
|
|
|
internal static void Delete()
|
|
{
|
|
try
|
|
{
|
|
if (Directory.Exists(InstallDirectory))
|
|
{
|
|
Directory.Delete(InstallDirectory, true);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
NeedleDebug.LogException(TracingScenario.Any, e);
|
|
}
|
|
}
|
|
|
|
internal static Task<bool> Initialize(bool silent = false)
|
|
{
|
|
#if UNITY_EDITOR
|
|
// We assume that if both package lock files exist then the installation was successful
|
|
var lock1 = InstallDirectory + "/node_modules/.package-lock.json";
|
|
var lock2 = InstallDirectory + "/package-lock.json";
|
|
if (File.Exists(lock1) && File.Exists(lock2))
|
|
{
|
|
// on the main thread we can check if the didInitialize bool is true
|
|
if (UnityThreads.IsMainThread())
|
|
{
|
|
if (didInitialize) return EnsureDependencies();
|
|
}
|
|
// if we have any files in the node_modules directory then we assume that the installation was successful
|
|
else if (Directory.EnumerateDirectories(InstallDirectory).Any())
|
|
{
|
|
return EnsureDependencies();
|
|
}
|
|
}
|
|
|
|
if (initializationTask != null)
|
|
{
|
|
NeedleDebug.Log(TracingScenario.NetworkRequests, "Initialization task... Status=" + initializationTask.Status);
|
|
if (initializationTask.Status == TaskStatus.RanToCompletion && initializationTask.Result && File.Exists(InstallDirectory + "/node_modules/.package-lock.json"))
|
|
return initializationTask;
|
|
if (initializationTask.Status != TaskStatus.RanToCompletion)
|
|
return initializationTask;
|
|
}
|
|
|
|
if (!silent)
|
|
{
|
|
Debug.Log("Initializing Needle Engine Tools...".LowContrast());
|
|
}
|
|
|
|
try
|
|
{
|
|
var t = CreateToolsPackage().ContinueWith(r =>
|
|
{
|
|
didInitialize = r.Result;
|
|
return r.Result;
|
|
}, TaskScheduler.FromCurrentSynchronizationContext());
|
|
initializationTask = t;
|
|
return t;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogError("Failed to initialize Needle Engine Tools: " + ex);
|
|
if (EditorUtility.DisplayDialog("Tools Initialization Failed",
|
|
"Needle Engine Tools failed to initialize because of \"" + ex.Message +
|
|
"\"\n\nDo you want to try again?", "Yes try again", "No"))
|
|
{
|
|
return Initialize(silent);
|
|
}
|
|
return Task.FromResult(false);
|
|
}
|
|
#else
|
|
return Task.FromResult(false);
|
|
#endif
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
private static bool didInitialize
|
|
{
|
|
get => SessionState.GetBool("NPMToolsDidInitialize", false);
|
|
set => SessionState.SetBool("NPMToolsDidInitialize", value);
|
|
}
|
|
|
|
private static Task<bool> initializationTask;
|
|
|
|
private static async Task<bool> CreateToolsPackage(int iteration = 0)
|
|
{
|
|
Directory.CreateDirectory(InstallDirectory);
|
|
if (!File.Exists(PackageJsonPath))
|
|
{
|
|
File.WriteAllText(PackageJsonPath, "{}");
|
|
}
|
|
|
|
var logFilePath = InstallDirectory + "/npm.log";
|
|
var json = File.ReadAllText(PackageJsonPath);
|
|
var obj = JObject.Parse(json);
|
|
obj["name"] = "@needle-tools/editor-tools";
|
|
obj["version"] = ProjectInfo.GetCurrentPackageVersion(Constants.UnityPackageName, out _) ?? "1.0.0";
|
|
obj["description"] =
|
|
$"Npm Tools generated by {Constants.UnityPackageName}@{ProjectInfo.GetCurrentPackageVersion(Constants.UnityPackageName, out _)}";
|
|
File.WriteAllText(PackageJsonPath, obj.ToString());
|
|
var lockPath = InstallDirectory + "/package-lock.json";
|
|
if (File.Exists(lockPath)) File.Delete(lockPath);
|
|
var res = await EnsureDependencies();
|
|
// if this fails for some reason we try it again once more
|
|
if(!res && iteration < 1)
|
|
{
|
|
await Task.Delay(1000);
|
|
await FileUtils.DeleteDirectoryRecursive(InstallDirectory);
|
|
return await CreateToolsPackage(iteration + 1);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
private static Task<bool> EnsureDependencies()
|
|
{
|
|
var json = File.ReadAllText(PackageJsonPath);
|
|
var obj = JObject.Parse(json);
|
|
var deps = obj.TryGetValue("dependencies", out var _deps) ? (JObject) _deps : new JObject();
|
|
var changed = false;
|
|
changed |= AddDependency(Constants.GltfBuildPipelineNpmPackageName, deps);
|
|
changed |= AddDependency(Constants.ToolsNpmPackageName, deps);
|
|
changed |= AddDependency(Constants.ComponentCompilerNpmPackageName, deps, "^1.0.0-pre");
|
|
if (changed)
|
|
{
|
|
obj["dependencies"] = deps;
|
|
File.WriteAllText(PackageJsonPath, obj.ToString());
|
|
var logFilePath = Application.dataPath + "/../Logs/Needle-npm-install.log";
|
|
var cmd = "npm set registry https://registry.npmjs.org && npm update && " + NpmUtils.GetInstallCommand(InstallDirectory);
|
|
return ProcessHelper.RunCommand(cmd, InstallDirectory, logFilePath, true, false, -1);
|
|
}
|
|
return Task.FromResult(true);
|
|
}
|
|
|
|
private static bool AddDependency(string packageName, JObject deps, string defaultVersion = "latest")
|
|
{
|
|
var existing = deps[packageName];
|
|
var recommended = NpmUnityEditorVersions.TryGetRecommendedVersion(packageName, defaultVersion);
|
|
if (existing == null)
|
|
{
|
|
deps.Add(packageName, NpmUnityEditorVersions.TryGetRecommendedVersion(packageName, defaultVersion));
|
|
return true;
|
|
}
|
|
if (recommended != existing.ToString())
|
|
{
|
|
deps[packageName] = recommended;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
} |