update libs
This commit is contained in:
@@ -0,0 +1,304 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using AssetStoreTools.Utility;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using CacheConstants = AssetStoreTools.Constants.Cache;
|
||||
|
||||
namespace AssetStoreTools.Exporter
|
||||
{
|
||||
internal class DefaultPackageExporter : PackageExporterBase
|
||||
{
|
||||
private const string TemporaryExportPathName = "CustomExport";
|
||||
|
||||
private DefaultExporterSettings _defaultExportSettings;
|
||||
|
||||
public DefaultPackageExporter(DefaultExporterSettings settings) : base(settings)
|
||||
{
|
||||
_defaultExportSettings = settings;
|
||||
}
|
||||
|
||||
protected override void ValidateSettings()
|
||||
{
|
||||
base.ValidateSettings();
|
||||
|
||||
if (_defaultExportSettings.ExportPaths == null || _defaultExportSettings.ExportPaths.Length == 0)
|
||||
throw new ArgumentException("Export paths array cannot be empty");
|
||||
}
|
||||
|
||||
protected override async Task<PackageExporterResult> ExportImpl()
|
||||
{
|
||||
return await this.Export();
|
||||
}
|
||||
|
||||
private new async Task<PackageExporterResult> Export()
|
||||
{
|
||||
ASDebug.Log("Using custom package exporter");
|
||||
|
||||
// Save assets before exporting
|
||||
EditorUtility.DisplayProgressBar(ProgressBarTitle, ProgressBarStepSavingAssets, 0.1f);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
try
|
||||
{
|
||||
// Create a temporary export path
|
||||
PostExportCleanup();
|
||||
var temporaryExportPath = GetTemporaryExportPath();
|
||||
if (!Directory.Exists(temporaryExportPath))
|
||||
Directory.CreateDirectory(temporaryExportPath);
|
||||
|
||||
// Construct an unzipped package structure
|
||||
CreateTempPackageStructure(temporaryExportPath);
|
||||
|
||||
var previewGenerationResult = await GeneratePreviews();
|
||||
InjectPreviews(previewGenerationResult, temporaryExportPath);
|
||||
|
||||
// Build a .unitypackage file from the temporary folder
|
||||
CreateUnityPackage(temporaryExportPath, _defaultExportSettings.OutputFilename);
|
||||
|
||||
EditorUtility.RevealInFinder(_defaultExportSettings.OutputFilename);
|
||||
|
||||
ASDebug.Log($"Package file has been created at {_defaultExportSettings.OutputFilename}");
|
||||
return new PackageExporterResult() { Success = true, ExportedPath = _defaultExportSettings.OutputFilename, PreviewGenerationResult = previewGenerationResult };
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return new PackageExporterResult() { Success = false, Exception = e };
|
||||
}
|
||||
finally
|
||||
{
|
||||
PostExportCleanup();
|
||||
}
|
||||
}
|
||||
|
||||
private string GetTemporaryExportPath()
|
||||
{
|
||||
return $"{CacheConstants.TempCachePath}/{TemporaryExportPathName}";
|
||||
}
|
||||
|
||||
private void CreateTempPackageStructure(string tempOutputPath)
|
||||
{
|
||||
EditorUtility.DisplayProgressBar(ProgressBarTitle, ProgressBarStepGatheringFiles, 0.4f);
|
||||
var pathGuidPairs = GetPathGuidPairs(_defaultExportSettings.ExportPaths);
|
||||
|
||||
foreach (var pair in pathGuidPairs)
|
||||
{
|
||||
var originalAssetPath = pair.Key;
|
||||
var outputAssetPath = $"{tempOutputPath}/{pair.Value}";
|
||||
|
||||
if (Directory.Exists(outputAssetPath))
|
||||
{
|
||||
var path1 = File.ReadAllText($"{outputAssetPath}/pathname");
|
||||
var path2 = originalAssetPath;
|
||||
throw new InvalidOperationException($"Multiple assets with guid {pair.Value} have been detected " +
|
||||
$"when exporting the package. Please resolve the guid conflicts and try again:\n{path1}\n{path2}");
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(outputAssetPath);
|
||||
|
||||
// Every exported asset has a pathname file
|
||||
using (StreamWriter writer = new StreamWriter($"{outputAssetPath}/pathname"))
|
||||
writer.Write(originalAssetPath);
|
||||
|
||||
// Only files (not folders) have an asset file
|
||||
if (File.Exists(originalAssetPath))
|
||||
File.Copy(originalAssetPath, $"{outputAssetPath}/asset");
|
||||
|
||||
// Most files and folders have an asset.meta file (but ProjectSettings folder assets do not)
|
||||
if (File.Exists($"{originalAssetPath}.meta"))
|
||||
File.Copy($"{originalAssetPath}.meta", $"{outputAssetPath}/asset.meta");
|
||||
|
||||
// To-do: handle previews in hidden folders as they are not part of the AssetDatabase
|
||||
var previewObject = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(originalAssetPath);
|
||||
if (previewObject == null)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_defaultExportSettings.Dependencies == null || _defaultExportSettings.Dependencies.Length == 0)
|
||||
return;
|
||||
|
||||
var exportDependenciesDict = new JObject();
|
||||
var allRegistryPackages = PackageUtility.GetAllRegistryPackages();
|
||||
|
||||
foreach (var exportDependency in _defaultExportSettings.Dependencies)
|
||||
{
|
||||
var registryPackage = allRegistryPackages.FirstOrDefault(x => x.name == exportDependency);
|
||||
if (registryPackage == null)
|
||||
{
|
||||
// Package is either not from a registry source or does not exist in the project
|
||||
UnityEngine.Debug.LogWarning($"Found an unsupported Package Manager dependency: {exportDependency}.\n" +
|
||||
"This dependency is not supported in the project's manifest.json and will be skipped.");
|
||||
continue;
|
||||
}
|
||||
|
||||
exportDependenciesDict[registryPackage.name] = registryPackage.version;
|
||||
}
|
||||
|
||||
if (exportDependenciesDict.Count == 0)
|
||||
return;
|
||||
|
||||
var exportManifestJson = new JObject();
|
||||
exportManifestJson["dependencies"] = exportDependenciesDict;
|
||||
|
||||
var tempManifestDirectoryPath = $"{tempOutputPath}/packagemanagermanifest";
|
||||
Directory.CreateDirectory(tempManifestDirectoryPath);
|
||||
var tempManifestFilePath = $"{tempManifestDirectoryPath}/asset";
|
||||
|
||||
File.WriteAllText(tempManifestFilePath, exportManifestJson.ToString());
|
||||
}
|
||||
|
||||
private Dictionary<string, string> GetPathGuidPairs(string[] exportPaths)
|
||||
{
|
||||
var pathGuidPairs = new Dictionary<string, string>();
|
||||
|
||||
foreach (var exportPath in exportPaths)
|
||||
{
|
||||
var assetPaths = GetAssetPaths(exportPath);
|
||||
|
||||
foreach (var assetPath in assetPaths)
|
||||
{
|
||||
var guid = GetAssetGuid(assetPath, true, true);
|
||||
if (string.IsNullOrEmpty(guid))
|
||||
continue;
|
||||
|
||||
pathGuidPairs.Add(assetPath, guid);
|
||||
}
|
||||
}
|
||||
|
||||
return pathGuidPairs;
|
||||
}
|
||||
|
||||
private async Task<PreviewGenerationResult> GeneratePreviews()
|
||||
{
|
||||
if (_defaultExportSettings.PreviewGenerator == null)
|
||||
return null;
|
||||
|
||||
void ReportProgress(float progress)
|
||||
{
|
||||
EditorUtility.DisplayProgressBar(ProgressBarTitle, ProgressBarStepGeneratingPreviews, progress);
|
||||
}
|
||||
|
||||
_defaultExportSettings.PreviewGenerator.OnProgressChanged += ReportProgress;
|
||||
var result = await _defaultExportSettings.PreviewGenerator.Generate();
|
||||
_defaultExportSettings.PreviewGenerator.OnProgressChanged -= ReportProgress;
|
||||
EditorUtility.ClearProgressBar();
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning($"An error was encountered while generating previews. Exported package may be missing previews.\n{result.Exception}");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void InjectPreviews(PreviewGenerationResult result, string temporaryExportPath)
|
||||
{
|
||||
if (result == null || !result.Success)
|
||||
return;
|
||||
|
||||
var injector = new PreviewInjector(result);
|
||||
injector.Inject(temporaryExportPath);
|
||||
}
|
||||
|
||||
private void CreateUnityPackage(string pathToArchive, string outputPath)
|
||||
{
|
||||
if (Directory.GetDirectories(pathToArchive).Length == 0)
|
||||
throw new InvalidOperationException("Unable to export package. The specified path is empty");
|
||||
|
||||
EditorUtility.DisplayProgressBar(ProgressBarTitle, ProgressBarStepCompressingPackage, 0.8f);
|
||||
|
||||
// Archiving process working path will be set to the
|
||||
// temporary package path so adjust the output path accordingly
|
||||
if (!Path.IsPathRooted(outputPath))
|
||||
outputPath = $"{Application.dataPath.Substring(0, Application.dataPath.Length - "/Assets".Length)}/{outputPath}";
|
||||
|
||||
#if UNITY_EDITOR_WIN
|
||||
CreateUnityPackageUniversal(pathToArchive, outputPath);
|
||||
#elif UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
|
||||
CreateUnityPackageOsxLinux(pathToArchive, outputPath);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void CreateUnityPackageUniversal(string pathToArchive, string outputPath)
|
||||
{
|
||||
var _7zPath = EditorApplication.applicationContentsPath;
|
||||
#if UNITY_EDITOR_WIN
|
||||
_7zPath = Path.Combine(_7zPath, "Tools", "7z.exe");
|
||||
#elif UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
|
||||
_7zPath = Path.Combine(_7zPath, "Tools", "7za");
|
||||
#endif
|
||||
if (!File.Exists(_7zPath))
|
||||
throw new FileNotFoundException("Archiving utility was not found in your Unity installation directory");
|
||||
|
||||
var argumentsTar = $"a -r -ttar -y -bd archtemp.tar .";
|
||||
var result = StartProcess(_7zPath, argumentsTar, pathToArchive);
|
||||
if (result != 0)
|
||||
throw new Exception("Failed to compress the package");
|
||||
|
||||
// Create a GZIP archive
|
||||
var argumentsGzip = $"a -tgzip -bd -y \"{outputPath}\" archtemp.tar";
|
||||
result = StartProcess(_7zPath, argumentsGzip, pathToArchive);
|
||||
if (result != 0)
|
||||
throw new Exception("Failed to compress the package");
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
|
||||
private void CreateUnityPackageOsxLinux(string pathToArchive, string outputPath)
|
||||
{
|
||||
var tarPath = "/usr/bin/tar";
|
||||
|
||||
if (!File.Exists(tarPath))
|
||||
{
|
||||
// Fallback to the universal export method
|
||||
ASDebug.LogWarning("'/usr/bin/tar' executable not found. Falling back to 7za");
|
||||
CreateUnityPackageUniversal(pathToArchive, outputPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a TAR archive
|
||||
var arguments = $"-czpf \"{outputPath}\" .";
|
||||
var result = StartProcess(tarPath, arguments, pathToArchive);
|
||||
if (result != 0)
|
||||
throw new Exception("Failed to compress the package");
|
||||
}
|
||||
#endif
|
||||
|
||||
private int StartProcess(string processPath, string arguments, string workingDirectory)
|
||||
{
|
||||
var info = new ProcessStartInfo()
|
||||
{
|
||||
FileName = processPath,
|
||||
Arguments = arguments,
|
||||
WorkingDirectory = workingDirectory,
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false
|
||||
};
|
||||
|
||||
#if UNITY_EDITOR_OSX
|
||||
// Prevent OSX-specific archive pollution
|
||||
info.EnvironmentVariables.Add("COPYFILE_DISABLE", "1");
|
||||
#endif
|
||||
|
||||
using (Process process = Process.Start(info))
|
||||
{
|
||||
process.WaitForExit();
|
||||
return process.ExitCode;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void PostExportCleanup()
|
||||
{
|
||||
base.PostExportCleanup();
|
||||
|
||||
var tempExportPath = GetTemporaryExportPath();
|
||||
if (Directory.Exists(tempExportPath))
|
||||
Directory.Delete(tempExportPath, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user