update libs

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

View File

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

View File

@@ -0,0 +1,56 @@
using AssetStoreTools.Previews.Data;
using System;
using System.IO;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
namespace AssetStoreTools.Previews.UI.Data
{
internal class AssetPreview : IAssetPreview
{
private PreviewMetadata _metadata;
private UnityEngine.Object _cachedAsset;
private string _cachedAssetPath;
private Texture2D _cachedTexture;
public UnityEngine.Object Asset => _cachedAsset ?? (_cachedAsset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(AssetPath));
public string AssetPath => _cachedAssetPath ?? (_cachedAssetPath = AssetDatabase.GUIDToAssetPath(_metadata.Guid));
public AssetPreview(PreviewMetadata metadata)
{
_metadata = metadata;
}
public string GetAssetPath()
{
var assetPath = AssetDatabase.GUIDToAssetPath(_metadata.Guid);
return assetPath;
}
public async Task LoadImage(Action<Texture2D> onSuccess)
{
if (_cachedTexture == null)
{
if (!_metadata.Exists())
return;
await Task.Yield();
try
{
_cachedTexture = new Texture2D(1, 1);
_cachedTexture.LoadImage(File.ReadAllBytes(_metadata.Path));
}
catch (Exception e)
{
Debug.LogException(e);
return;
}
}
onSuccess?.Invoke(_cachedTexture);
}
}
}

View File

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

View File

@@ -0,0 +1,46 @@
using AssetStoreTools.Previews.Data;
using System;
using System.Collections.Generic;
namespace AssetStoreTools.Previews.UI.Data
{
internal class AssetPreviewCollection : IAssetPreviewCollection
{
private GenerationType _generationType;
private List<IAssetPreview> _images;
public event Action OnCollectionChanged;
public AssetPreviewCollection()
{
_images = new List<IAssetPreview>();
}
public GenerationType GetGenerationType()
{
return _generationType;
}
public IEnumerable<IAssetPreview> GetPreviews()
{
return _images;
}
public void Refresh(GenerationType generationType, IEnumerable<PreviewMetadata> previews)
{
_images.Clear();
_generationType = generationType;
foreach (var entry in previews)
{
if (!entry.Exists())
continue;
_images.Add(new AssetPreview(entry));
}
OnCollectionChanged?.Invoke();
}
}
}

View File

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

View File

@@ -0,0 +1,13 @@
using System;
using System.Threading.Tasks;
using UnityEngine;
namespace AssetStoreTools.Previews.UI.Data
{
internal interface IAssetPreview
{
UnityEngine.Object Asset { get; }
string GetAssetPath();
Task LoadImage(Action<Texture2D> onSuccess);
}
}

View File

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

View File

@@ -0,0 +1,15 @@
using AssetStoreTools.Previews.Data;
using System;
using System.Collections.Generic;
namespace AssetStoreTools.Previews.UI.Data
{
internal interface IAssetPreviewCollection
{
event Action OnCollectionChanged;
GenerationType GetGenerationType();
IEnumerable<IAssetPreview> GetPreviews();
void Refresh(GenerationType generationType, IEnumerable<PreviewMetadata> previews);
}
}

View File

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

View File

@@ -0,0 +1,27 @@
using AssetStoreTools.Previews.Data;
using AssetStoreTools.Previews.Generators;
using System;
using System.Collections.Generic;
namespace AssetStoreTools.Previews.UI.Data
{
internal interface IPreviewGeneratorSettings
{
event Action OnGenerationTypeChanged;
event Action OnGenerationPathsChanged;
void LoadSettings(PreviewGenerationSettings settings);
GenerationType GetGenerationType();
void SetGenerationType(GenerationType type);
List<GenerationType> GetAvailableGenerationTypes();
List<string> GetGenerationPaths();
void AddGenerationPath(string path);
void RemoveGenerationPath(string path);
void ClearGenerationPaths();
bool IsGenerationPathValid(string path, out string error);
IPreviewGenerator CreateGenerator();
}
}

View File

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

View File

@@ -0,0 +1,212 @@
using AssetStoreTools.Previews.Data;
using AssetStoreTools.Previews.Generators;
using AssetStoreTools.Utility;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
namespace AssetStoreTools.Previews.UI.Data
{
internal class PreviewGeneratorSettings : IPreviewGeneratorSettings
{
private readonly GenerationType[] _availableGenerationTypes = new GenerationType[]
{
GenerationType.Native,
GenerationType.Custom
};
private List<string> _inputPaths;
private GenerationType _generationType;
public event Action OnGenerationTypeChanged;
public event Action OnGenerationPathsChanged;
public PreviewGeneratorSettings()
{
_inputPaths = new List<string>();
_generationType = GenerationType.Native;
}
public void LoadSettings(PreviewGenerationSettings settings)
{
if (settings == null)
return;
_inputPaths = settings.InputPaths.ToList();
OnGenerationPathsChanged?.Invoke();
switch (settings)
{
case NativePreviewGenerationSettings _:
_generationType = GenerationType.Native;
break;
case CustomPreviewGenerationSettings _:
_generationType = GenerationType.Custom;
break;
default:
return;
}
OnGenerationTypeChanged?.Invoke();
}
public GenerationType GetGenerationType()
{
return _generationType;
}
public void SetGenerationType(GenerationType type)
{
_generationType = type;
OnGenerationTypeChanged?.Invoke();
}
public List<GenerationType> GetAvailableGenerationTypes()
{
return _availableGenerationTypes.ToList();
}
public List<string> GetGenerationPaths()
{
return _inputPaths;
}
public void AddGenerationPath(string path)
{
if (string.IsNullOrEmpty(path))
return;
if (_inputPaths.Contains(path))
return;
// Prevent redundancy for new paths
var existingPath = _inputPaths.FirstOrDefault(x => path.StartsWith(x + "/"));
if (existingPath != null)
{
Debug.LogWarning($"Path '{path}' is already included with existing path: '{existingPath}'");
return;
}
// Prevent redundancy for already added paths
var redundantPaths = _inputPaths.Where(x => x.StartsWith(path + "/")).ToArray();
foreach (var redundantPath in redundantPaths)
{
Debug.LogWarning($"Existing validation path '{redundantPath}' has been made redundant by the inclusion of new validation path: '{path}'");
_inputPaths.Remove(redundantPath);
}
_inputPaths.Add(path);
OnGenerationPathsChanged?.Invoke();
}
public void RemoveGenerationPath(string path)
{
if (!_inputPaths.Contains(path))
return;
_inputPaths.Remove(path);
OnGenerationPathsChanged?.Invoke();
}
public void ClearGenerationPaths()
{
if (_inputPaths.Count == 0)
return;
_inputPaths.Clear();
OnGenerationPathsChanged?.Invoke();
}
public bool IsGenerationPathValid(string path, out string error)
{
error = string.Empty;
if (string.IsNullOrEmpty(path))
{
error = "Path cannot be empty";
return false;
}
var isAssetsPath = path.StartsWith("Assets/")
|| path.Equals("Assets");
var isPackagePath = PackageUtility.GetPackageByManifestPath($"{path}/package.json", out _);
if (!isAssetsPath && !isPackagePath)
{
error = "Selected path must be within the Assets folder or point to a root path of a package";
return false;
}
if (!Directory.Exists(path))
{
error = "Path does not exist";
return false;
}
if (path.Split('/').Any(x => x.StartsWith(".") || x.EndsWith("~")))
{
error = $"Path '{path}' cannot be selected as it is a hidden folder and not part of the Asset Database";
return false;
}
return true;
}
public IPreviewGenerator CreateGenerator()
{
switch (_generationType)
{
case GenerationType.Native:
return CreateNativeGenerator();
case GenerationType.Custom:
return CreateCustomGenerator();
default:
throw new NotImplementedException("Undefined generator type");
}
}
private IPreviewGenerator CreateNativeGenerator()
{
var settings = new NativePreviewGenerationSettings()
{
InputPaths = _inputPaths.ToArray(),
OutputPath = Constants.Previews.Native.DefaultOutputPath,
PreviewFileNamingFormat = Constants.Previews.DefaultFileNameFormat,
Format = Constants.Previews.Native.DefaultFormat,
WaitForPreviews = Constants.Previews.Native.DefaultWaitForPreviews,
ChunkedPreviewLoading = Constants.Previews.Native.DefaultChunkedPreviewLoading,
ChunkSize = Constants.Previews.Native.DefaultChunkSize,
OverwriteExisting = true
};
return new NativePreviewGenerator(settings);
}
private IPreviewGenerator CreateCustomGenerator()
{
var settings = new CustomPreviewGenerationSettings()
{
InputPaths = _inputPaths.ToArray(),
OutputPath = Constants.Previews.Custom.DefaultOutputPath,
Width = Constants.Previews.Custom.DefaultWidth,
Height = Constants.Previews.Custom.DefaultHeight,
Depth = Constants.Previews.Custom.DefaultDepth,
NativeWidth = Constants.Previews.Custom.DefaultNativeWidth,
NativeHeight = Constants.Previews.Custom.DefaultNativeHeight,
PreviewFileNamingFormat = Constants.Previews.DefaultFileNameFormat,
Format = Constants.Previews.Custom.DefaultFormat,
AudioSampleColor = Constants.Previews.Custom.DefaultAudioSampleColor,
AudioBackgroundColor = Constants.Previews.Custom.DefaultAudioBackgroundColor,
OverwriteExisting = true
};
var generator = new CustomPreviewGenerator(settings);
return generator;
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,83 @@
using AssetStoreTools.Previews.UI.Data;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace AssetStoreTools.Previews.UI.Elements
{
internal class AssetPreviewElement : VisualElement
{
// Data
private IAssetPreview _assetPreview;
// UI
private Image _image;
private Label _label;
public AssetPreviewElement()
{
AddToClassList("preview-list-image");
Create();
RegisterCallback<MouseDownEvent>(OnImageClicked);
}
private void Create()
{
CreateFiller();
CreateImage();
CreateLabel();
}
private void CreateImage()
{
_image = new Image();
Add(_image);
}
private void CreateFiller()
{
var filler = new VisualElement() { name = "Filler" };
Add(filler);
}
private void CreateLabel()
{
_label = new Label();
Add(_label);
}
private void SetImage(Texture2D texture)
{
_image.style.width = texture.width < 128 ? texture.width : 128;
_image.style.height = texture.height < 128 ? texture.height : 128;
_image.style.backgroundImage = texture;
}
private void OnImageClicked(MouseDownEvent _)
{
EditorGUIUtility.PingObject(_assetPreview.Asset);
}
public void SetSource(IAssetPreview assetPreview)
{
_assetPreview = assetPreview;
_assetPreview.LoadImage(SetImage);
var assetPath = _assetPreview.GetAssetPath();
if (string.IsNullOrEmpty(assetPath))
{
_label.text = "[Missing]";
tooltip = "This asset has been deleted";
return;
}
var assetNameWithExtension = assetPath.Split('/').Last();
_label.text = assetNameWithExtension;
tooltip = assetPath;
}
}
}

View File

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

View File

@@ -0,0 +1,140 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
namespace AssetStoreTools.Previews.UI.Elements
{
internal class GridListElement : VisualElement
{
public int ElementWidth;
public int ElementHeight;
private int _visibilityHeadroom => ElementHeight;
public IList ItemSource;
public Func<VisualElement> MakeItem;
public Action<VisualElement, int> BindItem;
private ScrollView _scrollView;
public GridListElement()
{
style.flexGrow = 1;
Create();
_scrollView.contentViewport.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
_scrollView.verticalScroller.valueChanged += OnVerticalScroll;
#if UNITY_2021_1_OR_NEWER
_scrollView.horizontalScrollerVisibility = ScrollerVisibility.Hidden;
#else
_scrollView.showHorizontal = false;
#endif
}
private void Create()
{
_scrollView = new ScrollView();
Add(_scrollView);
}
private void OnGeometryChanged(GeometryChangedEvent evt)
{
Redraw();
}
private void OnVerticalScroll(float value)
{
Redraw();
}
public void Redraw()
{
if (ElementWidth == 0
|| ElementHeight == 0
|| ItemSource == null
|| MakeItem == null
|| BindItem == null)
return;
_scrollView.Clear();
var rowCapacity = Mathf.FloorToInt(_scrollView.contentContainer.worldBound.width / ElementWidth);
if (rowCapacity == 0)
rowCapacity = 1;
var totalRequiredRows = ItemSource.Count / rowCapacity;
if (ItemSource.Count % rowCapacity != 0)
totalRequiredRows++;
_scrollView.contentContainer.style.height = totalRequiredRows * ElementHeight;
var visibleRows = new List<int>();
for (int i = 0; i < totalRequiredRows; i++)
{
var visible = IsRowVisible(i);
if (!visible)
continue;
var rowElement = CreateRow(i);
for (int j = 0; j < rowCapacity; j++)
{
var elementIndex = i * rowCapacity + j;
if (elementIndex >= ItemSource.Count)
{
rowElement.Add(CreateFillerElement());
continue;
}
var element = MakeItem?.Invoke();
BindItem?.Invoke(element, elementIndex);
rowElement.Add(element);
}
_scrollView.Add(rowElement);
}
}
private bool IsRowVisible(int rowIndex)
{
var contentStartY = _scrollView.contentContainer.worldBound.yMin;
var visibleContentMinY = _scrollView.contentViewport.worldBound.yMin - _visibilityHeadroom;
var visibleContentMaxY = _scrollView.contentViewport.worldBound.yMax + _visibilityHeadroom;
if (_scrollView.contentViewport.worldBound.height == 0)
visibleContentMaxY = this.worldBound.yMax;
var rowMinY = (rowIndex * ElementHeight) + contentStartY;
var rowMaxY = (rowIndex * ElementHeight) + ElementHeight + contentStartY;
var fullyVisible = rowMinY >= visibleContentMinY && rowMaxY <= visibleContentMaxY;
var partiallyAbove = rowMinY < visibleContentMinY && rowMaxY > visibleContentMinY;
var partiallyBelow = rowMaxY > visibleContentMaxY && rowMinY < visibleContentMaxY;
return fullyVisible || partiallyAbove || partiallyBelow;
}
private VisualElement CreateRow(int rowIndex)
{
var rowElement = new VisualElement() { name = $"Row {rowIndex}" };
rowElement.style.flexDirection = FlexDirection.Row;
rowElement.style.position = Position.Absolute;
rowElement.style.top = ElementHeight * rowIndex;
rowElement.style.width = _scrollView.contentViewport.worldBound.width;
rowElement.style.justifyContent = Justify.SpaceAround;
return rowElement;
}
private VisualElement CreateFillerElement()
{
var element = new VisualElement();
element.style.width = ElementWidth;
element.style.height = ElementHeight;
return element;
}
}
}

View File

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

View File

@@ -0,0 +1,116 @@
using AssetStoreTools.Previews.Data;
using AssetStoreTools.Previews.UI.Data;
using System.Linq;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UIElements;
namespace AssetStoreTools.Previews.UI.Elements
{
internal class PreviewCollectionElement : VisualElement
{
// Data
private IAssetPreviewCollection _collection;
// UI
private Label _previewCountLabel;
private GridListElement _gridListElement;
public PreviewCollectionElement(IAssetPreviewCollection collection)
{
AddToClassList("preview-list");
_collection = collection;
_collection.OnCollectionChanged += RefreshList;
Create();
RefreshList();
SubscribeToSceneChanges();
}
private void Create()
{
CreateLabel();
CreateGridListElement();
}
private void CreateLabel()
{
_previewCountLabel = new Label();
_previewCountLabel.style.display = DisplayStyle.None;
Add(_previewCountLabel);
}
private void CreateGridListElement()
{
_gridListElement = new GridListElement();
_gridListElement.MakeItem = CreatePreview;
_gridListElement.BindItem = BindPreview;
_gridListElement.ElementWidth = 140 + 10; // Accounting for margin style
_gridListElement.ElementHeight = 160 + 10; // Accounting for margin style
Add(_gridListElement);
}
private VisualElement CreatePreview()
{
var preview = new AssetPreviewElement();
return preview;
}
private void BindPreview(VisualElement element, int index)
{
var previewElement = (AssetPreviewElement)element;
var preview = _collection.GetPreviews().ToList()[index];
previewElement.SetSource(preview);
}
private void RefreshList()
{
var type = _collection.GetGenerationType();
var items = _collection.GetPreviews().ToList();
_previewCountLabel.text = $"Displaying {items.Count} {ConvertGenerationTypeName(type)} previews";
_previewCountLabel.style.display = DisplayStyle.Flex;
_previewCountLabel.style.alignSelf = Align.Center;
_previewCountLabel.style.marginBottom = 10;
_previewCountLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
_gridListElement.ItemSource = items;
_gridListElement.Redraw();
}
private string ConvertGenerationTypeName(GenerationType type)
{
switch (type)
{
case GenerationType.Custom:
return "high resolution";
default:
return type.ToString().ToLower();
}
}
private void SubscribeToSceneChanges()
{
var windowToSubscribeTo = Resources.FindObjectsOfTypeAll<PreviewGeneratorWindow>().FirstOrDefault();
UnityAction<Scene, Scene> sceneChanged = null;
sceneChanged = new UnityAction<Scene, Scene>((_, __) => RefreshObjects(windowToSubscribeTo));
EditorSceneManager.activeSceneChangedInEditMode += sceneChanged;
void RefreshObjects(PreviewGeneratorWindow subscribedWindow)
{
// Remove callback if preview generator window instance changed
var activeWindow = Resources.FindObjectsOfTypeAll<PreviewGeneratorWindow>().FirstOrDefault();
if (subscribedWindow == null || subscribedWindow != activeWindow)
{
EditorSceneManager.activeSceneChangedInEditMode -= sceneChanged;
return;
}
RefreshList();
}
}
}
}

View File

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

View File

@@ -0,0 +1,50 @@
using AssetStoreTools.Previews.UI.Data;
using System;
using UnityEngine.UIElements;
namespace AssetStoreTools.Previews.UI.Elements
{
internal class PreviewGenerateButtonElement : VisualElement
{
// Data
private IPreviewGeneratorSettings _settings;
// UI
private Button _generateButton;
public event Action OnGenerate;
public PreviewGenerateButtonElement(IPreviewGeneratorSettings settings)
{
_settings = settings;
_settings.OnGenerationPathsChanged += GenerationPathsChanged;
Create();
Deserialize();
}
private void Create()
{
_generateButton = new Button(Validate) { text = "Generate" };
_generateButton.AddToClassList("preview-generate-button");
Add(_generateButton);
}
private void Validate()
{
OnGenerate?.Invoke();
}
private void GenerationPathsChanged()
{
var inputPathsPresent = _settings.GetGenerationPaths().Count > 0;
_generateButton.SetEnabled(inputPathsPresent);
}
private void Deserialize()
{
GenerationPathsChanged();
}
}
}

View File

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

View File

@@ -0,0 +1,122 @@
using AssetStoreTools.Previews.UI.Data;
using AssetStoreTools.Utility;
using UnityEditor;
using UnityEngine.UIElements;
namespace AssetStoreTools.Validator.UI.Elements
{
internal class PreviewGeneratorPathsElement : VisualElement
{
// Data
private IPreviewGeneratorSettings _settings;
// UI
private ScrollView _pathBoxScrollView;
public PreviewGeneratorPathsElement(IPreviewGeneratorSettings settings)
{
AddToClassList("preview-paths");
_settings = settings;
_settings.OnGenerationPathsChanged += InputPathsChanged;
Create();
Deserialize();
}
private void Create()
{
var pathSelectionRow = new VisualElement();
pathSelectionRow.AddToClassList("preview-settings-selection-row");
VisualElement labelHelpRow = new VisualElement();
labelHelpRow.AddToClassList("preview-settings-selection-label-help-row");
labelHelpRow.style.alignSelf = Align.FlexStart;
Label pathLabel = new Label { text = "Input paths" };
Image pathLabelTooltip = new Image
{
tooltip = "Select the folder (or multiple folders) to generate asset previews for."
};
labelHelpRow.Add(pathLabel);
labelHelpRow.Add(pathLabelTooltip);
var fullPathBox = new VisualElement() { name = "PreviewPaths" };
fullPathBox.AddToClassList("preview-paths-box");
_pathBoxScrollView = new ScrollView { name = "PreviewPathsScrollView" };
_pathBoxScrollView.AddToClassList("preview-paths-scroll-view");
VisualElement scrollViewBottomRow = new VisualElement();
scrollViewBottomRow.AddToClassList("preview-paths-scroll-view-bottom-row");
var addExtraPathsButton = new Button(BrowsePath) { text = "Add a path" };
addExtraPathsButton.AddToClassList("preview-paths-add-button");
scrollViewBottomRow.Add(addExtraPathsButton);
fullPathBox.Add(_pathBoxScrollView);
fullPathBox.Add(scrollViewBottomRow);
pathSelectionRow.Add(labelHelpRow);
pathSelectionRow.Add(fullPathBox);
Add(pathSelectionRow);
}
private VisualElement CreateSinglePathElement(string path)
{
var validationPath = new VisualElement();
validationPath.AddToClassList("preview-paths-path-row");
var folderPathLabel = new Label(path);
folderPathLabel.AddToClassList("preview-paths-path-row-input-field");
var removeButton = new Button(() =>
{
_settings.RemoveGenerationPath(path);
});
removeButton.text = "X";
removeButton.AddToClassList("preview-paths-path-row-remove-button");
validationPath.Add(folderPathLabel);
validationPath.Add(removeButton);
return validationPath;
}
private void BrowsePath()
{
string absolutePath = EditorUtility.OpenFolderPanel("Select a directory", "Assets", "");
if (string.IsNullOrEmpty(absolutePath))
return;
var relativePath = FileUtility.AbsolutePathToRelativePath(absolutePath, ASToolsPreferences.Instance.EnableSymlinkSupport);
if (!_settings.IsGenerationPathValid(relativePath, out var error))
{
EditorUtility.DisplayDialog("Invalid path", error, "OK");
return;
}
_settings.AddGenerationPath(relativePath);
}
private void InputPathsChanged()
{
var inputPaths = _settings.GetGenerationPaths();
_pathBoxScrollView.Clear();
foreach (var path in inputPaths)
{
_pathBoxScrollView.Add(CreateSinglePathElement(path));
}
}
private void Deserialize()
{
InputPathsChanged();
}
}
}

View File

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

View File

@@ -0,0 +1,99 @@
using AssetStoreTools.Previews.Data;
using AssetStoreTools.Previews.UI.Data;
using AssetStoreTools.Validator.UI.Elements;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace AssetStoreTools.Previews.UI.Elements
{
internal class PreviewGeneratorSettingsElement : VisualElement
{
// Data
private IPreviewGeneratorSettings _settings;
// UI
private PreviewGeneratorPathsElement _previewPathsElement;
private ToolbarMenu _generationTypeMenu;
public PreviewGeneratorSettingsElement(IPreviewGeneratorSettings settings)
{
AddToClassList("preview-settings");
_settings = settings;
_settings.OnGenerationTypeChanged += GenerationTypeChanged;
Create();
Deserialize();
}
private void Create()
{
CreateGenerationType();
CreateInputPathsElement();
}
private void CreateInputPathsElement()
{
_previewPathsElement = new PreviewGeneratorPathsElement(_settings);
Add(_previewPathsElement);
}
private void CreateGenerationType()
{
var typeSelectionBox = new VisualElement();
typeSelectionBox.AddToClassList("preview-settings-selection-row");
VisualElement labelHelpRow = new VisualElement();
labelHelpRow.AddToClassList("preview-settings-selection-label-help-row");
Label generationTypeLabel = new Label { text = "Generation type" };
Image categoryLabelTooltip = new Image
{
tooltip = "Choose the generation type for your previews.\n\n" +
"- Native: retrieve previews from the Asset Database which are generated by Unity Editor internally\n" +
"- High Resolution (experimental): generate previews using a custom implementation. Resulting previews are of higher resolution " +
"than those generated by Unity Editor. Note that they may look slightly different from native previews"
};
labelHelpRow.Add(generationTypeLabel);
labelHelpRow.Add(categoryLabelTooltip);
_generationTypeMenu = new ToolbarMenu { name = "GenerationTypeMenu" };
_generationTypeMenu.AddToClassList("preview-settings-selection-dropdown");
typeSelectionBox.Add(labelHelpRow);
typeSelectionBox.Add(_generationTypeMenu);
// Append available categories
var types = _settings.GetAvailableGenerationTypes();
foreach (var t in types)
{
_generationTypeMenu.menu.AppendAction(ConvertGenerationTypeName(t), _ => _settings.SetGenerationType(t));
}
Add(typeSelectionBox);
}
private string ConvertGenerationTypeName(GenerationType type)
{
switch (type)
{
case GenerationType.Custom:
return "High Resolution (experimental)";
default:
return type.ToString();
}
}
private void GenerationTypeChanged()
{
var t = _settings.GetGenerationType();
_generationTypeMenu.text = ConvertGenerationTypeName(t);
}
private void Deserialize()
{
GenerationTypeChanged();
}
}
}

View File

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

View File

@@ -0,0 +1,87 @@
using UnityEngine.UIElements;
namespace AssetStoreTools.Previews.UI.Elements
{
internal class PreviewWindowDescriptionElement : VisualElement
{
private const string DescriptionFoldoutText = "Generate and inspect asset preview images to be displayed in your package listing page on the Asset Store.";
private const string DescriptionFoldoutContentText = "Images generated in this window will be reused when exporting a package. Any missing images generated during the package export process will also appear here.\n\n" +
"Preview images are displayed on the Asset Store under the 'Package Content' section of the package listing. " +
"They are also displayed in the package importer window that appears during the package import process. " +
"Note that these images will not replace the images used for the assets in the Project window after the package gets imported.";
private VisualElement _descriptionSimpleContainer;
private Button _showMoreButton;
private VisualElement _descriptionFullContainer;
private Button _showLessButton;
public PreviewWindowDescriptionElement()
{
AddToClassList("asset-preview-description");
Create();
}
private void Create()
{
CreateSimpleDescription();
CreateFullDescription();
}
private void CreateSimpleDescription()
{
_descriptionSimpleContainer = new VisualElement();
_descriptionSimpleContainer.AddToClassList("asset-preview-description-simple-container");
var simpleDescription = new Label(DescriptionFoldoutText);
simpleDescription.AddToClassList("asset-preview-description-simple-label");
_showMoreButton = new Button(ToggleFullDescription) { text = "Show more..." };
_showMoreButton.AddToClassList("asset-preview-description-hyperlink-button");
_showMoreButton.AddToClassList("asset-preview-description-show-button");
_descriptionSimpleContainer.Add(simpleDescription);
_descriptionSimpleContainer.Add(_showMoreButton);
Add(_descriptionSimpleContainer);
}
private void CreateFullDescription()
{
_descriptionFullContainer = new VisualElement();
_descriptionFullContainer.AddToClassList("asset-preview-description-full-container");
var validatorDescription = new Label()
{
text = DescriptionFoldoutContentText
};
validatorDescription.AddToClassList("asset-preview-description-full-label");
_showLessButton = new Button(ToggleFullDescription) { text = "Show less..." };
_showLessButton.AddToClassList("asset-preview-description-hide-button");
_showLessButton.AddToClassList("asset-preview-description-hyperlink-button");
_descriptionFullContainer.Add(validatorDescription);
_descriptionFullContainer.Add(_showLessButton);
_descriptionFullContainer.style.display = DisplayStyle.None;
Add(_descriptionFullContainer);
}
private void ToggleFullDescription()
{
var displayFullDescription = _descriptionFullContainer.style.display == DisplayStyle.None;
if (displayFullDescription)
{
_showMoreButton.style.display = DisplayStyle.None;
_descriptionFullContainer.style.display = DisplayStyle.Flex;
}
else
{
_showMoreButton.style.display = DisplayStyle.Flex;
_descriptionFullContainer.style.display = DisplayStyle.None;
}
}
}
}

View File

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

View File

@@ -0,0 +1,51 @@
using AssetStoreTools.Previews.Data;
using AssetStoreTools.Previews.Services;
using AssetStoreTools.Previews.UI.Views;
using AssetStoreTools.Utility;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace AssetStoreTools.Previews.UI
{
internal class PreviewGeneratorWindow : AssetStoreToolsWindow
{
protected override string WindowTitle => "Preview Generator";
private ICachingService _cachingService;
private PreviewListView _previewListView;
protected override void Init()
{
minSize = new Vector2(350, 350);
this.SetAntiAliasing(4);
VisualElement root = rootVisualElement;
// Getting a reference to the USS Document and adding stylesheet to the root
root.styleSheets.Add(StyleSelector.PreviewGeneratorWindow.PreviewGeneratorWindowStyle);
root.styleSheets.Add(StyleSelector.PreviewGeneratorWindow.PreviewGeneratorWindowTheme);
GetServices();
ConstructWindow();
}
private void GetServices()
{
_cachingService = PreviewServiceProvider.Instance.GetService<ICachingService>();
}
private void ConstructWindow()
{
_previewListView = new PreviewListView(_cachingService);
rootVisualElement.Add(_previewListView);
}
public void Load(PreviewGenerationSettings settings)
{
_previewListView.LoadSettings(settings);
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,142 @@
using AssetStoreTools.Previews.Data;
using AssetStoreTools.Previews.Services;
using AssetStoreTools.Previews.UI.Data;
using AssetStoreTools.Previews.UI.Elements;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace AssetStoreTools.Previews.UI.Views
{
internal class PreviewListView : VisualElement
{
//Data
private PreviewDatabase _previewDatabase;
private IPreviewGeneratorSettings _previewGeneratorSettings;
private IAssetPreviewCollection _previewCollection;
private ICachingService _cachingService;
// UI
private PreviewWindowDescriptionElement _descriptionElement;
private PreviewGeneratorSettingsElement _settingsElement;
private PreviewGenerateButtonElement _generateButtonElement;
private PreviewCollectionElement _previewCollectionElement;
public PreviewListView(ICachingService cachingService)
{
_cachingService = cachingService;
_previewGeneratorSettings = new PreviewGeneratorSettings();
_previewCollection = new AssetPreviewCollection();
_previewGeneratorSettings.OnGenerationTypeChanged += RefreshPreviewList;
_previewGeneratorSettings.OnGenerationPathsChanged += RefreshPreviewList;
Create();
RefreshPreviewList();
}
private void Create()
{
CreateDescription();
CreateSettings();
CreateGenerateButton();
CreatePreviewList();
}
private void CreateDescription()
{
_descriptionElement = new PreviewWindowDescriptionElement();
Add(_descriptionElement);
}
private void CreateSettings()
{
_settingsElement = new PreviewGeneratorSettingsElement(_previewGeneratorSettings);
Add(_settingsElement);
}
private void CreateGenerateButton()
{
_generateButtonElement = new PreviewGenerateButtonElement(_previewGeneratorSettings);
_generateButtonElement.OnGenerate += GeneratePreviews;
Add(_generateButtonElement);
}
private void CreatePreviewList()
{
_previewCollectionElement = new PreviewCollectionElement(_previewCollection);
Add(_previewCollectionElement);
}
private async void GeneratePreviews()
{
try
{
_settingsElement.SetEnabled(false);
_generateButtonElement.SetEnabled(false);
_previewCollectionElement.SetEnabled(false);
var generator = _previewGeneratorSettings.CreateGenerator();
generator.OnProgressChanged += DisplayProgress;
var result = await generator.Generate();
generator.OnProgressChanged -= DisplayProgress;
if (!result.Success)
{
EditorUtility.DisplayDialog("Error", result.Exception.Message, "OK");
Debug.LogException(result.Exception);
return;
}
RefreshPreviewList();
}
finally
{
_settingsElement.SetEnabled(true);
_generateButtonElement.SetEnabled(true);
_previewCollectionElement.SetEnabled(true);
EditorUtility.ClearProgressBar();
}
}
private void DisplayProgress(float progress)
{
EditorUtility.DisplayProgressBar("Generating", "Generating previews...", progress);
}
public void LoadSettings(PreviewGenerationSettings settings)
{
_previewGeneratorSettings.LoadSettings(settings);
}
private void RefreshPreviewList()
{
if (!_cachingService.GetCachedMetadata(out _previewDatabase))
_previewDatabase = new PreviewDatabase();
var paths = _previewGeneratorSettings.GetGenerationPaths();
var guids = AssetDatabase.FindAssets("", paths.ToArray());
var displayedPreviews = new List<PreviewMetadata>();
foreach (var entry in _previewDatabase.Previews)
{
if (!entry.Exists())
continue;
if (entry.Type != _previewGeneratorSettings.GetGenerationType())
continue;
if (!guids.Any(x => x == entry.Guid))
continue;
displayedPreviews.Add(entry);
}
_previewCollection.Refresh(_previewGeneratorSettings.GetGenerationType(), displayedPreviews);
}
}
}

View File

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