update libs

This commit is contained in:
Kirill Chikalin
2025-02-13 17:48:12 +03:00
parent e17e7c2786
commit 275dc598c7
816 changed files with 22479 additions and 10792 deletions

View File

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

View File

@@ -0,0 +1,170 @@
using AssetStoreTools.Uploader.Data;
using AssetStoreTools.Validator.Data;
using System.Linq;
using UnityEditor;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal abstract class ValidationElementBase : VisualElement
{
// Data
protected IWorkflow Workflow;
// UI
protected VisualElement ResultsBox;
protected Image ResultsBoxImage;
protected Label ResultsBoxLabel;
protected ValidationElementBase(IWorkflow workflow)
{
Workflow = workflow;
Create();
}
private void Create()
{
CreateInfoRow();
CreateResultsBox();
}
private void CreateInfoRow()
{
VisualElement validatorButtonRow = new VisualElement();
validatorButtonRow.AddToClassList("package-content-option-box");
VisualElement validatorLabelHelpRow = new VisualElement();
validatorLabelHelpRow.AddToClassList("package-content-option-label-help-row");
Label validatorLabel = new Label { text = "Validation" };
Image validatorLabelTooltip = new Image
{
tooltip = "You can use the Asset Store Validator to check your package for common publishing issues"
};
var validateButton = new Button(Validate) { name = "ValidateButton", text = "Validate" };
validatorLabelHelpRow.Add(validatorLabel);
validatorLabelHelpRow.Add(validatorLabelTooltip);
validatorButtonRow.Add(validatorLabelHelpRow);
validatorButtonRow.Add(validateButton);
Add(validatorButtonRow);
}
private void CreateResultsBox()
{
ResultsBox = new Box { name = "InfoBox" };
ResultsBox.style.display = DisplayStyle.None;
ResultsBox.AddToClassList("validation-result-box");
ResultsBoxImage = new Image();
ResultsBoxLabel = new Label { name = "ValidationLabel" };
ResultsBox.Add(ResultsBoxImage);
ResultsBox.Add(ResultsBoxLabel);
Add(ResultsBox);
}
protected virtual bool ConfirmValidation()
{
// Child classes can implement pre-validation prompts
return true;
}
private void Validate()
{
if (!ConfirmValidation())
return;
var validationResult = Workflow.Validate();
if (validationResult.Status == ValidationStatus.Cancelled)
return;
if (validationResult.Status != ValidationStatus.RanToCompletion)
{
EditorUtility.DisplayDialog("Validation failed", $"Package validation failed: {validationResult.Exception.Message}", "OK");
return;
}
DisplayResult(validationResult);
}
private void DisplayResult(ValidationResult result)
{
ResultsBox.style.display = DisplayStyle.Flex;
UpdateValidationResultImage(result);
UpdateValidationResultLabel(result);
}
public void HideResult()
{
ResultsBox.style.display = DisplayStyle.None;
}
protected void UpdateValidationResultImage(ValidationResult result)
{
switch (GetValidationSummaryStatus(result))
{
case TestResultStatus.Pass:
ResultsBoxImage.image = EditorGUIUtility.IconContent("console.infoicon@2x").image;
break;
case TestResultStatus.Warning:
ResultsBoxImage.image = EditorGUIUtility.IconContent("console.warnicon@2x").image;
break;
case TestResultStatus.Fail:
ResultsBoxImage.image = EditorGUIUtility.IconContent("console.erroricon@2x").image;
break;
default:
ResultsBoxImage.image = EditorGUIUtility.IconContent("_Help@2x").image;
break;
}
}
private void UpdateValidationResultLabel(ValidationResult result)
{
var errorCount = result.Tests.Where(x => x.Result.Status == TestResultStatus.Fail).Count();
var warningCount = result.Tests.Where(x => x.Result.Status == TestResultStatus.Warning).Count();
string text = string.Empty;
if (result.HadCompilationErrors)
{
text += "- Package caused compilation errors\n";
}
if (errorCount > 0)
{
text += $"- Validation reported {errorCount} error(s)\n";
}
if (warningCount > 0)
{
text += $"- Validation reported {warningCount} warning(s)\n";
}
if (string.IsNullOrEmpty(text))
{
text = "No issues were found!";
}
else
{
text = text.Substring(0, text.Length - "\n".Length);
}
ResultsBoxLabel.text = text;
}
private TestResultStatus GetValidationSummaryStatus(ValidationResult result)
{
if (result.HadCompilationErrors ||
result.Tests.Any(x => x.Result.Status == TestResultStatus.Fail))
return TestResultStatus.Fail;
if (result.Tests.Any(x => x.Result.Status == TestResultStatus.Warning))
return TestResultStatus.Warning;
return TestResultStatus.Pass;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: cb20404763eac7144b562c18ad1c37fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/ValidationElementBase.cs
uploadId: 724584

View File

@@ -0,0 +1,151 @@
using AssetStoreTools.Uploader.Data;
using AssetStoreTools.Utility;
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal abstract class WorkflowElementBase : VisualElement
{
// Data
protected IWorkflow Workflow;
public string Name => Workflow.Name;
public string DisplayName => Workflow.DisplayName;
// UI Elements that all workflows have
protected PathSelectionElement PathSelectionElement;
protected PreviewGenerationElement PreviewGenerationElement;
protected ValidationElementBase ValidationElement;
protected PackageUploadElement UploadElement;
public event Action OnInteractionAvailable;
public event Action OnInteractionUnavailable;
public WorkflowElementBase(IWorkflow workflow)
{
Workflow = workflow;
}
protected void CreatePathElement(string labelText, string labelTooltip)
{
PathSelectionElement = new PathSelectionElement(labelText, labelTooltip);
PathSelectionElement.OnBrowse += BrowsePath;
Add(PathSelectionElement);
}
protected void CreatePreviewGenerationElement()
{
PreviewGenerationElement = new PreviewGenerationElement(Workflow);
PreviewGenerationElement.style.display = DisplayStyle.None;
var callback = new Action(() =>
PreviewGenerationElement.style.display = ASToolsPreferences.Instance.UseLegacyExporting
? DisplayStyle.None
: DisplayStyle.Flex);
RegisterCallback<AttachToPanelEvent>((_) => { ASToolsPreferences.OnSettingsChange += callback; });
RegisterCallback<DetachFromPanelEvent>((_) => { ASToolsPreferences.OnSettingsChange -= callback; });
Add(PreviewGenerationElement);
}
protected void CreateValidationElement(ValidationElementBase validationElement)
{
ValidationElement = validationElement;
ValidationElement.style.display = DisplayStyle.None;
Add(ValidationElement);
}
protected void CreateUploadElement(IWorkflow workflow, bool exposeExportButton)
{
UploadElement = new PackageUploadElement(workflow, exposeExportButton);
UploadElement.OnInteractionAvailable += EnableInteraction;
UploadElement.OnInteractionUnavailable += DisableInteraction;
UploadElement.style.display = DisplayStyle.None;
Add(UploadElement);
}
protected abstract void BrowsePath();
protected void SetPathSelectionTextField(string value)
{
if (string.IsNullOrEmpty(value))
return;
PathSelectionElement.SetPath(value);
ValidationElement.style.display = DisplayStyle.Flex;
UploadElement.style.display = DisplayStyle.Flex;
if (PreviewGenerationElement != null && !ASToolsPreferences.Instance.UseLegacyExporting)
{
PreviewGenerationElement.style.display = DisplayStyle.Flex;
}
}
protected void CheckForMissingMetas(IEnumerable<string> paths)
{
bool displayDialog = ASToolsPreferences.Instance.DisplayHiddenMetaDialog && FileUtility.IsMissingMetaFiles(paths);
if (!displayDialog)
return;
var selectedOption = EditorUtility.DisplayDialogComplex(
"Notice",
"Your package includes hidden folders which do not contain meta files. " +
"Hidden folders will not be exported unless they contain meta files.\n\nWould you like meta files to be generated?",
"Yes", "No", "No and do not display this again");
switch (selectedOption)
{
case 0:
try
{
FileUtility.GenerateMetaFiles(paths);
EditorUtility.DisplayDialog(
"Success",
"Meta files have been generated. Please note that further manual tweaking may be required to set up correct references",
"OK");
}
catch (Exception e)
{
EditorUtility.DisplayDialog(
"Error",
$"Meta file generation failed: {e.Message}",
"OK"
);
}
break;
case 1:
// Do nothing
return;
case 2:
ASToolsPreferences.Instance.DisplayHiddenMetaDialog = false;
ASToolsPreferences.Instance.Save();
return;
}
}
public bool Is(IWorkflow workflow)
{
return Workflow == workflow;
}
protected virtual void EnableInteraction()
{
PathSelectionElement.SetEnabled(true);
ValidationElement.SetEnabled(true);
PreviewGenerationElement?.SetEnabled(true);
UploadElement.SetEnabled(true);
OnInteractionAvailable?.Invoke();
}
protected virtual void DisableInteraction()
{
PathSelectionElement.SetEnabled(false);
ValidationElement.SetEnabled(false);
PreviewGenerationElement?.SetEnabled(false);
UploadElement.SetEnabled(false);
OnInteractionUnavailable?.Invoke();
}
protected abstract void Deserialize();
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 45d1bf267c3ea9048bfdd75d0d19c8bd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/WorkflowElementBase.cs
uploadId: 724584

View File

@@ -0,0 +1,102 @@
using AssetStoreTools.Api.Models;
using System;
using System.Threading.Tasks;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class AccountToolbar : VisualElement
{
private Image _accountImage;
private Label _accountEmailLabel;
private Button _refreshButton;
public event Func<Task> OnRefresh;
public event Action OnLogout;
public AccountToolbar()
{
Create();
}
private void Create()
{
AddToClassList("account-toolbar");
// Left side of the toolbar
VisualElement leftSideContainer = new VisualElement { name = "LeftSideContainer" };
leftSideContainer.AddToClassList("account-toolbar-left-side-container");
_accountImage = new Image();
_accountImage.AddToClassList("account-toolbar-user-image");
_accountEmailLabel = new Label() { name = "AccountEmail" };
_accountEmailLabel.AddToClassList("account-toolbar-email-label");
leftSideContainer.Add(_accountImage);
leftSideContainer.Add(_accountEmailLabel);
// Right side of the toolbar
VisualElement rightSideContainer = new VisualElement { name = "RightSideContainer" };
rightSideContainer.AddToClassList("account-toolbar-right-side-container");
// Refresh button
_refreshButton = new Button(Refresh) { name = "RefreshButton", text = "Refresh" };
_refreshButton.AddToClassList("account-toolbar-button-refresh");
// Logout button
var logoutButton = new Button(Logout) { name = "LogoutButton", text = "Log out" };
logoutButton.AddToClassList("account-toolbar-button-logout");
rightSideContainer.Add(_refreshButton);
rightSideContainer.Add(logoutButton);
// Constructing the final toolbar
Add(leftSideContainer);
Add(rightSideContainer);
}
private async void Refresh()
{
_refreshButton.SetEnabled(false);
await OnRefresh?.Invoke();
_refreshButton.SetEnabled(true);
}
private void Logout()
{
OnLogout?.Invoke();
}
public void SetUser(User user)
{
if (user == null)
{
_accountEmailLabel.text = string.Empty;
_accountImage.tooltip = string.Empty;
return;
}
var userEmail = !string.IsNullOrEmpty(user.Username) ? user.Username : "Unknown";
var publisherName = !string.IsNullOrEmpty(user.Name) ? user.Name : "Unknown";
var publisherId = !string.IsNullOrEmpty(user.PublisherId) ? user.PublisherId : "Unknown";
var userInfo =
$"Username: {userEmail}\n" +
$"Publisher Name: {publisherName}\n" +
$"Publisher ID: {publisherId}";
_accountEmailLabel.text = userEmail;
_accountImage.tooltip = userInfo;
}
public void EnableButtons()
{
_refreshButton.SetEnabled(true);
}
public void DisableButtons()
{
_refreshButton.SetEnabled(false);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 3c275be3817d1684ca1802c2738ac4d9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AccountToolbar.cs
uploadId: 724584

View File

@@ -0,0 +1,215 @@
using AssetStoreTools.Uploader.Data;
using AssetStoreTools.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class AssetsWorkflowElement : WorkflowElementBase
{
// Data
private AssetsWorkflow _workflow;
// UI
private VisualElement _dependenciesToggleElement;
private Toggle _dependenciesToggle;
private MultiToggleSelectionElement _dependenciesElement;
private MultiToggleSelectionElement _specialFoldersElement;
private const string PathSelectionTooltip = "Select the main folder of your package" +
"\n\nAll files and folders of your package should preferably be contained within a single root folder that is named after your package" +
"\n\nExample: 'Assets/[MyPackageName]'" +
"\n\nNote: If your content makes use of special folders that are required to be placed in the root Assets folder (e.g. 'StreamingAssets')," +
" you will be able to include them after selecting the main folder";
public AssetsWorkflowElement(AssetsWorkflow workflow) : base(workflow)
{
_workflow = workflow;
Create();
Deserialize();
}
private void Create()
{
CreatePathElement("Folder path", PathSelectionTooltip);
CreateDependenciesToggleElement();
CreateDependenciesSelectionElement();
CreateSpecialFoldersElement();
CreatePreviewGenerationElement();
CreateValidationElement(new CurrentProjectValidationElement(_workflow));
CreateUploadElement(_workflow, true);
}
private void CreateDependenciesToggleElement()
{
_dependenciesToggleElement = new VisualElement() { name = "Dependencies Toggle" };
_dependenciesToggleElement.AddToClassList("package-content-option-box");
VisualElement dependenciesLabelHelpRow = new VisualElement();
dependenciesLabelHelpRow.AddToClassList("package-content-option-label-help-row");
Label dependenciesLabel = new Label { text = "Dependencies" };
Image dependenciesLabelTooltip = new Image
{
tooltip = "Tick this checkbox if your package content has dependencies on Unity packages from the Package Manager"
};
_dependenciesToggle = new Toggle { name = "DependenciesToggle", text = "Include Package Manifest" };
_dependenciesToggle.AddToClassList("package-content-option-toggle");
var callback = new Action(() => DependencyToggleValueChange(true));
_dependenciesToggle.RegisterValueChangedCallback((_) => DependencyToggleValueChange(true));
RegisterCallback<AttachToPanelEvent>((_) => { ASToolsPreferences.OnSettingsChange += callback; });
RegisterCallback<DetachFromPanelEvent>((_) => { ASToolsPreferences.OnSettingsChange -= callback; });
dependenciesLabelHelpRow.Add(dependenciesLabel);
dependenciesLabelHelpRow.Add(dependenciesLabelTooltip);
_dependenciesToggleElement.Add(dependenciesLabelHelpRow);
_dependenciesToggleElement.Add(_dependenciesToggle);
_dependenciesToggleElement.style.display = DisplayStyle.None;
Add(_dependenciesToggleElement);
}
private void CreateDependenciesSelectionElement()
{
_dependenciesElement = new MultiToggleSelectionElement()
{
DisplayElementLabel = false,
ElementLabel = "Dependencies",
NoSelectionLabel = "No packages match this criteria"
};
var setDependencies = new Action<Dictionary<string, bool>>((dict) => _workflow.SetDependencies(dict.Where(x => x.Value).Select(x => x.Key), true));
_dependenciesElement.OnValuesChanged += setDependencies;
_dependenciesElement.style.display = DisplayStyle.None;
Add(_dependenciesElement);
}
private void CreateSpecialFoldersElement()
{
_specialFoldersElement = new MultiToggleSelectionElement()
{
ElementLabel = "Special Folders",
ElementTooltip = "If your package content relies on Special Folders (e.g. StreamingAssets), please select which of these folders should be included in the package.",
NoSelectionLabel = "No folders match this criteria."
};
var setSpecialFolders = new Action<Dictionary<string, bool>>((dict) => _workflow.SetSpecialFolders(dict.Where(x => x.Value).Select(x => x.Key), true));
_specialFoldersElement.OnValuesChanged += setSpecialFolders;
_specialFoldersElement.style.display = DisplayStyle.None;
Add(_specialFoldersElement);
}
protected override void BrowsePath()
{
string absoluteExportPath = string.Empty;
bool includeAllAssets = false;
if (_workflow.IsCompleteProject)
{
includeAllAssets = EditorUtility.DisplayDialog("Notice",
"Your package draft is set to a category that is treated" +
" as a complete project. Project settings will be included automatically. Would you like everything in the " +
"'Assets' folder to be included?\n\nYou will still be able to change the selected assets before uploading",
"Yes, include all folders and assets",
"No, I'll select what to include manually");
if (includeAllAssets)
absoluteExportPath = Application.dataPath;
}
if (!includeAllAssets)
{
absoluteExportPath = EditorUtility.OpenFolderPanel(
"Select folder to compress into a package", "Assets/", "");
if (string.IsNullOrEmpty(absoluteExportPath))
return;
}
var relativeExportPath = FileUtility.AbsolutePathToRelativePath(absoluteExportPath, ASToolsPreferences.Instance.EnableSymlinkSupport);
if (!_workflow.IsPathValid(relativeExportPath, out var error))
{
EditorUtility.DisplayDialog("Invalid selection", error, "OK");
return;
}
HandlePathSelection(relativeExportPath, true);
CheckForMissingMetas();
}
private void HandlePathSelection(string relativeExportPath, bool serialize)
{
if (string.IsNullOrEmpty(relativeExportPath))
return;
_workflow.SetMainExportPath(relativeExportPath, serialize);
SetPathSelectionTextField(relativeExportPath + "/");
_dependenciesToggleElement.style.display = DisplayStyle.Flex;
UpdateSpecialFoldersElement();
}
private void CheckForMissingMetas()
{
var paths = new List<string>() { _workflow.GetMainExportPath() };
paths.AddRange(_workflow.GetSpecialFolders());
CheckForMissingMetas(paths);
}
private void DependencyToggleValueChange(bool serialize)
{
_workflow.SetIncludeDependencies(_dependenciesToggle.value, serialize);
if (_dependenciesToggle.value && !ASToolsPreferences.Instance.UseLegacyExporting)
{
var allDependencies = _workflow.GetAvailableDependencies();
var selectedDependencies = allDependencies.ToDictionary(x => x, y => _workflow.GetDependencies().Any(x => x.name == y));
_dependenciesElement.Populate(selectedDependencies);
_dependenciesElement.style.display = DisplayStyle.Flex;
}
else
{
_dependenciesElement.style.display = DisplayStyle.None;
}
}
private void UpdateSpecialFoldersElement()
{
var availableSpecialFolders = _workflow.GetAvailableSpecialFolders();
var selectedSpecialFolders = availableSpecialFolders.ToDictionary(x => x, y => _workflow.GetSpecialFolders().Any(x => x == y));
_specialFoldersElement.Populate(selectedSpecialFolders);
_specialFoldersElement.style.display = availableSpecialFolders.Count > 0 ? DisplayStyle.Flex : DisplayStyle.None;
}
protected override void EnableInteraction()
{
base.EnableInteraction();
_dependenciesToggleElement.SetEnabled(true);
_dependenciesElement.SetEnabled(true);
_specialFoldersElement.SetEnabled(true);
}
protected override void DisableInteraction()
{
base.DisableInteraction();
_dependenciesToggleElement.SetEnabled(false);
_dependenciesElement.SetEnabled(false);
_specialFoldersElement.SetEnabled(false);
}
protected override void Deserialize()
{
HandlePathSelection(_workflow.GetMainExportPath(), false);
_dependenciesToggle.SetValueWithoutNotify(_workflow.GetIncludeDependencies());
DependencyToggleValueChange(false);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 1f62ea8ab5c102e4fa574a3dcac7f6fb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AssetsWorkflowElement.cs
uploadId: 724584

View File

@@ -0,0 +1,31 @@
using AssetStoreTools.Uploader.Data;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class CurrentProjectValidationElement : ValidationElementBase
{
public CurrentProjectValidationElement(IWorkflow workflow) : base(workflow)
{
Create();
}
private void Create()
{
CreateResultsBox();
}
private void CreateResultsBox()
{
var _viewReportButton = new Button(ViewReport) { text = "View report" };
_viewReportButton.AddToClassList("validation-result-view-report-button");
ResultsBox.Add(_viewReportButton);
}
private void ViewReport()
{
AssetStoreTools.ShowAssetStoreToolsValidator(Workflow.LastValidationSettings, Workflow.LastValidationResult);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 21a1f13231b167b4c80079a2c1212101
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/CurrentProjectValidationElement.cs
uploadId: 724584

View File

@@ -0,0 +1,92 @@
using AssetStoreTools.Uploader.Data;
using AssetStoreTools.Utility;
using AssetStoreTools.Validator;
using System;
using System.IO;
using UnityEditor;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class ExternalProjectValidationElement : ValidationElementBase
{
private VisualElement _projectButtonContainer;
public ExternalProjectValidationElement(IWorkflow workflow) : base(workflow)
{
Create();
}
private void Create()
{
CreateProjectButtonContainer();
CreateProjectButtons();
}
private void CreateProjectButtonContainer()
{
_projectButtonContainer = new VisualElement();
_projectButtonContainer.AddToClassList("validation-result-view-report-button-container");
ResultsBox.Add(_projectButtonContainer);
}
private void CreateProjectButtons()
{
var openButton = new Button(OpenProject) { text = "Open Project" };
openButton.AddToClassList("validation-result-view-report-button");
var saveButton = new Button(SaveProject) { text = "Save Project" };
saveButton.AddToClassList("validation-result-view-report-button");
_projectButtonContainer.Add(openButton);
_projectButtonContainer.Add(saveButton);
}
private void OpenProject()
{
try
{
EditorUtility.DisplayProgressBar("Waiting...", "Validation project is open. Waiting for it to exit...", 0.4f);
var projectPath = Workflow.LastValidationResult.ProjectPath;
ExternalProjectValidator.OpenExternalValidationProject(projectPath);
}
finally
{
EditorUtility.ClearProgressBar();
}
}
private void SaveProject()
{
try
{
var projectPath = Workflow.LastValidationResult.ProjectPath;
var savePath = EditorUtility.SaveFolderPanel("Select a folder", Environment.GetFolderPath(Environment.SpecialFolder.Desktop), string.Empty);
if (string.IsNullOrEmpty(savePath))
return;
var saveDir = new DirectoryInfo(savePath);
if (!saveDir.Exists || saveDir.GetFileSystemInfos().Length != 0)
{
EditorUtility.DisplayDialog("Saving project failed", "Selected directory must be an empty folder", "OK");
return;
}
EditorUtility.DisplayProgressBar("Saving...", "Saving project...", 0.4f);
FileUtility.CopyDirectory(projectPath, savePath, true);
}
finally
{
EditorUtility.ClearProgressBar();
}
}
protected override bool ConfirmValidation()
{
return EditorUtility.DisplayDialog("Notice", "Pre-exported package validation is performed in a separate temporary project. " +
"It may take some time for the temporary project to be created, which will halt any actions in the current project. " +
"The current project will resume work after the temporary project is exited.\n\nDo you wish to proceed?", "Yes", "No");
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 706f01d53c7eaf04bae07fb36684e31b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/ExternalProjectValidationElement.cs
uploadId: 724584

View File

@@ -0,0 +1,116 @@
using AssetStoreTools.Uploader.Data;
using AssetStoreTools.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class HybridPackageWorkflowElement : WorkflowElementBase
{
// Data
private HybridPackageWorkflow _workflow;
// UI
private MultiToggleSelectionElement _dependenciesElement;
public HybridPackageWorkflowElement(HybridPackageWorkflow workflow) : base(workflow)
{
_workflow = workflow;
Create();
Deserialize();
}
private void Create()
{
CreatePathElement("Package path", "Select a local Package you would like to export and upload to the Store.");
CreateDependenciesElement();
CreatePreviewGenerationElement();
CreateValidationElement(new CurrentProjectValidationElement(_workflow));
CreateUploadElement(_workflow, true);
}
private void CreateDependenciesElement()
{
_dependenciesElement = new MultiToggleSelectionElement()
{
ElementLabel = "Dependencies",
ElementTooltip = "Select which local package dependencies should be included when exporting." +
"\n\nNote that only local or embedded dependencies defined in the package.json can be selected.",
NoSelectionLabel = "No packages match this criteria"
};
var setDependencies = new Action<Dictionary<string, bool>>((dict) => _workflow.SetDependencies(dict.Where(x => x.Value).Select(x => x.Key), true));
_dependenciesElement.OnValuesChanged += setDependencies;
Add(_dependenciesElement);
_dependenciesElement.style.display = DisplayStyle.None;
}
protected override void BrowsePath()
{
var absoluteExportPath = EditorUtility.OpenFilePanel("Select a package.json file", "Packages/", "json");
if (string.IsNullOrEmpty(absoluteExportPath))
return;
if (!_workflow.IsPathValid(absoluteExportPath, out var error))
{
EditorUtility.DisplayDialog("Invalid selection", error, "OK");
return;
}
HandlePathSelection(absoluteExportPath, true);
CheckForMissingMetas();
}
private void HandlePathSelection(string packageManifestPath, bool serialize)
{
if (string.IsNullOrEmpty(packageManifestPath))
return;
_workflow.SetPackage(packageManifestPath, serialize);
var packageFolderPath = _workflow.GetPackage().assetPath;
SetPathSelectionTextField(packageFolderPath + "/");
UpdateDependenciesElement();
}
private void CheckForMissingMetas()
{
var paths = new List<string>() { _workflow.GetPackage().assetPath };
paths.AddRange(_workflow.GetDependencies().Select(x => x.assetPath));
CheckForMissingMetas(paths);
}
private void UpdateDependenciesElement()
{
var availableDependencies = _workflow.GetAvailableDependencies();
var selectedDependencies = availableDependencies.ToDictionary(x => x.name, y => _workflow.GetDependencies().Any(x => x.name == y.name));
_dependenciesElement.Populate(selectedDependencies);
_dependenciesElement.style.display = availableDependencies.Count > 0 ? DisplayStyle.Flex : DisplayStyle.None;
}
protected override void EnableInteraction()
{
base.EnableInteraction();
_dependenciesElement.SetEnabled(true);
}
protected override void DisableInteraction()
{
base.DisableInteraction();
_dependenciesElement.SetEnabled(false);
}
protected override void Deserialize()
{
var package = _workflow.GetPackage();
if (package == null)
return;
HandlePathSelection(AssetDatabase.GetAssetPath(package.GetManifestAsset()), false);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 34cd1e5cbe87bb546937a521bd2bc69c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/HybridPackageWorkflowElement.cs
uploadId: 724584

View File

@@ -0,0 +1,52 @@
using UnityEditor;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class LoadingSpinner : VisualElement
{
// Data
private int _spinIndex;
private double _spinTimer;
private double _spinThreshold = 0.1;
// UI
private Image _spinnerImage;
public LoadingSpinner()
{
AddToClassList("loading-spinner-box");
_spinnerImage = new Image { name = "SpinnerImage" };
_spinnerImage.AddToClassList("loading-spinner-image");
Add(_spinnerImage);
}
public void Show()
{
EditorApplication.update += SpinnerLoop;
style.display = DisplayStyle.Flex;
}
public void Hide()
{
EditorApplication.update -= SpinnerLoop;
style.display = DisplayStyle.None;
}
private void SpinnerLoop()
{
if (_spinTimer + _spinThreshold > EditorApplication.timeSinceStartup)
return;
_spinTimer = EditorApplication.timeSinceStartup;
_spinnerImage.image = EditorGUIUtility.IconContent($"WaitSpin{_spinIndex:00}").image;
_spinIndex += 1;
if (_spinIndex > 11)
_spinIndex = 0;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 7c7cdef91eb9a894091869ca10d9d178
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/LoadingSpinner.cs
uploadId: 724584

View File

@@ -0,0 +1,187 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class MultiToggleSelectionElement : VisualElement
{
// Data
private Dictionary<string, bool> _selections;
private readonly List<string> _selectionFilters = new List<string> { "All", "Selected", "Not Selected" };
private string _activeFilter;
public bool DisplayElementLabel
{
get => _multiToggleSelectionHelpRow.style.visibility == Visibility.Visible;
set { _multiToggleSelectionHelpRow.style.visibility = value ? Visibility.Visible : Visibility.Hidden; }
}
public string ElementLabel { get => _multiToggleSelectionLabel.text; set { _multiToggleSelectionLabel.text = value; } }
public string ElementTooltip { get => _multiToggleSelectionTooltip.tooltip; set { _multiToggleSelectionTooltip.tooltip = value; } }
public string NoSelectionLabel { get => _noSelectionsLabel.text; set { _noSelectionsLabel.text = value; } }
// UI
private VisualElement _multiToggleSelectionHelpRow;
private Label _multiToggleSelectionLabel;
private Image _multiToggleSelectionTooltip;
private ScrollView _selectionTogglesBox;
private Label _noSelectionsLabel;
private ToolbarMenu _filteringDropdown;
public event Action<Dictionary<string, bool>> OnValuesChanged;
public MultiToggleSelectionElement()
{
_activeFilter = _selectionFilters[0];
AddToClassList("package-content-option-box");
Create();
}
private void Create()
{
_multiToggleSelectionHelpRow = new VisualElement();
_multiToggleSelectionHelpRow.AddToClassList("package-content-option-label-help-row");
_multiToggleSelectionLabel = new Label();
_multiToggleSelectionTooltip = new Image();
VisualElement fullSelectionBox = new VisualElement();
fullSelectionBox.AddToClassList("multi-toggle-box");
_selectionTogglesBox = new ScrollView { name = "DependencyToggles" };
_selectionTogglesBox.AddToClassList("multi-toggle-box-scrollview");
_noSelectionsLabel = new Label();
_noSelectionsLabel.AddToClassList("multi-toggle-box-empty-label");
var scrollContainer = _selectionTogglesBox.Q<VisualElement>("unity-content-viewport");
scrollContainer.Add(_noSelectionsLabel);
VisualElement filteringBox = new VisualElement();
filteringBox.AddToClassList("multi-toggle-box-toolbar");
// Select - deselect buttons
VisualElement selectingBox = new VisualElement();
selectingBox.AddToClassList("multi-toggle-box-toolbar-selecting-box");
Button selectAllButton = new Button(SelectAllToggles)
{
text = "Select All"
};
Button deSelectAllButton = new Button(UnselectAllToggles)
{
text = "Deselect All"
};
selectingBox.Add(selectAllButton);
selectingBox.Add(deSelectAllButton);
// Filtering dropdown
VisualElement filteringDropdownBox = new VisualElement();
filteringDropdownBox.AddToClassList("multi-toggle-box-toolbar-filtering-box");
_filteringDropdown = new ToolbarMenu { text = _selectionFilters[0] };
foreach (var filter in _selectionFilters)
_filteringDropdown.menu.AppendAction(filter, (_) => { FilterDependencies(filter); });
filteringDropdownBox.Add(_filteringDropdown);
// Final adding
filteringBox.Add(filteringDropdownBox);
filteringBox.Add(selectingBox);
fullSelectionBox.Add(_selectionTogglesBox);
fullSelectionBox.Add(filteringBox);
_multiToggleSelectionHelpRow.Add(_multiToggleSelectionLabel);
_multiToggleSelectionHelpRow.Add(_multiToggleSelectionTooltip);
Add(_multiToggleSelectionHelpRow);
Add(fullSelectionBox);
}
public void Populate(Dictionary<string, bool> selections)
{
_selectionTogglesBox.Clear();
_selections = selections;
EventCallback<ChangeEvent<bool>, string> callback = OnToggle;
foreach (var kvp in selections)
{
var toggle = new Toggle() { text = kvp.Key, value = kvp.Value };
toggle.AddToClassList("multi-toggle-box-toggle");
toggle.RegisterCallback(callback, toggle.text);
_selectionTogglesBox.Add(toggle);
}
FilterDependencies(_activeFilter);
}
private void FilterDependencies(string filter)
{
_activeFilter = filter;
var allToggles = _selectionTogglesBox.Children().Cast<Toggle>().ToArray();
var selectedIndex = _selectionFilters.FindIndex(x => x == filter);
switch (selectedIndex)
{
case 0:
foreach (var toggle in allToggles)
toggle.style.display = DisplayStyle.Flex;
break;
case 1:
foreach (var toggle in allToggles)
toggle.style.display = toggle.value ? DisplayStyle.Flex : DisplayStyle.None;
break;
case 2:
foreach (var toggle in allToggles)
toggle.style.display = toggle.value ? DisplayStyle.None : DisplayStyle.Flex;
break;
}
// Check if any toggles are displayed
var count = allToggles.Count(toggle => toggle.style.display == DisplayStyle.Flex);
_noSelectionsLabel.style.display = count > 0 ? DisplayStyle.None : DisplayStyle.Flex;
_filteringDropdown.text = filter;
}
private void OnToggle(ChangeEvent<bool> evt, string text)
{
FilterDependencies(_activeFilter);
_selections[text] = evt.newValue;
OnValuesChanged?.Invoke(_selections);
}
private void OnAllToggles(bool value)
{
var allToggles = _selectionTogglesBox.Children().Cast<Toggle>();
foreach (var toggle in allToggles)
toggle.SetValueWithoutNotify(value);
foreach (var key in _selections.Keys.ToArray())
_selections[key] = value;
FilterDependencies(_activeFilter);
OnValuesChanged?.Invoke(_selections);
}
private void SelectAllToggles()
{
OnAllToggles(true);
}
private void UnselectAllToggles()
{
OnAllToggles(false);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 19e30766043794345beb432973e0eb3c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/MultiToggleSelectionElement.cs
uploadId: 724584

View File

@@ -0,0 +1,137 @@
using AssetStoreTools.Uploader.Data;
using AssetStoreTools.Utility;
using System.Collections.Generic;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class PackageContentElement : VisualElement
{
// Data
private IPackageContent _content;
private List<WorkflowElementBase> _workflowElements;
// UI
private VisualElement _workflowSelectionBox;
private ToolbarMenu _toolbarMenu;
public PackageContentElement(IPackageContent content)
{
_content = content;
content.OnActiveWorkflowChanged += ActiveWorkflowChanged;
_workflowElements = new List<WorkflowElementBase>();
Create();
}
private void Create()
{
AddToClassList("package-content-element");
CreateWorkflowSelection();
CreateWorkflows();
Deserialize();
}
private void CreateWorkflowSelection()
{
_workflowSelectionBox = new VisualElement();
_workflowSelectionBox.AddToClassList("package-content-option-box");
VisualElement labelHelpRow = new VisualElement();
labelHelpRow.AddToClassList("package-content-option-label-help-row");
Label workflowLabel = new Label { text = "Upload type" };
Image workflowLabelTooltip = new Image
{
tooltip = "Select what content you are uploading to the Asset Store"
+ "\n\n- From Assets Folder - content located within the project's 'Assets' folder or one of its subfolders"
+ "\n\n- Pre-exported .unitypackage - content that has already been compressed into a .unitypackage file"
#if UNITY_ASTOOLS_EXPERIMENTAL
+ "\n\n- Local UPM Package - content that is located within the project's 'Packages' folder. Only embedded and local packages are supported"
#endif
};
labelHelpRow.Add(workflowLabel);
labelHelpRow.Add(workflowLabelTooltip);
_toolbarMenu = new ToolbarMenu();
_toolbarMenu.AddToClassList("package-content-option-dropdown");
foreach (var workflow in _content.GetAvailableWorkflows())
{
AppendToolbarActionForWorkflow(workflow);
}
_workflowSelectionBox.Add(labelHelpRow);
_workflowSelectionBox.Add(_toolbarMenu);
Add(_workflowSelectionBox);
}
private void AppendToolbarActionForWorkflow(IWorkflow workflow)
{
_toolbarMenu.menu.AppendAction(workflow.DisplayName, _ =>
{
_content.SetActiveWorkflow(workflow);
});
}
private void CreateWorkflows()
{
foreach (var workflow in _content.GetAvailableWorkflows())
{
WorkflowElementBase element;
switch (workflow)
{
case AssetsWorkflow assetsWorkflow:
element = new AssetsWorkflowElement(assetsWorkflow);
break;
case UnityPackageWorkflow unityPackageWorkflow:
element = new UnityPackageWorkflowElement(unityPackageWorkflow);
break;
#if UNITY_ASTOOLS_EXPERIMENTAL
case HybridPackageWorkflow hybridPackageWorkflow:
element = new HybridPackageWorkflowElement(hybridPackageWorkflow);
break;
#endif
default:
ASDebug.LogWarning("Package Content Element received an undefined workflow");
continue;
}
element.OnInteractionAvailable += EnableInteraction;
element.OnInteractionUnavailable += DisableInteraction;
_workflowElements.Add(element);
Add(element);
}
}
private void ActiveWorkflowChanged(IWorkflow workflow)
{
_toolbarMenu.text = workflow.DisplayName;
foreach (var workflowElement in _workflowElements)
{
bool show = workflowElement.Is(workflow);
workflowElement.style.display = show ? DisplayStyle.Flex : DisplayStyle.None;
}
}
private void EnableInteraction()
{
_workflowSelectionBox.SetEnabled(true);
}
private void DisableInteraction()
{
_workflowSelectionBox.SetEnabled(false);
}
private void Deserialize()
{
ActiveWorkflowChanged(_content.GetActiveWorkflow());
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 09927e9c8fd6e074fa451add92b7ab6f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageContentElement.cs
uploadId: 724584

View File

@@ -0,0 +1,215 @@
using AssetStoreTools.Api;
using AssetStoreTools.Uploader.Data;
using AssetStoreTools.Uploader.Services;
using System;
#if !UNITY_2021_1_OR_NEWER
using UnityEditor.UIElements;
#endif
using UnityEngine;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class PackageElement : VisualElement
{
// Data
private IPackage _package;
private bool _isSelected;
private IPackageFactoryService _packageFactory;
// UI
private Button _foldoutBox;
private Label _expanderLabel;
private Label _assetLabel;
private Label _lastDateSizeLabel;
private Image _assetImage;
private ProgressBar _uploadProgressBar;
private VisualElement _uploadProgressBarBackground;
private PackageContentElement _contentElement;
public event Action OnSelected;
public PackageElement(IPackage package, IPackageFactoryService packageFactory)
{
_package = package;
_package.OnUpdate += Refresh;
_package.OnIconUpdate += SetPackageThumbnail;
_packageFactory = packageFactory;
_isSelected = false;
Create();
}
private void Create()
{
AddToClassList("package-full-box");
_foldoutBox = new Button { name = "Package" };
_foldoutBox.AddToClassList("package-foldout-box");
if (_package.IsDraft)
_foldoutBox.AddToClassList("package-foldout-box-draft");
_foldoutBox.clickable.clicked += Toggle;
// Expander, Icon and Asset Label
VisualElement foldoutBoxInfo = new VisualElement { name = "foldoutBoxInfo" };
foldoutBoxInfo.AddToClassList("package-foldout-box-info");
VisualElement labelExpanderRow = new VisualElement { name = "labelExpanderRow" };
labelExpanderRow.AddToClassList("package-expander-label-row");
_expanderLabel = new Label { name = "ExpanderLabel", text = "►" };
_expanderLabel.AddToClassList("package-expander");
_expanderLabel.style.display = _package.IsDraft ? DisplayStyle.Flex : DisplayStyle.None;
_assetImage = new Image { name = "AssetImage" };
_assetImage.AddToClassList("package-image");
VisualElement assetLabelInfoBox = new VisualElement { name = "assetLabelInfoBox" };
assetLabelInfoBox.AddToClassList("package-label-info-box");
_assetLabel = new Label { name = "AssetLabel", text = _package.Name };
_assetLabel.AddToClassList("package-label");
_lastDateSizeLabel = new Label { name = "AssetInfoLabel", text = FormatDateSize() };
_lastDateSizeLabel.AddToClassList("package-info");
assetLabelInfoBox.Add(_assetLabel);
assetLabelInfoBox.Add(_lastDateSizeLabel);
labelExpanderRow.Add(_expanderLabel);
labelExpanderRow.Add(_assetImage);
labelExpanderRow.Add(assetLabelInfoBox);
var openInBrowserButton = new Button(OpenPackageInBrowser)
{
name = "OpenInBrowserButton",
tooltip = "View your package in the Publishing Portal."
};
openInBrowserButton.AddToClassList("package-open-in-browser-button");
// Header Progress bar
_uploadProgressBar = new ProgressBar { name = "HeaderProgressBar" };
_uploadProgressBar.AddToClassList("package-header-progress-bar");
_uploadProgressBar.style.display = DisplayStyle.None;
_uploadProgressBarBackground = _uploadProgressBar.Q<VisualElement>(className: "unity-progress-bar__progress");
// Connect it all
foldoutBoxInfo.Add(labelExpanderRow);
foldoutBoxInfo.Add(openInBrowserButton);
_foldoutBox.Add(foldoutBoxInfo);
_foldoutBox.Add(_uploadProgressBar);
Add(_foldoutBox);
}
private void CreateFoldoutContent()
{
var content = _packageFactory.CreatePackageContent(_package);
if (content == null)
return;
_contentElement = new PackageContentElement(content);
_contentElement.style.display = DisplayStyle.None;
Add(_contentElement);
SubscribeToContentWorkflowUpdates(content);
}
private void SubscribeToContentWorkflowUpdates(IPackageContent content)
{
foreach (var workflow in content.GetAvailableWorkflows())
{
workflow.OnUploadStateChanged += UpdateProgressBar;
}
}
private void UpdateProgressBar(UploadStatus? status, float? progress)
{
if (status != null)
{
_uploadProgressBarBackground.style.backgroundColor = PackageUploadElement.GetColorByStatus(status.Value);
}
if (progress != null)
{
_uploadProgressBar.value = progress.Value;
}
}
private void Toggle()
{
if (!_package.IsDraft)
return;
if (!Contains(_contentElement))
CreateFoldoutContent();
var shouldExpand = !_isSelected;
_expanderLabel.text = shouldExpand ? "▼" : "►";
if (shouldExpand)
_foldoutBox.AddToClassList("package-foldout-box-expanded");
else
_foldoutBox.RemoveFromClassList("package-foldout-box-expanded");
_contentElement.style.display = shouldExpand ? DisplayStyle.Flex : DisplayStyle.None;
_isSelected = !_isSelected;
ToggleProgressBar();
if (_isSelected)
OnSelected?.Invoke();
}
private void ToggleProgressBar()
{
if (!_isSelected && _uploadProgressBar.value != 0)
_uploadProgressBar.style.display = DisplayStyle.Flex;
else
_uploadProgressBar.style.display = DisplayStyle.None;
}
public bool Is(IPackage package)
{
return package == _package;
}
public void Select()
{
if (!_isSelected)
Toggle();
}
public void Unselect()
{
if (_isSelected)
Toggle();
}
private void SetPackageThumbnail()
{
_assetImage.image = _package.Icon;
}
private void Refresh()
{
_assetLabel.text = _package.Name;
_lastDateSizeLabel.text = FormatDateSize();
}
private string FormatDateSize()
{
return $"{_package.Category} | {_package.FormattedSize()} | {_package.FormattedModified()}";
}
private void OpenPackageInBrowser()
{
Application.OpenURL($"https://publisher.unity.com/packages/{_package.VersionId}/edit/upload");
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: cef5f23043d318945b844bcac7a7a984
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageElement.cs
uploadId: 724584

View File

@@ -0,0 +1,149 @@
using AssetStoreTools.Uploader.Data;
using AssetStoreTools.Uploader.Services;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class PackageGroupElement : VisualElement
{
// Data
public string Name => _packageGroup.Name;
private IPackageGroup _packageGroup;
private List<PackageElement> _packageElements;
private bool _isExpanded;
private IPackageFactoryService _packageFactory;
// UI
private Button _groupExpanderBox;
private VisualElement _groupContent;
private Label _expanderLabel;
private Label _groupLabel;
public PackageGroupElement(IPackageGroup packageGroup, IPackageFactoryService packageFactory)
{
_packageGroup = packageGroup;
_packageElements = new List<PackageElement>();
_packageGroup.OnPackagesSorted += RefreshPackages;
_packageGroup.OnPackagesFiltered += RefreshPackages;
_packageFactory = packageFactory;
Create();
}
private void Create()
{
CreatePackageGroup();
CreatePackageGroupContent();
AddPackagesToGroupContent();
}
protected void CreatePackageGroup()
{
_groupExpanderBox = new Button(OnPackageGroupClicked);
_groupExpanderBox.AddToClassList("package-group-expander-box");
_expanderLabel = new Label { name = "ExpanderLabel", text = "►" };
_expanderLabel.AddToClassList("package-group-expander");
_groupLabel = new Label { text = $"{_packageGroup.Name} ({_packageGroup.Packages.Count})" };
_groupLabel.AddToClassList("package-group-label");
FormatGroupLabel(_packageGroup.Packages.Count);
_groupExpanderBox.Add(_expanderLabel);
_groupExpanderBox.Add(_groupLabel);
Add(_groupExpanderBox);
}
private void CreatePackageGroupContent()
{
_groupContent = new VisualElement { name = "GroupContentBox" };
_groupContent.AddToClassList("package-group-content-box");
Toggle(false);
var groupSeparator = new VisualElement { name = "GroupSeparator" };
groupSeparator.AddToClassList("package-group-separator");
if (_packageGroup.Name.ToLower() != "draft")
{
_groupLabel.SetEnabled(false);
_groupContent.AddToClassList("unity-disabled");
groupSeparator.style.display = DisplayStyle.Flex;
}
Add(_groupContent);
Add(groupSeparator);
}
private void AddPackagesToGroupContent()
{
foreach (var package in _packageGroup.Packages)
{
var packageElement = new PackageElement(package, _packageFactory);
packageElement.OnSelected += () => OnPackageSelected(packageElement);
_packageElements.Add(packageElement);
}
}
private void FormatGroupLabel(int displayedPackageCount)
{
if (_packageGroup.Packages.Count == displayedPackageCount)
_groupLabel.text = $"{Name} ({displayedPackageCount})";
else
_groupLabel.text = $"{Name} ({displayedPackageCount}/{_packageGroup.Packages.Count})";
}
private void RefreshPackages(List<IPackage> packages)
{
_groupContent.Clear();
foreach (var package in packages)
{
var correspondingElement = _packageElements.FirstOrDefault(x => x.Is(package));
if (correspondingElement == null)
continue;
_groupContent.Add(correspondingElement);
}
FormatGroupLabel(packages.Count());
}
private void OnPackageGroupClicked()
{
Toggle(!_isExpanded);
}
public void Toggle(bool expand)
{
if (expand)
{
_expanderLabel.text = "▼";
_groupContent.style.display = DisplayStyle.Flex;
}
else
{
_expanderLabel.text = "►";
_groupContent.style.display = DisplayStyle.None;
}
_isExpanded = expand;
}
private void OnPackageSelected(PackageElement packageElement)
{
foreach (var element in _packageElements)
{
if (element == packageElement)
continue;
element.Unselect();
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 41e322a1418ab824182eade111145dff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageGroupElement.cs
uploadId: 724584

View File

@@ -0,0 +1,58 @@
using AssetStoreTools.Uploader.Data;
using System.Collections.Generic;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class PackageListToolbar : VisualElement
{
private List<IPackageGroup> _packageGroups;
public PackageListToolbar()
{
Create();
}
private void Create()
{
AddToClassList("package-list-toolbar");
// Search
var searchField = new ToolbarSearchField { name = "SearchField" };
searchField.AddToClassList("package-search-field");
// Sorting menu button
var sortMenu = new ToolbarMenu() { text = "Sort: Name ↓" };
sortMenu.menu.AppendAction("Sort: Name ↓", (_) => { sortMenu.text = "Sort: Name ↓"; Sort(PackageSorting.Name); });
sortMenu.menu.AppendAction("Sort: Updated ↓", (_) => { sortMenu.text = "Sort: Updated ↓"; Sort(PackageSorting.Date); });
sortMenu.menu.AppendAction("Sort: Category ↓", (_) => { sortMenu.text = "Sort: Category ↓"; Sort(PackageSorting.Category); });
sortMenu.AddToClassList("package-sort-menu");
// Finalize the bar
Add(searchField);
Add(sortMenu);
// Add Callbacks and click events
searchField.RegisterCallback<ChangeEvent<string>>(SearchFilter);
}
public void SetPackageGroups(List<IPackageGroup> packageGroups)
{
_packageGroups = packageGroups;
}
private void SearchFilter(ChangeEvent<string> evt)
{
var searchString = evt.newValue.ToLower();
foreach (var packageGroup in _packageGroups)
packageGroup.Filter(searchString);
}
public void Sort(PackageSorting sortingType)
{
foreach (var packageGroup in _packageGroups)
packageGroup.Sort(sortingType);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 6d2659328222e0e4cb36cd194e023f4b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageListToolbar.cs
uploadId: 724584

View File

@@ -0,0 +1,321 @@
using AssetStoreTools.Api;
using AssetStoreTools.Api.Responses;
using AssetStoreTools.Exporter;
using AssetStoreTools.Uploader.Data;
using AssetStoreTools.Utility;
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using UnityEditor;
#if !UNITY_2021_1_OR_NEWER
using UnityEditor.UIElements;
#endif
using UnityEngine;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class PackageUploadElement : VisualElement
{
// Data
private IWorkflow _workflow;
private bool _enableExporting;
// UI
private VisualElement _exportAndUploadContainer;
private Button _cancelUploadButton;
private VisualElement _uploadProgressContainer;
private ProgressBar _uploadProgressBar;
private VisualElement _uploadProgressBarBackground;
public event Action OnInteractionAvailable;
public event Action OnInteractionUnavailable;
public PackageUploadElement(IWorkflow workflow, bool exposeExportButton)
{
_workflow = workflow;
_enableExporting = exposeExportButton;
Create();
}
private void Create()
{
AddToClassList("uploading-box");
CreateButtonContainer();
CreateProgressContainer();
}
private void CreateButtonContainer()
{
_exportAndUploadContainer = new VisualElement();
_exportAndUploadContainer.AddToClassList("uploading-export-and-upload-container");
CreateExportButton();
CreateUploadButton();
Add(_exportAndUploadContainer);
}
private void CreateExportButton()
{
if (!_enableExporting)
return;
var _exportAndUploadButton = new Button(async () => await Export(true)) { name = "ExportButton", text = "Export" };
_exportAndUploadButton.AddToClassList("uploading-export-button");
_exportAndUploadContainer.Add(_exportAndUploadButton);
}
private void CreateUploadButton()
{
var _uploadButton = new Button(Upload) { name = "UploadButton" };
_uploadButton.text = _enableExporting ? "Export and Upload" : "Upload";
_uploadButton.AddToClassList("uploading-upload-button");
_exportAndUploadContainer.Add(_uploadButton);
}
private void CreateProgressContainer()
{
_uploadProgressContainer = new VisualElement();
_uploadProgressContainer.AddToClassList("uploading-progress-container");
_uploadProgressContainer.style.display = DisplayStyle.None;
_uploadProgressBar = new ProgressBar { name = "UploadProgressBar" };
_uploadProgressBar.AddToClassList("uploading-progress-bar");
_uploadProgressBarBackground = _uploadProgressBar.Q<VisualElement>(className: "unity-progress-bar__progress");
_cancelUploadButton = new Button() { name = "CancelButton", text = "Cancel" };
_cancelUploadButton.AddToClassList("uploading-cancel-button");
_uploadProgressContainer.Add(_uploadProgressBar);
_uploadProgressContainer.Add(_cancelUploadButton);
Add(_uploadProgressContainer);
}
private async Task<PackageExporterResult> Export(bool interactive)
{
try
{
DisableInteraction();
if (!_workflow.IsPathSet)
{
EditorUtility.DisplayDialog("Exporting failed", "No path was selected. Please " +
"select a path and try again.", "OK");
return new PackageExporterResult() { Success = false, Exception = new Exception("No path was selected.") };
}
var rootProjectPath = Constants.RootProjectPath;
var packageNameStripped = Regex.Replace(_workflow.PackageName, "[^a-zA-Z0-9]", "");
var outputName = $"{packageNameStripped}-{DateTime.Now:yyyy-dd-M--HH-mm-ss}";
string outputPath;
if (interactive)
{
outputPath = EditorUtility.SaveFilePanel("Export Package", rootProjectPath,
outputName, _workflow.PackageExtension.Remove(0, 1)); // Ignoring the '.' character since SaveFilePanel already appends it
if (string.IsNullOrEmpty(outputPath))
return new PackageExporterResult() { Success = false, Exception = null };
}
else
{
outputPath = $"Temp/{outputName}{_workflow.PackageExtension}";
}
var exportResult = await _workflow.ExportPackage(outputPath);
if (!exportResult.Success)
{
Debug.LogError($"Package exporting failed: {exportResult.Exception}");
EditorUtility.DisplayDialog("Exporting failed", exportResult.Exception.Message, "OK");
}
else if (interactive)
Debug.Log($"Package exported to '{Path.GetFullPath(exportResult.ExportedPath).Replace("\\", "/")}'");
return exportResult;
}
finally
{
if (interactive)
EnableInteraction();
}
}
private async void Upload()
{
DisableInteraction();
if (await ValidateUnityVersionsBeforeUpload() == false)
{
EnableInteraction();
return;
}
var exportResult = await Export(false);
if (!exportResult.Success)
{
EnableInteraction();
return;
}
if (!_workflow.IsPathSet)
{
EditorUtility.DisplayDialog("Uploading failed", "No path was selected. Please " +
"select a path and try again.", "OK");
EnableInteraction();
return;
}
_exportAndUploadContainer.style.display = DisplayStyle.None;
_uploadProgressContainer.style.display = DisplayStyle.Flex;
_cancelUploadButton.clicked += Cancel;
_workflow.OnUploadStateChanged += UpdateProgressBar;
var response = await _workflow.UploadPackage(exportResult.ExportedPath);
_workflow.OnUploadStateChanged -= UpdateProgressBar;
await OnUploadingStopped(response);
}
private async Task<bool> ValidateUnityVersionsBeforeUpload()
{
var validationEnabled = ASToolsPreferences.Instance.UploadVersionCheck;
if (!validationEnabled)
return true;
var requiredVersionUploaded = await _workflow.ValidatePackageUploadedVersions();
if (requiredVersionUploaded)
return true;
var result = EditorUtility.DisplayDialogComplex("Asset Store Tools", $"You may upload this package, but you will need to add a package using Unity version {Constants.Uploader.MinRequiredUnitySupportVersion} " +
"or higher to be able to submit a new asset", "Upload", "Cancel", "Upload and do not display this again");
switch (result)
{
case 1:
return false;
case 2:
ASToolsPreferences.Instance.UploadVersionCheck = false;
ASToolsPreferences.Instance.Save();
break;
}
return true;
}
private void UpdateProgressBar(UploadStatus? status, float? progress)
{
if (status != null)
{
_uploadProgressBarBackground.style.backgroundColor = GetColorByStatus(status.Value);
}
if (progress != null)
{
_uploadProgressBar.value = progress.Value;
_uploadProgressBar.title = $"{progress.Value:0.#}%";
if (progress == 100f && _cancelUploadButton.enabledInHierarchy)
_cancelUploadButton.SetEnabled(false);
}
}
private void Cancel()
{
_cancelUploadButton.SetEnabled(false);
_workflow.AbortUpload();
}
private async Task OnUploadingStopped(PackageUploadResponse response)
{
if (!response.Success && !response.Cancelled)
{
Debug.LogException(response.Exception);
}
if (response.Success)
{
await _workflow.RefreshPackage();
}
if (response.Status == UploadStatus.ResponseTimeout)
{
Debug.LogWarning($"All bytes for the package '{_workflow.PackageName}' have been uploaded, but a response " +
$"from the server was not received. This can happen because of Firewall restrictions. " +
$"Please make sure that a new version of your package has reached the Publishing Portal.");
}
_uploadProgressBar.title = GetProgressBarTitleByStatus(response.Status);
_cancelUploadButton.clickable = null;
_cancelUploadButton.clicked += Reset;
_cancelUploadButton.text = "Done";
_cancelUploadButton.SetEnabled(true);
}
private void Reset()
{
_cancelUploadButton.clickable = null;
_cancelUploadButton.text = "Cancel";
_workflow.ResetUploadStatus();
UpdateProgressBar(UploadStatus.Default, 0f);
_uploadProgressContainer.style.display = DisplayStyle.None;
_exportAndUploadContainer.style.display = DisplayStyle.Flex;
EnableInteraction();
}
public static Color GetColorByStatus(UploadStatus status)
{
switch (status)
{
default:
case UploadStatus.Default:
return new Color(0.13f, 0.59f, 0.95f);
case UploadStatus.Success:
case UploadStatus.ResponseTimeout:
return new Color(0f, 0.50f, 0.14f);
case UploadStatus.Cancelled:
return new Color(0.78f, 0.59f, 0f);
case UploadStatus.Fail:
return new Color(0.69f, 0.04f, 0.04f);
}
}
private string GetProgressBarTitleByStatus(UploadStatus status)
{
var progressBarTitle = "Upload: ";
switch (status)
{
case UploadStatus.ResponseTimeout:
progressBarTitle += UploadStatus.Success;
break;
default:
progressBarTitle += status;
break;
}
return progressBarTitle;
}
private void EnableInteraction()
{
_exportAndUploadContainer.SetEnabled(true);
OnInteractionAvailable?.Invoke();
}
private void DisableInteraction()
{
_exportAndUploadContainer.SetEnabled(false);
OnInteractionUnavailable?.Invoke();
SetEnabled(true);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 242524e968bd4484eaeb154d8013f427
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageUploadElement.cs
uploadId: 724584

View File

@@ -0,0 +1,63 @@
using System;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class PathSelectionElement : VisualElement
{
// Data
private string _labelText;
private string _labelTooltip;
public event Action OnBrowse;
// UI
private TextField _pathSelectionTextField;
public PathSelectionElement(string labelText, string labelTooltip)
{
AddToClassList("package-content-option-box");
_labelText = labelText;
_labelTooltip = labelTooltip;
Create();
}
private void Create()
{
VisualElement labelHelpRow = new VisualElement();
labelHelpRow.AddToClassList("package-content-option-label-help-row");
Label folderPathLabel = new Label { text = _labelText };
Image folderPathLabelTooltip = new Image
{
tooltip = _labelTooltip
};
labelHelpRow.Add(folderPathLabel);
labelHelpRow.Add(folderPathLabelTooltip);
_pathSelectionTextField = new TextField();
_pathSelectionTextField.AddToClassList("package-content-option-textfield");
_pathSelectionTextField.isReadOnly = true;
Button browsePathButton = new Button(Browse) { name = "BrowsePathButton", text = "Browse" };
browsePathButton.AddToClassList("package-content-option-button");
Add(labelHelpRow);
Add(_pathSelectionTextField);
Add(browsePathButton);
}
private void Browse()
{
OnBrowse?.Invoke();
}
public void SetPath(string path)
{
_pathSelectionTextField.value = path;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 753d4442293e5cc4b9efcab089da4d59
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PathSelectionElement.cs
uploadId: 724584

View File

@@ -0,0 +1,109 @@
using AssetStoreTools.Previews.Data;
using AssetStoreTools.Uploader.Data;
using System.Linq;
using UnityEditor;
using UnityEngine.UIElements;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class PreviewGenerationElement : VisualElement
{
// Data
private IWorkflow _workflow;
// UI
private VisualElement _toggleRow;
private Toggle _previewToggle;
private VisualElement _buttonRow;
private VisualElement _viewButton;
public PreviewGenerationElement(IWorkflow workflow)
{
_workflow = workflow;
Create();
}
private void Create()
{
CreateInfoRow();
CreateViewButton();
}
private void CreateInfoRow()
{
_toggleRow = new VisualElement();
_toggleRow.AddToClassList("package-content-option-box");
VisualElement toggleLabelHelpRow = new VisualElement();
toggleLabelHelpRow.AddToClassList("package-content-option-label-help-row");
Label toggleLabel = new Label { text = "Asset Previews" };
Image toggleLabelTooltip = new Image
{
tooltip = "Select how the previews for your assets will be generated.\n\n" +
"Unity generates asset preview images natively up to a size of 128x128. " +
"You can try generating previews which are of higher resolution, up to 300x300.\n\n" +
"Note: these asset preview images will only be displayed in the 'Package Content' section of the " +
"Asset Store listing page once the package is published, and in the package importer window that appears during the package import process.\n" +
"They will not replace the images used for the assets in the Project window after the package gets imported."
};
_previewToggle = new Toggle { name = "PreviewToggle", text = "Generate Hi-Res (experimental)" };
_previewToggle.AddToClassList("package-content-option-toggle");
_previewToggle.RegisterValueChangedCallback((_) => DependencyToggleValueChange());
toggleLabelHelpRow.Add(toggleLabel);
toggleLabelHelpRow.Add(toggleLabelTooltip);
_toggleRow.Add(toggleLabelHelpRow);
_toggleRow.Add(_previewToggle);
Add(_toggleRow);
}
private void CreateViewButton()
{
_buttonRow = new VisualElement();
_buttonRow.AddToClassList("package-content-option-box");
_buttonRow.style.display = DisplayStyle.None;
var spaceFiller = new VisualElement();
spaceFiller.AddToClassList("package-content-option-label-help-row");
_viewButton = new Button(ViewClicked) { text = "Inspect Previews" };
_buttonRow.Add(spaceFiller);
_buttonRow.Add(_viewButton);
Add(_buttonRow);
}
private void DependencyToggleValueChange()
{
_workflow.GenerateHighQualityPreviews = _previewToggle.value;
_buttonRow.style.display = _previewToggle.value ? DisplayStyle.Flex : DisplayStyle.None;
}
private void ViewClicked()
{
PreviewGenerationSettings settings;
if (_workflow.GenerateHighQualityPreviews)
{
settings = new CustomPreviewGenerationSettings() { InputPaths = _workflow.GetAllPaths().ToArray() };
}
else
{
settings = new NativePreviewGenerationSettings() { InputPaths = _workflow.GetAllPaths().ToArray() };
}
AssetStoreTools.ShowAssetStoreToolsPreviewGenerator(settings);
}
private void DisplayProgress(float value)
{
EditorUtility.DisplayProgressBar("Generating", "Generating previews...", value);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 54c7971e2ad639644936d3552b4f4f49
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PreviewGenerationElement.cs
uploadId: 724584

View File

@@ -0,0 +1,58 @@
using AssetStoreTools.Uploader.Data;
using AssetStoreTools.Utility;
using UnityEditor;
namespace AssetStoreTools.Uploader.UI.Elements
{
internal class UnityPackageWorkflowElement : WorkflowElementBase
{
// Data
private UnityPackageWorkflow _workflow;
public UnityPackageWorkflowElement(UnityPackageWorkflow workflow) : base(workflow)
{
_workflow = workflow;
Create();
}
private void Create()
{
CreatePathElement("Package path", "Select the .unitypackage file you would like to upload.");
CreateValidationElement(new ExternalProjectValidationElement(_workflow));
CreateUploadElement(_workflow, false);
Deserialize();
}
protected override void BrowsePath()
{
// Path retrieval
var absolutePackagePath = EditorUtility.OpenFilePanel("Select a .unitypackage file", Constants.RootProjectPath, "unitypackage");
if (string.IsNullOrEmpty(absolutePackagePath))
return;
var relativeExportPath = FileUtility.AbsolutePathToRelativePath(absolutePackagePath, ASToolsPreferences.Instance.EnableSymlinkSupport);
if (!_workflow.IsPathValid(relativeExportPath, out var error))
{
EditorUtility.DisplayDialog("Invalid selection", error, "OK");
return;
}
HandleUnityPackageUploadPathSelection(relativeExportPath, true);
}
private void HandleUnityPackageUploadPathSelection(string selectedPackagePath, bool serialize)
{
if (string.IsNullOrEmpty(selectedPackagePath))
return;
_workflow.SetPackagePath(selectedPackagePath, serialize);
SetPathSelectionTextField(selectedPackagePath);
}
protected override void Deserialize()
{
HandleUnityPackageUploadPathSelection(_workflow.GetPackagePath(), false);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 7a0c8a79b7dba9e458ddc54eec30ea66
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 115
packageName: Asset Store Publishing Tools
packageVersion: 12.0.1
assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/UnityPackageWorkflowElement.cs
uploadId: 724584