Update
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
using DA_Assets.DAI;
|
||||
using DA_Assets.Extensions;
|
||||
using DA_Assets.FCU.Extensions;
|
||||
using DA_Assets.FCU.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DA_Assets.FCU
|
||||
{
|
||||
[Serializable]
|
||||
public class SpriteColorizer : MonoBehaviourLinkerRuntime<FigmaConverterUnity>
|
||||
{
|
||||
public async Task ColorizeSprites(List<FObject> fobjects)
|
||||
{
|
||||
if (monoBeh.UsingSVG())
|
||||
return;
|
||||
|
||||
foreach (FObject fobject in fobjects)
|
||||
{
|
||||
if (monoBeh.IsCancellationRequested(TokenType.Import))
|
||||
return;
|
||||
|
||||
if (fobject.Data.FcuImageType != FcuImageType.Downloadable)
|
||||
continue;
|
||||
|
||||
if (monoBeh.UsingSpriteRenderer())
|
||||
{
|
||||
if (fobject.Data.Graphic.SpriteSingleColor.IsDefault())
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fobject.Data.Graphic.SpriteSingleColor.IsDefault() &&
|
||||
fobject.Data.Graphic.SpriteSingleLinearGradient.IsDefault())
|
||||
continue;
|
||||
}
|
||||
|
||||
if (File.Exists(fobject.Data.SpritePath.GetFullAssetPath()) == false)
|
||||
continue;
|
||||
|
||||
byte[] rawData = File.ReadAllBytes(fobject.Data.SpritePath.GetFullAssetPath());
|
||||
Texture2D tex = new Texture2D(fobject.Data.SpriteSize.x, fobject.Data.SpriteSize.y);
|
||||
tex.LoadImage(rawData);
|
||||
|
||||
tex.Colorize(Color.white);
|
||||
|
||||
byte[] bytes = new byte[0];
|
||||
|
||||
switch (monoBeh.Settings.ImageSpritesSettings.ImageFormat)
|
||||
{
|
||||
case ImageFormat.PNG:
|
||||
bytes = tex.EncodeToPNG();
|
||||
break;
|
||||
case ImageFormat.JPG:
|
||||
bytes = tex.EncodeToJPG();
|
||||
break;
|
||||
}
|
||||
|
||||
File.WriteAllBytes(fobject.Data.SpritePath, bytes);
|
||||
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79a42f153b8ec0444b26f8cc9b2fda41
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,484 @@
|
||||
using DA_Assets.FCU.Model;
|
||||
using DA_Assets.DAI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using DA_Assets.FCU.Extensions;
|
||||
using UnityEngine;
|
||||
using DA_Assets.Logging;
|
||||
using DA_Assets.Extensions;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
#if JSONNET_EXISTS
|
||||
using Newtonsoft.Json;
|
||||
#endif
|
||||
|
||||
namespace DA_Assets.FCU
|
||||
{
|
||||
[Serializable]
|
||||
public class SpriteDownloader : MonoBehaviourLinkerRuntime<FigmaConverterUnity>
|
||||
{
|
||||
private int _maxConcurrentDownloads = 100;
|
||||
private int _maxDownloadAttempts = 3;
|
||||
private float _maxChunkSize = 24_000_000;
|
||||
private int _errorLogSplitLimit = 50;
|
||||
private int _logDelayMs = 1000;
|
||||
private int _maxSpritesCount = 100;
|
||||
private Dictionary<ImageFormatScaleKey, List<List<SpriteData>>> idFormatChunks;
|
||||
|
||||
public async Task CreateImageChunks(List<FObject> fobjects)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
List<FObject> needDownload = fobjects
|
||||
.Where(x => x.Data.NeedDownload)
|
||||
.GroupBy(x => x.Data.Hash)
|
||||
.Select(g => g.First())
|
||||
.ToList();
|
||||
|
||||
idFormatChunks = GetIdFormatChunks(needDownload);
|
||||
});
|
||||
}
|
||||
|
||||
public async Task DownloadSprites(List<FObject> fobjects)
|
||||
{
|
||||
DALogger.Log($"Download Sprites");
|
||||
|
||||
List<FObject> needDownload = fobjects
|
||||
.Where(x => x.Data.NeedDownload)
|
||||
.GroupBy(x => x.Data.Hash)
|
||||
.Select(g => g.First())
|
||||
.ToList();
|
||||
|
||||
if (needDownload.IsEmpty())
|
||||
{
|
||||
DALogger.Log($"DownloadSprites no need");
|
||||
return;
|
||||
}
|
||||
|
||||
int totalCount = needDownload.Count;
|
||||
int downloadedCount = 0;
|
||||
int lastLoggedCount = -1;
|
||||
|
||||
CancellationTokenSource downloadLogTokenSource = new CancellationTokenSource();
|
||||
|
||||
var missingSpriteLinks = await GetSpriteLinks(needDownload);
|
||||
|
||||
SemaphoreSlim semaphore = new SemaphoreSlim(_maxConcurrentDownloads);
|
||||
List<Task> tasks = new List<Task>();
|
||||
|
||||
ConcurrentBag<FObject> failedObjects = new ConcurrentBag<FObject>();
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
while (!downloadLogTokenSource.Token.IsCancellationRequested)
|
||||
{
|
||||
if (lastLoggedCount != downloadedCount)
|
||||
{
|
||||
DALogger.Log(FcuLocKey.log_downloading_images.Localize(downloadedCount, totalCount));
|
||||
lastLoggedCount = downloadedCount;
|
||||
}
|
||||
|
||||
await Task.Delay(_logDelayMs, downloadLogTokenSource.Token);
|
||||
}
|
||||
}, downloadLogTokenSource.Token);
|
||||
|
||||
DALogger.Log(FcuLocKey.log_start_download_images.Localize());
|
||||
|
||||
foreach (var formatChunks in missingSpriteLinks)
|
||||
{
|
||||
foreach (var chunk in formatChunks.Value)
|
||||
{
|
||||
foreach (var idFormatLink in chunk)
|
||||
{
|
||||
await semaphore.WaitAsync();
|
||||
|
||||
Task task = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
bool success = await DownloadSprite(idFormatLink, _maxDownloadAttempts);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
failedObjects.Add(idFormatLink.FObject);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogException(ex);
|
||||
failedObjects.Add(idFormatLink.FObject);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Increment(ref downloadedCount);
|
||||
semaphore.Release();
|
||||
}
|
||||
});
|
||||
|
||||
tasks.Add(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
downloadLogTokenSource.Cancel();
|
||||
|
||||
DALogger.Log(FcuLocKey.log_downloading_images.Localize(downloadedCount, totalCount));
|
||||
|
||||
LogFailedDownloads(failedObjects);
|
||||
}
|
||||
|
||||
public async Task<bool> DownloadSprite(SpriteData idFormatLink, int maxDownloadAttempts)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (idFormatLink.Link.IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DARequest request = new DARequest
|
||||
{
|
||||
RequestType = RequestType.GetFile,
|
||||
Query = idFormatLink.Link
|
||||
};
|
||||
|
||||
DAResult<byte[]> result = default;
|
||||
int attempts = 0;
|
||||
|
||||
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
|
||||
{
|
||||
while (attempts < maxDownloadAttempts && result.Object == null)
|
||||
{
|
||||
attempts++;
|
||||
result = await monoBeh.RequestSender.SendRequest<byte[]>(request);
|
||||
}
|
||||
}
|
||||
|
||||
switch (result.Error.Status)
|
||||
{
|
||||
case 909:
|
||||
DALogger.LogError(FcuLocKey.log_ssl_error.Localize(result.Error.Message, result.Error.Status));
|
||||
monoBeh.Events.OnImportFail?.Invoke(monoBeh);
|
||||
monoBeh.AssetTools.StopImport(StopImportReason.Error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.Object == null)
|
||||
{
|
||||
throw new NullReferenceException();
|
||||
}
|
||||
|
||||
File.WriteAllBytes(idFormatLink.FObject.Data.SpritePath, result.Object);
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<Dictionary<ImageFormatScaleKey, List<List<SpriteData>>>> GetSpriteLinks(List<FObject> fobjects)
|
||||
{
|
||||
|
||||
var idFormatLinkChunks = new Dictionary<ImageFormatScaleKey, List<List<SpriteData>>>();
|
||||
|
||||
int totalLinks = fobjects.Count;
|
||||
int obtainedLinks = 0;
|
||||
int lastLoggedLinks = -1;
|
||||
|
||||
CancellationTokenSource linkLogTokenSource = new CancellationTokenSource();
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
while (!linkLogTokenSource.Token.IsCancellationRequested)
|
||||
{
|
||||
if (lastLoggedLinks != obtainedLinks)
|
||||
{
|
||||
DALogger.Log(FcuLocKey.log_getting_links.Localize(obtainedLinks, totalLinks));
|
||||
lastLoggedLinks = obtainedLinks;
|
||||
}
|
||||
|
||||
await Task.Delay(_logDelayMs, linkLogTokenSource.Token);
|
||||
}
|
||||
}, linkLogTokenSource.Token);
|
||||
|
||||
foreach (var idFormatChunk in idFormatChunks)
|
||||
{
|
||||
if (monoBeh.IsCancellationRequested(TokenType.Import))
|
||||
break;
|
||||
|
||||
foreach (List<SpriteData> chunk in idFormatChunk.Value)
|
||||
{
|
||||
IEnumerable<string> ids = chunk.Select(x => x.FObject.Id);
|
||||
|
||||
DARequest request = RequestCreator.CreateImageLinksRequest(
|
||||
monoBeh.Settings.MainSettings.ProjectUrl,
|
||||
idFormatChunk.Key.ImageFormat.ToLower(),
|
||||
idFormatChunk.Key.Scale,
|
||||
ids,
|
||||
monoBeh.RequestSender.GetRequestHeader(monoBeh.Authorizer.Token));
|
||||
|
||||
DAResult<FigmaImageRequest> result = await monoBeh.RequestSender.SendRequest<FigmaImageRequest>(request);
|
||||
|
||||
if (result.Success && result.Object.images.IsEmpty())
|
||||
{
|
||||
Debug.LogError("result.Success && result.Object.images.IsEmpty()");
|
||||
}
|
||||
else if (result.Success)
|
||||
{
|
||||
if (!idFormatLinkChunks.ContainsKey(idFormatChunk.Key))
|
||||
{
|
||||
idFormatLinkChunks[idFormatChunk.Key] = new List<List<SpriteData>>();
|
||||
}
|
||||
|
||||
List<SpriteData> linkChunk = new List<SpriteData>();
|
||||
|
||||
foreach (var idFormat in chunk)
|
||||
{
|
||||
result.Object.images.TryGetValue(idFormat.FObject.Id, out string link);
|
||||
|
||||
if (monoBeh.Settings.MainSettings.Https == false)
|
||||
{
|
||||
link = link.Replace("https://", "http://");
|
||||
}
|
||||
|
||||
linkChunk.Add(new SpriteData
|
||||
{
|
||||
FObject = idFormat.FObject,
|
||||
Format = idFormat.Format,
|
||||
Link = link ?? string.Empty
|
||||
});
|
||||
|
||||
Interlocked.Increment(ref obtainedLinks);
|
||||
}
|
||||
|
||||
idFormatLinkChunks[idFormatChunk.Key].Add(linkChunk);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError(result.Error.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
linkLogTokenSource.Cancel();
|
||||
|
||||
DALogger.Log(FcuLocKey.log_getting_links.Localize(obtainedLinks, totalLinks));
|
||||
|
||||
return idFormatLinkChunks;
|
||||
}
|
||||
|
||||
public async Task SetScalesAndMaxSpriteSizes(List<FObject> fobjects)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
Parallel.ForEach(fobjects.Where(x => x.IsSprite()), fobject =>
|
||||
{
|
||||
fobject.Data.MaxSpriteSize = GetMaxSpriteSize(fobject);
|
||||
fobject.Data.Scale = GetMaxAllowedScale(fobject.Data.MaxSpriteSize, monoBeh.Settings.ImageSpritesSettings.MaxSpriteSize, _maxChunkSize);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public Dictionary<ImageFormatScaleKey, List<List<SpriteData>>> GetIdFormatChunks(List<FObject> fobjects)
|
||||
{
|
||||
var formatChunks = new Dictionary<ImageFormatScaleKey, List<List<SpriteData>>>();
|
||||
|
||||
// Group FObjects by their ImageFormat and Scale
|
||||
var fobjectsByFormatAndScale = new Dictionary<ImageFormatScaleKey, List<FObject>>();
|
||||
|
||||
foreach (FObject fobject in fobjects.Where(x => x.IsSprite()))
|
||||
{
|
||||
ImageFormatScaleKey key = new ImageFormatScaleKey
|
||||
{
|
||||
ImageFormat = fobject.Data.ImageFormat,
|
||||
Scale = fobject.Data.Scale
|
||||
};
|
||||
|
||||
if (!fobjectsByFormatAndScale.ContainsKey(key))
|
||||
{
|
||||
fobjectsByFormatAndScale[key] = new List<FObject>();
|
||||
}
|
||||
|
||||
fobjectsByFormatAndScale[key].Add(fobject);
|
||||
}
|
||||
|
||||
// For each group (ImageFormat + Scale) create chunks
|
||||
foreach (var kvp in fobjectsByFormatAndScale)
|
||||
{
|
||||
ImageFormatScaleKey key = kvp.Key;
|
||||
List<FObject> fobjectList = kvp.Value;
|
||||
|
||||
List<List<SpriteData>> chunks = new List<List<SpriteData>>();
|
||||
List<SpriteData> currentChunk = new List<SpriteData>();
|
||||
float currentChunkSize = 0;
|
||||
|
||||
foreach (FObject fobject in fobjectList)
|
||||
{
|
||||
float spriteSize = fobject.Data.MaxSpriteSize.x * fobject.Data.MaxSpriteSize.y * fobject.Data.Scale;
|
||||
//Debug.LogError($"{spriteSize} | {fobject.Data.MaxSpriteSize.x * fobject.Data.Scale} | {fobject.Data.MaxSpriteSize.y * fobject.Data.Scale}");
|
||||
// If adding this image exceeds the maximum chunk size, create a new chunk
|
||||
if (currentChunkSize + spriteSize > _maxChunkSize || currentChunk.Count > _maxSpritesCount)
|
||||
{
|
||||
if (currentChunk.Count > 0)
|
||||
{
|
||||
chunks.Add(currentChunk);
|
||||
}
|
||||
|
||||
currentChunk = new List<SpriteData>();
|
||||
currentChunkSize = 0;
|
||||
}
|
||||
|
||||
// Add the image to the current chunk
|
||||
currentChunk.Add(new SpriteData
|
||||
{
|
||||
FObject = fobject,
|
||||
Format = key.ImageFormat.ToString(),
|
||||
Scale = key.Scale
|
||||
});
|
||||
currentChunkSize += spriteSize;
|
||||
}
|
||||
|
||||
// Add the last chunk if it's not empty
|
||||
if (currentChunk.Count > 0)
|
||||
{
|
||||
chunks.Add(currentChunk);
|
||||
}
|
||||
|
||||
formatChunks[key] = chunks;
|
||||
}
|
||||
|
||||
return formatChunks;
|
||||
}
|
||||
|
||||
private void LogFailedDownloads(ConcurrentBag<FObject> failedObjects)
|
||||
{
|
||||
if (failedObjects.Count() > 0)
|
||||
{
|
||||
List<List<string>> comps = failedObjects.Select(x => x.Data.NameHierarchy).Split(_errorLogSplitLimit);
|
||||
|
||||
foreach (List<string> comp in comps)
|
||||
{
|
||||
string hierarchies = string.Join("\n", comp);
|
||||
|
||||
DALogger.LogError(
|
||||
FcuLocKey.log_malformed_url.Localize(comp.Count, hierarchies));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2 GetMaxSpriteSize(FObject fobject)
|
||||
{
|
||||
float maxX;
|
||||
float maxY;
|
||||
|
||||
bool hasBoundingSize = fobject.GetBoundingSize(out Vector2 bSize);
|
||||
bool hasRenderSize = fobject.GetRenderSize(out Vector2 rSize);
|
||||
|
||||
if (hasBoundingSize && hasRenderSize)
|
||||
{
|
||||
maxX = Mathf.Max(bSize.x, rSize.x);
|
||||
maxY = Mathf.Max(bSize.y, rSize.y);
|
||||
}
|
||||
else if (hasRenderSize)
|
||||
{
|
||||
maxX = rSize.x;
|
||||
maxY = rSize.y;
|
||||
}
|
||||
else if (hasBoundingSize)
|
||||
{
|
||||
maxX = bSize.x;
|
||||
maxY = bSize.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxX = fobject.Size.x;
|
||||
maxY = fobject.Size.y;
|
||||
}
|
||||
|
||||
return new Vector2(maxX, maxY);
|
||||
}
|
||||
|
||||
public float GetMaxAllowedScale(
|
||||
Vector2 imageSize,
|
||||
Vector2 maxSpriteSize,
|
||||
float maxChunkSize,
|
||||
float minScale = FcuConfig.IMAGE_SCALE_MIN,
|
||||
float maxScale = FcuConfig.IMAGE_SCALE_MAX)
|
||||
{
|
||||
if (monoBeh.UsingSVG())
|
||||
{
|
||||
return 1f;
|
||||
}
|
||||
|
||||
float effectiveMaxSpriteWidth = Mathf.Min(maxSpriteSize.x, monoBeh.Settings.ImageSpritesSettings.MaxSpriteSize.x);
|
||||
float effectiveMaxSpriteHeight = Mathf.Min(maxSpriteSize.y, monoBeh.Settings.ImageSpritesSettings.MaxSpriteSize.y);
|
||||
|
||||
float scaleX = effectiveMaxSpriteWidth / imageSize.x;
|
||||
float scaleY = effectiveMaxSpriteHeight / imageSize.y;
|
||||
float maxScaleBySpriteSize = Mathf.Min(scaleX, scaleY);
|
||||
maxScaleBySpriteSize = Mathf.Max(1f, maxScaleBySpriteSize);
|
||||
|
||||
float maxScaleByChunkSize = Mathf.Sqrt(maxChunkSize / (imageSize.x * imageSize.y));
|
||||
float maxScaleAllowed = Mathf.Min(maxScaleBySpriteSize, maxScaleByChunkSize);
|
||||
maxScaleAllowed = Mathf.Clamp(maxScaleAllowed, minScale, maxScale);
|
||||
maxScaleAllowed = (float)Math.Round(maxScaleAllowed, 2);
|
||||
|
||||
//Debug.Log($"imageSize: {imageSize}, scaleX: {scaleX}, scaleY: {scaleY}, maxScaleBySpriteSize: {maxScaleBySpriteSize}, maxScaleAllowed: {maxScaleAllowed}");
|
||||
|
||||
return maxScaleAllowed;
|
||||
}
|
||||
|
||||
public struct FigmaImageRequest
|
||||
{
|
||||
#if JSONNET_EXISTS
|
||||
[JsonProperty("err")]
|
||||
#endif
|
||||
public string error;
|
||||
#if JSONNET_EXISTS
|
||||
[JsonProperty("images")]
|
||||
#endif
|
||||
// key = id, value = link
|
||||
public Dictionary<string, string> images;
|
||||
}
|
||||
public struct ImageFormatScaleKey
|
||||
{
|
||||
public ImageFormat ImageFormat { get; set; }
|
||||
public float Scale { get; set; }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is ImageFormatScaleKey))
|
||||
return false;
|
||||
|
||||
var other = (ImageFormatScaleKey)obj;
|
||||
return ImageFormat == other.ImageFormat && Scale.Equals(other.Scale);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 17;
|
||||
hash = hash * 23 + ImageFormat.GetHashCode();
|
||||
hash = hash * 23 + Scale.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
public struct SpriteData
|
||||
{
|
||||
public FObject FObject { get; set; }
|
||||
public string Format { get; set; }
|
||||
public string Link { get; set; }
|
||||
public float Scale { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7918ee99b0328741b3924857b8be388
|
||||
@@ -0,0 +1,371 @@
|
||||
using DA_Assets.DAI;
|
||||
using DA_Assets.Extensions;
|
||||
using DA_Assets.FCU.Extensions;
|
||||
using DA_Assets.FCU.Model;
|
||||
using DA_Assets.Logging;
|
||||
using DA_Assets.SVGMeshUnity;
|
||||
using DA_Assets.Tools;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DA_Assets.FCU
|
||||
{
|
||||
[Serializable]
|
||||
public class SpriteGenerator : MonoBehaviourLinkerRuntime<FigmaConverterUnity>
|
||||
{
|
||||
[SerializeField] RectTransform rectTransform;
|
||||
[SerializeField] MeshRenderer meshRenderer;
|
||||
[SerializeField] MeshFilter meshFilter;
|
||||
[SerializeField] Camera camera;
|
||||
|
||||
private float spriteGenerationDelay = 0.25f;
|
||||
private int meshUpscaleFactor = 16;
|
||||
private int renderAntialiasing = 8;
|
||||
private float blurCoof = 10f;
|
||||
|
||||
private FilterMode filterMode = FilterMode.Bilinear;
|
||||
private TextureFormat textureFormat = TextureFormat.ARGB32;
|
||||
private RenderTextureFormat renderTextureFormat = RenderTextureFormat.ARGB32;
|
||||
|
||||
public async Task GenerateSprites(List<FObject> fobjects)
|
||||
{
|
||||
List<FObject> generative = fobjects.Where(x => x.Data.NeedGenerate).ToList();
|
||||
|
||||
if (generative.IsEmpty())
|
||||
return;
|
||||
|
||||
if (camera == null)
|
||||
{
|
||||
GameObject cameraGo = MonoBehExtensions.CreateEmptyGameObject();
|
||||
cameraGo.name = "SpriteGeneratorCamera";
|
||||
cameraGo.TryAddComponent(out camera);
|
||||
camera.orthographic = true;
|
||||
camera.backgroundColor = new Color(0, 0, 0, 0);
|
||||
camera.clearFlags = CameraClearFlags.Color;
|
||||
}
|
||||
|
||||
int generatedCount = 0;
|
||||
|
||||
_ = DACycles.ForEach(generative, fobject =>
|
||||
{
|
||||
FcuLogger.Debug($"GenerateSprites | {fobject.Data.NameHierarchy} | {fobject.Data.NeedGenerate}");
|
||||
|
||||
try
|
||||
{
|
||||
Texture2D fillTexture = null;
|
||||
Texture2D strokeTexture = null;
|
||||
Texture2D finalTexture = null;
|
||||
|
||||
FGraphic graphic = fobject.Data.Graphic;
|
||||
|
||||
if (!graphic.HasFill && graphic.HasStroke && !fobject.ContainsRoundedCorners())
|
||||
{
|
||||
IndividualStrokeWeights ind = fobject.IndividualStrokeWeights;
|
||||
|
||||
if (ind.IsDefault())
|
||||
{
|
||||
ind = new IndividualStrokeWeights
|
||||
{
|
||||
Left = fobject.StrokeWeight,
|
||||
Right = fobject.StrokeWeight,
|
||||
Top = fobject.StrokeWeight,
|
||||
Bottom = fobject.StrokeWeight,
|
||||
};
|
||||
}
|
||||
|
||||
if (ind.Left != 0 && ind.Left < 1)
|
||||
{
|
||||
ind.Left = 1;
|
||||
}
|
||||
|
||||
if (ind.Right != 0 && ind.Right < 1)
|
||||
{
|
||||
ind.Right = 1;
|
||||
}
|
||||
|
||||
if (ind.Top != 0 && ind.Top < 1)
|
||||
{
|
||||
ind.Top = 1;
|
||||
}
|
||||
|
||||
if (ind.Bottom != 0 && ind.Bottom < 1)
|
||||
{
|
||||
ind.Bottom = 1;
|
||||
}
|
||||
|
||||
float coof = monoBeh.Settings.ImageSpritesSettings.ImageScale;
|
||||
|
||||
int texWidth = (int)(fobject.Size.x * coof);
|
||||
int texHeight = (int)(fobject.Size.y * coof);
|
||||
|
||||
int leftWidth = (int)(ind.Left * coof);
|
||||
int rightWidth = (int)(ind.Right * coof);
|
||||
int topWidth = (int)(ind.Top * coof);
|
||||
int bottomWidth = (int)(ind.Bottom * coof);
|
||||
|
||||
finalTexture = TextureBorderDrawer.CreateTextureWithBorder(
|
||||
texWidth, texHeight,
|
||||
leftWidth, rightWidth, topWidth, bottomWidth,
|
||||
Color.white);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2Int finalSize = default;
|
||||
|
||||
if (graphic.HasFill)
|
||||
{
|
||||
Vector2 fillSize = fobject.Size;
|
||||
fillSize -= new Vector2Int(1, 0);
|
||||
fillSize.IsSupportedRenderSize(monoBeh.Settings.ImageSpritesSettings.ImageScale, out finalSize, out Vector2Int bakeFillSize);
|
||||
|
||||
string fillPath = fobject.FillGeometry[0].Path;
|
||||
|
||||
Color textureColor;
|
||||
|
||||
if (graphic.HasFill && graphic.HasStroke)
|
||||
{
|
||||
textureColor = graphic.Fill.SolidPaint.Color;
|
||||
}
|
||||
else
|
||||
{
|
||||
textureColor = Color.white;
|
||||
}
|
||||
|
||||
fillTexture = GenerateTexture(fillPath, fillSize, bakeFillSize, textureColor);
|
||||
}
|
||||
|
||||
if (graphic.HasStroke)
|
||||
{
|
||||
Vector2 strokeSize = fobject.Size;
|
||||
strokeSize += new Vector2(fobject.StrokeWeight * 2, fobject.StrokeWeight * 2);
|
||||
strokeSize.IsSupportedRenderSize(monoBeh.Settings.ImageSpritesSettings.ImageScale, out finalSize, out Vector2Int bakeStrokeSize);
|
||||
|
||||
string strokePath = fobject.StrokeGeometry[0].Path;
|
||||
|
||||
Color textureColor;
|
||||
|
||||
if (graphic.HasFill && graphic.HasStroke)
|
||||
{
|
||||
textureColor = graphic.Stroke.SolidPaint.Color;
|
||||
}
|
||||
else
|
||||
{
|
||||
textureColor = Color.white;
|
||||
}
|
||||
|
||||
strokeTexture = GenerateTexture(strokePath, strokeSize, bakeStrokeSize, textureColor);
|
||||
}
|
||||
|
||||
FcuLogger.Debug($"GenerateSprites | {fobject.Data.NameHierarchy} | hasFills: {graphic.HasFill} | hasStrokes: {graphic.HasStroke}", FcuLogType.Default);
|
||||
|
||||
if (fillTexture != null && strokeTexture != null)
|
||||
{
|
||||
finalTexture = strokeTexture.Merge(fillTexture);
|
||||
}
|
||||
else if (strokeTexture != null)
|
||||
{
|
||||
finalTexture = strokeTexture;
|
||||
}
|
||||
else if (fillTexture != null)
|
||||
{
|
||||
finalTexture = fillTexture;
|
||||
}
|
||||
|
||||
if (finalTexture == null)
|
||||
{
|
||||
throw new Exception("finalTexture is null");
|
||||
}
|
||||
|
||||
finalTexture.Blur(monoBeh.Settings.ImageSpritesSettings.ImageScale / blurCoof);
|
||||
finalTexture.Resize(finalSize, 0, filterMode, renderTextureFormat);
|
||||
}
|
||||
|
||||
byte[] textureBytes = finalTexture.EncodeToPNG();
|
||||
finalTexture.Destroy();
|
||||
|
||||
File.WriteAllBytes(fobject.Data.SpritePath, textureBytes);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FcuLogger.Debug($"Can't generate '{fobject.Data.NameHierarchy}'\n{ex}", FcuLogType.Error);
|
||||
fobject.Data.FcuImageType = FcuImageType.Drawable;
|
||||
}
|
||||
|
||||
generatedCount++;
|
||||
}, spriteGenerationDelay, 1);
|
||||
|
||||
while (true)
|
||||
{
|
||||
DALogger.Log(FcuLocKey.log_generating_sprites.Localize(generatedCount, generative.Count));
|
||||
|
||||
if (generatedCount >= generative.Count)
|
||||
break;
|
||||
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
|
||||
camera.gameObject.Destroy();
|
||||
}
|
||||
|
||||
public Texture2D GenerateTexture(string svgPath, Vector2 sourceSize, Vector2Int bakeResolution, Color color)
|
||||
{
|
||||
GameObject meshObject = MonoBehExtensions.CreateEmptyGameObject();
|
||||
meshObject.name = sourceSize.ToString();
|
||||
meshObject.transform.position = new Vector3(-20000, -20000, 0);
|
||||
|
||||
try
|
||||
{
|
||||
GenerateMesh(meshObject, sourceSize, svgPath);
|
||||
Texture2D bakedTexture = BakeTexture(meshObject, bakeResolution, color);
|
||||
return bakedTexture;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
meshObject.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateMesh(GameObject meshObject, Vector2 objectSize, string svgPath)
|
||||
{
|
||||
meshFilter = meshObject.AddComponent<MeshFilter>();
|
||||
meshRenderer = meshObject.AddComponent<MeshRenderer>();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Material spriteMaterial = UnityEditor.AssetDatabase.GetBuiltinExtraResource<Material>("Sprites-Default.mat");
|
||||
meshRenderer.material = spriteMaterial;
|
||||
#endif
|
||||
|
||||
SVGMesh svgMesh = new SVGMesh();
|
||||
svgMesh.Init(meshUpscaleFactor);
|
||||
|
||||
SVGData svgData = new SVGData();
|
||||
svgData.Path(svgPath);
|
||||
svgMesh.Fill(svgData, meshFilter);
|
||||
}
|
||||
|
||||
private Texture2D BakeTexture(GameObject meshObject, Vector2Int bakeResolution, Color color)
|
||||
{
|
||||
RenderTexture renderTexture = RenderTexture.GetTemporary(bakeResolution.x, bakeResolution.y, 8, renderTextureFormat);
|
||||
|
||||
renderTexture.antiAliasing = renderAntialiasing;
|
||||
renderTexture.filterMode = filterMode;
|
||||
|
||||
camera.targetTexture = renderTexture;
|
||||
camera.SetToObject(meshObject);
|
||||
camera.Render();
|
||||
|
||||
Texture2D texture = new Texture2D(bakeResolution.x, bakeResolution.y, textureFormat, false);
|
||||
texture.filterMode = filterMode;
|
||||
|
||||
RenderTexture.active = renderTexture;
|
||||
|
||||
texture.ReadPixels(new Rect(0, 0, bakeResolution.x, bakeResolution.y), 0, 0);
|
||||
texture.Apply();
|
||||
|
||||
texture.Colorize(color);
|
||||
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
RenderTexture.active = null;
|
||||
camera.targetTexture = null;
|
||||
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SpriteGeneratorExtensions
|
||||
{
|
||||
public static void SetToObject(this Camera camera, GameObject target)
|
||||
{
|
||||
target.transform.position = new Vector3((int)target.transform.position.x, (int)target.transform.position.y, (int)target.transform.position.z);
|
||||
|
||||
Renderer objectRenderer = target.GetComponent<Renderer>();
|
||||
Vector3 objectSize = objectRenderer.bounds.size;
|
||||
Vector3 objectPosition = objectRenderer.bounds.center;
|
||||
|
||||
camera.transform.position = new Vector3(objectPosition.x, objectPosition.y, -1);
|
||||
camera.orthographicSize = Mathf.Max(objectSize.x / (2f * camera.aspect), objectSize.y / 2f);
|
||||
}
|
||||
}
|
||||
|
||||
public class TextureBorderDrawer
|
||||
{
|
||||
public static Texture2D CreateTextureWithBorder(int width, int height, int leftWidth, int rightWidth, int topWidth, int bottomWidth, Color borderColor)
|
||||
{
|
||||
Texture2D texture = new Texture2D(width, height);
|
||||
|
||||
Color transparent = new Color(0, 0, 0, 0);
|
||||
|
||||
for (int y = 0; y < texture.height; y++)
|
||||
{
|
||||
for (int x = 0; x < texture.width; x++)
|
||||
{
|
||||
texture.SetPixel(x, y, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
if (leftWidth > 0)
|
||||
DrawLeftBorder(texture, leftWidth, borderColor);
|
||||
if (rightWidth > 0)
|
||||
DrawRightBorder(texture, rightWidth, borderColor);
|
||||
if (topWidth > 0)
|
||||
DrawTopBorder(texture, topWidth, borderColor);
|
||||
if (bottomWidth > 0)
|
||||
DrawBottomBorder(texture, bottomWidth, borderColor);
|
||||
|
||||
texture.Apply();
|
||||
return texture;
|
||||
}
|
||||
|
||||
private static void DrawLeftBorder(Texture2D texture, int borderWidth, Color borderColor)
|
||||
{
|
||||
for (int x = 0; x < borderWidth; x++)
|
||||
{
|
||||
for (int y = 0; y < texture.height; y++)
|
||||
{
|
||||
texture.SetPixel(x, y, borderColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawRightBorder(Texture2D texture, int borderWidth, Color borderColor)
|
||||
{
|
||||
for (int x = texture.width - borderWidth; x < texture.width; x++)
|
||||
{
|
||||
for (int y = 0; y < texture.height; y++)
|
||||
{
|
||||
texture.SetPixel(x, y, borderColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawTopBorder(Texture2D texture, int borderWidth, Color borderColor)
|
||||
{
|
||||
for (int y = texture.height - borderWidth; y < texture.height; y++)
|
||||
{
|
||||
for (int x = 0; x < texture.width; x++)
|
||||
{
|
||||
texture.SetPixel(x, y, borderColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawBottomBorder(Texture2D texture, int borderWidth, Color borderColor)
|
||||
{
|
||||
for (int y = 0; y < borderWidth; y++)
|
||||
{
|
||||
for (int x = 0; x < texture.width; x++)
|
||||
{
|
||||
texture.SetPixel(x, y, borderColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 724f10c01606ebc4886699e920ab4818
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,178 @@
|
||||
using DA_Assets.Extensions;
|
||||
using DA_Assets.FCU.Extensions;
|
||||
using DA_Assets.FCU.Model;
|
||||
using DA_Assets.DAI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DA_Assets.FCU
|
||||
{
|
||||
[Serializable]
|
||||
public class SpritePathSetter : MonoBehaviourLinkerRuntime<FigmaConverterUnity>
|
||||
{
|
||||
public async Task SetSpritePaths(List<FObject> fobjects)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
List<FObject> canHasFile = fobjects
|
||||
.Where(x => x.IsDownloadableType() || x.IsGenerativeType())
|
||||
.ToList();
|
||||
|
||||
List<FObject> noDuplicates = canHasFile
|
||||
.GroupBy(x => x.Data.Hash)
|
||||
.Select(x => x.First())
|
||||
.ToList();
|
||||
|
||||
await Task.Yield();
|
||||
|
||||
string filter = $"t:{typeof(Sprite).Name}";
|
||||
|
||||
string[] searchInFolder = new string[]
|
||||
{
|
||||
monoBeh.Settings.ImageSpritesSettings.SpritesPath
|
||||
};
|
||||
|
||||
string[] assetSpritePathes = UnityEditor.AssetDatabase
|
||||
.FindAssets(filter, searchInFolder)
|
||||
.Select(x => UnityEditor.AssetDatabase.GUIDToAssetPath(x))
|
||||
.ToArray();
|
||||
|
||||
await DACycles.ForEach(noDuplicates, item =>
|
||||
{
|
||||
bool imageFileExists = GetSpritePath(item, assetSpritePathes, out string spritePath);
|
||||
|
||||
SetNeedDownloadFileFlag(item, imageFileExists);
|
||||
SetNeedGenerateFlag(item, imageFileExists);
|
||||
|
||||
foreach (FObject fobject in fobjects)
|
||||
{
|
||||
if (fobject.Data.Hash == item.Data.Hash)
|
||||
{
|
||||
if (imageFileExists)
|
||||
{
|
||||
fobject.Data.SpritePath = spritePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
fobject.Data.SpritePath = GetSpritePath(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 0.01f, 500);
|
||||
#endif
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
private string GetSpritePath(FObject fobject)
|
||||
{
|
||||
string spriteDir;
|
||||
|
||||
if (fobject.Data.IsMutual)
|
||||
spriteDir = "Mutual";
|
||||
else
|
||||
spriteDir = fobject.Data.RootFrame.Names.FileName;
|
||||
|
||||
string absoluteFramePath = Path.Combine(monoBeh.Settings.ImageSpritesSettings.SpritesPath.GetFullAssetPath(), spriteDir);
|
||||
string relativeAssetPath = Path.Combine(monoBeh.Settings.ImageSpritesSettings.SpritesPath, spriteDir, fobject.Data.Names.FileName);
|
||||
absoluteFramePath.CreateFolderIfNotExists();
|
||||
|
||||
return relativeAssetPath;
|
||||
}
|
||||
|
||||
private bool IsTargetExtension(FObject fobject, string spritePath)
|
||||
{
|
||||
string spriteExt = Path.GetExtension(spritePath);
|
||||
if (spriteExt.StartsWith(".") && spriteExt.Length > 1)
|
||||
spriteExt = spriteExt.Remove(0, 1);
|
||||
|
||||
string targetExt = null;
|
||||
|
||||
if (monoBeh.UsingSvgImage())
|
||||
{
|
||||
if (fobject.CanUseUnityImage(monoBeh))
|
||||
{
|
||||
targetExt = ImageFormat.PNG.ToLower();
|
||||
}
|
||||
}
|
||||
|
||||
if (targetExt == null)
|
||||
{
|
||||
targetExt = monoBeh.Settings.ImageSpritesSettings.ImageFormat.ToLower();
|
||||
}
|
||||
|
||||
return spriteExt == targetExt;
|
||||
}
|
||||
|
||||
public bool GetSpritePath(FObject fobject, string[] spritePathes, out string path)
|
||||
{
|
||||
foreach (string spritePath in spritePathes)
|
||||
{
|
||||
bool get1 = spritePath.TryParseSpriteName(out float scale1, out System.Numerics.BigInteger hash1);
|
||||
bool get2 = fobject.Data.Names.FileName.TryParseSpriteName(out float scale2, out System.Numerics.BigInteger hash2);
|
||||
|
||||
bool hasData = get1 && get2;
|
||||
bool validExtension = IsTargetExtension(fobject, spritePath);
|
||||
bool sameHash = hash1 == hash2;
|
||||
//bool sameScale = scale1 == scale2;
|
||||
|
||||
if (hasData && validExtension && sameHash/* && sameScale*/)
|
||||
{
|
||||
path = spritePath;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
path = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetNeedDownloadFileFlag(FObject fobject, bool imageFileExists)
|
||||
{
|
||||
if (fobject.IsDownloadableType()/* || fobject.IsGenerativeType()*/)
|
||||
{
|
||||
if (monoBeh.Settings.ImageSpritesSettings.RedownloadSprites)
|
||||
{
|
||||
fobject.Data.NeedDownload = true;
|
||||
}
|
||||
else if (imageFileExists)
|
||||
{
|
||||
fobject.Data.NeedDownload = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fobject.Data.NeedDownload = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fobject.Data.NeedDownload = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetNeedGenerateFlag(FObject fobject, bool imageFileExists)
|
||||
{
|
||||
if (fobject.IsGenerativeType())
|
||||
{
|
||||
if (monoBeh.Settings.ImageSpritesSettings.RedownloadSprites)
|
||||
{
|
||||
fobject.Data.NeedGenerate = true;
|
||||
}
|
||||
else if (imageFileExists)
|
||||
{
|
||||
fobject.Data.NeedGenerate = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fobject.Data.NeedGenerate = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fobject.Data.NeedGenerate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 879ebdbc04dd0c949ae23093a9598549
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,285 @@
|
||||
using DA_Assets.DAI;
|
||||
using DA_Assets.Extensions;
|
||||
using DA_Assets.FCU.Extensions;
|
||||
using DA_Assets.FCU.Model;
|
||||
using DA_Assets.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
#if VECTOR_GRAPHICS_EXISTS && UNITY_EDITOR
|
||||
using Unity.VectorGraphics.Editor;
|
||||
#endif
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace DA_Assets.FCU
|
||||
{
|
||||
[Serializable]
|
||||
public class SpriteProcessor : MonoBehaviourLinkerRuntime<FigmaConverterUnity>
|
||||
{
|
||||
private int _errorLogSplitLimit = 50;
|
||||
ConcurrentBag<FObject> failedObjects = new ConcurrentBag<FObject>();
|
||||
|
||||
public Sprite GetSprite(FObject fobject)
|
||||
{
|
||||
if (fobject.Data.SpritePath.IsEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Sprite sprite = null;
|
||||
#if UNITY_EDITOR
|
||||
sprite = (Sprite)AssetDatabase.LoadAssetAtPath(fobject.Data.SpritePath, typeof(Sprite));
|
||||
#endif
|
||||
return sprite;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public async Task MarkAsSprites(List<FObject> fobjects)
|
||||
{
|
||||
failedObjects = new ConcurrentBag<FObject>();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
List<FObject> fobjectWithSprite = fobjects.Where(x => x.Data.SpritePath != null).ToList();
|
||||
|
||||
int allCount = fobjectWithSprite.Count();
|
||||
int count = 0;
|
||||
|
||||
foreach (FObject fobject in fobjectWithSprite)
|
||||
{
|
||||
if (monoBeh.IsCancellationRequested(TokenType.Import))
|
||||
return;
|
||||
|
||||
if (fobject.Data.SpritePath.IsEmpty())
|
||||
continue;
|
||||
|
||||
_ = SetImgTypeSprite(fobject, () =>
|
||||
{
|
||||
count++;
|
||||
});
|
||||
}
|
||||
|
||||
int tempCount = -1;
|
||||
while (FcuLogger.WriteLogBeforeEqual(
|
||||
ref count,
|
||||
ref allCount,
|
||||
FcuLocKey.log_mark_as_sprite.Localize(count, allCount),
|
||||
ref tempCount))
|
||||
{
|
||||
if (monoBeh.IsCancellationRequested(TokenType.Import))
|
||||
return;
|
||||
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
|
||||
LogFailedSprites(failedObjects);
|
||||
}
|
||||
|
||||
private void LogFailedSprites(ConcurrentBag<FObject> failedObjects)
|
||||
{
|
||||
if (failedObjects.Count() > 0)
|
||||
{
|
||||
List<List<string>> comps = failedObjects.Select(x => x.Data.NameHierarchy).Split(_errorLogSplitLimit);
|
||||
|
||||
foreach (List<string> comp in comps)
|
||||
{
|
||||
string hierarchies = string.Join("\n", comp);
|
||||
|
||||
DALogger.LogError(
|
||||
FcuLocKey.cant_load_sprites.Localize(comp.Count, hierarchies));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SetImgTypeSprite(FObject fobject, Action callback)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (monoBeh.IsCancellationRequested(TokenType.Import))
|
||||
return;
|
||||
|
||||
bool success;
|
||||
|
||||
if (fobject.IsSvgExtension())
|
||||
{
|
||||
success = SetVectorTextureSettings(fobject);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = SetRasterTextureSettings(fobject);
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
callback.Invoke();
|
||||
break;
|
||||
}
|
||||
|
||||
await Task.Delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
private bool SetVectorTextureSettings(FObject fobject)
|
||||
{
|
||||
try
|
||||
{
|
||||
#if VECTOR_GRAPHICS_EXISTS
|
||||
SVGImporter importer = AssetImporter.GetAtPath(fobject.Data.SpritePath) as SVGImporter;
|
||||
UpdateVectorTextureSettings(importer, fobject.Data.SpritePath);
|
||||
if (IsVectorTextureSettingsCorrect(importer))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateVectorTextureSettings(importer, fobject.Data.SpritePath);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FcuLogger.Debug(ex);
|
||||
failedObjects.Add(fobject);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#if VECTOR_GRAPHICS_EXISTS
|
||||
private bool IsVectorTextureSettingsCorrect(SVGImporter importer)
|
||||
{
|
||||
bool settingsCorrect = importer.SvgType == monoBeh.Settings.SVGImporterSettings.SvgType &&
|
||||
importer.SvgPixelsPerUnit == monoBeh.Settings.ImageSpritesSettings.ImageScale &&
|
||||
importer.GradientResolution == monoBeh.Settings.SVGImporterSettings.GradientResolution &&
|
||||
importer.CustomPivot == monoBeh.Settings.SVGImporterSettings.CustomPivot &&
|
||||
importer.GeneratePhysicsShape == monoBeh.Settings.SVGImporterSettings.GeneratePhysicsShape &&
|
||||
importer.ViewportOptions == monoBeh.Settings.SVGImporterSettings.ViewportOptions &&
|
||||
importer.StepDistance == monoBeh.Settings.SVGImporterSettings.StepDistance &&
|
||||
importer.SamplingStepDistance == monoBeh.Settings.SVGImporterSettings.SamplingSteps &&
|
||||
importer.AdvancedMode == monoBeh.Settings.SVGImporterSettings.AdvancedMode &&
|
||||
importer.MaxCordDeviationEnabled == monoBeh.Settings.SVGImporterSettings.MaxCordDeviationEnabled &&
|
||||
importer.MaxTangentAngleEnabled == monoBeh.Settings.SVGImporterSettings.MaxTangentAngleEnabled;
|
||||
|
||||
return settingsCorrect;
|
||||
}
|
||||
|
||||
private void UpdateVectorTextureSettings(SVGImporter importer, string spritePath)
|
||||
{
|
||||
var svgImporterSettings = monoBeh.Settings.SvgImageSettings;
|
||||
|
||||
importer.SvgType = monoBeh.Settings.SVGImporterSettings.SvgType;
|
||||
importer.SvgPixelsPerUnit = monoBeh.Settings.ImageSpritesSettings.ImageScale;
|
||||
importer.GradientResolution = monoBeh.Settings.SVGImporterSettings.GradientResolution <= ushort.MaxValue ? (ushort)monoBeh.Settings.SVGImporterSettings.GradientResolution : ushort.MaxValue;
|
||||
importer.CustomPivot = monoBeh.Settings.SVGImporterSettings.CustomPivot;
|
||||
importer.GeneratePhysicsShape = monoBeh.Settings.SVGImporterSettings.GeneratePhysicsShape;
|
||||
importer.ViewportOptions = monoBeh.Settings.SVGImporterSettings.ViewportOptions;
|
||||
importer.StepDistance = monoBeh.Settings.SVGImporterSettings.StepDistance;
|
||||
importer.SamplingStepDistance = monoBeh.Settings.SVGImporterSettings.SamplingSteps;
|
||||
importer.AdvancedMode = monoBeh.Settings.SVGImporterSettings.AdvancedMode;
|
||||
|
||||
importer.MaxCordDeviationEnabled = monoBeh.Settings.SVGImporterSettings.MaxCordDeviationEnabled;
|
||||
importer.MaxCordDeviation = monoBeh.Settings.SVGImporterSettings.MaxCordDeviation;
|
||||
|
||||
importer.MaxTangentAngleEnabled = monoBeh.Settings.SVGImporterSettings.MaxTangentAngleEnabled;
|
||||
importer.MaxTangentAngle = monoBeh.Settings.SVGImporterSettings.MaxTangentAngle;
|
||||
|
||||
SaveAsset(importer);
|
||||
}
|
||||
#endif
|
||||
private void SaveAsset(AssetImporter importer)
|
||||
{
|
||||
importer.SetDirtyExt();
|
||||
importer.SaveAndReimport();
|
||||
}
|
||||
|
||||
private bool SetRasterTextureSettings(FObject fobject)
|
||||
{
|
||||
try
|
||||
{
|
||||
TextureImporter importer = AssetImporter.GetAtPath(fobject.Data.SpritePath) as TextureImporter;
|
||||
|
||||
SetRasterTextureSize(fobject, importer);
|
||||
|
||||
if (IsRasterTextureSettingsCorrect(importer))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateRasterTextureSettings(importer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FcuLogger.Debug(ex);
|
||||
failedObjects.Add(fobject);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetRasterTextureSize(FObject fobject, TextureImporter importer)
|
||||
{
|
||||
importer.GetTextureSize(out int width, out int height);
|
||||
importer.SetMaxTextureSize(width, height);
|
||||
fobject.Data.SpriteSize = new Vector2Int(width, height);
|
||||
}
|
||||
|
||||
private bool IsRasterTextureSettingsCorrect(TextureImporter importer)
|
||||
{
|
||||
bool part1 = importer.isReadable == monoBeh.Settings.TextureImporterSettings.IsReadable &&
|
||||
importer.textureType == monoBeh.Settings.TextureImporterSettings.TextureType &&
|
||||
importer.crunchedCompression == monoBeh.Settings.TextureImporterSettings.CrunchedCompression &&
|
||||
importer.textureCompression == monoBeh.Settings.TextureImporterSettings.TextureCompression &&
|
||||
importer.mipmapEnabled == monoBeh.Settings.TextureImporterSettings.MipmapEnabled &&
|
||||
importer.spriteImportMode == monoBeh.Settings.TextureImporterSettings.SpriteImportMode;
|
||||
|
||||
bool perUnit;
|
||||
|
||||
if (monoBeh.UsingSpriteRenderer())
|
||||
{
|
||||
perUnit = importer.spritePixelsPerUnit == monoBeh.Settings.ImageSpritesSettings.ImageScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
perUnit = importer.spritePixelsPerUnit == monoBeh.Settings.ImageSpritesSettings.PixelsPerUnit;
|
||||
}
|
||||
|
||||
return part1 && perUnit;
|
||||
}
|
||||
|
||||
private void UpdateRasterTextureSettings(TextureImporter importer)
|
||||
{
|
||||
importer.isReadable = monoBeh.Settings.TextureImporterSettings.IsReadable;
|
||||
importer.textureType = monoBeh.Settings.TextureImporterSettings.TextureType;
|
||||
importer.crunchedCompression = monoBeh.Settings.TextureImporterSettings.CrunchedCompression;
|
||||
importer.textureCompression = monoBeh.Settings.TextureImporterSettings.TextureCompression;
|
||||
importer.mipmapEnabled = monoBeh.Settings.TextureImporterSettings.MipmapEnabled;
|
||||
importer.spriteImportMode = monoBeh.Settings.TextureImporterSettings.SpriteImportMode;
|
||||
|
||||
if (monoBeh.UsingSpriteRenderer())
|
||||
{
|
||||
importer.spritePixelsPerUnit = monoBeh.Settings.ImageSpritesSettings.ImageScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
importer.spritePixelsPerUnit = monoBeh.Settings.ImageSpritesSettings.PixelsPerUnit;
|
||||
}
|
||||
|
||||
if (importer.crunchedCompression)
|
||||
{
|
||||
importer.compressionQuality = monoBeh.Settings.TextureImporterSettings.CompressionQuality;
|
||||
}
|
||||
|
||||
SaveAsset(importer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed8e2a5f3d4c49247902b6a0ed46cf4b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
using DA_Assets.DAI;
|
||||
using DA_Assets.Extensions;
|
||||
using DA_Assets.FCU.Extensions;
|
||||
using DA_Assets.FCU.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DA_Assets.FCU
|
||||
{
|
||||
[Serializable]
|
||||
public class SpriteSlicer : MonoBehaviourLinkerRuntime<FigmaConverterUnity>
|
||||
{
|
||||
public async Task SliceSprites(List<FObject> fobjects)
|
||||
{
|
||||
foreach (FObject fobject in fobjects)
|
||||
{
|
||||
if (monoBeh.IsCancellationRequested(TokenType.Import))
|
||||
return;
|
||||
|
||||
if (!fobject.IsSprite())
|
||||
continue;
|
||||
|
||||
if (fobject.Children.IsEmpty())
|
||||
continue;
|
||||
|
||||
if (fobject.Children.Count != 9)
|
||||
continue;
|
||||
|
||||
Sprite sprite = monoBeh.SpriteProcessor.GetSprite(fobject);
|
||||
|
||||
if (sprite == null)
|
||||
continue;
|
||||
|
||||
FObject child0 = fobject.Children[0];
|
||||
FObject child1 = fobject.Children[1];
|
||||
FObject child2 = fobject.Children[2];
|
||||
FObject child3 = fobject.Children[3];
|
||||
FObject child4 = fobject.Children[4];
|
||||
FObject child5 = fobject.Children[5];
|
||||
FObject child6 = fobject.Children[6];
|
||||
FObject child7 = fobject.Children[7];
|
||||
FObject child8 = fobject.Children[8];
|
||||
|
||||
float imageScale = monoBeh.Settings.ImageSpritesSettings.ImageScale;
|
||||
|
||||
int left = (int)(child0.Size.x * imageScale);
|
||||
int top = (int)(child0.Size.y * imageScale);
|
||||
int right = (int)(child2.Size.x * imageScale);
|
||||
int bottom = (int)(child6.Size.y * imageScale);
|
||||
|
||||
monoBeh.DelegateHolder.SetSpriteRects(sprite, left, top, right, bottom);
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a8421a366c33a94fb1e185550eaa21a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user