update libs
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae99e2e3b5a83d1469110306c96f4c58
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,19 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AssetStoreTools.Previews.Data
|
||||
{
|
||||
internal class CustomPreviewGenerationSettings : PreviewGenerationSettings
|
||||
{
|
||||
public override GenerationType GenerationType => GenerationType.Custom;
|
||||
|
||||
public int Width;
|
||||
public int Height;
|
||||
public int Depth;
|
||||
|
||||
public int NativeWidth;
|
||||
public int NativeHeight;
|
||||
|
||||
public Color AudioSampleColor;
|
||||
public Color AudioBackgroundColor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ccb1292c1c4ba94cb6f4022ecfdfa50
|
||||
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/Data/CustomPreviewGenerationSettings.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace AssetStoreTools.Previews.Data
|
||||
{
|
||||
internal enum FileNameFormat
|
||||
{
|
||||
Guid = 0,
|
||||
FullAssetPath = 1,
|
||||
AssetName = 2,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38a1babecfeaf524f98e8d67882acf48
|
||||
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/Data/FileNameFormat.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace AssetStoreTools.Previews.Data
|
||||
{
|
||||
internal enum GenerationType
|
||||
{
|
||||
Unknown = 0,
|
||||
Native = 1,
|
||||
Custom = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 66697a5d16404d948ba3191ddfc60bd9
|
||||
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/Data/GenerationType.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace AssetStoreTools.Previews.Data
|
||||
{
|
||||
internal class NativePreviewGenerationSettings : PreviewGenerationSettings
|
||||
{
|
||||
public override GenerationType GenerationType => GenerationType.Native;
|
||||
public bool WaitForPreviews;
|
||||
public bool ChunkedPreviewLoading;
|
||||
public int ChunkSize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b2ef019acae6fe43b5565858e15433a
|
||||
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/Data/NativePreviewGenerationSettings.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetStoreTools.Previews.Data
|
||||
{
|
||||
internal class PreviewDatabase
|
||||
{
|
||||
public List<PreviewMetadata> Previews;
|
||||
|
||||
public PreviewDatabase()
|
||||
{
|
||||
Previews = new List<PreviewMetadata>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf8cef28a68324742a7e4b47efc87563
|
||||
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/Data/PreviewDatabase.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace AssetStoreTools.Previews.Data
|
||||
{
|
||||
internal enum PreviewFormat
|
||||
{
|
||||
JPG = 0,
|
||||
PNG = 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0500e4459ebfe8448a13194af49f89fa
|
||||
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/Data/PreviewFormat.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetStoreTools.Previews.Data
|
||||
{
|
||||
internal class PreviewGenerationResult
|
||||
{
|
||||
public GenerationType GenerationType;
|
||||
public bool Success;
|
||||
public IEnumerable<PreviewMetadata> GeneratedPreviews;
|
||||
public IEnumerable<PreviewMetadata> Previews;
|
||||
public Exception Exception;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e040f2cdf0177824dacb158b23a63374
|
||||
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/Data/PreviewGenerationResult.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace AssetStoreTools.Previews.Data
|
||||
{
|
||||
internal abstract class PreviewGenerationSettings
|
||||
{
|
||||
public abstract GenerationType GenerationType { get; }
|
||||
public string[] InputPaths;
|
||||
public string OutputPath;
|
||||
public PreviewFormat Format;
|
||||
public FileNameFormat PreviewFileNamingFormat;
|
||||
public bool OverwriteExisting;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e578ae6616505a4795da8f632d63229
|
||||
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/Data/PreviewGenerationSettings.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.IO;
|
||||
|
||||
namespace AssetStoreTools.Previews.Data
|
||||
{
|
||||
internal class PreviewMetadata
|
||||
{
|
||||
public GenerationType Type;
|
||||
public string Guid;
|
||||
public string Name;
|
||||
public string Path;
|
||||
|
||||
public bool Exists()
|
||||
{
|
||||
return File.Exists(Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ff6be4e277d8314e921baff52ea25bc
|
||||
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/Data/PreviewMetadata.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed651159a2004574789e97726da5090c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f675855c3d971694785806c0c7a463be
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,97 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom
|
||||
{
|
||||
internal class AudioChannel
|
||||
{
|
||||
private int _yMin;
|
||||
private int _yMax;
|
||||
|
||||
private int _yBaseline;
|
||||
private int _yAmplitude;
|
||||
|
||||
private List<float> _samples;
|
||||
|
||||
public AudioChannel(int minY, int maxY, List<float> samples)
|
||||
{
|
||||
_yMin = minY;
|
||||
_yMax = maxY;
|
||||
|
||||
_yBaseline = (_yMin + _yMax) / 2;
|
||||
_yAmplitude = _yMax - _yBaseline;
|
||||
|
||||
_samples = samples;
|
||||
}
|
||||
|
||||
public IEnumerable<AudioChannelCoordinate> GetCoordinateData(int desiredWidth)
|
||||
{
|
||||
var coordinates = new List<AudioChannelCoordinate>();
|
||||
var step = Mathf.RoundToInt((float)_samples.Count / desiredWidth);
|
||||
|
||||
for (int i = 0; i < desiredWidth; i++)
|
||||
{
|
||||
var startIndex = i * step;
|
||||
var endIndex = (i + 1) * step;
|
||||
var sampleChunk = CreateChunk(startIndex, endIndex);
|
||||
|
||||
if (sampleChunk.Count() == 0)
|
||||
break;
|
||||
|
||||
DownsampleMax(sampleChunk, out var aboveBaseline, out var belowBaseline);
|
||||
|
||||
var yAboveBaseline = SampleToCoordinate(aboveBaseline);
|
||||
var yBelowBaseline = SampleToCoordinate(belowBaseline);
|
||||
|
||||
coordinates.Add(new AudioChannelCoordinate(i, _yBaseline, yAboveBaseline, yBelowBaseline));
|
||||
}
|
||||
|
||||
// If there weren't enough samples to complete the desired width - fill out the rest with zeroes
|
||||
for (int i = coordinates.Count; i < desiredWidth; i++)
|
||||
coordinates.Add(new AudioChannelCoordinate(i, _yBaseline, 0, 0));
|
||||
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
private IEnumerable<float> CreateChunk(int startIndex, int endIndex)
|
||||
{
|
||||
var chunk = new List<float>();
|
||||
for (int i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
if (i >= _samples.Count)
|
||||
break;
|
||||
|
||||
chunk.Add(_samples[i]);
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
private void DownsampleMax(IEnumerable<float> samples, out float valueAboveBaseline, out float valueBelowBaseline)
|
||||
{
|
||||
valueAboveBaseline = 0;
|
||||
valueBelowBaseline = 0;
|
||||
|
||||
foreach (var sample in samples)
|
||||
{
|
||||
if (sample > 0 && sample > valueAboveBaseline)
|
||||
{
|
||||
valueAboveBaseline = sample;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sample < 0 && sample < valueBelowBaseline)
|
||||
{
|
||||
valueBelowBaseline = sample;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int SampleToCoordinate(float sample)
|
||||
{
|
||||
return _yBaseline + (int)(sample * _yAmplitude);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82fab55b08a1be94cb2e18f3feae91ec
|
||||
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/Generators/Custom/AudioChannel.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace AssetStoreTools.Previews.Generators.Custom
|
||||
{
|
||||
internal struct AudioChannelCoordinate
|
||||
{
|
||||
public int X { get; private set; }
|
||||
public int YBaseline { get; private set; }
|
||||
public int YAboveBaseline { get; private set; }
|
||||
public int YBelowBaseline { get; private set; }
|
||||
|
||||
public AudioChannelCoordinate(int x, int yBaseline, int yAboveBaseline, int yBelowBaseline)
|
||||
{
|
||||
X = x;
|
||||
YBaseline = yBaseline;
|
||||
YAboveBaseline = yAboveBaseline;
|
||||
YBelowBaseline = yBelowBaseline;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b54462f6af82a2644944d6e4bde23c9e
|
||||
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/Generators/Custom/AudioChannelCoordinate.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c07070deed666d54cb72a89a5fcd7ef7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.Screenshotters
|
||||
{
|
||||
internal interface ISceneScreenshotter
|
||||
{
|
||||
SceneScreenshotterSettings Settings { get; }
|
||||
|
||||
string Screenshot(string outputPath);
|
||||
string Screenshot(GameObject target, string outputPath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 045ac265a792af243918af0849ee2ac8
|
||||
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/Generators/Custom/Screenshotters/ISceneScreenshotter.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,32 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.Screenshotters
|
||||
{
|
||||
internal class MaterialScreenshotter : SceneScreenshotterBase
|
||||
{
|
||||
public MaterialScreenshotter(SceneScreenshotterSettings settings) : base(settings) { }
|
||||
|
||||
public override void PositionCamera(GameObject target)
|
||||
{
|
||||
var renderers = target.GetComponentsInChildren<Renderer>();
|
||||
if (renderers == null || renderers.Length == 0)
|
||||
return;
|
||||
|
||||
var bounds = GetGlobalBounds(renderers);
|
||||
|
||||
var materialSphereRadius = bounds.extents.y * 1.1f;
|
||||
|
||||
var angle = Camera.fieldOfView / 2;
|
||||
var sinAngle = Mathf.Sin(angle * Mathf.Deg2Rad);
|
||||
var distance = materialSphereRadius / sinAngle;
|
||||
|
||||
Camera.transform.position = new Vector3(bounds.center.x, bounds.center.y + distance, bounds.center.z);
|
||||
Camera.transform.LookAt(bounds.center);
|
||||
Camera.transform.RotateAround(bounds.center, Vector3.left, 60);
|
||||
Camera.transform.RotateAround(bounds.center, Vector3.up, -45);
|
||||
|
||||
Camera.nearClipPlane = 0.01f;
|
||||
Camera.farClipPlane = 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2bd7b01b0cebeb43a6fbc53377f0ea6
|
||||
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/Generators/Custom/Screenshotters/MaterialScreenshotter.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,33 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.Screenshotters
|
||||
{
|
||||
internal class MeshScreenshotter : SceneScreenshotterBase
|
||||
{
|
||||
public MeshScreenshotter(SceneScreenshotterSettings settings) : base(settings) { }
|
||||
|
||||
public override void PositionCamera(GameObject target)
|
||||
{
|
||||
var renderers = target.GetComponentsInChildren<Renderer>();
|
||||
if (renderers == null || renderers.Length == 0)
|
||||
return;
|
||||
|
||||
var bounds = GetGlobalBounds(renderers);
|
||||
|
||||
var encapsulatingSphereDiameter = (bounds.max - bounds.min).magnitude;
|
||||
var encapsulatingSphereRadius = encapsulatingSphereDiameter / 2;
|
||||
|
||||
var angle = Camera.fieldOfView / 2;
|
||||
var sinAngle = Mathf.Sin(angle * Mathf.Deg2Rad);
|
||||
var distance = encapsulatingSphereRadius / sinAngle;
|
||||
|
||||
Camera.transform.position = new Vector3(bounds.center.x, bounds.center.y + distance, bounds.center.z);
|
||||
Camera.transform.LookAt(bounds.center);
|
||||
Camera.transform.RotateAround(bounds.center, Vector3.left, 65);
|
||||
Camera.transform.RotateAround(bounds.center, Vector3.up, 235);
|
||||
|
||||
Camera.nearClipPlane = 0.01f;
|
||||
Camera.farClipPlane = 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0339d22d91b7c94ebc18b1de6f1e287
|
||||
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/Generators/Custom/Screenshotters/MeshScreenshotter.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,124 @@
|
||||
using AssetStoreTools.Previews.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.Screenshotters
|
||||
{
|
||||
internal abstract class SceneScreenshotterBase : ISceneScreenshotter
|
||||
{
|
||||
public SceneScreenshotterSettings Settings { get; }
|
||||
|
||||
protected Camera Camera => GetCamera();
|
||||
private Camera _camera;
|
||||
|
||||
public SceneScreenshotterBase(SceneScreenshotterSettings settings)
|
||||
{
|
||||
Settings = settings;
|
||||
}
|
||||
|
||||
private Camera GetCamera()
|
||||
{
|
||||
if (_camera == null)
|
||||
{
|
||||
#if UNITY_2022_3_OR_NEWER
|
||||
_camera = GameObject.FindFirstObjectByType<Camera>(FindObjectsInactive.Include);
|
||||
#else
|
||||
_camera = GameObject.FindObjectOfType<Camera>();
|
||||
#endif
|
||||
}
|
||||
|
||||
return _camera;
|
||||
}
|
||||
|
||||
public virtual void ValidateSettings()
|
||||
{
|
||||
if (Settings.Width <= 0)
|
||||
throw new ArgumentException("Width should be larger than 0");
|
||||
|
||||
if (Settings.Height <= 0)
|
||||
throw new ArgumentException("Height should be larger than 0");
|
||||
|
||||
if (Settings.Depth <= 0)
|
||||
throw new ArgumentException("Depth should be larger than 0");
|
||||
|
||||
if (Settings.NativeWidth <= 0)
|
||||
throw new ArgumentException("Native width should be larger than 0");
|
||||
|
||||
if (Settings.NativeHeight <= 0)
|
||||
throw new ArgumentException("Native height should be larger than 0");
|
||||
}
|
||||
|
||||
public abstract void PositionCamera(GameObject target);
|
||||
|
||||
public string Screenshot(string outputPath)
|
||||
{
|
||||
ValidateSettings();
|
||||
|
||||
var texture = GraphicsUtility.GetTextureFromCamera(Camera, Settings.NativeWidth, Settings.NativeHeight, Settings.Depth);
|
||||
|
||||
if (Settings.Width < Settings.NativeWidth || Settings.Height < Settings.NativeHeight)
|
||||
texture = GraphicsUtility.ResizeTexture(texture, Settings.Width, Settings.Height);
|
||||
|
||||
var extension = PreviewConvertUtility.ConvertExtension(Settings.Format);
|
||||
var writtenPath = $"{outputPath}.{extension}";
|
||||
var bytes = PreviewConvertUtility.ConvertTexture(texture, Settings.Format);
|
||||
File.WriteAllBytes(writtenPath, bytes);
|
||||
|
||||
return writtenPath;
|
||||
}
|
||||
|
||||
public string Screenshot(GameObject target, string outputPath)
|
||||
{
|
||||
PositionCamera(target);
|
||||
PositionLighting(target);
|
||||
return Screenshot(outputPath);
|
||||
}
|
||||
|
||||
private void PositionLighting(GameObject target)
|
||||
{
|
||||
#if UNITY_2022_3_OR_NEWER
|
||||
var light = GameObject.FindFirstObjectByType<Light>(FindObjectsInactive.Include);
|
||||
#else
|
||||
var light = GameObject.FindObjectOfType<Light>();
|
||||
#endif
|
||||
light.transform.position = Camera.transform.position;
|
||||
light.transform.LookAt(target.transform);
|
||||
light.transform.RotateAround(target.transform.position, Vector3.forward, 60f);
|
||||
}
|
||||
|
||||
protected Bounds GetGlobalBounds(IEnumerable<Renderer> renderers)
|
||||
{
|
||||
var center = Vector3.zero;
|
||||
|
||||
foreach (var renderer in renderers)
|
||||
{
|
||||
center += renderer.bounds.center;
|
||||
}
|
||||
center /= renderers.Count();
|
||||
|
||||
var globalBounds = new Bounds(center, Vector3.zero);
|
||||
|
||||
foreach (var renderer in renderers)
|
||||
{
|
||||
globalBounds.Encapsulate(renderer.bounds);
|
||||
}
|
||||
|
||||
return globalBounds;
|
||||
}
|
||||
|
||||
protected Bounds GetNormalizedBounds(Bounds bounds)
|
||||
{
|
||||
var largestExtent = Mathf.Max(bounds.extents.x, bounds.extents.y, bounds.extents.z);
|
||||
var normalizedBounds = new Bounds()
|
||||
{
|
||||
center = bounds.center,
|
||||
extents = new Vector3(largestExtent, largestExtent, largestExtent)
|
||||
};
|
||||
|
||||
return normalizedBounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce77aefdce8a37f498d17d73da53d0a4
|
||||
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/Generators/Custom/Screenshotters/SceneScreenshotterBase.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,16 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.Screenshotters
|
||||
{
|
||||
internal class SceneScreenshotterSettings
|
||||
{
|
||||
public int Width;
|
||||
public int Height;
|
||||
public int Depth;
|
||||
|
||||
public int NativeWidth;
|
||||
public int NativeHeight;
|
||||
|
||||
public PreviewFormat Format;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa34806e243bad949892d06dd47295e2
|
||||
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/Generators/Custom/Screenshotters/SceneScreenshotterSettings.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4bb2dd0960418d4a8d4efd34b92a418
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators
|
||||
{
|
||||
internal class AudioTypeGeneratorSettings : TypeGeneratorSettings
|
||||
{
|
||||
public int Width;
|
||||
public int Height;
|
||||
|
||||
public Color SampleColor;
|
||||
public Color BackgroundColor;
|
||||
public PreviewFormat Format;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b7ab1b072d95be4daf221ee23af1c80
|
||||
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/Generators/Custom/TypeGenerators/AudioTypeGeneratorSettings.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,207 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using AssetStoreTools.Previews.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators
|
||||
{
|
||||
internal class AudioTypePreviewGenerator : TypePreviewGeneratorBase
|
||||
{
|
||||
private AudioTypeGeneratorSettings _settings;
|
||||
private Texture2D _texture;
|
||||
|
||||
public override event Action<int, int> OnAssetProcessed;
|
||||
|
||||
public AudioTypePreviewGenerator(AudioTypeGeneratorSettings settings) : base(settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public override void ValidateSettings()
|
||||
{
|
||||
base.ValidateSettings();
|
||||
|
||||
if (_settings.Width <= 0)
|
||||
throw new ArgumentException("Width must be larger than 0");
|
||||
|
||||
if (_settings.Height <= 0)
|
||||
throw new ArgumentException("Height must be larger than 0");
|
||||
}
|
||||
|
||||
protected override IEnumerable<UnityEngine.Object> CollectAssets()
|
||||
{
|
||||
var assets = new List<UnityEngine.Object>();
|
||||
var materialGuids = AssetDatabase.FindAssets("t:audioclip", Settings.InputPaths);
|
||||
foreach (var guid in materialGuids)
|
||||
{
|
||||
var audioClip = AssetDatabase.LoadAssetAtPath<AudioClip>(AssetDatabase.GUIDToAssetPath(guid));
|
||||
|
||||
// Skip nested audio clips
|
||||
if (!AssetDatabase.IsMainAsset(audioClip))
|
||||
continue;
|
||||
|
||||
// Skip materials with an error shader
|
||||
if (!IsLoadTypeSupported(audioClip))
|
||||
{
|
||||
Debug.LogWarning($"Audio clip '{audioClip}' is using a load type which cannot retrieve sample data. Preview will not be generated.");
|
||||
continue;
|
||||
}
|
||||
|
||||
assets.Add(audioClip);
|
||||
}
|
||||
|
||||
return assets;
|
||||
}
|
||||
|
||||
private bool IsLoadTypeSupported(AudioClip audioClip)
|
||||
{
|
||||
if (audioClip.loadType == AudioClipLoadType.DecompressOnLoad)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override async Task<List<PreviewMetadata>> GenerateImpl(IEnumerable<UnityEngine.Object> assets)
|
||||
{
|
||||
var generatedPreviews = new List<PreviewMetadata>();
|
||||
var audioClips = assets.ToList();
|
||||
for (int i = 0; i < audioClips.Count; i++)
|
||||
{
|
||||
var audioClip = audioClips[i] as AudioClip;
|
||||
if (audioClip != null)
|
||||
{
|
||||
var texture = GenerateAudioClipTexture(audioClip);
|
||||
|
||||
var outputPath = GenerateOutputPathWithExtension(audioClip, _settings.PreviewFileNamingFormat, _settings.Format);
|
||||
var bytes = PreviewConvertUtility.ConvertTexture(texture, _settings.Format);
|
||||
File.WriteAllBytes(outputPath, bytes);
|
||||
generatedPreviews.Add(ObjectToMetadata(audioClip, outputPath));
|
||||
}
|
||||
|
||||
OnAssetProcessed?.Invoke(i, audioClips.Count);
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
return generatedPreviews;
|
||||
}
|
||||
|
||||
private Texture2D GenerateAudioClipTexture(AudioClip audioClip)
|
||||
{
|
||||
if (!audioClip.LoadAudioData())
|
||||
throw new Exception("Could not load audio data");
|
||||
|
||||
try
|
||||
{
|
||||
if (_texture == null)
|
||||
_texture = new Texture2D(_settings.Width, _settings.Height);
|
||||
else
|
||||
#if UNITY_2021_3_OR_NEWER || UNITY_2022_1_OR_NEWER || UNITY_2021_2_OR_NEWER
|
||||
_texture.Reinitialize(_settings.Width, _settings.Height);
|
||||
#else
|
||||
_texture.Resize(_settings.Width, _settings.Height);
|
||||
#endif
|
||||
|
||||
FillTextureBackground();
|
||||
FillTextureForeground(audioClip);
|
||||
|
||||
_texture.Apply();
|
||||
return _texture;
|
||||
}
|
||||
finally
|
||||
{
|
||||
audioClip.UnloadAudioData();
|
||||
}
|
||||
}
|
||||
|
||||
private void FillTextureBackground()
|
||||
{
|
||||
for (int i = 0; i < _texture.width; i++)
|
||||
{
|
||||
for (int j = 0; j < _texture.height; j++)
|
||||
{
|
||||
_texture.SetPixel(i, j, _settings.BackgroundColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FillTextureForeground(AudioClip audioClip)
|
||||
{
|
||||
var channels = CreateChannels(audioClip);
|
||||
|
||||
for (int i = 0; i < channels.Count; i++)
|
||||
{
|
||||
DrawChannel(channels[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private List<AudioChannel> CreateChannels(AudioClip audioClip)
|
||||
{
|
||||
var channelSamples = GetChannelSamples(audioClip);
|
||||
var sectionSize = _texture.height / audioClip.channels;
|
||||
|
||||
var channels = new List<AudioChannel>();
|
||||
|
||||
for (int i = 0; i < audioClip.channels; i++)
|
||||
{
|
||||
var channelMaxY = (_texture.height - 1) - i * sectionSize;
|
||||
var channelMinY = _texture.height - (i + 1) * sectionSize;
|
||||
var channel = new AudioChannel(channelMinY, channelMaxY, channelSamples[i]);
|
||||
channels.Add(channel);
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
private List<List<float>> GetChannelSamples(AudioClip audioClip)
|
||||
{
|
||||
var channelSamples = new List<List<float>>();
|
||||
var allSamples = new float[audioClip.samples * audioClip.channels];
|
||||
|
||||
if (!audioClip.GetData(allSamples, 0))
|
||||
throw new Exception("Could not retrieve audio samples");
|
||||
|
||||
for (int i = 0; i < audioClip.channels; i++)
|
||||
{
|
||||
var samples = new List<float>();
|
||||
var sampleIndex = i;
|
||||
while (sampleIndex < allSamples.Length)
|
||||
{
|
||||
samples.Add(allSamples[sampleIndex]);
|
||||
sampleIndex += audioClip.channels;
|
||||
}
|
||||
|
||||
channelSamples.Add(samples);
|
||||
}
|
||||
|
||||
return channelSamples;
|
||||
}
|
||||
|
||||
private void DrawChannel(AudioChannel channel)
|
||||
{
|
||||
var sectionData = channel.GetCoordinateData(_texture.width);
|
||||
|
||||
foreach (var data in sectionData)
|
||||
{
|
||||
DrawVerticalColumn(data.X, data.YBaseline, data.YAboveBaseline, data.YBelowBaseline, _settings.SampleColor);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawVerticalColumn(int x, int yBaseline, int y1, int y2, Color color)
|
||||
{
|
||||
_texture.SetPixel(x, yBaseline, color);
|
||||
|
||||
var startIndex = y1 < y2 ? y1 : y2;
|
||||
var endIndex = y1 < y2 ? y2 : y1;
|
||||
|
||||
for (int i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
_texture.SetPixel(x, i, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ddf69bb2dca51a42aff247b3a471bb3
|
||||
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/Generators/Custom/TypeGenerators/AudioTypePreviewGenerator.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,16 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators
|
||||
{
|
||||
internal interface ITypePreviewGenerator
|
||||
{
|
||||
TypeGeneratorSettings Settings { get; }
|
||||
|
||||
event Action<int, int> OnAssetProcessed;
|
||||
|
||||
Task<List<PreviewMetadata>> Generate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d9cd368dc73a23478390ee1332cb0be
|
||||
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/Generators/Custom/TypeGenerators/ITypePreviewGenerator.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,85 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators
|
||||
{
|
||||
internal class MaterialTypePreviewGenerator : TypePreviewGeneratorFromScene
|
||||
{
|
||||
public override event Action<int, int> OnAssetProcessed;
|
||||
|
||||
public MaterialTypePreviewGenerator(TypePreviewGeneratorFromSceneSettings settings) : base(settings) { }
|
||||
|
||||
protected override IEnumerable<UnityEngine.Object> CollectAssets()
|
||||
{
|
||||
var assets = new List<UnityEngine.Object>();
|
||||
var materialGuids = AssetDatabase.FindAssets("t:material", Settings.InputPaths);
|
||||
foreach (var guid in materialGuids)
|
||||
{
|
||||
var mat = AssetDatabase.LoadAssetAtPath<Material>(AssetDatabase.GUIDToAssetPath(guid));
|
||||
|
||||
// Skip nested materials
|
||||
if (!AssetDatabase.IsMainAsset(mat))
|
||||
continue;
|
||||
|
||||
// Skip materials with an error shader
|
||||
if (IsShaderInvalid(mat.shader))
|
||||
{
|
||||
Debug.LogWarning($"Material '{mat}' is using an erroring shader. Preview will not be generated.");
|
||||
continue;
|
||||
}
|
||||
|
||||
assets.Add(mat);
|
||||
}
|
||||
|
||||
return assets;
|
||||
}
|
||||
|
||||
protected override async Task<List<PreviewMetadata>> GeneratePreviewsInScene(IEnumerable<UnityEngine.Object> assets)
|
||||
{
|
||||
var generatedPreviews = new List<PreviewMetadata>();
|
||||
var materials = assets.ToList();
|
||||
var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||||
|
||||
var hasMeshRenderer = sphere.TryGetComponent<Renderer>(out var meshRenderer);
|
||||
if (!hasMeshRenderer)
|
||||
throw new Exception($"Could not find a MeshRenderer for {sphere}");
|
||||
|
||||
for (int i = 0; i < materials.Count; i++)
|
||||
{
|
||||
ThrowIfSceneChanged();
|
||||
|
||||
var material = materials[i] as Material;
|
||||
|
||||
if (material != null)
|
||||
{
|
||||
meshRenderer.sharedMaterial = material;
|
||||
var previewPath = Settings.Screenshotter.Screenshot(sphere, GenerateOutputPathWithoutExtension(material, Settings.PreviewFileNamingFormat));
|
||||
if (!string.IsNullOrEmpty(previewPath))
|
||||
generatedPreviews.Add(ObjectToMetadata(material, previewPath));
|
||||
}
|
||||
|
||||
OnAssetProcessed?.Invoke(i, materials.Count);
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
UnityEngine.Object.DestroyImmediate(sphere);
|
||||
return generatedPreviews;
|
||||
}
|
||||
|
||||
private bool IsShaderInvalid(Shader shader)
|
||||
{
|
||||
if (ShaderUtil.ShaderHasError(shader))
|
||||
return true;
|
||||
|
||||
if (!shader.isSupported)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4e121bae63a199458e53a523dd18c8c
|
||||
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/Generators/Custom/TypeGenerators/MaterialTypePreviewGenerator.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,86 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators
|
||||
{
|
||||
internal class ModelTypePreviewGenerator : TypePreviewGeneratorFromScene
|
||||
{
|
||||
public override event Action<int, int> OnAssetProcessed;
|
||||
|
||||
public ModelTypePreviewGenerator(TypePreviewGeneratorFromSceneSettings settings) : base(settings) { }
|
||||
|
||||
protected override IEnumerable<UnityEngine.Object> CollectAssets()
|
||||
{
|
||||
var models = new List<UnityEngine.Object>();
|
||||
var modelGuids = AssetDatabase.FindAssets("t:model", Settings.InputPaths);
|
||||
|
||||
foreach (var guid in modelGuids)
|
||||
{
|
||||
var model = AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(guid));
|
||||
|
||||
// Skip nested models
|
||||
if (!AssetDatabase.IsMainAsset(model))
|
||||
continue;
|
||||
|
||||
// Skip models without renderers
|
||||
if (model.GetComponentsInChildren<Renderer>().Length == 0)
|
||||
continue;
|
||||
|
||||
models.Add(model);
|
||||
}
|
||||
|
||||
return models;
|
||||
}
|
||||
|
||||
protected override async Task<List<PreviewMetadata>> GeneratePreviewsInScene(IEnumerable<UnityEngine.Object> assets)
|
||||
{
|
||||
var generatedPreviews = new List<PreviewMetadata>();
|
||||
var models = assets.ToList();
|
||||
var referenceShader = GetDefaultObjectShader();
|
||||
|
||||
for (int i = 0; i < models.Count; i++)
|
||||
{
|
||||
ThrowIfSceneChanged();
|
||||
|
||||
var model = models[i] as GameObject;
|
||||
|
||||
if (model != null)
|
||||
{
|
||||
var go = UnityEngine.Object.Instantiate(model, Vector3.zero, Quaternion.Euler(0, 0, 0));
|
||||
ReplaceShaders(go, referenceShader);
|
||||
|
||||
var previewPath = Settings.Screenshotter.Screenshot(go, GenerateOutputPathWithoutExtension(model, Settings.PreviewFileNamingFormat));
|
||||
if (!string.IsNullOrEmpty(previewPath))
|
||||
generatedPreviews.Add(ObjectToMetadata(model, previewPath));
|
||||
|
||||
UnityEngine.Object.DestroyImmediate(go);
|
||||
}
|
||||
|
||||
OnAssetProcessed?.Invoke(i, models.Count);
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
return generatedPreviews;
|
||||
}
|
||||
|
||||
private void ReplaceShaders(GameObject go, Shader shader)
|
||||
{
|
||||
var meshRenderers = go.GetComponentsInChildren<Renderer>();
|
||||
foreach (var mr in meshRenderers)
|
||||
{
|
||||
var materialArray = mr.sharedMaterials;
|
||||
for (int i = 0; i < materialArray.Length; i++)
|
||||
{
|
||||
materialArray[i] = new Material(shader) { color = new Color(0.7f, 0.7f, 0.7f) };
|
||||
}
|
||||
|
||||
mr.sharedMaterials = materialArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fca8a1fa8a211874cb84d3d811a0158c
|
||||
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/Generators/Custom/TypeGenerators/ModelTypePreviewGenerator.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,113 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators
|
||||
{
|
||||
internal class PrefabTypePreviewGenerator : TypePreviewGeneratorFromScene
|
||||
{
|
||||
public override event Action<int, int> OnAssetProcessed;
|
||||
|
||||
public PrefabTypePreviewGenerator(TypePreviewGeneratorFromSceneSettings settings) : base(settings) { }
|
||||
|
||||
protected override IEnumerable<UnityEngine.Object> CollectAssets()
|
||||
{
|
||||
var prefabs = new List<UnityEngine.Object>();
|
||||
var prefabGuids = AssetDatabase.FindAssets("t:prefab", Settings.InputPaths);
|
||||
|
||||
foreach (var guid in prefabGuids)
|
||||
{
|
||||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(guid));
|
||||
|
||||
// Skip nested prefabs
|
||||
if (!AssetDatabase.IsMainAsset(prefab))
|
||||
continue;
|
||||
|
||||
// Skip prefabs without renderers
|
||||
if (prefab.GetComponentsInChildren<Renderer>().Length == 0)
|
||||
continue;
|
||||
|
||||
prefabs.Add(prefab);
|
||||
}
|
||||
|
||||
return prefabs;
|
||||
}
|
||||
|
||||
protected override async Task<List<PreviewMetadata>> GeneratePreviewsInScene(IEnumerable<UnityEngine.Object> assets)
|
||||
{
|
||||
var generatedPreviews = new List<PreviewMetadata>();
|
||||
var prefabs = assets.ToList();
|
||||
var objectReferenceShader = GetDefaultObjectShader();
|
||||
var particleReferenceShader = GetDefaultParticleShader();
|
||||
|
||||
for (int i = 0; i < prefabs.Count; i++)
|
||||
{
|
||||
ThrowIfSceneChanged();
|
||||
|
||||
var prefab = prefabs[i] as GameObject;
|
||||
if (prefab != null)
|
||||
{
|
||||
var go = UnityEngine.Object.Instantiate(prefab, Vector3.zero, Quaternion.Euler(0, 0, 0));
|
||||
|
||||
ReplaceMissingShaders(go, objectReferenceShader, particleReferenceShader);
|
||||
|
||||
HandleParticleSystems(go);
|
||||
|
||||
var previewPath = Settings.Screenshotter.Screenshot(go, GenerateOutputPathWithoutExtension(prefab, Settings.PreviewFileNamingFormat));
|
||||
if (!string.IsNullOrEmpty(previewPath))
|
||||
generatedPreviews.Add(ObjectToMetadata(prefab, previewPath));
|
||||
|
||||
UnityEngine.Object.DestroyImmediate(go);
|
||||
}
|
||||
|
||||
OnAssetProcessed?.Invoke(i, prefabs.Count);
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
return generatedPreviews;
|
||||
}
|
||||
|
||||
private void ReplaceMissingShaders(GameObject go, Shader objectShader, Shader particleShader)
|
||||
{
|
||||
var meshRenderers = go.GetComponentsInChildren<Renderer>();
|
||||
foreach (var mr in meshRenderers)
|
||||
{
|
||||
var shaderToUse = mr is ParticleSystemRenderer ? particleShader : objectShader;
|
||||
|
||||
var materialArray = mr.sharedMaterials;
|
||||
for (int i = 0; i < materialArray.Length; i++)
|
||||
{
|
||||
if (materialArray[i] == null)
|
||||
{
|
||||
materialArray[i] = new Material(shaderToUse);
|
||||
}
|
||||
else if (!materialArray[i].shader.isSupported)
|
||||
{
|
||||
materialArray[i].shader = shaderToUse;
|
||||
}
|
||||
}
|
||||
|
||||
mr.sharedMaterials = materialArray;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleParticleSystems(GameObject go)
|
||||
{
|
||||
var particleSystems = go.GetComponentsInChildren<ParticleSystem>();
|
||||
if (particleSystems.Length == 0)
|
||||
return;
|
||||
|
||||
foreach (var ps in particleSystems)
|
||||
{
|
||||
ps.Stop();
|
||||
ps.Clear();
|
||||
ps.randomSeed = 1;
|
||||
ps.Simulate(10, false, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24b15b10bc361c84581f46cb6dd644cc
|
||||
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/Generators/Custom/TypeGenerators/PrefabTypePreviewGenerator.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,11 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators
|
||||
{
|
||||
internal class TextureTypeGeneratorSettings : TypeGeneratorSettings
|
||||
{
|
||||
public int MaxWidth;
|
||||
public int MaxHeight;
|
||||
public PreviewFormat Format;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 058d746982619b04eb5e200363003899
|
||||
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/Generators/Custom/TypeGenerators/TextureTypeGeneratorSettings.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,116 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using AssetStoreTools.Previews.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators
|
||||
{
|
||||
internal class TextureTypePreviewGenerator : TypePreviewGeneratorBase
|
||||
{
|
||||
private TextureTypeGeneratorSettings _settings;
|
||||
|
||||
public override event Action<int, int> OnAssetProcessed;
|
||||
|
||||
public TextureTypePreviewGenerator(TextureTypeGeneratorSettings settings) : base(settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public override void ValidateSettings()
|
||||
{
|
||||
base.ValidateSettings();
|
||||
|
||||
if (_settings.MaxWidth <= 0)
|
||||
throw new ArgumentException("Max width should be larger than 0");
|
||||
|
||||
if (_settings.MaxHeight <= 0)
|
||||
throw new ArgumentException("Max height should be larger than 0");
|
||||
}
|
||||
|
||||
protected override IEnumerable<UnityEngine.Object> CollectAssets()
|
||||
{
|
||||
var textures = new List<UnityEngine.Object>();
|
||||
var textureGuids = AssetDatabase.FindAssets("t:texture", Settings.InputPaths);
|
||||
|
||||
foreach (var guid in textureGuids)
|
||||
{
|
||||
var texture = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath(guid));
|
||||
|
||||
// Skip nested textures
|
||||
if (!AssetDatabase.IsMainAsset(texture))
|
||||
continue;
|
||||
|
||||
textures.Add(texture);
|
||||
}
|
||||
|
||||
return textures;
|
||||
}
|
||||
|
||||
protected override async Task<List<PreviewMetadata>> GenerateImpl(IEnumerable<UnityEngine.Object> assets)
|
||||
{
|
||||
var generatedPreviews = new List<PreviewMetadata>();
|
||||
var textures = assets.ToList();
|
||||
|
||||
for (int i = 0; i < textures.Count; i++)
|
||||
{
|
||||
var texture = textures[i] as Texture2D;
|
||||
|
||||
if (texture != null)
|
||||
{
|
||||
Texture2D resizedTexture;
|
||||
CalculateTextureSize(texture, out var resizeWidth, out var resizeHeight);
|
||||
|
||||
var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture)) as TextureImporter;
|
||||
if (importer != null && importer.textureType == TextureImporterType.NormalMap)
|
||||
resizedTexture = GraphicsUtility.ResizeTextureNormalMap(texture, resizeWidth, resizeHeight);
|
||||
else
|
||||
resizedTexture = GraphicsUtility.ResizeTexture(texture, resizeWidth, resizeHeight);
|
||||
|
||||
var previewPath = GenerateOutputPathWithExtension(texture, _settings.PreviewFileNamingFormat, _settings.Format);
|
||||
|
||||
// Some textures may be transparent and need to be encoded as PNG to look correctly
|
||||
var targetFormat = texture.alphaIsTransparency ? PreviewFormat.PNG : _settings.Format;
|
||||
var bytes = PreviewConvertUtility.ConvertTexture(resizedTexture, targetFormat);
|
||||
|
||||
File.WriteAllBytes(previewPath, bytes);
|
||||
generatedPreviews.Add(ObjectToMetadata(texture, previewPath));
|
||||
}
|
||||
|
||||
OnAssetProcessed?.Invoke(i, textures.Count);
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
return generatedPreviews;
|
||||
}
|
||||
|
||||
private void CalculateTextureSize(Texture2D texture, out int width, out int height)
|
||||
{
|
||||
if (texture.width <= _settings.MaxWidth && texture.height <= _settings.MaxHeight)
|
||||
{
|
||||
width = texture.width;
|
||||
height = texture.height;
|
||||
return;
|
||||
}
|
||||
|
||||
var widthLongerThanHeight = texture.width > texture.height;
|
||||
|
||||
if (widthLongerThanHeight)
|
||||
{
|
||||
var ratio = (float)texture.width / texture.height;
|
||||
width = _settings.MaxWidth;
|
||||
height = Mathf.RoundToInt(width / ratio);
|
||||
}
|
||||
else
|
||||
{
|
||||
var ratio = (float)texture.height / texture.width;
|
||||
height = _settings.MaxHeight;
|
||||
width = Mathf.RoundToInt(height / ratio);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b04f55867ee575c489803356220feb31
|
||||
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/Generators/Custom/TypeGenerators/TextureTypePreviewGenerator.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,12 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators
|
||||
{
|
||||
internal abstract class TypeGeneratorSettings
|
||||
{
|
||||
public string[] InputPaths;
|
||||
public string[] IgnoredGuids;
|
||||
public string OutputPath;
|
||||
public FileNameFormat PreviewFileNamingFormat;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a224a4b41a8c7cf4cb53dd77d6f2518b
|
||||
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/Generators/Custom/TypeGenerators/TypeGeneratorSettings.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,126 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using AssetStoreTools.Previews.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators
|
||||
{
|
||||
internal abstract class TypePreviewGeneratorBase : ITypePreviewGenerator
|
||||
{
|
||||
public TypeGeneratorSettings Settings { get; }
|
||||
|
||||
public abstract event Action<int, int> OnAssetProcessed;
|
||||
|
||||
public TypePreviewGeneratorBase(TypeGeneratorSettings settings)
|
||||
{
|
||||
Settings = settings;
|
||||
}
|
||||
|
||||
public virtual void ValidateSettings()
|
||||
{
|
||||
if (Settings.InputPaths == null || Settings.InputPaths.Length == 0)
|
||||
throw new ArgumentException("Input path cannot be null");
|
||||
|
||||
foreach (var path in Settings.InputPaths)
|
||||
{
|
||||
var inputPath = path.EndsWith("/") ? path.Remove(path.Length - 1) : path;
|
||||
if (!AssetDatabase.IsValidFolder(inputPath))
|
||||
throw new ArgumentException($"Input path '{inputPath}' is not a valid ADB folder");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(Settings.OutputPath))
|
||||
throw new ArgumentException("Output path cannot be null");
|
||||
}
|
||||
|
||||
public async Task<List<PreviewMetadata>> Generate()
|
||||
{
|
||||
var generatedPreviews = new List<PreviewMetadata>();
|
||||
ValidateSettings();
|
||||
|
||||
var assets = CollectAssets();
|
||||
assets = FilterIgnoredAssets(assets);
|
||||
|
||||
if (assets.Count() == 0)
|
||||
return generatedPreviews;
|
||||
|
||||
return await GenerateImpl(assets);
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<UnityEngine.Object> CollectAssets();
|
||||
|
||||
private IEnumerable<UnityEngine.Object> FilterIgnoredAssets(IEnumerable<UnityEngine.Object> assets)
|
||||
{
|
||||
if (Settings.IgnoredGuids == null || Settings.IgnoredGuids.Length == 0)
|
||||
return assets;
|
||||
|
||||
var filteredAssets = new List<UnityEngine.Object>();
|
||||
foreach (var asset in assets)
|
||||
{
|
||||
if (!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(asset, out var guid, out long _))
|
||||
continue;
|
||||
|
||||
if (Settings.IgnoredGuids.Any(x => x == guid))
|
||||
continue;
|
||||
|
||||
filteredAssets.Add(asset);
|
||||
}
|
||||
|
||||
return filteredAssets;
|
||||
}
|
||||
|
||||
protected abstract Task<List<PreviewMetadata>> GenerateImpl(IEnumerable<UnityEngine.Object> assets);
|
||||
|
||||
protected PreviewMetadata ObjectToMetadata(UnityEngine.Object obj, string previewPath)
|
||||
{
|
||||
if (!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _))
|
||||
throw new Exception($"Could not retrieve guid for object {obj}");
|
||||
|
||||
return new PreviewMetadata()
|
||||
{
|
||||
Type = GenerationType.Custom,
|
||||
Guid = guid,
|
||||
Name = obj.name,
|
||||
Path = previewPath
|
||||
};
|
||||
}
|
||||
|
||||
protected string GenerateOutputPathWithoutExtension(UnityEngine.Object asset, FileNameFormat fileNameFormat)
|
||||
{
|
||||
PrepareOutputFolder(Settings.OutputPath, false);
|
||||
var directoryPath = Settings.OutputPath;
|
||||
var fileName = PreviewConvertUtility.ConvertFilename(asset, fileNameFormat);
|
||||
var fullPath = $"{directoryPath}/{fileName}";
|
||||
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
protected string GenerateOutputPathWithExtension(UnityEngine.Object asset, FileNameFormat fileNameFormat, PreviewFormat previewFormat)
|
||||
{
|
||||
var partialOutputPath = GenerateOutputPathWithoutExtension(asset, fileNameFormat);
|
||||
var extension = PreviewConvertUtility.ConvertExtension(previewFormat);
|
||||
|
||||
return $"{partialOutputPath}.{extension}";
|
||||
}
|
||||
|
||||
private void PrepareOutputFolder(string outputPath, bool cleanup)
|
||||
{
|
||||
var dir = new DirectoryInfo(outputPath);
|
||||
|
||||
if (!dir.Exists)
|
||||
{
|
||||
dir.Create();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cleanup)
|
||||
return;
|
||||
|
||||
dir.Delete(true);
|
||||
dir.Create();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6fb2d639232bce4698338a252f47f3c
|
||||
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/Generators/Custom/TypeGenerators/TypePreviewGeneratorBase.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,111 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using AssetStoreTools.Previews.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators
|
||||
{
|
||||
internal abstract class TypePreviewGeneratorFromScene : TypePreviewGeneratorBase
|
||||
{
|
||||
protected new TypePreviewGeneratorFromSceneSettings Settings;
|
||||
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
|
||||
public TypePreviewGeneratorFromScene(TypePreviewGeneratorFromSceneSettings settings) : base(settings)
|
||||
{
|
||||
Settings = settings;
|
||||
}
|
||||
|
||||
public override void ValidateSettings()
|
||||
{
|
||||
base.ValidateSettings();
|
||||
|
||||
if (Settings.Screenshotter == null)
|
||||
throw new ArgumentException("Screenshotter cannot be null");
|
||||
}
|
||||
|
||||
protected sealed override async Task<List<PreviewMetadata>> GenerateImpl(IEnumerable<UnityEngine.Object> assets)
|
||||
{
|
||||
var originalScenePath = EditorSceneManager.GetActiveScene().path;
|
||||
await PreviewSceneUtility.OpenPreviewSceneForCurrentPipeline();
|
||||
|
||||
try
|
||||
{
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
EditorSceneManager.sceneOpened += SceneOpenedDuringGeneration;
|
||||
return await GeneratePreviewsInScene(assets);
|
||||
}
|
||||
finally
|
||||
{
|
||||
EditorSceneManager.sceneOpened -= SceneOpenedDuringGeneration;
|
||||
_cancellationTokenSource.Dispose();
|
||||
if (!string.IsNullOrEmpty(originalScenePath))
|
||||
EditorSceneManager.OpenScene(originalScenePath);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Task<List<PreviewMetadata>> GeneratePreviewsInScene(IEnumerable<UnityEngine.Object> assets);
|
||||
|
||||
private void SceneOpenedDuringGeneration(Scene _, OpenSceneMode __)
|
||||
{
|
||||
if (!_cancellationTokenSource.IsCancellationRequested)
|
||||
_cancellationTokenSource.Cancel();
|
||||
}
|
||||
|
||||
protected void ThrowIfSceneChanged()
|
||||
{
|
||||
if (_cancellationTokenSource.Token.IsCancellationRequested)
|
||||
throw new Exception("Preview generation was aborted due to a change of the scene");
|
||||
}
|
||||
|
||||
protected Shader GetDefaultObjectShader()
|
||||
{
|
||||
switch (RenderPipelineUtility.GetCurrentPipeline())
|
||||
{
|
||||
case RenderPipeline.BiRP:
|
||||
return Shader.Find("Standard");
|
||||
case RenderPipeline.URP:
|
||||
return Shader.Find("Universal Render Pipeline/Lit");
|
||||
case RenderPipeline.HDRP:
|
||||
return Shader.Find("HDRP/Lit");
|
||||
default:
|
||||
throw new NotImplementedException("Undefined Render Pipeline");
|
||||
}
|
||||
}
|
||||
|
||||
protected Shader GetDefaultParticleShader()
|
||||
{
|
||||
switch (RenderPipelineUtility.GetCurrentPipeline())
|
||||
{
|
||||
case RenderPipeline.BiRP:
|
||||
return Shader.Find("Particles/Standard Unlit");
|
||||
case RenderPipeline.URP:
|
||||
return Shader.Find("Universal Render Pipeline/Particles/Unlit");
|
||||
case RenderPipeline.HDRP:
|
||||
return Shader.Find("HDRP/Unlit");
|
||||
default:
|
||||
throw new NotImplementedException("Undefined Render Pipeline");
|
||||
}
|
||||
}
|
||||
|
||||
protected Shader GetDefaultTextureShader()
|
||||
{
|
||||
switch (RenderPipelineUtility.GetCurrentPipeline())
|
||||
{
|
||||
case RenderPipeline.BiRP:
|
||||
return Shader.Find("Unlit/Texture");
|
||||
case RenderPipeline.URP:
|
||||
return Shader.Find("Universal Render Pipeline/Unlit");
|
||||
case RenderPipeline.HDRP:
|
||||
return Shader.Find("HDRP/Unlit");
|
||||
default:
|
||||
throw new NotImplementedException("Undefined Render Pipeline");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1bf0eb8d7ef65f340be785dae96e4b73
|
||||
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/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromScene.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,9 @@
|
||||
using AssetStoreTools.Previews.Generators.Custom.Screenshotters;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators
|
||||
{
|
||||
internal class TypePreviewGeneratorFromSceneSettings : TypeGeneratorSettings
|
||||
{
|
||||
public ISceneScreenshotter Screenshotter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a6b871798f99ad44d9fca46789239ec1
|
||||
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/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromSceneSettings.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,213 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using AssetStoreTools.Previews.Generators;
|
||||
using AssetStoreTools.Previews.Generators.Custom.Screenshotters;
|
||||
using AssetStoreTools.Previews.Generators.Custom.TypeGenerators;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
|
||||
namespace AssetStoreTools.Previews
|
||||
{
|
||||
internal class CustomPreviewGenerator : PreviewGeneratorBase
|
||||
{
|
||||
private CustomPreviewGenerationSettings _customSettings;
|
||||
|
||||
public override event Action<float> OnProgressChanged;
|
||||
|
||||
public CustomPreviewGenerator(CustomPreviewGenerationSettings settings)
|
||||
: base(settings)
|
||||
{
|
||||
_customSettings = settings;
|
||||
}
|
||||
|
||||
protected override void Validate()
|
||||
{
|
||||
base.Validate();
|
||||
|
||||
if (_customSettings.Width <= 0)
|
||||
throw new ArgumentException("Width should be larger than 0");
|
||||
|
||||
if (_customSettings.Height <= 0)
|
||||
throw new ArgumentException("Height should be larger than 0");
|
||||
|
||||
if (_customSettings.Depth <= 0)
|
||||
throw new ArgumentException("Depth should be larger than 0");
|
||||
|
||||
if (_customSettings.NativeWidth <= 0)
|
||||
throw new ArgumentException("Native width should be larger than 0");
|
||||
|
||||
if (_customSettings.NativeHeight <= 0)
|
||||
throw new ArgumentException("Native height should be larger than 0");
|
||||
}
|
||||
|
||||
protected override async Task<PreviewGenerationResult> GenerateImpl()
|
||||
{
|
||||
var result = new PreviewGenerationResult()
|
||||
{
|
||||
GenerationType = _customSettings.GenerationType
|
||||
};
|
||||
|
||||
OnProgressChanged?.Invoke(0f);
|
||||
|
||||
var generatedPreviews = new List<PreviewMetadata>();
|
||||
var existingPreviews = GetExistingPreviews();
|
||||
var generators = CreateGenerators(existingPreviews);
|
||||
|
||||
var currentGenerator = 0;
|
||||
Action<int, int> generatorProgressCallback = null;
|
||||
generatorProgressCallback = (currentAsset, totalAssets) => ReportProgress(currentGenerator, generators.Count(), currentAsset, totalAssets);
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var generator in generators)
|
||||
{
|
||||
generator.OnAssetProcessed += generatorProgressCallback;
|
||||
var typeGeneratorPreviews = await generator.Generate();
|
||||
generatedPreviews.AddRange(typeGeneratorPreviews);
|
||||
currentGenerator++;
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
var allPreviews = new List<PreviewMetadata>();
|
||||
allPreviews.AddRange(generatedPreviews);
|
||||
allPreviews.AddRange(existingPreviews);
|
||||
|
||||
result.Success = true;
|
||||
result.GeneratedPreviews = generatedPreviews;
|
||||
result.Previews = allPreviews;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.Success = false;
|
||||
result.Exception = e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (var generator in generators)
|
||||
generator.OnAssetProcessed -= generatorProgressCallback;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private IEnumerable<PreviewMetadata> GetExistingPreviews()
|
||||
{
|
||||
var existingPreviews = new List<PreviewMetadata>();
|
||||
|
||||
if (Settings.OverwriteExisting || !CachingService.GetCachedMetadata(out var database))
|
||||
return existingPreviews;
|
||||
|
||||
var inputGuids = AssetDatabase.FindAssets("", _customSettings.InputPaths);
|
||||
existingPreviews = database.Previews.Where(x => x.Type == GenerationType.Custom && x.Exists() && inputGuids.Any(y => y.Equals(x.Guid))).ToList();
|
||||
return existingPreviews;
|
||||
}
|
||||
|
||||
private IEnumerable<ITypePreviewGenerator> CreateGenerators(IEnumerable<PreviewMetadata> existingPreviews)
|
||||
{
|
||||
var ignoredGuids = existingPreviews.Select(x => x.Guid).ToArray();
|
||||
|
||||
var generators = new ITypePreviewGenerator[]
|
||||
{
|
||||
CreateAudioPreviewGenerator(ignoredGuids),
|
||||
CreateMaterialPreviewGenerator(ignoredGuids),
|
||||
CreateModelPreviewGenerator(ignoredGuids),
|
||||
CreatePrefabPreviewGenerator(ignoredGuids),
|
||||
CreateTexturePreviewGenerator(ignoredGuids)
|
||||
};
|
||||
|
||||
return generators;
|
||||
}
|
||||
|
||||
private ITypePreviewGenerator CreateAudioPreviewGenerator(string[] ignoredGuids)
|
||||
{
|
||||
var settings = new AudioTypeGeneratorSettings()
|
||||
{
|
||||
Width = _customSettings.Width,
|
||||
Height = _customSettings.Height,
|
||||
InputPaths = _customSettings.InputPaths,
|
||||
OutputPath = _customSettings.OutputPath,
|
||||
PreviewFileNamingFormat = _customSettings.PreviewFileNamingFormat,
|
||||
Format = _customSettings.Format,
|
||||
SampleColor = _customSettings.AudioSampleColor,
|
||||
BackgroundColor = _customSettings.AudioBackgroundColor,
|
||||
IgnoredGuids = ignoredGuids
|
||||
};
|
||||
|
||||
return new AudioTypePreviewGenerator(settings);
|
||||
}
|
||||
|
||||
private ITypePreviewGenerator CreateMaterialPreviewGenerator(string[] ignoredGuids)
|
||||
{
|
||||
var settings = CreateSceneGeneratorSettings(new MaterialScreenshotter(CreateScreenshotterSettings()), ignoredGuids);
|
||||
return new MaterialTypePreviewGenerator(settings);
|
||||
}
|
||||
|
||||
private ITypePreviewGenerator CreateModelPreviewGenerator(string[] ignoredGuids)
|
||||
{
|
||||
var settings = CreateSceneGeneratorSettings(new MeshScreenshotter(CreateScreenshotterSettings()), ignoredGuids);
|
||||
return new ModelTypePreviewGenerator(settings);
|
||||
}
|
||||
|
||||
private ITypePreviewGenerator CreatePrefabPreviewGenerator(string[] ignoredGuids)
|
||||
{
|
||||
var settings = CreateSceneGeneratorSettings(new MeshScreenshotter(CreateScreenshotterSettings()), ignoredGuids);
|
||||
return new PrefabTypePreviewGenerator(settings);
|
||||
}
|
||||
|
||||
private ITypePreviewGenerator CreateTexturePreviewGenerator(string[] ignoredGuids)
|
||||
{
|
||||
var settings = new TextureTypeGeneratorSettings()
|
||||
{
|
||||
MaxWidth = _customSettings.Width,
|
||||
MaxHeight = _customSettings.Height,
|
||||
InputPaths = _customSettings.InputPaths,
|
||||
OutputPath = _customSettings.OutputPath,
|
||||
Format = _customSettings.Format,
|
||||
PreviewFileNamingFormat = _customSettings.PreviewFileNamingFormat,
|
||||
IgnoredGuids = ignoredGuids
|
||||
};
|
||||
|
||||
return new TextureTypePreviewGenerator(settings);
|
||||
}
|
||||
|
||||
private TypePreviewGeneratorFromSceneSettings CreateSceneGeneratorSettings(ISceneScreenshotter screenshotter, string[] ignoredGuids)
|
||||
{
|
||||
var settings = new TypePreviewGeneratorFromSceneSettings()
|
||||
{
|
||||
InputPaths = _customSettings.InputPaths,
|
||||
OutputPath = _customSettings.OutputPath,
|
||||
PreviewFileNamingFormat = _customSettings.PreviewFileNamingFormat,
|
||||
Screenshotter = screenshotter,
|
||||
IgnoredGuids = ignoredGuids
|
||||
};
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
private SceneScreenshotterSettings CreateScreenshotterSettings()
|
||||
{
|
||||
var settings = new SceneScreenshotterSettings()
|
||||
{
|
||||
Width = _customSettings.Width,
|
||||
Height = _customSettings.Height,
|
||||
Depth = _customSettings.Depth,
|
||||
Format = _customSettings.Format,
|
||||
NativeWidth = _customSettings.NativeWidth,
|
||||
NativeHeight = _customSettings.NativeHeight,
|
||||
};
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
private void ReportProgress(int currentGenerator, int totalGenerators, int currentGeneratorAsset, int totalCurrentGeneratorAssets)
|
||||
{
|
||||
var completedGeneratorProgress = (float)currentGenerator / totalGenerators;
|
||||
var currentGeneratorProgress = ((float)currentGeneratorAsset / totalCurrentGeneratorAssets) / totalGenerators;
|
||||
var progressToReport = completedGeneratorProgress + currentGeneratorProgress;
|
||||
OnProgressChanged?.Invoke(progressToReport);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e5906f8cb3e4eec489a2f7a82844bb3f
|
||||
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/Generators/CustomPreviewGenerator.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,15 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators
|
||||
{
|
||||
internal interface IPreviewGenerator
|
||||
{
|
||||
PreviewGenerationSettings Settings { get; }
|
||||
|
||||
event Action<float> OnProgressChanged;
|
||||
|
||||
Task<PreviewGenerationResult> Generate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ebddaccb94ca6e34aa36b535d0a47249
|
||||
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/Generators/IPreviewGenerator.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,362 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using AssetStoreTools.Previews.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Tilemaps;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators
|
||||
{
|
||||
internal class NativePreviewGenerator : PreviewGeneratorBase
|
||||
{
|
||||
private const double InitialPreviewLoadingTimeoutSeconds = 10;
|
||||
|
||||
private NativePreviewGenerationSettings _nativeSettings;
|
||||
|
||||
private RenderTexture _renderTexture;
|
||||
|
||||
private int _generatedPreviewsCount;
|
||||
private int _totalPreviewsCount;
|
||||
|
||||
public override event Action<float> OnProgressChanged;
|
||||
|
||||
public NativePreviewGenerator(NativePreviewGenerationSettings settings)
|
||||
: base(settings)
|
||||
{
|
||||
_nativeSettings = settings;
|
||||
}
|
||||
|
||||
protected override void Validate()
|
||||
{
|
||||
base.Validate();
|
||||
|
||||
if (_nativeSettings.ChunkSize <= 0)
|
||||
throw new ArgumentException("Chunk size must be larger than 0");
|
||||
}
|
||||
|
||||
protected override async Task<PreviewGenerationResult> GenerateImpl()
|
||||
{
|
||||
var result = new PreviewGenerationResult()
|
||||
{
|
||||
GenerationType = _nativeSettings.GenerationType
|
||||
};
|
||||
|
||||
OnProgressChanged?.Invoke(0f);
|
||||
|
||||
try
|
||||
{
|
||||
var objects = GetObjectsRequiringPreviews(_nativeSettings.InputPaths);
|
||||
var filteredObjects = new List<PreviewMetadata>();
|
||||
var reusedPreviews = new List<PreviewMetadata>();
|
||||
FilterObjects(objects, filteredObjects, reusedPreviews);
|
||||
|
||||
_generatedPreviewsCount = 0;
|
||||
_totalPreviewsCount = objects.Count;
|
||||
|
||||
Directory.CreateDirectory(_nativeSettings.OutputPath);
|
||||
|
||||
var generatedPreviews = new List<PreviewMetadata>();
|
||||
if (!_nativeSettings.WaitForPreviews)
|
||||
{
|
||||
WritePreviewsWithoutWaiting(filteredObjects, out generatedPreviews);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_nativeSettings.ChunkedPreviewLoading)
|
||||
{
|
||||
await WaitAndWritePreviewsChunked(filteredObjects, generatedPreviews);
|
||||
}
|
||||
else
|
||||
{
|
||||
await WaitAndWritePreviews(filteredObjects, generatedPreviews);
|
||||
}
|
||||
}
|
||||
|
||||
var allPreviews = new List<PreviewMetadata>();
|
||||
allPreviews.AddRange(generatedPreviews);
|
||||
allPreviews.AddRange(reusedPreviews);
|
||||
|
||||
result.Success = true;
|
||||
result.GeneratedPreviews = generatedPreviews;
|
||||
result.Previews = allPreviews;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.Success = false;
|
||||
result.Exception = e;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<PreviewMetadata> GetObjectsRequiringPreviews(string[] inputPaths)
|
||||
{
|
||||
var objects = new List<PreviewMetadata>();
|
||||
var guids = AssetDatabase.FindAssets("", inputPaths);
|
||||
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
if (objects.Any(x => x.Guid == guid))
|
||||
continue;
|
||||
|
||||
var assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
var obj = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath);
|
||||
if (!ShouldHavePreview(obj))
|
||||
continue;
|
||||
|
||||
objects.Add(new PreviewMetadata() { Type = GenerationType.Native, Guid = guid });
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
||||
|
||||
private void FilterObjects(List<PreviewMetadata> objects, List<PreviewMetadata> filteredObjects, List<PreviewMetadata> reusedPreviews)
|
||||
{
|
||||
if (Settings.OverwriteExisting || !CachingService.GetCachedMetadata(out var database))
|
||||
{
|
||||
filteredObjects.AddRange(objects);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
var matchingEntry = database.Previews.FirstOrDefault(x =>
|
||||
x.Guid == obj.Guid
|
||||
&& x.Type == GenerationType.Native
|
||||
&& x.Exists());
|
||||
|
||||
if (matchingEntry == null)
|
||||
{
|
||||
filteredObjects.Add(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
reusedPreviews.Add(matchingEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldHavePreview(UnityEngine.Object asset)
|
||||
{
|
||||
if (asset == null)
|
||||
return false;
|
||||
|
||||
if (!AssetDatabase.IsMainAsset(asset))
|
||||
return false;
|
||||
|
||||
switch (asset)
|
||||
{
|
||||
case AudioClip _:
|
||||
case Material _:
|
||||
case Mesh _:
|
||||
case TerrainLayer _:
|
||||
case Texture _:
|
||||
case Tile _:
|
||||
return true;
|
||||
case GameObject go:
|
||||
var renderers = go.GetComponentsInChildren<Renderer>();
|
||||
return renderers != null && renderers.Length > 0;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private PreviewMetadata WritePreviewToDisk(PreviewMetadata metadata, Texture2D texture)
|
||||
{
|
||||
var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(AssetDatabase.GUIDToAssetPath(metadata.Guid));
|
||||
var width = Mathf.Min(texture.width, 128);
|
||||
var height = Mathf.Min(texture.height, 128);
|
||||
var readableTexture = GraphicsUtility.ResizeTexture(texture, width, height);
|
||||
var fileName = PreviewConvertUtility.ConvertFilenameWithExtension(asset, _nativeSettings.PreviewFileNamingFormat, _nativeSettings.Format);
|
||||
var filePath = $"{_nativeSettings.OutputPath}/{fileName}";
|
||||
var bytes = PreviewConvertUtility.ConvertTexture(readableTexture, _nativeSettings.Format);
|
||||
|
||||
File.WriteAllBytes(filePath, bytes);
|
||||
|
||||
metadata.Type = GenerationType.Native;
|
||||
metadata.Name = asset.name;
|
||||
metadata.Path = filePath;
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private void WritePreviewsWithoutWaiting(List<PreviewMetadata> objects, out List<PreviewMetadata> generatedPreviews)
|
||||
{
|
||||
generatedPreviews = new List<PreviewMetadata>();
|
||||
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
var texture = GetAssetPreviewFromGuid(obj.Guid);
|
||||
if (texture == null)
|
||||
continue;
|
||||
|
||||
var generatedPreview = WritePreviewToDisk(obj, texture);
|
||||
generatedPreviews.Add(generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
private Texture2D GetAssetPreviewFromGuid(string guid)
|
||||
{
|
||||
var method = typeof(AssetPreview).GetMethod("GetAssetPreviewFromGUID", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, null, new[] { typeof(string) }, null);
|
||||
var args = new object[] { guid };
|
||||
|
||||
return method?.Invoke(null, args) as Texture2D;
|
||||
}
|
||||
|
||||
private async Task WaitAndWritePreviewsChunked(List<PreviewMetadata> objects, List<PreviewMetadata> generatedPreviews)
|
||||
{
|
||||
var chunks = objects.Count / _nativeSettings.ChunkSize;
|
||||
var remainder = objects.Count % _nativeSettings.ChunkSize;
|
||||
if (remainder != 0)
|
||||
chunks += 1;
|
||||
|
||||
for (int i = 0; i < chunks; i++)
|
||||
{
|
||||
var chunkObjects = new List<PreviewMetadata>();
|
||||
|
||||
for (int j = 0; j < _nativeSettings.ChunkSize; j++)
|
||||
{
|
||||
var index = i * _nativeSettings.ChunkSize + j;
|
||||
if (index == objects.Count)
|
||||
break;
|
||||
|
||||
chunkObjects.Add(objects[index]);
|
||||
}
|
||||
|
||||
var generatedPreviewsChunk = new List<PreviewMetadata>();
|
||||
await WaitAndWritePreviews(chunkObjects, generatedPreviewsChunk);
|
||||
generatedPreviews.AddRange(generatedPreviewsChunk);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task WaitAndWritePreviews(List<PreviewMetadata> objects, List<PreviewMetadata> generatedPreviews)
|
||||
{
|
||||
var initialObjectCount = objects.Count();
|
||||
if (initialObjectCount == 0)
|
||||
return;
|
||||
|
||||
await WaitAndWritePreviewIteration(objects, generatedPreviews);
|
||||
var remainingObjectCount = objects.Count;
|
||||
|
||||
// First iteration may take longer to start loading objects
|
||||
var firstIterationStartTime = EditorApplication.timeSinceStartup;
|
||||
while (true)
|
||||
{
|
||||
if (remainingObjectCount < initialObjectCount)
|
||||
break;
|
||||
|
||||
if (EditorApplication.timeSinceStartup - firstIterationStartTime > InitialPreviewLoadingTimeoutSeconds)
|
||||
throw new Exception("Preview loading timed out.");
|
||||
|
||||
await WaitAndWritePreviewIteration(objects, generatedPreviews);
|
||||
remainingObjectCount = objects.Count;
|
||||
}
|
||||
|
||||
if (remainingObjectCount == 0)
|
||||
return;
|
||||
|
||||
while (true)
|
||||
{
|
||||
await WaitForEndOfFrame(1);
|
||||
await WaitAndWritePreviewIteration(objects, generatedPreviews);
|
||||
|
||||
// If no more previews are being loaded, try one more time before quitting
|
||||
if (objects.Count == remainingObjectCount)
|
||||
{
|
||||
await WaitForEndOfFrame(1);
|
||||
await WaitAndWritePreviewIteration(objects, generatedPreviews);
|
||||
|
||||
if (objects.Count == remainingObjectCount)
|
||||
{
|
||||
var missingObjects = string.Join("\n", objects.Select(x => AssetDatabase.GUIDToAssetPath(x.Guid)));
|
||||
Debug.LogWarning($"Unity Editor failed to fetch previews for {objects.Count} objects:\n{missingObjects}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
remainingObjectCount = objects.Count;
|
||||
|
||||
// Exit when all previews are loaded
|
||||
if (remainingObjectCount == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task WaitAndWritePreviewIteration(List<PreviewMetadata> objects, List<PreviewMetadata> generatedPreviews)
|
||||
{
|
||||
var cacheSize = Mathf.Max(_nativeSettings.ChunkSize * 2, objects.Count() + _nativeSettings.ChunkSize);
|
||||
AssetPreview.SetPreviewTextureCacheSize(cacheSize);
|
||||
|
||||
// Initial queueing
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(AssetDatabase.GUIDToAssetPath(obj.Guid));
|
||||
AssetPreview.GetAssetPreview(asset);
|
||||
}
|
||||
|
||||
await WaitForEndOfFrame();
|
||||
|
||||
// Waiting (NOTE: works inconsistently across Unity streams)
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(AssetDatabase.GUIDToAssetPath(obj.Guid));
|
||||
if (AssetPreview.IsLoadingAssetPreview(asset.GetInstanceID()))
|
||||
{
|
||||
await WaitForEndOfFrame();
|
||||
}
|
||||
}
|
||||
|
||||
// Writing
|
||||
for (int i = 0; i < objects.Count; i++)
|
||||
{
|
||||
var obj = objects[i];
|
||||
|
||||
var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(AssetDatabase.GUIDToAssetPath(obj.Guid));
|
||||
var texture = AssetPreview.GetAssetPreview(asset);
|
||||
if (texture == null)
|
||||
continue;
|
||||
|
||||
WritePreviewToDisk(obj, texture);
|
||||
generatedPreviews.Add(obj);
|
||||
_generatedPreviewsCount++;
|
||||
OnProgressChanged?.Invoke((float)_generatedPreviewsCount / _totalPreviewsCount);
|
||||
}
|
||||
|
||||
// Removing written objects from the list
|
||||
for (int i = objects.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (objects[i].Exists())
|
||||
objects.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task WaitForEndOfFrame(double atLeastSeconds)
|
||||
{
|
||||
var startTime = EditorApplication.timeSinceStartup;
|
||||
while (EditorApplication.timeSinceStartup - startTime <= atLeastSeconds)
|
||||
{
|
||||
await WaitForEndOfFrame();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task WaitForEndOfFrame()
|
||||
{
|
||||
var isNextFrame = false;
|
||||
EditorApplication.CallbackFunction callback = null;
|
||||
callback = () =>
|
||||
{
|
||||
EditorApplication.update -= callback;
|
||||
isNextFrame = true;
|
||||
};
|
||||
|
||||
EditorApplication.update += callback;
|
||||
while (!isNextFrame)
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd6eeb2f97a2ed34db51ab5ac0b3ffa1
|
||||
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/Generators/NativePreviewGenerator.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,45 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using AssetStoreTools.Previews.Services;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AssetStoreTools.Previews.Generators
|
||||
{
|
||||
internal abstract class PreviewGeneratorBase : IPreviewGenerator
|
||||
{
|
||||
public PreviewGenerationSettings Settings { get; }
|
||||
protected ICachingService CachingService;
|
||||
|
||||
public abstract event Action<float> OnProgressChanged;
|
||||
|
||||
public PreviewGeneratorBase(PreviewGenerationSettings settings)
|
||||
{
|
||||
Settings = settings;
|
||||
CachingService = PreviewServiceProvider.Instance.GetService<ICachingService>();
|
||||
}
|
||||
|
||||
public async Task<PreviewGenerationResult> Generate()
|
||||
{
|
||||
Validate();
|
||||
|
||||
var result = await GenerateImpl();
|
||||
if (result.Success)
|
||||
{
|
||||
CachingService.CacheMetadata(result.GeneratedPreviews);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected virtual void Validate()
|
||||
{
|
||||
if (Settings.InputPaths == null || Settings.InputPaths.Length == 0)
|
||||
throw new ArgumentException("Input paths cannot be null");
|
||||
|
||||
if (string.IsNullOrEmpty(Settings.OutputPath))
|
||||
throw new ArgumentException("Output path cannot be null");
|
||||
}
|
||||
|
||||
protected abstract Task<PreviewGenerationResult> GenerateImpl();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cedf01448e0edcc4fb55f19f2e92b740
|
||||
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/Generators/PreviewGeneratorBase.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa18c820f185bfc4d8cd59e3418e2c4e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb61a60f2ff91a448a7808ef2a25f871
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,87 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using AssetStoreTools.Utility;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStoreTools.Previews.Services
|
||||
{
|
||||
internal class CachingService : ICachingService
|
||||
{
|
||||
public void CacheMetadata(IEnumerable<PreviewMetadata> previews)
|
||||
{
|
||||
var updatedDatabase = UpdatePreviewDatabase(previews);
|
||||
|
||||
var serializerSettings = new JsonSerializerSettings()
|
||||
{
|
||||
ContractResolver = PreviewDatabaseContractResolver.Instance,
|
||||
Converters = new List<JsonConverter>() { new StringEnumConverter() },
|
||||
Formatting = Formatting.Indented
|
||||
};
|
||||
|
||||
CacheUtil.CreateFileInTempCache(Constants.Previews.PreviewDatabaseFile, JsonConvert.SerializeObject(updatedDatabase, serializerSettings), true);
|
||||
}
|
||||
|
||||
public bool GetCachedMetadata(out PreviewDatabase previewDatabase)
|
||||
{
|
||||
previewDatabase = null;
|
||||
if (!CacheUtil.GetFileFromTempCache(Constants.Previews.PreviewDatabaseFile, out string filePath))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
var serializerSettings = new JsonSerializerSettings()
|
||||
{
|
||||
ContractResolver = PreviewDatabaseContractResolver.Instance,
|
||||
Converters = new List<JsonConverter>() { new StringEnumConverter() }
|
||||
};
|
||||
|
||||
previewDatabase = JsonConvert.DeserializeObject<PreviewDatabase>(File.ReadAllText(filePath, Encoding.UTF8), serializerSettings);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private PreviewDatabase UpdatePreviewDatabase(IEnumerable<PreviewMetadata> previews)
|
||||
{
|
||||
PreviewDatabase database;
|
||||
if (!GetCachedMetadata(out database))
|
||||
database = new PreviewDatabase();
|
||||
|
||||
// Delete missing previews
|
||||
for (int i = database.Previews.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (database.Previews[i].Exists())
|
||||
continue;
|
||||
|
||||
database.Previews.RemoveAt(i);
|
||||
}
|
||||
|
||||
// Append new previews & Replace existing previews
|
||||
foreach (var preview in previews)
|
||||
{
|
||||
var matchingPreviews = database.Previews.Where(x => x.Guid == preview.Guid).ToList();
|
||||
foreach (var matchingPreview in matchingPreviews)
|
||||
{
|
||||
// Delete previously generated preview of the same type
|
||||
if (matchingPreview.Type == preview.Type)
|
||||
database.Previews.Remove(matchingPreview);
|
||||
// Delete previously generated preview of a different type if the path matches
|
||||
else if (matchingPreview.Path.Equals(preview.Path))
|
||||
database.Previews.Remove(matchingPreview);
|
||||
}
|
||||
|
||||
database.Previews.Add(preview);
|
||||
}
|
||||
|
||||
database.Previews = database.Previews.OrderBy(x => x.Guid).ThenBy(x => x.Type).ToList();
|
||||
return database;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e0b6cf909c8798b4590744959571a21f
|
||||
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/Services/Caching/CachingService.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,11 @@
|
||||
using AssetStoreTools.Previews.Data;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetStoreTools.Previews.Services
|
||||
{
|
||||
internal interface ICachingService : IPreviewService
|
||||
{
|
||||
void CacheMetadata(IEnumerable<PreviewMetadata> previews);
|
||||
bool GetCachedMetadata(out PreviewDatabase previewDatabase);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eeaeae010299dcd489adb00dbf51b274
|
||||
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/Services/Caching/ICachingService.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace AssetStoreTools.Previews.Services
|
||||
{
|
||||
public interface IPreviewService { }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c2761fe05638644d8e3a265865beef8
|
||||
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/Services/IPreviewService.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,17 @@
|
||||
using AssetStoreTools.Utility;
|
||||
|
||||
namespace AssetStoreTools.Previews.Services
|
||||
{
|
||||
internal class PreviewServiceProvider : ServiceProvider<IPreviewService>
|
||||
{
|
||||
public static PreviewServiceProvider Instance => _instance ?? (_instance = new PreviewServiceProvider());
|
||||
private static PreviewServiceProvider _instance;
|
||||
|
||||
private PreviewServiceProvider() { }
|
||||
|
||||
protected override void RegisterServices()
|
||||
{
|
||||
Register<ICachingService, CachingService>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a19bf5a4e3e441047bbc1b894e2a1149
|
||||
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/Services/PreviewServiceProvider.cs
|
||||
uploadId: 724584
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4738f3648c8368244a968bc840c1152b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23a2f4eadd444194a91ff4ce509e4798
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 700ec0107b011824892281e880281bb1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user