();
+
+ public static PackageView GetPackage(PackageData packageData)
+ {
+ string versionId = packageData.VersionId;
+ if (SavedPackages.ContainsKey(versionId))
+ {
+ var savedPackage = SavedPackages[versionId];
+ savedPackage.UpdateDataValues(packageData);
+ return savedPackage;
+ }
+
+ var package = new PackageView(packageData);
+ SavedPackages.Add(package.VersionId, package);
+ return package;
+ }
+
+ public static void Reset()
+ {
+ SavedPackages.Clear();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Utility/PackageViewStorer.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Utility/PackageViewStorer.cs.meta
new file mode 100644
index 000000000..73f9d3aa0
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Utility/PackageViewStorer.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 582639e8ed53f37499d12efcb4cde2c9
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles.meta
new file mode 100644
index 000000000..6040ca4ab
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f9398c14296d30f479b9de5f3ec3b827
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base.meta
new file mode 100644
index 000000000..0eb5e4d88
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: b2d1d4985f5314246a7cb4ef749974af
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Dark.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Dark.uss
new file mode 100644
index 000000000..47ced1197
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Dark.uss
@@ -0,0 +1,37 @@
+.primary-colors
+{
+ /* Light - lighter */
+ background-color: rgb(220, 220, 220);
+ /* Light - middle */
+ background-color: rgb(200, 200, 200);
+ /* Light - darker */
+ background-color: rgb(180, 180, 180);
+
+ /* Dark - lighter */
+ background-color: rgb(78, 78, 78);
+ /* Dark - middle */
+ background-color: rgb(68, 68, 68);
+ /* Dark - darker */
+ background-color: rgb(58, 58, 58);
+
+ /* Border color - light */
+ border-color: rgb(200, 200, 200);
+ /* Border color - dark */
+ border-color: rgb(33, 33, 33);
+}
+
+.accent-color
+{
+ border-color: rgb(58, 121, 187);
+}
+
+.empty-color
+{
+ background-color: rgba(0, 0, 0, 0);
+ border-color: rgba(0, 0, 0, 0);
+}
+
+.root
+{
+
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Dark.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Dark.uss.meta
new file mode 100644
index 000000000..670acb8db
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Dark.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d00412342a1b6c943b91cc06edad1202
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Light.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Light.uss
new file mode 100644
index 000000000..47423f77d
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Light.uss
@@ -0,0 +1,37 @@
+.primary-colors
+{
+ /* Light - lighter */
+ background-color: rgb(220, 220, 220);
+ /* Light - middle */
+ background-color: rgb(200, 200, 200);
+ /* Light - darker */
+ background-color: rgb(180, 180, 180);
+
+ /* Dark - lighter */
+ background-color: rgb(50, 50, 50);
+ /* Dark - middle */
+ background-color: rgb(28, 28, 28);
+ /* Dark - darker */
+ background-color: rgb(0, 0, 0);
+
+ /* Border color - light */
+ border-color: rgb(200, 200, 200);
+ /* Border color - dark */
+ border-color: rgb(33, 33, 33);
+}
+
+.accent-color
+{
+ border-color: rgb(58, 121, 187);
+}
+
+.empty-color
+{
+ background-color: rgba(0, 0, 0, 0);
+ border-color: rgba(0, 0, 0, 0);
+}
+
+.root
+{
+
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Light.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Light.uss.meta
new file mode 100644
index 000000000..9263cae66
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Light.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a9e3b7e7e1851a140b1a5c23270ded34
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Main.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Main.uss
new file mode 100644
index 000000000..860ec4d19
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Main.uss
@@ -0,0 +1,15 @@
+#MainScrollView > * > .unity-scroll-view__content-container
+{
+ flex-grow: 1;
+}
+
+#MainScrollView > * > .unity-scroll-view__content-viewport
+{
+ flex-shrink: 1;
+}
+
+#MainScrollView > * > * > .unity-scroll-view__content-container
+{
+ flex-grow: 1;
+ flex-shrink: 1;
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Main.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Main.uss.meta
new file mode 100644
index 000000000..1777f6cd0
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Main.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0bebc765ff411f3428c6b3b23d5eb8e7
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Main.uxml b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Main.uxml
new file mode 100644
index 000000000..b99a4b82e
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Main.uxml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Main.uxml.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Main.uxml.meta
new file mode 100644
index 000000000..d9495b96c
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Base/BaseWindow_Main.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: dc5a13143b609774da7101bb8313dd7a
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login.meta
new file mode 100644
index 000000000..03b4bc1db
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f0a004d57c1a4db4a83df517f42de8a1
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Dark.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Dark.uss
new file mode 100644
index 000000000..8b9dcc1b6
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Dark.uss
@@ -0,0 +1,43 @@
+.asset-store-logo
+{
+ background-image: url("../../Icons/publisher_portal_white.png");
+}
+
+.or-label
+{
+ color: rgb(200, 200, 200);
+}
+
+.login-error-box
+{
+ background-color: rgb(63, 63, 63);
+}
+
+.manual-login-box
+{
+ background-color: rgb(63, 63, 63);
+}
+
+.hyperlink-button
+{
+ color: rgb(68, 113, 229);
+
+ border-color: rgba(0, 0, 0, 0);
+
+ background-color: rgba(0, 0, 0, 0);
+}
+
+.hyperlink-button:hover
+{
+ color: rgb(68, 133, 229);
+}
+
+.hyperlink-button:active
+{
+ color: rgb(68, 93, 229);
+}
+
+.login-error-box > Image
+{
+ --unity-image: resource("console.erroricon@2x");
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Dark.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Dark.uss.meta
new file mode 100644
index 000000000..3fa1522f6
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Dark.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 13a732708670b6040ac77e49fceae9c5
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Light.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Light.uss
new file mode 100644
index 000000000..bff5e2588
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Light.uss
@@ -0,0 +1,43 @@
+.asset-store-logo
+{
+ background-image: url("../../Icons/publisher_portal_black.png");
+}
+
+.or-label
+{
+ color: rgb(28, 28, 28);
+}
+
+.login-error-box
+{
+ background-color: rgb(212, 212, 212);
+}
+
+.manual-login-box
+{
+ background-color: rgb(212, 212, 212);
+}
+
+.hyperlink-button
+{
+ color: rgb(68, 113, 229);
+
+ border-color: rgba(0, 0, 0, 0);
+
+ background-color: rgba(0, 0, 0, 0);
+}
+
+.hyperlink-button:hover
+{
+ color: rgb(68, 133, 229);
+}
+
+.hyperlink-button:active
+{
+ color: rgb(68, 93, 229);
+}
+
+.login-error-box > Image
+{
+ --unity-image: resource("console.erroricon@2x");
+}
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Light.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Light.uss.meta
new file mode 100644
index 000000000..c1afd4517
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Light.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 526a426fa6626ce498c3bd03c67737e4
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Main.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Main.uss
new file mode 100644
index 000000000..d9084e0e7
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Main.uss
@@ -0,0 +1,135 @@
+.popup-window-test
+{
+ position: absolute;
+}
+
+.asset-store-logo
+{
+ flex-shrink: 0;
+ flex-grow: 1;
+
+ align-self: center;
+
+ height: 32px;
+ width: 250px;
+
+ margin: 40px 0;
+
+ -unity-background-scale-mode: scale-to-fit;
+}
+
+.login-button-cloud
+{
+ align-self: center;
+
+ width: 300px;
+}
+
+.login-description
+{
+ -unity-text-align: middle-center;
+ white-space: normal;
+
+ min-height: 24px;
+ padding-right: 4px;
+}
+
+.or-label
+{
+ align-self: center;
+
+ -unity-text-align: middle-center;
+
+ margin: 10px 0;
+}
+
+.manual-login-box
+{
+ align-self: center;
+
+ width: 300px;
+
+ padding: 15px;
+}
+
+.input-box-login
+{
+ align-self: center;
+
+ width: 250px;
+
+ margin: 5px 0;
+}
+
+.input-box-login > Label
+{
+ -unity-text-align: upper-left;
+
+ margin: 2px 0;
+}
+
+.input-box-login > TextField
+{
+ height: 20px;
+ margin: 0 1px;
+}
+
+.login-button-cred
+{
+ align-self: center;
+
+ width: 250px;
+ margin: 10px 0 15px 0;
+}
+
+.login-error-box
+{
+ flex-direction: row;
+ flex-shrink: 0;
+
+ align-self: center;
+
+ min-width: 300px;
+ max-width: 300px;
+
+ margin: 5px 0 5px 1px;
+}
+
+.login-error-box > Image
+{
+ flex-direction: row;
+
+ width: 32px;
+ height: 32px;
+
+ margin: 5px 10px;
+}
+
+.login-error-box > Label
+{
+ flex-grow: 1;
+ flex-shrink: 1;
+
+ -unity-text-align: middle-left;
+ white-space: normal;
+
+ margin-right: 5px;
+ padding: 2px 0;
+}
+
+.helper-button-box
+{
+ flex-direction: row;
+
+ align-self: center;
+ justify-content: space-between;
+
+ width: 300px;
+ margin: 5px 0;
+}
+
+.hyperlink-button
+{
+ margin: 0;
+ padding: 0;
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Main.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Main.uss.meta
new file mode 100644
index 000000000..4412d163f
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Login/Login_Main.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6c6827adc58f1b146bde5b52679588d7
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload.meta
new file mode 100644
index 000000000..2f197c652
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2fcc7023ae026264a9f05c37d0064aea
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages.meta
new file mode 100644
index 000000000..934cc0118
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: be1208fb3d0e8174a8075d0078069e72
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Dark.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Dark.uss
new file mode 100644
index 000000000..deae271ac
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Dark.uss
@@ -0,0 +1,322 @@
+/* Uploading Window */
+
+.assets-scroll-view
+{
+
+}
+
+.unity-scroller
+{
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+}
+
+.assets-scroll-view > .unity-scroll-view__content-viewport
+{
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+
+ background-color: rgb(68, 68, 68);
+}
+
+.assets-scroll-view > * > .unity-scroll-view__vertical-scroller
+{
+ border-right-width: 0;
+}
+
+.spinner-image
+{
+ --unity-image: resource("WaitSpin00");
+}
+
+.top-tools-row
+{
+ border-bottom-width: 1px;
+ border-color: rgb(33, 33, 33);
+
+ background-color: rgb(68, 68, 68);
+}
+
+.sort-menu
+{
+ color: rgb(238, 238, 238);
+
+ border-width: 1px;
+ border-radius: 3px;
+ border-color: rgb(36, 36, 36);
+
+ background-color: rgb(88, 88, 88);
+}
+
+.sort-menu:hover
+{
+ background-color: rgb(103, 103, 103);
+}
+
+.sort-menu:active
+{
+ background-color: rgb(73, 73, 73);
+}
+
+.sorting-header
+{
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+}
+
+.sort-button
+{
+ color: rgb(200, 200, 200);
+
+ border-width: 0;
+ background-color: rgba(0, 0, 0, 0);
+}
+
+.sort-button:hover
+{
+ color: rgb(220, 220, 220);
+}
+
+.sort-button:active
+{
+ color: rgb(180, 180, 180);
+}
+
+.sort-separator
+{
+ color: rgb(200, 200, 200);
+}
+
+.group-expander-box
+{
+ border-width: 0;
+ border-color: rgba(33, 33, 33, 0);
+
+ background-color: rgba(68, 68, 68, 0);
+}
+
+.group-label
+{
+ color: rgb(255, 255, 255);
+}
+
+.info-box, .group-info-box
+{
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+}
+
+.info-box > Image, .group-info-box > Image
+{
+ --unity-image: resource("console.infoicon@2x");
+}
+
+.hyperlink-button
+{
+ color: rgb(68, 113, 229);
+
+ border-color: rgba(0, 0, 0, 0);
+
+ background-color: rgba(0, 0, 0, 0);
+}
+
+.hyperlink-button:hover
+{
+ color: rgb(68, 133, 229);
+}
+
+.hyperlink-button:active
+{
+ color: rgb(68, 93, 229);
+}
+
+.group-content-box
+{
+
+}
+
+.foldout-box
+{
+ border-width: 0;
+ border-radius: 0;
+ background-color: rgb(56, 56, 56);
+}
+
+.foldout-box:hover
+{
+ background-color: rgb(68, 68, 68);
+}
+
+.foldout-box:active
+{
+ background-color: rgb(48, 48, 48);
+}
+
+.foldout-box-expanded
+{
+ background-color: rgb(68, 68, 68);
+}
+
+.open-in-browser-button
+{
+ border-width: 0;
+ border-radius: 0;
+
+ background-color: rgba(0, 0, 0, 0);
+ background-image: url("../../../Icons/open-in-browser.png");
+
+ -unity-background-image-tint-color: rgb(200, 200, 200);
+}
+
+.open-in-browser-button:hover
+{
+ -unity-background-image-tint-color: rgb(255, 255, 255);
+}
+
+.open-in-browser-button:active
+{
+ -unity-background-image-tint-color: rgb(155, 155, 155);
+}
+
+.expander
+{
+ color: rgb(104, 104, 104);
+}
+
+.package-image
+{
+ border-radius: 5px;
+ background-image: resource("Sprite Icon");
+}
+
+.package-image-not-found
+{
+ background-color: rgb(88, 88, 88);
+}
+
+.asset-label
+{
+ color: rgb(255, 255, 255);
+}
+
+.asset-info
+{
+ color: rgb(200, 200, 200);
+}
+
+.category-label
+{
+ color: rgb(200, 200, 200);
+}
+
+.header-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background
+{
+ border-width: 0;
+ background-color: rgba(0, 0, 0, 0);
+}
+
+.header-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background > .unity-progress-bar__progress
+{
+ background-image: none;
+ background-color: rgb(33, 150, 243);
+}
+
+.group-separator
+{
+ background-color: rgb(48, 48, 48);
+}
+
+/* Uploading functionality Window */
+
+.functionality-box
+{
+ background-color: rgb(68, 68, 68);
+}
+
+.workflow-dropdown
+{
+ color: rgb(238, 238, 238);
+
+ border-width: 1px;
+ border-radius: 3px;
+ border-color: rgb(36, 36, 36);
+
+ background-color: rgb(88, 88, 88);
+}
+
+.workflow-dropdown:hover
+{
+ background-color: rgb(103, 103, 103);
+}
+
+.extra-packages-scroll-view
+{
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+
+ background-color: rgb(58, 58, 58);
+}
+
+.extra-packages-scroll-view > * > .unity-scroll-view__vertical-scroller
+{
+ border-right-width: 0;
+}
+
+.filter-packages-dropdown
+{
+ color: rgb(188, 188, 188);
+
+ border-width: 1px;
+ border-radius: 3px;
+ border-color: rgb(36, 36, 36);
+
+ background-color: rgb(88, 88, 88);
+}
+
+.filter-packages-dropdown:hover
+{
+ background-color: rgb(103, 103, 103);
+}
+
+.filter-packages-dropdown:active
+{
+ background-color: rgb(73, 73, 73);
+}
+
+.no-packages-label
+{
+ color: rgb(200, 200, 200);
+}
+
+.packages-filtering-box
+{
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+
+ background-color: rgb(58, 58, 58);
+}
+
+.label-help-row > Image
+{
+ --unity-image: resource("d__Help@2x");
+}
+
+.upload-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background
+{
+ border-width: 0;
+ border-radius: 2px;
+}
+
+.upload-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background > .unity-progress-bar__progress
+{
+ background-image: none;
+ background-color: rgb(33, 150, 243);
+}
+
+.export-button, .upload-button, .cancel-button
+{
+ color: rgb(220, 220, 220);
+
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Dark.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Dark.uss.meta
new file mode 100644
index 000000000..a0a5bf97d
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Dark.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6320179b9eae0cc4cb6728a4392c4da5
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Light.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Light.uss
new file mode 100644
index 000000000..648ae05ff
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Light.uss
@@ -0,0 +1,291 @@
+/* Uploading Window */
+
+.assets-scroll-view
+{
+
+}
+
+.unity-scroller
+{
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+}
+
+.assets-scroll-view > .unity-scroll-view__content-viewport
+{
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+
+ background-color: rgb(200, 200, 200);
+}
+
+.assets-scroll-view > * > .unity-scroll-view__vertical-scroller
+{
+ border-right-width: 0;
+}
+
+.spinner-image
+{
+ --unity-image: resource("WaitSpin00");
+}
+
+.top-tools-row
+{
+ border-bottom-width: 1px;
+ border-color: rgb(33, 33, 33);
+
+ background-color: rgb(200, 200, 200);
+}
+
+.sort-menu
+{
+ color: rgb(9, 9, 9);
+
+ border-width: 1px;
+ border-radius: 3px;
+ border-color: rgb(178, 178, 178);
+
+ background-color: rgb(228, 228, 228);
+}
+
+.sort-menu:hover
+{
+ background-color: rgb(236, 236, 236);
+}
+
+.sort-menu:active
+{
+ background-color: rgb(220, 220, 220);
+}
+
+.group-expander-box
+{
+ border-width: 0;
+ border-color: rgba(0, 0, 0, 0);
+
+ background-color: rgba(0, 0, 0, 0);
+}
+
+.group-label
+{
+ color: rgb(0, 0, 0);
+}
+
+.info-box, .group-info-box
+{
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+}
+
+.info-box > Image, .group-info-box > Image
+{
+ --unity-image: resource("console.infoicon@2x");
+}
+
+.hyperlink-button
+{
+ color: rgb(68, 113, 229);
+
+ border-color: rgba(0, 0, 0, 0);
+
+ background-color: rgba(0, 0, 0, 0);
+}
+
+.hyperlink-button:hover
+{
+ color: rgb(68, 133, 229);
+}
+
+.hyperlink-button:active
+{
+ color: rgb(68, 93, 229);
+}
+
+.group-content-box
+{
+
+}
+
+.foldout-box
+{
+ border-width: 0;
+ border-radius: 0;
+ background-color: rgb(198, 198, 198);
+}
+
+.foldout-box:hover
+{
+ background-color: rgb(212, 212, 212);
+}
+
+.foldout-box:active
+{
+ background-color: rgb(180, 180, 180);
+}
+
+.foldout-box-expanded
+{
+ background-color: rgb(212, 212, 212);
+}
+
+.open-in-browser-button
+{
+ border-width: 0;
+ border-radius: 0;
+
+ background-color: rgba(0, 0, 0, 0);
+ background-image: url("../../../Icons/open-in-browser.png");
+
+ -unity-background-image-tint-color: rgb(200, 200, 200);
+}
+
+.open-in-browser-button:hover
+{
+ -unity-background-image-tint-color: rgb(255, 255, 255);
+}
+
+.open-in-browser-button:active
+{
+ -unity-background-image-tint-color: rgb(155, 155, 155);
+}
+
+.expander
+{
+ color: rgb(77, 77, 77);
+}
+
+.package-image
+{
+ border-radius: 5px;
+ background-image: resource("Sprite Icon");
+}
+
+.package-image-not-found
+{
+ background-color: rgb(160, 160, 160);
+}
+
+.asset-label
+{
+ color: rgb(0, 0, 0);
+}
+
+.asset-info
+{
+ color: rgb(48, 48, 48);
+}
+
+.category-label
+{
+ color: rgb(48, 48, 48);
+}
+
+.header-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background
+{
+ border-width: 0;
+ background-color: rgba(0, 0, 0, 0);
+}
+
+.header-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background > .unity-progress-bar__progress
+{
+ background-image: none;
+ background-color: rgb(108, 157, 243);
+}
+
+.group-separator
+{
+ background-color: rgb(48, 48, 48);
+}
+
+/* Uploading functionality Window */
+
+.functionality-box
+{
+ background-color: rgb(212, 212, 212);
+}
+
+.workflow-dropdown
+{
+ color: rgb(9, 9, 9);
+
+ border-width: 1px;
+ border-radius: 3px;
+ border-color: rgb(178, 178, 178);
+
+ background-color: rgb(228, 228, 228);
+}
+
+.workflow-dropdown:hover
+{
+ background-color: rgb(236, 236, 236);
+}
+
+.extra-packages-scroll-view
+{
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+
+ background-color: rgb(200, 200, 200);
+}
+
+.extra-packages-scroll-view > * > .unity-scroll-view__vertical-scroller
+{
+ border-right-width: 0;
+}
+
+.filter-packages-dropdown
+{
+ color: rgb(9, 9, 9);
+
+ border-width: 1px;
+ border-radius: 3px;
+ border-color: rgb(178, 178, 178);
+
+ background-color: rgb(228, 228, 228);
+}
+
+.filter-packages-dropdown:hover
+{
+ background-color: rgb(236, 236, 236);
+}
+
+.filter-packages-dropdown:active
+{
+ background-color: rgb(220, 220, 220);
+}
+
+.no-packages-label
+{
+ color: rgb(0, 0, 0);
+}
+
+.packages-filtering-box
+{
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+
+ background-color: rgb(200, 200, 200);
+}
+
+.label-help-row > Image
+{
+ --unity-image: resource("_Help@2x");
+}
+
+.upload-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background
+{
+ border-width: 0;
+ border-radius: 2px;
+}
+
+.upload-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background > .unity-progress-bar__progress
+{
+ background-image: none;
+ background-color: rgb(108, 157, 243);
+}
+
+.export-button, .upload-button, .cancel-button
+{
+ border-width: 1px;
+ border-color: rgb(33, 33, 33);
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Light.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Light.uss.meta
new file mode 100644
index 000000000..93652113d
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Light.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2e1bb62d57954d94690fac6155f453ab
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Main.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Main.uss
new file mode 100644
index 000000000..ff116df6b
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Main.uss
@@ -0,0 +1,574 @@
+.assets-scroll-view
+{
+ flex-grow: 1;
+ flex-shrink: 1;
+}
+
+.assets-scroll-view > .unity-scroll-view__content-viewport
+{
+ margin-left: 1px;
+}
+
+.assets-scroll-view > * > .unity-scroll-view__vertical-scroller
+{
+ width: 14px;
+}
+
+.spinner-box
+{
+ flex-grow: 1;
+ flex-shrink: 1;
+
+ justify-content: center;
+}
+
+.spinner-image
+{
+ align-self: center;
+
+ width: 16px;
+ height: 16px;
+}
+
+.top-tools-row
+{
+ flex-direction: row;
+ flex-shrink: 0;
+
+ justify-content: space-between;
+
+ height: 24px;
+
+ margin: 0 -1px 0 -1px;
+}
+
+.package-search-field
+{
+ flex-grow: 1;
+ flex-shrink: 1;
+
+ align-items: center;
+
+ width: 250px;
+ margin: 1px 5px;
+}
+
+.package-search-field > #unity-search
+{
+ margin-top: 0;
+}
+
+.package-search-field > * > .unity-base-field__input
+{
+ font-size: 12px;
+
+ padding-left: 5px;
+}
+
+.sort-menu
+{
+ flex-grow: 0;
+ flex-shrink: 0;
+
+ align-self: center;
+
+ width: 155px;
+ height: 19px;
+
+ margin: 1px 3px;
+ padding: 1px 6px;
+}
+
+.package-group
+{
+ overflow: hidden;
+}
+
+.group-expander-box
+{
+ flex-direction: row;
+ flex-grow: 0;
+ flex-shrink: 0;
+
+ align-items: center;
+
+ min-width: 200px;
+ min-height: 30px;
+
+ margin: 10px -1px 2px -1px;
+}
+
+.group-label
+{
+ font-size: 14px;
+ -unity-font-style: bold;
+}
+
+.group-info-box
+{
+ margin: 5px;
+}
+
+.group-content-box
+{
+ margin: -2px -2px -2px -2px;
+}
+
+.full-package-box
+{
+ flex-direction: column;
+ flex-shrink: 0;
+ flex-grow: 0;
+}
+
+.foldout-box
+{
+ flex-direction: column;
+}
+
+.foldout-box-info
+{
+ flex-direction: row;
+ flex-grow: 0;
+ flex-shrink: 0;
+
+ align-items: center;
+ justify-content: space-between;
+
+ min-width: 200px;
+ min-height: 50px;
+
+ margin: 2px;
+}
+
+.foldout-box-expanded
+{
+ padding-top: 5px;
+ top: -4px;
+}
+
+.expander-label-row
+{
+ flex-basis: 200px;
+ flex-direction: row;
+ flex-grow: 1;
+}
+
+.asset-label-info-box
+{
+ flex-direction: column;
+ flex-grow: 1;
+ flex-shrink: 1;
+
+ align-self: center;
+}
+
+.asset-label
+{
+ flex-shrink: 1;
+
+ align-self: stretch;
+
+ -unity-text-align: middle-left;
+ -unity-font-style: bold;
+ white-space: normal;
+}
+
+.asset-info
+{
+ font-size: 11px;
+ -unity-text-align: middle-left;
+ white-space: normal;
+}
+
+.expander
+{
+ align-self: center;
+
+ width: 30px;
+ height: 30px;
+}
+
+.open-in-browser-button
+{
+ flex-shrink: 0;
+
+ width: 16px;
+ height: 16px;
+
+ -unity-background-scale-mode: scale-to-fit;
+}
+
+.package-image
+{
+ flex-shrink: 0;
+
+ width: 48px;
+ height: 48px;
+
+ margin: 0 5px;
+}
+
+.header-progress-bar
+{
+ margin: 0 -6px -1px -6px;
+ padding: 0 0 2px 0;
+}
+
+.header-progress-bar > * > .unity-progress-bar__background
+{
+ height: 5px;
+}
+
+.group-separator
+{
+ height: 2px;
+
+ margin: 5px 15px;
+
+ display: none;
+}
+
+/*
+PACKAGE OPTIONS
+*/
+
+.title-text-row
+{
+ flex-direction: row;
+ flex-shrink: 0;
+
+ justify-content: flex-start;
+}
+
+.info-title
+{
+ -unity-font-style: bold;
+}
+
+.info-text
+{
+ white-space: normal;
+}
+
+.title-icon-row
+{
+ flex-direction: row;
+ flex-shrink: 0;
+
+ justify-content: flex-start;
+
+ margin-top: 10px;
+ margin-bottom: 4px;
+}
+
+.upload-label
+{
+ font-size: 14px;
+ -unity-text-align: middle-left;
+ -unity-font-style: bold;
+}
+
+.section-icon
+{
+ height: 14px;
+ width: 14px;
+ align-self: center;
+}
+
+.functionality-box
+{
+ flex-grow: 1;
+ flex-shrink: 0;
+
+ margin: -5px 3px 2px 3px;
+ padding: 5px 10px 5px 40px;
+}
+
+.upload-box
+{
+ margin-top: 10px;
+ padding-bottom: 10px;
+}
+
+/* NEW */
+
+.selection-box-row
+{
+ flex-direction: row;
+
+ margin-top: 10px;
+}
+
+.label-help-row
+{
+ flex-direction: row;
+ flex-shrink: 0;
+
+ align-self: flex-start;
+ align-items: center;
+ justify-content: flex-start;
+
+ width: 115px;
+}
+
+.label-help-row > Label
+{
+ -unity-text-align: middle-left;
+}
+
+.label-help-row > Image
+{
+ height: 16px;
+ width: 16px;
+}
+
+.workflow-dropdown
+{
+ flex-grow: 1;
+ flex-shrink: 1;
+
+ align-self: stretch;
+
+ margin-right: 0;
+ margin-left: 3px;
+}
+
+.path-selection-field
+{
+ flex-grow: 1;
+ flex-shrink: 1;
+
+ align-self: stretch;
+}
+
+.dependencies-toggle > * > .unity-label
+{
+ margin-left: 5px;
+}
+
+.browse-button
+{
+ margin-right: 0;
+}
+
+.special-folders-toggles-box
+{
+ flex-grow: 1;
+}
+
+.extra-packages-box
+{
+ flex-grow: 1;
+ flex-direction: column;
+}
+
+.no-packages-label
+{
+ flex-grow: 1;
+
+ font-size: 11px;
+ -unity-text-align: middle-center;
+ white-space: normal;
+
+ display: none;
+}
+
+.packages-filtering-box
+{
+ flex-direction: row;
+
+ margin: -1px 0 0 3px;
+}
+
+.filtering-packages-dropdown-box
+{
+ flex-grow: 1;
+ flex-direction: row;
+
+ align-items: center;
+ justify-content: flex-start;
+
+ margin-top: 1px;
+ margin-left: 1px;
+}
+
+.filtering-packages-buttons-box
+{
+ flex-grow: 1;
+ flex-shrink: 1;
+ flex-direction: row;
+
+ align-items: center;
+ justify-content: flex-end;
+
+ margin-top: 1px;
+}
+
+.filter-packages-toggle
+{
+ width: 19px;
+ height: 19px;
+
+ margin: 0;
+}
+
+.filter-packages-dropdown
+{
+ width: 100px;
+
+ margin: 0;
+}
+
+.filter-packages-button
+{
+ flex-shrink: 1;
+
+ width: 75px;
+
+ margin-right: 0;
+}
+
+.extra-packages-buttons-box
+{
+ flex-grow: 1;
+ flex-direction: row;
+}
+
+.extra-packages-scroll-view
+{
+ flex-grow: 1;
+
+ height: 100px;
+
+ margin-left: 3px;
+}
+
+.extra-packages-scroll-view > .unity-scroll-view__content-viewport
+{
+ margin-left: 1px;
+}
+
+.extra-packages-scroll-view > * > .unity-scroll-view__content-container
+{
+ padding: 3px 0 5px 0;
+}
+
+.extra-packages-scroll-view > * > .unity-scroll-view__vertical-scroller
+{
+ margin: -1px 0;
+}
+
+.extra-packages-toggle
+{
+ padding: 2px 0 0 5px;
+}
+
+.special-folder-toggle > * > .unity-label, .extra-packages-toggle > * > .unity-label
+{
+ margin-left: 5px;
+}
+
+.info-box, .group-info-box
+{
+ flex-direction: row;
+
+ align-items: center;
+
+ font-size: 12px;
+
+ margin-top: 5px;
+}
+
+.info-box > Image, .group-info-box > Image
+{
+ flex-direction: row;
+ flex-shrink: 0;
+
+ width: 32px;
+ height: 32px;
+
+ margin: 5px 10px;
+}
+
+.info-box > Label, .group-info-box > Label
+{
+ flex-grow: 1;
+ flex-shrink: 1;
+
+ -unity-text-align: middle-left;
+ white-space: normal;
+
+ margin-right: 5px;
+}
+
+.info-box > Button
+{
+ margin-right: 10px;
+}
+
+.hyperlink-button-container
+{
+ flex-shrink: 0;
+ padding: 0 10px 0 10px;
+}
+
+.hyperlink-button
+{
+ margin: 0;
+ padding: 4px 0 4px 0;
+}
+
+.progress-upload-box
+{
+ margin-top: 10px;
+}
+
+.export-and-upload-container, .upload-progress-container
+{
+ flex-direction: row;
+}
+
+.export-button
+{
+ flex-grow: 1;
+
+ width: 95px;
+ height: 24px;
+
+ margin: 0 5px 0 0;
+}
+
+ .upload-button
+ {
+ flex-grow: 1;
+
+ width: 95px;
+ height: 24px;
+
+ margin: 0;
+ }
+
+.cancel-button
+{
+ width: 95px;
+ height: 24px;
+
+ margin: 0;
+}
+
+.upload-progress-bar
+{
+ flex-grow: 1;
+ flex-shrink: 1;
+
+ justify-content: center;
+
+ padding: 0;
+ margin: 0 10px 0 0;
+}
+
+.upload-progress-bar > * > .unity-progress-bar__background
+{
+ height: 22px;
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Main.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Main.uss.meta
new file mode 100644
index 000000000..f90d2d06c
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/AllPackages/AllPackages_Main.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 703ea091ed1e85049b6c0e6b94f4aba3
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Dark.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Dark.uss
new file mode 100644
index 000000000..7613a4a6d
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Dark.uss
@@ -0,0 +1,7 @@
+.bottom-tools-row
+{
+ border-top-width: 1px;
+ border-color: rgb(33, 33, 33);
+
+ background-color: rgb(68, 68, 68);
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Dark.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Dark.uss.meta
new file mode 100644
index 000000000..1627de3a9
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Dark.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 42629fa0950d47d4fb25ead7ae74591f
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Light.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Light.uss
new file mode 100644
index 000000000..175243ef6
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Light.uss
@@ -0,0 +1,7 @@
+.bottom-tools-row
+{
+ border-top-width: 1px;
+ border-color: rgb(33, 33, 33);
+
+ background-color: rgb(200, 200, 200);
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Light.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Light.uss.meta
new file mode 100644
index 000000000..6f2afd5d4
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Light.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a7a6eb19ec987844280ce30ca2135cca
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Main.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Main.uss
new file mode 100644
index 000000000..39cfd7fd6
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Main.uss
@@ -0,0 +1,34 @@
+#UploadWindow
+{
+ flex-grow: 1;
+ overflow: hidden;
+}
+
+.bottom-tools-row
+{
+ flex-direction: row;
+ flex-shrink: 0;
+
+ justify-content: space-between;
+ margin: 0;
+}
+
+.toolbar-left-side-container
+{
+ align-self: center;
+ flex-direction: row;
+ margin: 3px 0 3px 5px;
+}
+
+.toolbar-right-side-container
+{
+ align-self: center;
+ flex-direction: row;
+ flex-shrink: 0;
+ margin: 0;
+}
+
+.refresh-button, .logout-button, .ongoing-uploads-button, .all-packages-button
+{
+ min-width: 50px;
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Main.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Main.uss.meta
new file mode 100644
index 000000000..8508fca16
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Upload/UploadWindow_Main.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fd40f16a3ddafd6438ecc0f5c2017593
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility.meta b/Packages/com.unity.asset-store-tools/Editor/Utility.meta
new file mode 100644
index 000000000..9a2bdffe5
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3dfd03e520c145b45a32c7e2915fe3cb
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs
new file mode 100644
index 000000000..ad8acb90b
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs
@@ -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;
+ }
+ }
+ }
+}
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs.meta
new file mode 100644
index 000000000..2f4aab787
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 478caa497d99100429a0509fa487bfe4
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ASError.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/ASError.cs
new file mode 100644
index 000000000..c5d9433e0
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ASError.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Net;
+using System.Net.Http;
+
+namespace AssetStoreTools.Utility
+{
+ ///
+ /// A structure for retrieving and converting errors from Asset Store Tools class methods
+ ///
+ 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("", StringComparison.Ordinal) + "".Length;
+ var endIndex = html.IndexOf("
", 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ASError.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/ASError.cs.meta
new file mode 100644
index 000000000..3e3eee6e7
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ASError.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 265ad6f65404f8c42aec35d3b8e6f970
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs
new file mode 100644
index 000000000..32bb0f529
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs
@@ -0,0 +1,122 @@
+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()
+ {
+ LegacyVersionCheck = PlayerPrefs.GetInt("AST_LegacyVersionCheck", 1) == 1;
+ UploadVersionCheck = PlayerPrefs.GetInt("AST_UploadVersionCheck", 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_LegacyVersionCheck", LegacyVersionCheck ? 1 : 0);
+ PlayerPrefs.SetInt("AST_UploadVersionCheck", UploadVersionCheck ? 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();
+ }
+
+ ///
+ /// Check if legacy Asset Store Tools are in the Project
+ ///
+ public bool LegacyVersionCheck;
+
+ ///
+ /// Check if the package has been uploader from a correct Unity version at least once
+ ///
+ public bool UploadVersionCheck;
+
+ ///
+ /// Enables Junction symlink support
+ ///
+ public bool EnableSymlinkSupport;
+
+ ///
+ /// Enables legacy exporting for Folder Upload workflow
+ ///
+ public bool UseLegacyExporting;
+
+ ///
+ /// Enables DisplayDialog to be shown after the uploading ends
+ ///
+ public bool DisplayUploadDialog;
+ }
+
+ internal class ASToolsPreferencesProvider : SettingsProvider
+ {
+ private const string SettingsPath = "Project/Asset Store Tools";
+
+ private class Styles
+ {
+ 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 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 keywords = null)
+ : base(path, scopes, keywords) { }
+
+ public override void OnGUI(string searchContext)
+ {
+ var preferences = ASToolsPreferences.Instance;
+ EditorGUI.BeginChangeCheck();
+ using (CreateSettingsWindowGUIScope())
+ {
+ preferences.LegacyVersionCheck = EditorGUILayout.Toggle(Styles.LegacyVersionCheckLabel, preferences.LegacyVersionCheck);
+ preferences.UploadVersionCheck = EditorGUILayout.Toggle(Styles.UploadVersionCheckLabel, preferences.UploadVersionCheck);
+ 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());
+ return provider;
+ }
+
+ private IDisposable CreateSettingsWindowGUIScope()
+ {
+ var unityEditorAssembly = Assembly.GetAssembly(typeof(EditorWindow));
+ var type = unityEditorAssembly.GetType("UnityEditor.SettingsWindow+GUIScope");
+ return Activator.CreateInstance(type) as IDisposable;
+ }
+ }
+}
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs.meta
new file mode 100644
index 000000000..56807b0b8
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b75179c8d22a35b42a543d6fa7857ce0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs
new file mode 100644
index 000000000..c99f01b25
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs
@@ -0,0 +1,40 @@
+using System.IO;
+
+namespace AssetStoreTools.Utility
+{
+ internal static class FileUtility
+ {
+ 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);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs.meta
new file mode 100644
index 000000000..db285bb40
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 80819cf6868374d478a8a38ebaba8e27
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/Json.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/Json.cs
new file mode 100644
index 000000000..582e9b3aa
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/Json.cs
@@ -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 s)
+ {
+ return new JsonValue(s);
+ }
+
+ public static implicit operator List(JsonValue s)
+ {
+ return s.AsList();
+ }
+
+ public static implicit operator Dictionary(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; }
+ public bool IsDict() { return data is Dictionary; }
+ 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 AsList(bool nothrow = false)
+ {
+ if (data is List)
+ return (List)data;
+ if (!nothrow)
+ throw new JSONTypeException("Tried to read " + data.GetType().Name + " json value as list");
+ return null;
+ }
+ public Dictionary AsDict(bool nothrow = false)
+ {
+ if (data is Dictionary)
+ return (Dictionary)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());
+ }
+
+ public static JsonValue NewList()
+ {
+ return new JsonValue(new List());
+ }
+
+ public static JsonValue NewBool(bool val)
+ {
+ return new JsonValue(val);
+ }
+
+ public static JsonValue NewNull()
+ {
+ return new JsonValue(null);
+ }
+
+ public JsonValue InitList()
+ {
+ data = new List();
+ return this;
+ }
+
+ public JsonValue InitDict()
+ {
+ data = new Dictionary();
+ return this;
+ }
+
+ public JsonValue this[string index]
+ {
+ get
+ {
+ Dictionary dict = AsDict();
+ return dict[index];
+ }
+ set
+ {
+ if (data == null)
+ data = new Dictionary();
+ Dictionary 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 list = AsList();
+ if (value == null)
+ {
+ list.Add(NewNull());
+ return;
+ }
+ list.Add(NewString(value));
+ }
+
+ // Convenience list value add
+ public void Add(float value)
+ {
+ List list = AsList();
+ list.Add(NewFloat(value));
+ }
+
+ // Convenience list value add
+ public void Add(bool value)
+ {
+ List 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 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 arr = new List();
+ while (cur != ']')
+ {
+ arr.Add(ParseValue());
+ SkipWs();
+ if (cur == ',')
+ {
+ Next();
+ SkipWs();
+ }
+ }
+ Next();
+ return new JsonValue(arr);
+ }
+
+ private JsonValue ParseDict()
+ {
+ Next();
+ SkipWs();
+ Dictionary dict = new Dictionary();
+ 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());
+ }
+ };
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/Json.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/Json.cs.meta
new file mode 100644
index 000000000..fb4354035
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/Json.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 1
+guid: 0a7878c3076bf174ea5c0a1cf7bd3a39
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs
new file mode 100644
index 000000000..c9df7c216
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs
@@ -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);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs.meta
new file mode 100644
index 000000000..c16ca0a51
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 46ead42026b1f0b4e94153e1a7e10d12
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs
new file mode 100644
index 000000000..63a477521
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs
@@ -0,0 +1,56 @@
+#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
+ {
+ ///
+ /// 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
+ ///
+ 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)
+ .Where(x => x.isDirectDependency).ToArray();
+ return registryPackages;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs.meta
new file mode 100644
index 000000000..6ce8b3dff
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 605ea62f8b11d674a95a53f895df4c67
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs
new file mode 100644
index 000000000..d221cb47b
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs
@@ -0,0 +1,48 @@
+using UnityEditor;
+using UnityEngine.UIElements;
+
+namespace AssetStoreTools.Utility
+{
+ internal static class StyleSelector
+ {
+ private static StyleSheet GetStylesheet(string stylesheetPath)
+ {
+ return AssetDatabase.LoadAssetAtPath(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 BaseWindowStyle => GetStylesheet($"{StylesPath}/Validator_Main.uss");
+ public static StyleSheet BaseWindowTheme => !EditorGUIUtility.isProSkin ?
+ GetStylesheet($"{StylesPath}/Validator_Light.uss") :
+ GetStylesheet($"{StylesPath}/Validator_Dark.uss");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs.meta
new file mode 100644
index 000000000..d4ab01c42
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8b066ce502a289a4ca311a86fbf83f45
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs
new file mode 100644
index 000000000..ee7208a1a
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs
@@ -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;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs.meta
new file mode 100644
index 000000000..43c8aaf5c
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 92092535fd064bb1843017f98db213e1
+timeCreated: 1659013521
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator.meta b/Packages/com.unity.asset-store-tools/Editor/Validator.meta
new file mode 100644
index 000000000..e27c1efda
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 980c7bb65c02d464684c2220c57fcd75
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/AssetStoreValidator.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/AssetStoreValidator.cs
new file mode 100644
index 000000000..fe45a5795
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/AssetStoreValidator.cs
@@ -0,0 +1,50 @@
+using AssetStoreTools.Utility;
+using AssetStoreTools.Validator.UIElements;
+using System;
+using UnityEditor.UIElements;
+using UnityEngine;
+using UnityEngine.UIElements;
+
+namespace AssetStoreTools.Validator
+{
+ internal class AssetStoreValidator : AssetStoreToolsWindow
+ {
+ protected override string WindowTitle => "Asset Store Validator";
+
+ public static Action OnWindowDestroyed;
+
+ private AutomatedTestsGroup _automatedTestsGroup;
+
+ protected override void Init()
+ {
+ minSize = new Vector2(350, 350);
+
+ base.Init();
+ this.SetAntiAliasing(4);
+
+ VisualElement root = rootVisualElement;
+
+ root.AddToClassList("root");
+
+ // Clean it out, in case the window gets initialized again
+ root.Clear();
+
+ // Getting a reference to the USS Document and adding stylesheet to the root
+ root.styleSheets.Add(StyleSelector.ValidatorWindow.BaseWindowStyle);
+ root.styleSheets.Add(StyleSelector.ValidatorWindow.BaseWindowTheme);
+
+ ConstructWindow();
+ }
+
+ private void ConstructWindow()
+ {
+ _automatedTestsGroup = new AutomatedTestsGroup();
+ rootVisualElement.Add(_automatedTestsGroup);
+ }
+
+ private void OnDestroy()
+ {
+ OnWindowDestroyed?.Invoke();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/AssetStoreValidator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/AssetStoreValidator.cs.meta
new file mode 100644
index 000000000..2646fc81d
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/AssetStoreValidator.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4fdc092edc6b5b049bdf5c59068cd3bf
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons.meta
new file mode 100644
index 000000000..7f4c321da
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 8490c57c02b441e4dab99565da835c99
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png
new file mode 100644
index 000000000..8d294bc19
Binary files /dev/null and b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png differ
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png.meta
new file mode 100644
index 000000000..4217052ea
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png.meta
@@ -0,0 +1,128 @@
+fileFormatVersion: 2
+guid: 0cc0ccdb7de3e964ab553ce3c299d83c
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 0
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 1
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 0
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 0
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: iPhone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Android
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error_d.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error_d.png
new file mode 100644
index 000000000..451f64037
Binary files /dev/null and b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error_d.png differ
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error_d.png.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error_d.png.meta
new file mode 100644
index 000000000..5ccdf2678
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error_d.png.meta
@@ -0,0 +1,128 @@
+fileFormatVersion: 2
+guid: cdf8d51df19d58341886cc474e810c7b
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 0
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 1
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 0
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 0
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: iPhone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Android
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success.png
new file mode 100644
index 000000000..a5f78532b
Binary files /dev/null and b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success.png differ
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success.png.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success.png.meta
new file mode 100644
index 000000000..c08b38345
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success.png.meta
@@ -0,0 +1,128 @@
+fileFormatVersion: 2
+guid: 832e106a677623145b3d8dbe015e31a0
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 0
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 1
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 0
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 0
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: iPhone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Android
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png
new file mode 100644
index 000000000..094a810f9
Binary files /dev/null and b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png differ
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png.meta
new file mode 100644
index 000000000..674113081
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png.meta
@@ -0,0 +1,128 @@
+fileFormatVersion: 2
+guid: 3dc139a2b2a28a54a8f39e266fc0af9c
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 0
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 1
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 0
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 0
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: iPhone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Android
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined.png
new file mode 100644
index 000000000..a587baa45
Binary files /dev/null and b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined.png differ
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined.png.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined.png.meta
new file mode 100644
index 000000000..47db8b0e1
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined.png.meta
@@ -0,0 +1,128 @@
+fileFormatVersion: 2
+guid: 4a4eef842709db34cbb71baf22384730
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 0
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 1
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 0
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 0
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: iPhone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Android
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined_d.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined_d.png
new file mode 100644
index 000000000..b7e2681e6
Binary files /dev/null and b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined_d.png differ
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined_d.png.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined_d.png.meta
new file mode 100644
index 000000000..029753f10
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined_d.png.meta
@@ -0,0 +1,128 @@
+fileFormatVersion: 2
+guid: 88a36c7e4d60b6b4385c95cfc2d00c22
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 0
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 1
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 0
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 0
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: iPhone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Android
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning.png
new file mode 100644
index 000000000..aab9fee1e
Binary files /dev/null and b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning.png differ
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning.png.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning.png.meta
new file mode 100644
index 000000000..05dd39d25
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning.png.meta
@@ -0,0 +1,128 @@
+fileFormatVersion: 2
+guid: 83d0e58aa5f608a4b8232fbacca5ca89
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 0
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 1
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 0
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 0
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: iPhone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Android
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning_d.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning_d.png
new file mode 100644
index 000000000..553bb16d8
Binary files /dev/null and b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning_d.png differ
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning_d.png.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning_d.png.meta
new file mode 100644
index 000000000..3e0843ed1
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning_d.png.meta
@@ -0,0 +1,128 @@
+fileFormatVersion: 2
+guid: d27d359f48fa1a14e9e4f02196589805
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 0
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 1
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 0
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 0
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: iPhone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Android
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts.meta
new file mode 100644
index 000000000..5a815351c
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1b5ff7c95381e82438f6c9dc40069031
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories.meta
new file mode 100644
index 000000000..0c29f2c0d
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 7a971a9a200a4438945853d71066f16a
+timeCreated: 1657617558
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/CategoryEvaluator.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/CategoryEvaluator.cs
new file mode 100644
index 000000000..7eb5a10d5
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/CategoryEvaluator.cs
@@ -0,0 +1,45 @@
+using AssetStoreTools.Validator.Data;
+using AssetStoreTools.Validator.TestDefinitions;
+
+namespace AssetStoreTools.Validator.Categories
+{
+ internal class CategoryEvaluator
+ {
+ private string _category;
+
+ public CategoryEvaluator(string category)
+ {
+ _category = category;
+ }
+
+ public void SetCategory(string category)
+ {
+ _category = category;
+ }
+
+ public string GetCategory()
+ {
+ return _category;
+ }
+
+ public TestResult.ResultStatus Evaluate(ValidationTest validation, bool slugify = false)
+ {
+ var result = validation.Result.Result;
+ if (result != TestResult.ResultStatus.VariableSeverityIssue)
+ return result;
+
+ var category = _category;
+
+ if (slugify)
+ category = validation.Slugify(category);
+
+ return validation.CategoryInfo.EvaluateByFilter(category);
+ }
+
+ // Used by ab-builder
+ public TestResult.ResultStatus EvaluateAndSlugify(ValidationTest validation)
+ {
+ return Evaluate(validation, true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/CategoryEvaluator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/CategoryEvaluator.cs.meta
new file mode 100644
index 000000000..3bc124c61
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/CategoryEvaluator.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: eb61fd62b94248e4b5a3a07665b1a2bf
+timeCreated: 1661420659
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/ValidatorCategory.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/ValidatorCategory.cs
new file mode 100644
index 000000000..d62ae257f
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/ValidatorCategory.cs
@@ -0,0 +1,38 @@
+using AssetStoreTools.Validator.Data;
+using System;
+using System.Linq;
+
+namespace AssetStoreTools.Validator.Categories
+{
+ [System.Serializable]
+ internal class ValidatorCategory
+ {
+ public bool IsFailFilter = false;
+ public bool IsInclusiveFilter = true;
+ public bool AppliesToSubCategories = true;
+ public string[] Filter = { "Tools", "Art" };
+
+ public TestResult.ResultStatus EvaluateByFilter(string category)
+ {
+ if (AppliesToSubCategories)
+ category = category.Split('/')[0];
+
+ var isCategoryInFilter = Filter.Any(x => String.Compare(x, category, StringComparison.OrdinalIgnoreCase) == 0);
+
+ if (IsInclusiveFilter)
+ {
+ if (isCategoryInFilter)
+ return IsFailFilter ? TestResult.ResultStatus.Fail : TestResult.ResultStatus.Warning;
+ else
+ return IsFailFilter ? TestResult.ResultStatus.Warning : TestResult.ResultStatus.Fail;
+ }
+ else
+ {
+ if (isCategoryInFilter)
+ return IsFailFilter ? TestResult.ResultStatus.Warning : TestResult.ResultStatus.Fail;
+ else
+ return IsFailFilter ? TestResult.ResultStatus.Fail : TestResult.ResultStatus.Warning;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/ValidatorCategory.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/ValidatorCategory.cs.meta
new file mode 100644
index 000000000..269076976
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/ValidatorCategory.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: a5e60d3639f24063a4eabc21ea1a04a9
+timeCreated: 1657617578
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data.meta
new file mode 100644
index 000000000..3b4006366
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1c2a38ded8e054c4088aff1db7224f66
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions.cs
new file mode 100644
index 000000000..04a34d1c5
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions.cs
@@ -0,0 +1,75 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace AssetStoreTools.Validator.Data
+{
+ internal interface IMessageAction
+ {
+ string ActionTooltip { get; }
+
+ void Execute();
+ }
+
+ internal enum ClickActionType
+ {
+ None = 0,
+ HighlightObject = 1,
+ OpenAsset = 2
+ }
+
+ internal class MessageActionHighlight : IMessageAction
+ {
+ private Object _objectToHighlight;
+
+ public GlobalObjectId GlobalObjectIdentifier { get; set; }
+ public string ActionTooltip => "Click to highlight the associated object in Hierarchy/Project view";
+
+ public MessageActionHighlight(Object objectToHighlight)
+ {
+ this._objectToHighlight = objectToHighlight;
+ GlobalObjectIdentifier = GlobalObjectId.GetGlobalObjectIdSlow(objectToHighlight);
+ }
+
+ public MessageActionHighlight(string globalObjectId)
+ {
+ GlobalObjectId.TryParse(globalObjectId, out GlobalObjectId globalObjectIdentifier);
+ GlobalObjectIdentifier = globalObjectIdentifier;
+ }
+
+ public void Execute()
+ {
+ if(_objectToHighlight == null)
+ _objectToHighlight = GlobalObjectId.GlobalObjectIdentifierToObjectSlow(GlobalObjectIdentifier);
+
+ EditorGUIUtility.PingObject(_objectToHighlight);
+ }
+ }
+
+ internal class MessageActionOpenAsset : IMessageAction
+ {
+ private Object _objectToOpen;
+ public int LineNumber { get; set; }
+
+ public GlobalObjectId GlobalObjectIdentifier { get; set; }
+ public string ActionTooltip => "Click to open the associated asset";
+
+ public MessageActionOpenAsset(Object objectToOpen)
+ {
+ this._objectToOpen = objectToOpen;
+ GlobalObjectIdentifier = GlobalObjectId.GetGlobalObjectIdSlow(objectToOpen);
+ }
+
+ public MessageActionOpenAsset(string globalObjectId)
+ {
+ GlobalObjectId.TryParse(globalObjectId, out GlobalObjectId globalObjectIdentifier);
+ GlobalObjectIdentifier = globalObjectIdentifier;
+ }
+
+ public void Execute()
+ {
+ if (_objectToOpen == null)
+ _objectToOpen = GlobalObjectId.GlobalObjectIdentifierToObjectSlow(GlobalObjectIdentifier);
+ AssetDatabase.OpenAsset(_objectToOpen, LineNumber);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions.cs.meta
new file mode 100644
index 000000000..03495643d
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c6c8b1f23bf5c8841be44b13374e7baf
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResult.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResult.cs
new file mode 100644
index 000000000..ef23d751b
--- /dev/null
+++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResult.cs
@@ -0,0 +1,153 @@
+using System.Collections.Generic;
+using System;
+using UnityEngine;
+using UnityEditor;
+using Object = UnityEngine.Object;
+
+namespace AssetStoreTools.Validator.Data
+{
+ [Serializable]
+ internal struct TestResult
+ {
+ public ResultStatus Result;
+
+ [SerializeField, HideInInspector]
+ private List Messages;
+
+ public int MessageCount => Messages?.Count ?? 0;
+
+ public void AddMessage(string msg)
+ {
+ AddMessage(msg, null, null);
+ }
+
+ public void AddMessage(string msg, IMessageAction clickAction)
+ {
+ AddMessage(msg, clickAction, null);
+ }
+
+ public void AddMessage(string msg, IMessageAction clickAction, params UnityEngine.Object[] messageObjects)
+ {
+ if (Messages == null)
+ Messages = new List();
+
+ var message = new TestResultMessage(msg, clickAction);
+ if (messageObjects != null)
+ foreach (var obj in messageObjects)
+ message.AddMessageObject(obj);
+
+ Messages.Add(message);
+ }
+
+ public TestResultMessage GetMessage(int index)
+ {
+ if (Messages == null || index >= Messages.Count)
+ throw new InvalidOperationException();
+ return Messages[index];
+ }
+
+ public enum ResultStatus
+ {
+ Undefined = 0,
+ Pass = 1,
+ Fail = 2,
+ Warning = 3,
+ VariableSeverityIssue = 4
+ }
+
+ [Serializable]
+ internal class TestResultMessage : ISerializationCallbackReceiver
+ {
+ [SerializeField, HideInInspector]
+ private string Text;
+ [SerializeField, HideInInspector]
+ private List MessageObjects;
+ // Serialization
+ [SerializeField, HideInInspector]
+ private string SerializedClickAction;
+
+ private IMessageAction _clickAction;
+
+ public IMessageAction ClickAction => _clickAction;
+
+ public TestResultMessage() { }
+
+ public TestResultMessage(string text)
+ {
+ Text = text;
+ }
+
+ public TestResultMessage(string text, IMessageAction clickAction) : this(text)
+ {
+ _clickAction = clickAction;
+ }
+
+ public void AddMessageObject(Object obj)
+ {
+ if (MessageObjects == null)
+ MessageObjects = new List();
+ var globalObjectId = GlobalObjectId.GetGlobalObjectIdSlow(obj).ToString();
+ if (globalObjectId != "GlobalObjectId_V1-0-00000000000000000000000000000000-0-0")
+ MessageObjects.Add(GlobalObjectId.GetGlobalObjectIdSlow(obj).ToString());
+ else
+ Text += $"\n{obj.name}";
+ }
+
+ public Object[] GetMessageObjects()
+ {
+ if (MessageObjects == null)
+ return Array.Empty