first commit

This commit is contained in:
Kirill Chikalin
2024-11-16 13:20:07 +03:00
commit a3072a3693
538 changed files with 108153 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
using UnityEditor;
using UnityEngine;
namespace AssetStoreTools.Utility
{
internal static class ASDebug
{
private enum LogType
{
Log,
Warning,
Error
}
private static bool s_debugModeEnabled = EditorPrefs.GetBool("ASTDebugMode");
public static bool DebugModeEnabled
{
get => s_debugModeEnabled;
set
{
s_debugModeEnabled = value;
EditorPrefs.SetBool("ASTDebugMode", value);
}
}
public static void Log(object message)
{
LogMessage(message, LogType.Log);
}
public static void LogWarning(object message)
{
LogMessage(message, LogType.Warning);
}
public static void LogError(object message)
{
LogMessage(message, LogType.Error);
}
private static void LogMessage(object message, LogType type)
{
if (!DebugModeEnabled)
return;
switch (type)
{
case LogType.Log:
Debug.Log(message);
break;
case LogType.Warning:
Debug.LogWarning(message);
break;
case LogType.Error:
Debug.LogError(message);
break;
default:
Debug.Log(message);
break;
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 478caa497d99100429a0509fa487bfe4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs
uploadId: 681981

View File

@@ -0,0 +1,93 @@
using System;
using System.Net;
using System.Net.Http;
namespace AssetStoreTools.Utility
{
/// <summary>
/// A structure for retrieving and converting errors from Asset Store Tools class methods
/// </summary>
internal class ASError
{
public string Message { get; private set; }
public Exception Exception { get; private set; }
public ASError() { }
public static ASError GetGenericError(Exception ex)
{
ASError error = new ASError()
{
Message = ex.Message,
Exception = ex
};
return error;
}
public static ASError GetLoginError(HttpResponseMessage response) => GetLoginError(response, null);
public static ASError GetLoginError(HttpResponseMessage response, HttpRequestException ex)
{
ASError error = new ASError() { Exception = ex };
switch (response.StatusCode)
{
// Add common error codes here
case HttpStatusCode.Unauthorized:
error.Message = "Incorrect email and/or password. Please try again.";
break;
case HttpStatusCode.InternalServerError:
error.Message = "Authentication request failed\nIf you were logging in with your Unity Cloud account, please make sure you are still logged in.\n" +
"This might also be caused by too many invalid login attempts - if that is the case, please try again later.";
break;
default:
ParseHtmlMessage(response, out string message);
error.Message = message;
break;
}
return error;
}
public static ASError GetPublisherNullError(string publisherName)
{
ASError error = new ASError
{
Message = $"Your Unity ID {publisherName} is not currently connected to a publisher account. " +
$"Please create a publisher profile."
};
return error;
}
private static bool ParseHtmlMessage(HttpResponseMessage response, out string message)
{
message = "An undefined error has been encountered";
string html = response.Content.ReadAsStringAsync().Result;
if (!html.Contains("<!DOCTYPE HTML"))
return false;
message += " with the following message:\n\n";
var startIndex = html.IndexOf("<p>", StringComparison.Ordinal) + "<p>".Length;
var endIndex = html.IndexOf("</p>", StringComparison.Ordinal);
if (startIndex == -1 || endIndex == -1)
return false;
string htmlBodyMessage = html.Substring(startIndex, (endIndex - startIndex));
htmlBodyMessage = htmlBodyMessage.Replace("\n", " ");
message += htmlBodyMessage;
message += "\n\nIf this error message is not very informative, please report this to Unity";
return true;
}
public override string ToString()
{
return Message;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 265ad6f65404f8c42aec35d3b8e6f970
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/ASError.cs
uploadId: 681981

View File

@@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace AssetStoreTools.Utility
{
internal class ASToolsPreferences
{
private static ASToolsPreferences s_instance;
public static ASToolsPreferences Instance => s_instance ?? (s_instance = new ASToolsPreferences());
public static event Action OnSettingsChange;
private ASToolsPreferences()
{
Load();
}
private void Load()
{
CheckForUpdates = PlayerPrefs.GetInt("AST_CheckForUpdates", 1) == 1;
LegacyVersionCheck = PlayerPrefs.GetInt("AST_LegacyVersionCheck", 1) == 1;
UploadVersionCheck = PlayerPrefs.GetInt("AST_UploadVersionCheck", 1) == 1;
DisplayHiddenMetaDialog = PlayerPrefs.GetInt("AST_HiddenFolderMetaCheck", 1) == 1;
EnableSymlinkSupport = PlayerPrefs.GetInt("AST_EnableSymlinkSupport", 0) == 1;
UseLegacyExporting = PlayerPrefs.GetInt("AST_UseLegacyExporting", 0) == 1;
DisplayUploadDialog = PlayerPrefs.GetInt("AST_DisplayUploadDialog", 0) == 1;
}
public void Save(bool triggerSettingsChange = false)
{
PlayerPrefs.SetInt("AST_CheckForUpdates", CheckForUpdates ? 1 : 0);
PlayerPrefs.SetInt("AST_LegacyVersionCheck", LegacyVersionCheck ? 1 : 0);
PlayerPrefs.SetInt("AST_UploadVersionCheck", UploadVersionCheck ? 1 : 0);
PlayerPrefs.SetInt("AST_HiddenFolderMetaCheck", DisplayHiddenMetaDialog ? 1 : 0);
PlayerPrefs.SetInt("AST_EnableSymlinkSupport", EnableSymlinkSupport ? 1 : 0);
PlayerPrefs.SetInt("AST_UseLegacyExporting", UseLegacyExporting ? 1 : 0);
PlayerPrefs.SetInt("AST_DisplayUploadDialog", DisplayUploadDialog ? 1 : 0);
PlayerPrefs.Save();
if(triggerSettingsChange)
OnSettingsChange?.Invoke();
}
/// <summary>
/// Periodically check if an update for the Asset Store Publishing Tools is available
/// </summary>
public bool CheckForUpdates;
/// <summary>
/// Check if legacy Asset Store Tools are in the Project
/// </summary>
public bool LegacyVersionCheck;
/// <summary>
/// Check if the package has been uploader from a correct Unity version at least once
/// </summary>
public bool UploadVersionCheck;
/// <summary>
/// Enables a DisplayDialog when hidden folders are found to be missing meta files
/// </summary>
public bool DisplayHiddenMetaDialog;
/// <summary>
/// Enables Junction symlink support
/// </summary>
public bool EnableSymlinkSupport;
/// <summary>
/// Enables legacy exporting for Folder Upload workflow
/// </summary>
public bool UseLegacyExporting;
/// <summary>
/// Enables DisplayDialog to be shown after the uploading ends
/// </summary>
public bool DisplayUploadDialog;
}
internal class ASToolsPreferencesProvider : SettingsProvider
{
private const string SettingsPath = "Project/Asset Store Tools";
private class Styles
{
public static readonly GUIContent CheckForUpdatesLabel = EditorGUIUtility.TrTextContent("Check for Updates", "Periodically check if an update for the Asset Store Publishing Tools is available.");
public static readonly GUIContent LegacyVersionCheckLabel = EditorGUIUtility.TrTextContent("Legacy ASTools Check", "Enable Legacy Asset Store Tools version checking.");
public static readonly GUIContent UploadVersionCheckLabel = EditorGUIUtility.TrTextContent("Upload Version Check", "Check if the package has been uploader from a correct Unity version at least once.");
public static readonly GUIContent DisplayHiddenMetaDialogLabel = EditorGUIUtility.TrTextContent("Display Hidden Folder Meta Dialog", "Show a DisplayDialog when hidden folders are found to be missing meta files.\nNote: this only affects hidden folders ending with a '~' character");
public static readonly GUIContent EnableSymlinkSupportLabel = EditorGUIUtility.TrTextContent("Enable Symlink Support", "Enable Junction Symlink support. Note: folder selection validation will take longer.");
public static readonly GUIContent UseLegacyExportingLabel = EditorGUIUtility.TrTextContent("Use Legacy Exporting", "Enabling this option uses native Unity methods when exporting packages for the Folder Upload workflow.\nNote: individual package dependency selection when choosing to 'Include Package Manifest' is unavailable when this option is enabled.");
public static readonly GUIContent DisplayUploadDialogLabel = EditorGUIUtility.TrTextContent("Display Upload Dialog", "Show a DisplayDialog after the package uploading has finished.");
}
public static void OpenSettings()
{
SettingsService.OpenProjectSettings(SettingsPath);
}
private ASToolsPreferencesProvider(string path, SettingsScope scopes, IEnumerable<string> keywords = null)
: base(path, scopes, keywords) { }
public override void OnGUI(string searchContext)
{
var preferences = ASToolsPreferences.Instance;
EditorGUI.BeginChangeCheck();
using (CreateSettingsWindowGUIScope())
{
preferences.CheckForUpdates = EditorGUILayout.Toggle(Styles.CheckForUpdatesLabel, preferences.CheckForUpdates);
preferences.LegacyVersionCheck = EditorGUILayout.Toggle(Styles.LegacyVersionCheckLabel, preferences.LegacyVersionCheck);
preferences.UploadVersionCheck = EditorGUILayout.Toggle(Styles.UploadVersionCheckLabel, preferences.UploadVersionCheck);
preferences.DisplayHiddenMetaDialog = EditorGUILayout.Toggle(Styles.DisplayHiddenMetaDialogLabel, preferences.DisplayHiddenMetaDialog);
preferences.EnableSymlinkSupport = EditorGUILayout.Toggle(Styles.EnableSymlinkSupportLabel, preferences.EnableSymlinkSupport);
preferences.UseLegacyExporting = EditorGUILayout.Toggle(Styles.UseLegacyExportingLabel, preferences.UseLegacyExporting);
preferences.DisplayUploadDialog = EditorGUILayout.Toggle(Styles.DisplayUploadDialogLabel, preferences.DisplayUploadDialog);
}
if (EditorGUI.EndChangeCheck())
ASToolsPreferences.Instance.Save(true);
}
[SettingsProvider]
public static SettingsProvider CreateAssetStoreToolsSettingProvider()
{
var provider = new ASToolsPreferencesProvider(SettingsPath, SettingsScope.Project, GetSearchKeywordsFromGUIContentProperties<Styles>());
return provider;
}
private IDisposable CreateSettingsWindowGUIScope()
{
var unityEditorAssembly = Assembly.GetAssembly(typeof(EditorWindow));
var type = unityEditorAssembly.GetType("UnityEditor.SettingsWindow+GUIScope");
return Activator.CreateInstance(type) as IDisposable;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: b75179c8d22a35b42a543d6fa7857ce0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs
uploadId: 681981

View File

@@ -0,0 +1,251 @@
using AssetStoreTools.Uploader;
using System;
using System.Linq;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace AssetStoreTools.Utility
{
[InitializeOnLoad]
internal class ASToolsUpdater : AssetStoreToolsWindow
{
private const string AssetStoreToolsUrl = "https://assetstore.unity.com/packages/tools/utilities/asset-store-publishing-tools-115";
protected override string WindowTitle => "Asset Store Tools Update Check";
private VisualElement _loadingContainer;
private VisualElement _versionInfoContainer;
private Image _loadingImage;
private double _lastTimeSinceStartup;
private double _timeSinceLoadingImageChange;
private int _loadingImageIndex;
private static bool _updateCheckPerformed
{
get
{
return SessionState.GetBool("AST_UpdateChecked", false);
}
set
{
SessionState.SetBool("AST_UpdateChecked", value);
}
}
static ASToolsUpdater()
{
// Retrieving cached SessionState/PlayerPrefs values is not allowed from an instance field initializer
EditorApplication.update += CheckForUpdatesAfterEditorUpdate;
}
private static async void CheckForUpdatesAfterEditorUpdate()
{
EditorApplication.update -= CheckForUpdatesAfterEditorUpdate;
if (!ShouldCheckForUpdates())
return;
await CheckForUpdates((success, currentVersion, latestVersion) =>
{
if (success && currentVersion < latestVersion)
{
AssetStoreTools.OpenUpdateChecker();
}
});
}
private static bool ShouldCheckForUpdates()
{
if (!ASToolsPreferences.Instance.CheckForUpdates)
return false;
return _updateCheckPerformed == false;
}
private static async Task CheckForUpdates(Action<bool, Version, Version> OnUpdatesChecked)
{
_updateCheckPerformed = true;
var latestVersionResult = await AssetStoreAPI.GetLatestAssetStoreToolsVersion();
if (!latestVersionResult.Success)
{
OnUpdatesChecked?.Invoke(false, null, null);
return;
}
Version currentVersion = null;
Version latestVersion = null;
try
{
var latestVersionStr = latestVersionResult.Response["version"].AsString();
var currentVersionStr = PackageUtility.GetAllPackages().FirstOrDefault(x => x.name == "com.unity.asset-store-tools").version;
currentVersion = new Version(currentVersionStr);
latestVersion = new Version(latestVersionStr);
}
catch
{
OnUpdatesChecked?.Invoke(false, null, null);
}
OnUpdatesChecked?.Invoke(true, currentVersion, latestVersion);
}
protected override void Init()
{
base.Init();
rootVisualElement.styleSheets.Add(StyleSelector.UpdaterWindow.UpdaterWindowStyle);
rootVisualElement.styleSheets.Add(StyleSelector.UpdaterWindow.UpdaterWindowTheme);
SetupLoadingSpinner();
_ = CheckForUpdates(OnVersionsRetrieved);
}
private void OnVersionsRetrieved(bool success, Version currentVersion, Version latestVersion)
{
if (_loadingContainer != null)
_loadingContainer.style.display = DisplayStyle.None;
if (success)
{
SetupVersionInfo(currentVersion, latestVersion);
}
else
{
SetupFailInfo();
}
}
private void SetupLoadingSpinner()
{
_loadingContainer = new VisualElement();
_loadingContainer.AddToClassList("loading-container");
_loadingImage = new Image();
EditorApplication.update += LoadingSpinLoop;
_loadingContainer.Add(_loadingImage);
rootVisualElement.Add(_loadingContainer);
}
private void SetupVersionInfo(Version currentVersion, Version latestVersion)
{
_versionInfoContainer = new VisualElement();
_versionInfoContainer.AddToClassList("version-info-container");
AddDescriptionLabels(currentVersion, latestVersion);
AddUpdateButtons(currentVersion, latestVersion);
AddCheckForUpdatesToggle();
rootVisualElement.Add(_versionInfoContainer);
}
private void AddDescriptionLabels(Version currentVersion, Version latestVersion)
{
var descriptionText = currentVersion < latestVersion ?
"An update to the Asset Store Publishing Tools is available. Updating to the latest version is highly recommended." :
"Asset Store Publishing Tools are up to date!";
var labelContainer = new VisualElement();
labelContainer.AddToClassList("version-info-container-labels");
var descriptionLabel = new Label(descriptionText);
descriptionLabel.AddToClassList("version-info-container-labels-description");
var currentVersionRow = new VisualElement();
currentVersionRow.AddToClassList("version-info-container-labels-row");
var latestVersionRow = new VisualElement();
latestVersionRow.AddToClassList("version-info-container-labels-row");
var currentVersionLabel = new Label("Current version:");
currentVersionLabel.AddToClassList("version-info-container-labels-row-identifier");
var latestVersionLabel = new Label("Latest version:");
latestVersionLabel.AddToClassList("version-info-container-labels-row-identifier");
var currentVersionLabelValue = new Label(currentVersion.ToString());
var latestVersionLabelValue = new Label(latestVersion.ToString());
currentVersionRow.Add(currentVersionLabel);
currentVersionRow.Add(currentVersionLabelValue);
latestVersionRow.Add(latestVersionLabel);
latestVersionRow.Add(latestVersionLabelValue);
labelContainer.Add(descriptionLabel);
labelContainer.Add(currentVersionRow);
labelContainer.Add(latestVersionRow);
_versionInfoContainer.Add(labelContainer);
}
private void AddUpdateButtons(Version currentVersion, Version latestVersion)
{
if (currentVersion >= latestVersion)
return;
var buttonContainer = new VisualElement();
buttonContainer.AddToClassList("version-info-container-buttons");
var latestVersionButton = new Button(() => Application.OpenURL(AssetStoreToolsUrl)) { text = "Get the latest version" };
var skipVersionButton = new Button(Close) { text = "Skip for now" };
buttonContainer.Add(latestVersionButton);
buttonContainer.Add(skipVersionButton);
_versionInfoContainer.Add(buttonContainer);
}
private void AddCheckForUpdatesToggle()
{
var toggleContainer = new VisualElement();
toggleContainer.AddToClassList("version-info-container-toggle");
var checkForUpdatesToggle = new Toggle() { text = "Check for Updates", value = ASToolsPreferences.Instance.CheckForUpdates };
checkForUpdatesToggle.RegisterValueChangedCallback(OnCheckForUpdatesToggleChanged);
toggleContainer.Add(checkForUpdatesToggle);
_versionInfoContainer.Add(toggleContainer);
}
private void OnCheckForUpdatesToggleChanged(ChangeEvent<bool> evt)
{
ASToolsPreferences.Instance.CheckForUpdates = evt.newValue;
ASToolsPreferences.Instance.Save();
}
private void SetupFailInfo()
{
var failContainer = new VisualElement();
failContainer.AddToClassList("fail-container");
var failImage = new Image();
var failDescription = new Label("Asset Store Publishing Tools could not retrieve information about the latest version.");
failContainer.Add(failImage);
failContainer.Add(failDescription);
rootVisualElement.Add(failContainer);
}
private void LoadingSpinLoop()
{
var currentTimeSinceStartup = EditorApplication.timeSinceStartup;
var deltaTime = EditorApplication.timeSinceStartup - _lastTimeSinceStartup;
_lastTimeSinceStartup = currentTimeSinceStartup;
_timeSinceLoadingImageChange += deltaTime;
if (_timeSinceLoadingImageChange < 0.075)
return;
_timeSinceLoadingImageChange = 0;
_loadingImage.image = EditorGUIUtility.IconContent($"WaitSpin{_loadingImageIndex++:00}").image;
if (_loadingImageIndex > 11)
_loadingImageIndex = 0;
}
private void OnDestroy()
{
EditorApplication.update -= LoadingSpinLoop;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 2ac370b9d2279ed4c9faec7134ba2759
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsUpdater.cs
uploadId: 681981

View File

@@ -0,0 +1,139 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
namespace AssetStoreTools.Utility
{
internal static class FileUtility
{
private class RenameInfo
{
public string OriginalName;
public string CurrentName;
}
public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive)
{
// Get information about the source directory
var dir = new DirectoryInfo(sourceDir);
// Check if the source directory exists
if (!dir.Exists)
throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
// Cache directories before we start copying
DirectoryInfo[] dirs = dir.GetDirectories();
// Create the destination directory
Directory.CreateDirectory(destinationDir);
// Get the files in the source directory and copy to the destination directory
foreach (FileInfo file in dir.GetFiles())
{
string targetFilePath = Path.Combine(destinationDir, file.Name);
file.CopyTo(targetFilePath);
}
// If recursive and copying subdirectories, recursively call this method
if (recursive)
{
foreach (DirectoryInfo subDir in dirs)
{
string newDestinationDir = Path.Combine(destinationDir, subDir.Name);
CopyDirectory(subDir.FullName, newDestinationDir, true);
}
}
}
public static bool IsMissingMetaFiles(params string[] sourcePaths)
{
foreach (var sourcePath in sourcePaths)
{
var allDirectories = Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories);
foreach (var dir in allDirectories)
{
var dirInfo = new DirectoryInfo(dir);
if (dirInfo.Name.EndsWith("~"))
{
var nestedContent = dirInfo.GetFileSystemInfos("*", SearchOption.AllDirectories);
foreach (var nested in nestedContent)
{
// .meta files, hidden files and OSX .DS_STORE files do not require their own metas
if (nested.FullName.EndsWith(".meta")
|| nested.FullName.EndsWith("~")
|| nested.Name.Equals(".DS_Store"))
continue;
if (!File.Exists(nested.FullName + ".meta"))
return true;
}
}
}
}
return false;
}
public static void GenerateMetaFiles(params string[] sourcePaths)
{
var renameInfos = new List<RenameInfo>();
foreach (var sourcePath in sourcePaths)
{
var hiddenDirectoriesInPath = Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories).Where(x => x.EndsWith("~"));
foreach (var hiddenDir in hiddenDirectoriesInPath)
renameInfos.Add(new RenameInfo() { CurrentName = hiddenDir, OriginalName = hiddenDir });
}
try
{
EditorApplication.LockReloadAssemblies();
// Order paths from longest to shortest to avoid having to rename them multiple times
renameInfos = renameInfos.OrderByDescending(x => x.OriginalName.Length).ToList();
try
{
AssetDatabase.StartAssetEditing();
foreach (var renameInfo in renameInfos)
{
renameInfo.CurrentName = renameInfo.OriginalName.TrimEnd('~');
Directory.Move(renameInfo.OriginalName, renameInfo.CurrentName);
}
}
finally
{
AssetDatabase.StopAssetEditing();
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
}
// Restore the original path names in reverse order
renameInfos = renameInfos.OrderBy(x => x.OriginalName.Length).ToList();
try
{
AssetDatabase.StartAssetEditing();
foreach (var renameInfo in renameInfos)
{
Directory.Move(renameInfo.CurrentName, renameInfo.OriginalName);
if (File.Exists($"{renameInfo.CurrentName}.meta"))
File.Delete($"{renameInfo.CurrentName}.meta");
}
}
finally
{
AssetDatabase.StopAssetEditing();
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
}
}
finally
{
EditorApplication.UnlockReloadAssemblies();
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 80819cf6868374d478a8a38ebaba8e27
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs
uploadId: 681981

View File

@@ -0,0 +1,772 @@
/*
* Simple recursive descending JSON parser and
* JSON string builder.
*
* Jonas Drewsen - (C) Unity3d.com - 2010-2012
*
* JSONParser parser = new JSONParser(" { \"hello\" : 42.3 } ");
* JSONValue value = parser.Parse();
*
* bool is_it_float = value.isFloat();
* float the_float = value.asFloat();
* string the_string = value.Get("sub.structure.access").asString();
*
*/
using System.Collections.Generic;
using System;
namespace AssetStoreTools.Utility.Json
{
/*
* JSON value structure
*
* Example:
* JSONValue v = JSONValue.NewDict();
* v["hello"] = JSONValue.NewString("world");
* asset(v["hello"].AsString() == "world");
*
*/
internal struct JsonValue
{
public JsonValue(object o)
{
data = o;
}
public static implicit operator JsonValue(string s)
{
return new JsonValue(s);
}
public static implicit operator string(JsonValue s)
{
return s.AsString();
}
public static implicit operator JsonValue(float s)
{
return new JsonValue(s);
}
public static implicit operator float(JsonValue s)
{
return s.AsFloat();
}
public static implicit operator JsonValue(bool s)
{
return new JsonValue(s);
}
public static implicit operator bool(JsonValue s)
{
return s.AsBool();
}
public static implicit operator JsonValue(int s)
{
return new JsonValue((float)s);
}
public static implicit operator int(JsonValue s)
{
return (int)s.AsFloat();
}
public static implicit operator JsonValue(List<JsonValue> s)
{
return new JsonValue(s);
}
public static implicit operator List<JsonValue>(JsonValue s)
{
return s.AsList();
}
public static implicit operator Dictionary<string, JsonValue>(JsonValue s)
{
return s.AsDict();
}
public bool IsString() { return data is string; }
public bool IsFloat() { return data is float; }
public bool IsList() { return data is List<JsonValue>; }
public bool IsDict() { return data is Dictionary<string, JsonValue>; }
public bool IsBool() { return data is bool; }
public bool IsNull() { return data == null; }
public string AsString(bool nothrow = false)
{
if (data is string)
return (string)data;
if (!nothrow)
throw new JSONTypeException("Tried to read non-string json value as string");
return "";
}
public float AsFloat(bool nothrow = false)
{
if (data is float)
return (float)data;
if (!nothrow)
throw new JSONTypeException("Tried to read non-float json value as float");
return 0.0f;
}
public bool AsBool(bool nothrow = false)
{
if (data is bool)
return (bool)data;
if (!nothrow)
throw new JSONTypeException("Tried to read non-bool json value as bool");
return false;
}
public List<JsonValue> AsList(bool nothrow = false)
{
if (data is List<JsonValue>)
return (List<JsonValue>)data;
if (!nothrow)
throw new JSONTypeException("Tried to read " + data.GetType().Name + " json value as list");
return null;
}
public Dictionary<string, JsonValue> AsDict(bool nothrow = false)
{
if (data is Dictionary<string, JsonValue>)
return (Dictionary<string, JsonValue>)data;
if (!nothrow)
throw new JSONTypeException("Tried to read non-dictionary json value as dictionary");
return null;
}
public static JsonValue NewString(string val)
{
return new JsonValue(val);
}
public static JsonValue NewFloat(float val)
{
return new JsonValue(val);
}
public static JsonValue NewDict()
{
return new JsonValue(new Dictionary<string, JsonValue>());
}
public static JsonValue NewList()
{
return new JsonValue(new List<JsonValue>());
}
public static JsonValue NewBool(bool val)
{
return new JsonValue(val);
}
public static JsonValue NewNull()
{
return new JsonValue(null);
}
public JsonValue InitList()
{
data = new List<JsonValue>();
return this;
}
public JsonValue InitDict()
{
data = new Dictionary<string, JsonValue>();
return this;
}
public JsonValue this[string index]
{
get
{
Dictionary<string, JsonValue> dict = AsDict();
return dict[index];
}
set
{
if (data == null)
data = new Dictionary<string, JsonValue>();
Dictionary<string, JsonValue> dict = AsDict();
dict[index] = value;
}
}
public bool ContainsKey(string index)
{
if (!IsDict())
return false;
return AsDict().ContainsKey(index);
}
// Get the specified field in a dict or null json value if
// no such field exists. The key can point to a nested structure
// e.g. key1.key2 in { key1 : { key2 : 32 } }
public JsonValue Get(string key, out bool found)
{
found = false;
if (!IsDict())
return new JsonValue(null);
JsonValue value = this;
foreach (string part in key.Split('.'))
{
if (!value.ContainsKey(part))
return new JsonValue(null);
value = value[part];
}
found = true;
return value;
}
public JsonValue Get(string key)
{
bool found;
return Get(key, out found);
}
public bool Copy(string key, ref string dest)
{
return Copy(key, ref dest, true);
}
public bool Copy(string key, ref string dest, bool allowCopyNull)
{
bool found;
JsonValue jv = Get(key, out found);
if (found && (!jv.IsNull() || allowCopyNull))
dest = jv.IsNull() ? null : jv.AsString();
return found;
}
public bool Copy(string key, ref bool dest)
{
bool found;
JsonValue jv = Get(key, out found);
if (found && !jv.IsNull())
dest = jv.AsBool();
return found;
}
public bool Copy(string key, ref int dest)
{
bool found;
JsonValue jv = Get(key, out found);
if (found && !jv.IsNull())
dest = (int)jv.AsFloat();
return found;
}
// Convenience dict value setting
public void Set(string key, string value)
{
Set(key, value, true);
}
public void Set(string key, string value, bool allowNull)
{
if (value == null)
{
if (!allowNull)
return;
this[key] = NewNull();
return;
}
this[key] = NewString(value);
}
// Convenience dict value setting
public void Set(string key, float value)
{
this[key] = NewFloat(value);
}
// Convenience dict value setting
public void Set(string key, bool value)
{
this[key] = NewBool(value);
}
// Convenience list value add
public void Add(string value)
{
List<JsonValue> list = AsList();
if (value == null)
{
list.Add(NewNull());
return;
}
list.Add(NewString(value));
}
// Convenience list value add
public void Add(float value)
{
List<JsonValue> list = AsList();
list.Add(NewFloat(value));
}
// Convenience list value add
public void Add(bool value)
{
List<JsonValue> list = AsList();
list.Add(NewBool(value));
}
public override string ToString()
{
return ToString(null, "");
}
/*
* Serialize a JSON value to string.
* This will recurse down through dicts and list type JSONValues.
*/
public string ToString(string curIndent, string indent)
{
bool indenting = curIndent != null;
if (IsString())
{
return "\"" + EncodeString(AsString()) + "\"";
}
else if (IsFloat())
{
return AsFloat().ToString();
}
else if (IsList())
{
string res = "[";
string delim = "";
foreach (JsonValue i in AsList())
{
res += delim + i.ToString();
delim = ", ";
}
return res + "]";
}
else if (IsDict())
{
string res = "{" + (indenting ? "\n" : "");
string delim = "";
foreach (KeyValuePair<string, JsonValue> kv in AsDict())
{
res += delim + curIndent + indent + '"' + EncodeString(kv.Key) + "\" : " + kv.Value.ToString(curIndent + indent, indent);
delim = ", " + (indenting ? "\n" : "");
}
return res + (indenting ? "\n" + curIndent : "") + "}";
}
else if (IsBool())
{
return AsBool() ? "true" : "false";
}
else if (IsNull())
{
return "null";
}
else
{
throw new JSONTypeException("Cannot serialize json value of unknown type");
}
}
// Encode a string into a json string
private static string EncodeString(string str)
{
str = str.Replace("\\", "\\\\");
str = str.Replace("\"", "\\\"");
str = str.Replace("/", "\\/");
str = str.Replace("\b", "\\b");
str = str.Replace("\f", "\\f");
str = str.Replace("\n", "\\n");
str = str.Replace("\r", "\\r");
str = str.Replace("\t", "\\t");
// We do not use \uXXXX specifier but direct unicode in the string.
return str;
}
object data;
}
internal class JSONParseException : Exception
{
public JSONParseException(string msg) : base(msg)
{
}
}
internal class JSONTypeException : Exception
{
public JSONTypeException(string msg) : base(msg)
{
}
}
/*
* Top down recursive JSON parser
*
* Example:
* string json = "{ \"hello\" : \"world\", \"age\" : 100000, "sister" : null }";
* JSONValue val = JSONParser.SimpleParse(json);
* asset( val["hello"].AsString() == "world" );
*
*/
internal class JSONParser
{
private string json;
private int line;
private int linechar;
private int len;
private int idx;
private int pctParsed;
private char cur;
public static JsonValue SimpleParse(string jsondata)
{
var parser = new JSONParser(jsondata);
try
{
return parser.Parse();
}
catch (JSONParseException ex)
{
Console.WriteLine(ex.Message);
//DebugUtils.LogError(ex.Message);
}
return new JsonValue(null);
}
public static bool AssetStoreResponseParse(string responseJson, out ASError error, out JsonValue jval)
{
jval = new JsonValue();
error = null;
try
{
JSONParser parser = new JSONParser(responseJson);
jval = parser.Parse();
}
catch (JSONParseException)
{
error = ASError.GetGenericError(new Exception("Error parsing reply from AssetStore"));
return false;
}
// Some json responses return an error field on error
if (jval.ContainsKey("error"))
{
// Server side error message
// Do not write to console since this is an error that
// is "expected" ie. can be handled by the gui.
error = ASError.GetGenericError(new Exception(jval["error"].AsString(true)));
}
// Some json responses return status+message fields instead of an error field. Go figure.
else if (jval.ContainsKey("status") && jval["status"].AsString(true) != "ok")
{
error = ASError.GetGenericError(new Exception(jval["message"].AsString(true)));
}
return error == null;
}
/*
* Setup a parse to be ready for parsing the given string
*/
public JSONParser(string jsondata)
{
// TODO: fix that parser needs trailing spaces;
json = jsondata + " ";
line = 1;
linechar = 1;
len = json.Length;
idx = 0;
pctParsed = 0;
}
/*
* Parse the entire json data string into a JSONValue structure hierarchy
*/
public JsonValue Parse()
{
cur = json[idx];
return ParseValue();
}
private char Next()
{
if (cur == '\n')
{
line++;
linechar = 0;
}
idx++;
if (idx >= len)
throw new JSONParseException("End of json while parsing at " + PosMsg());
linechar++;
int newPct = (int)((float)idx * 100f / (float)len);
if (newPct != pctParsed)
{
pctParsed = newPct;
}
cur = json[idx];
return cur;
}
private void SkipWs()
{
const string ws = " \n\t\r";
while (ws.IndexOf(cur) != -1) Next();
}
private string PosMsg()
{
return "line " + line.ToString() + ", column " + linechar.ToString();
}
private JsonValue ParseValue()
{
// Skip spaces
SkipWs();
switch (cur)
{
case '[':
return ParseArray();
case '{':
return ParseDict();
case '"':
return ParseString();
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return ParseNumber();
case 't':
case 'f':
case 'n':
return ParseConstant();
default:
throw new JSONParseException("Cannot parse json value starting with '" + json.Substring(idx, 5) + "' at " + PosMsg());
}
}
private JsonValue ParseArray()
{
Next();
SkipWs();
List<JsonValue> arr = new List<JsonValue>();
while (cur != ']')
{
arr.Add(ParseValue());
SkipWs();
if (cur == ',')
{
Next();
SkipWs();
}
}
Next();
return new JsonValue(arr);
}
private JsonValue ParseDict()
{
Next();
SkipWs();
Dictionary<string, JsonValue> dict = new Dictionary<string, JsonValue>();
while (cur != '}')
{
JsonValue key = ParseValue();
if (!key.IsString())
throw new JSONParseException("Key not string type at " + PosMsg());
SkipWs();
if (cur != ':')
throw new JSONParseException("Missing dict entry delimiter ':' at " + PosMsg());
Next();
dict.Add(key.AsString(), ParseValue());
SkipWs();
if (cur == ',')
{
Next();
SkipWs();
}
}
Next();
return new JsonValue(dict);
}
static char[] endcodes = { '\\', '"' };
private JsonValue ParseString()
{
string res = "";
Next();
while (idx < len)
{
int endidx = json.IndexOfAny(endcodes, idx);
if (endidx < 0)
throw new JSONParseException("missing '\"' to end string at " + PosMsg());
res += json.Substring(idx, endidx - idx);
if (json[endidx] == '"')
{
cur = json[endidx];
idx = endidx;
break;
}
endidx++; // get escape code
if (endidx >= len)
throw new JSONParseException("End of json while parsing while parsing string at " + PosMsg());
// char at endidx is \
char ncur = json[endidx];
switch (ncur)
{
case '"':
goto case '/';
case '\\':
goto case '/';
case '/':
res += ncur;
break;
case 'b':
res += '\b';
break;
case 'f':
res += '\f';
break;
case 'n':
res += '\n';
break;
case 'r':
res += '\r';
break;
case 't':
res += '\t';
break;
case 'u':
// Unicode char specified by 4 hex digits
string digit = "";
if (endidx + 4 >= len)
throw new JSONParseException("End of json while parsing while parsing unicode char near " + PosMsg());
digit += json[endidx + 1];
digit += json[endidx + 2];
digit += json[endidx + 3];
digit += json[endidx + 4];
try
{
int d = Int32.Parse(digit, System.Globalization.NumberStyles.AllowHexSpecifier);
res += (char)d;
}
catch (FormatException)
{
throw new JSONParseException("Invalid unicode escape char near " + PosMsg());
}
endidx += 4;
break;
default:
throw new JSONParseException("Invalid escape char '" + ncur + "' near " + PosMsg());
}
idx = endidx + 1;
}
if (idx >= len)
throw new JSONParseException("End of json while parsing while parsing string near " + PosMsg());
cur = json[idx];
Next();
return new JsonValue(res);
}
private JsonValue ParseNumber()
{
string resstr = "";
if (cur == '-')
{
resstr = "-";
Next();
}
while (cur >= '0' && cur <= '9')
{
resstr += cur;
Next();
}
if (cur == '.')
{
Next();
resstr += '.';
while (cur >= '0' && cur <= '9')
{
resstr += cur;
Next();
}
}
if (cur == 'e' || cur == 'E')
{
resstr += "e";
Next();
if (cur != '-' && cur != '+')
{
// throw new JSONParseException("Missing - or + in 'e' potent specifier at " + PosMsg());
resstr += cur;
Next();
}
while (cur >= '0' && cur <= '9')
{
resstr += cur;
Next();
}
}
try
{
float f = Convert.ToSingle(resstr);
return new JsonValue(f);
}
catch (Exception)
{
throw new JSONParseException("Cannot convert string to float : '" + resstr + "' at " + PosMsg());
}
}
private JsonValue ParseConstant()
{
string c = "" + cur + Next() + Next() + Next();
Next();
if (c == "true")
{
return new JsonValue(true);
}
else if (c == "fals")
{
if (cur == 'e')
{
Next();
return new JsonValue(false);
}
}
else if (c == "null")
{
return new JsonValue(null);
}
throw new JSONParseException("Invalid token at " + PosMsg());
}
};
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 1
guid: 0a7878c3076bf174ea5c0a1cf7bd3a39
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/Json.cs
uploadId: 681981

View File

@@ -0,0 +1,86 @@
using System;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace AssetStoreTools.Utility
{
[InitializeOnLoad]
internal class LegacyToolsRemover
{
private const string MessagePart1 = "A legacy version of Asset Store Tools " +
"was detected at the following path:\n";
private const string MessagePart2 = "\n\nHaving both the legacy and the latest version installed at the same time is not supported " +
"and might prevent the latest version from functioning properly.\n\nWould you like the legacy version to be removed automatically?";
static LegacyToolsRemover()
{
try
{
if (Application.isBatchMode)
return;
CheckAndRemoveLegacyTools();
}
catch { }
}
private static void CheckAndRemoveLegacyTools()
{
if (!ASToolsPreferences.Instance.LegacyVersionCheck || !ProjectContainsLegacyTools(out string path))
return;
var relativePath = path.Substring(Application.dataPath.Length - "Assets".Length).Replace("\\", "/");
var result = EditorUtility.DisplayDialog("Asset Store Tools", MessagePart1 + relativePath + MessagePart2, "Yes", "No");
// If "No" - do nothing
if (!result)
return;
// If "Yes" - remove legacy tools
File.Delete(path);
File.Delete(path + ".meta");
RemoveEmptyFolders(Path.GetDirectoryName(path)?.Replace("\\", "/"));
AssetDatabase.Refresh();
// We could also optionally prevent future execution here
// but the ProjectContainsLegacyTools() function runs in less
// than a milisecond on an empty project
}
private static bool ProjectContainsLegacyTools(out string path)
{
path = null;
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
if (assembly.ManifestModule.Name == "AssetStoreTools.dll")
{
path = assembly.Location;
break;
}
}
if (string.IsNullOrEmpty(path))
return false;
return true;
}
private static void RemoveEmptyFolders(string directory)
{
if (directory.EndsWith(Application.dataPath))
return;
if (Directory.GetFiles(directory).Length == 0 && Directory.GetDirectories(directory).Length == 0)
{
var parentPath = Path.GetDirectoryName(directory).Replace("\\", "/");
Directory.Delete(directory);
File.Delete(directory + ".meta");
RemoveEmptyFolders(parentPath);
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 46ead42026b1f0b4e94153e1a7e10d12
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs
uploadId: 681981

View File

@@ -0,0 +1,58 @@
#if UNITY_2019 || UNITY_2020
using System;
using System.Reflection;
#endif
using UnityEngine;
using UnityEditor.PackageManager;
using System.Linq;
namespace AssetStoreTools.Utility
{
internal static class PackageUtility
{
/// <summary>
/// Returns the package path on disk. If the path is within the root
/// project folder, the returned path will be relative to the root project folder.
/// Otherwise, an absolute path is returned
/// </summary>
public static string GetConvenientPath(this PackageInfo packageInfo)
{
var path = packageInfo.resolvedPath.Replace("\\", "/");
var rootProjectPath = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length);
if (path.StartsWith(rootProjectPath))
path = path.Substring(rootProjectPath.Length);
return path;
}
public static PackageInfo[] GetAllPackages()
{
#if UNITY_2019 || UNITY_2020
var method = typeof(PackageInfo).GetMethod("GetAll", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, null, new Type[0], null);
var packages = method?.Invoke(null, null) as PackageInfo[];
#else
var packages = PackageInfo.GetAllRegisteredPackages();
#endif
return packages;
}
public static PackageInfo[] GetAllLocalPackages()
{
var packages = GetAllPackages();
var localPackages = packages.Where(x => x.source == PackageSource.Embedded || x.source == PackageSource.Local)
.Where(x => x.isDirectDependency).ToArray();
return localPackages;
}
public static PackageInfo[] GetAllRegistryPackages()
{
var packages = GetAllPackages();
var registryPackages = packages.Where(x => x.source == PackageSource.Registry || x.source == PackageSource.BuiltIn)
.OrderBy(x => string.Compare(x.type, "module", System.StringComparison.OrdinalIgnoreCase) == 0)
.ThenBy(x => x.name).ToArray();
return registryPackages;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 605ea62f8b11d674a95a53f895df4c67
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs
uploadId: 681981

View File

@@ -0,0 +1,58 @@
using UnityEditor;
using UnityEngine.UIElements;
namespace AssetStoreTools.Utility
{
internal static class StyleSelector
{
private static StyleSheet GetStylesheet(string stylesheetPath)
{
return AssetDatabase.LoadAssetAtPath<StyleSheet>(stylesheetPath);
}
public static class UploaderWindow
{
private const string StylesPath = "Packages/com.unity.asset-store-tools/Editor/Uploader/Styles";
public static StyleSheet BaseWindowStyle => GetStylesheet($"{StylesPath}/Base/BaseWindow_Main.uss");
public static StyleSheet BaseWindowTheme => !EditorGUIUtility.isProSkin ?
GetStylesheet($"{StylesPath}/Base/BaseWindow_Light.uss") :
GetStylesheet($"{StylesPath}/Base/BaseWindow_Dark.uss");
public static StyleSheet LoginWindowStyle => GetStylesheet($"{StylesPath}/Login/Login_Main.uss");
public static StyleSheet LoginWindowTheme => !EditorGUIUtility.isProSkin ?
GetStylesheet($"{StylesPath}/Login/Login_Light.uss") :
GetStylesheet($"{StylesPath}/Login/Login_Dark.uss");
public static StyleSheet UploadWindowStyle => GetStylesheet($"{StylesPath}/Upload/UploadWindow_Main.uss");
public static StyleSheet UploadWindowTheme => !EditorGUIUtility.isProSkin ?
GetStylesheet($"{StylesPath}/Upload/UploadWindow_Light.uss") :
GetStylesheet($"{StylesPath}/Upload/UploadWindow_Dark.uss");
public static StyleSheet AllPackagesStyle => GetStylesheet($"{StylesPath}/Upload/AllPackages/AllPackages_Main.uss");
public static StyleSheet AllPackagesTheme => !EditorGUIUtility.isProSkin ?
GetStylesheet($"{StylesPath}/Upload/AllPackages/AllPackages_Light.uss") :
GetStylesheet($"{StylesPath}/Upload/AllPackages/AllPackages_Dark.uss");
}
public static class ValidatorWindow
{
private const string StylesPath = "Packages/com.unity.asset-store-tools/Editor/Validator/Styles";
public static StyleSheet ValidatorWindowStyle => GetStylesheet($"{StylesPath}/Validator_Main.uss");
public static StyleSheet ValidatorWindowTheme => !EditorGUIUtility.isProSkin ?
GetStylesheet($"{StylesPath}/Validator_Light.uss") :
GetStylesheet($"{StylesPath}/Validator_Dark.uss");
}
public static class UpdaterWindow
{
private const string StylesPath = "Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater";
public static StyleSheet UpdaterWindowStyle => GetStylesheet($"{StylesPath}/Updater_Main.uss");
public static StyleSheet UpdaterWindowTheme => !EditorGUIUtility.isProSkin ?
GetStylesheet($"{StylesPath}/Updater_Light.uss") :
GetStylesheet($"{StylesPath}/Updater_Dark.uss");
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 8b066ce502a289a4ca311a86fbf83f45
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs
uploadId: 681981

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f730eb0b8c48c434d93cc60a0b8aff40
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5367435d9abe935438f4d7b588a55488
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
.loading-container > VisualElement > Image {
--unity-image: resource("d_WaitSpin00");
}
.fail-container > Image {
--unity-image: resource("console.erroricon@2x");
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 225786b34a57ee440b0c1b213902214a
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/Updater_Dark.uss
uploadId: 681981

View File

@@ -0,0 +1,7 @@
.loading-container > VisualElement > Image {
--unity-image: resource("WaitSpin00");
}
.fail-container > Image {
--unity-image: resource("console.erroricon@2x");
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 8cdc065c428afe14c96781ac6fd73d73
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/Updater_Light.uss
uploadId: 681981

View File

@@ -0,0 +1,76 @@
.loading-container {
flex-grow: 1;
align-items: center;
justify-content: center;
}
.loading-container > Image {
width: 16px;
height: 16px;
}
.version-info-container {
flex-grow: 1;
margin: 0 5px 5px 5px;
}
.version-info-container-labels {
flex-grow: 1;
margin-bottom: 10px;
margin-top: 5px;
}
.version-info-container-labels-description {
flex-grow: 0.5;
margin-bottom: 5px;
white-space: normal;
-unity-text-align: middle-left;
}
.version-info-container-labels-row {
flex-direction: row;
}
.version-info-container-labels-row-identifier {
-unity-font-style: bold;
}
.version-info-container-buttons {
flex-direction: row;
margin-bottom: 5px;
}
.version-info-container-buttons > Button {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 100%;
height: 25px;
}
.version-info-container-toggle {
align-self: flex-end;
}
.version-info-container-toggle > Toggle > VisualElement > Label {
margin-left: 5px;
}
.fail-container {
flex-grow: 1;
flex-direction: row;
margin: 0 5px 5px 5px;
justify-content: center;
align-items: center;
}
.fail-container > Image {
flex-shrink: 0;
width: 36px;
height: 36px;
margin-right: 5px;
}
.fail-container > Label {
flex-shrink: 1;
white-space: normal;
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: daf82dcb916f6ae498d03a6a127122c6
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/Updater_Main.uss
uploadId: 681981

View File

@@ -0,0 +1,67 @@
using System.IO;
namespace AssetStoreTools.Utility
{
internal static class SymlinkUtil
{
private const FileAttributes FolderSymlinkAttributes = FileAttributes.Directory | FileAttributes.ReparsePoint;
public static bool FindSymlinkFolderRelative(string folderPathAbsolute, out string relativePath)
{
// Get directory info for path outside of the project
var absoluteInfo = new DirectoryInfo(folderPathAbsolute);
// Get all directories within the project
var allFolderPaths = Directory.GetDirectories("Assets", "*", SearchOption.AllDirectories);
foreach (var path in allFolderPaths)
{
var fullPath = path.Replace("\\", "/");
// Get directory info for one of the paths within the project
var relativeInfo = new DirectoryInfo(fullPath);
// Check if project's directory is a symlink
if (!relativeInfo.Attributes.HasFlag(FolderSymlinkAttributes))
continue;
// Compare metadata of outside directory with a directories within the project
if (!CompareDirectories(absoluteInfo, relativeInfo))
continue;
// Found symlink within the project, assign it
relativePath = fullPath;
return true;
}
relativePath = string.Empty;
return false;
}
private static bool CompareDirectories(DirectoryInfo directory, DirectoryInfo directory2)
{
var contents = directory.EnumerateFileSystemInfos("*", SearchOption.AllDirectories).GetEnumerator();
var contents2 = directory2.EnumerateFileSystemInfos("*", SearchOption.AllDirectories).GetEnumerator();
while (true)
{
var firstNext = contents.MoveNext();
var secondNext = contents2.MoveNext();
if (firstNext != secondNext)
return false;
if (!firstNext && !secondNext)
break;
var equals = contents.Current?.Name == contents2.Current?.Name
&& contents.Current?.LastWriteTime == contents2.Current?.LastWriteTime;
if (!equals)
return false;
}
return true;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 92092535fd064bb1843017f98db213e1
timeCreated: 1659013521
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 11.4.3
assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs
uploadId: 681981