diff --git a/Assets/SpriteDicing/Editor/Editors/AtlasBuilder.cs b/Assets/SpriteDicing/Editor/Editors/AtlasBuilder.cs index d83ad68..d37ffb0 100644 --- a/Assets/SpriteDicing/Editor/Editors/AtlasBuilder.cs +++ b/Assets/SpriteDicing/Editor/Editors/AtlasBuilder.cs @@ -68,11 +68,13 @@ private List DiceTextures (IReadOnlyList sourceText private List PackTextures (IReadOnlyList dicedTextures) { DisplayProgressBar("Packing dices...", .5f); + var settings = new TextureSettings(); + settings.TryImportExisting(TexturesProperty.GetArrayElementAtIndex(0).objectReferenceValue as Texture); DeleteAtlasTextures(); var basePath = atlasPath.Substring(0, atlasPath.LastIndexOf(".", StringComparison.Ordinal)); - var textureSerializer = new TextureSerializer(basePath); - var texturePacker = new TexturePacker(textureSerializer, UVInset, ForceSquare, AtlasSizeLimit, UnitSize, Padding); - var atlasTextures = texturePacker.Pack(dicedTextures); + var serializer = new TextureSerializer(basePath, settings); + var packer = new TexturePacker(serializer, UVInset, ForceSquare, AtlasSizeLimit, UnitSize, Padding); + var atlasTextures = packer.Pack(dicedTextures); SaveAtlasTextures(); return atlasTextures; diff --git a/Assets/SpriteDicing/Editor/Processors/TextureSerializer.cs b/Assets/SpriteDicing/Editor/Processors/TextureSerializer.cs index f23c133..f701ac1 100644 --- a/Assets/SpriteDicing/Editor/Processors/TextureSerializer.cs +++ b/Assets/SpriteDicing/Editor/Processors/TextureSerializer.cs @@ -10,10 +10,12 @@ namespace SpriteDicing public class TextureSerializer : ITextureSerializer { private readonly string basePath; + private readonly TextureSettings settings; - public TextureSerializer (string basePath) + public TextureSerializer (string basePath, TextureSettings settings) { this.basePath = basePath; + this.settings = settings; } public Texture2D Serialize (Texture2D texture) @@ -21,8 +23,8 @@ public Texture2D Serialize (Texture2D texture) var filePath = BuildFilePath(); SaveAsPNG(texture, filePath); var png = AssetDatabase.LoadAssetAtPath(filePath); - var maxSize = Mathf.Max(texture.width, texture.height); - ApplyImportSettings(filePath, Mathf.NextPowerOfTwo(maxSize)); + var maxSize = Mathf.NextPowerOfTwo(Mathf.Max(texture.width, texture.height)); + ApplyImportSettings(filePath, maxSize); Object.DestroyImmediate(texture); return png; } @@ -35,7 +37,7 @@ private string BuildFilePath () return path; } - private static void SaveAsPNG (Texture2D texture, string filePath) + private void SaveAsPNG (Texture2D texture, string filePath) { var bytes = texture.EncodeToPNG(); using (var fileStream = File.Create(filePath)) @@ -44,13 +46,10 @@ private static void SaveAsPNG (Texture2D texture, string filePath) AssetDatabase.Refresh(); } - private static void ApplyImportSettings (string filePath, int maxSize) + private void ApplyImportSettings (string filePath, int maxSize) { var importer = (TextureImporter)AssetImporter.GetAtPath(filePath); - importer.textureType = TextureImporterType.Default; - importer.alphaIsTransparency = true; - importer.mipmapEnabled = false; - importer.textureCompression = TextureImporterCompression.Uncompressed; + settings.ApplyExistingOrDefault(importer); importer.maxTextureSize = maxSize; AssetDatabase.ImportAsset(filePath); } diff --git a/Assets/SpriteDicing/Editor/Processors/TextureSettings.cs b/Assets/SpriteDicing/Editor/Processors/TextureSettings.cs new file mode 100644 index 0000000..0e47798 --- /dev/null +++ b/Assets/SpriteDicing/Editor/Processors/TextureSettings.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace SpriteDicing +{ + public class TextureSettings + { + private const string defaultPlatformId = "default"; + private static readonly string[] platformIds = GetPlatformIds(); + private readonly TextureImporterSettings @base = new TextureImporterSettings(); + private readonly Dictionary platforms = + new Dictionary(); + + public void TryImportExisting (Texture texture) + { + if (!TryGetTextureImporter(texture, out var importer)) return; + importer.ReadTextureSettings(@base); + foreach (var platformId in platformIds) + platforms[platformId] = importer.GetPlatformTextureSettings(platformId); + platforms[defaultPlatformId] = importer.GetDefaultPlatformTextureSettings(); + } + + public void ApplyExistingOrDefault (TextureImporter importer) + { + if (platforms.Count == 0) ApplyDefault(importer); + else ApplyExisting(importer); + } + + private bool TryGetTextureImporter (Texture texture, out TextureImporter importer) + { + var assetPath = AssetDatabase.GetAssetPath(texture); + importer = AssetImporter.GetAtPath(assetPath) as TextureImporter; + return importer != null; + } + + private void ApplyDefault (TextureImporter importer) + { + importer.textureType = TextureImporterType.Default; + importer.alphaIsTransparency = true; + importer.mipmapEnabled = false; + importer.textureCompression = TextureImporterCompression.Uncompressed; + } + + private void ApplyExisting (TextureImporter importer) + { + importer.SetTextureSettings(@base); + foreach (var kv in platforms) + if (kv.Key == defaultPlatformId || kv.Value.overridden) + importer.SetPlatformTextureSettings(kv.Value); + } + + [SuppressMessage("ReSharper", "PossibleNullReferenceException")] + private static string[] GetPlatformIds () + { + // https://github.com/Unity-Technologies/UnityCsReference/blob/2019.4/Editor/Mono/BuildPipeline/BuildPlatform.cs + + Type platformsType = default, platformType = default; + foreach (var type in Assembly.GetAssembly(typeof(Editor)).GetTypes()) + if (type.Name == "BuildPlatforms") platformsType = type; + else if (type.Name == "BuildPlatform") platformType = type; + else if (platformsType != null && platformType != null) break; + var platformsInstance = platformsType.GetProperty("instance").GetValue(null); + var validPlatforms = (IEnumerable)platformsType + .GetMethod("GetValidPlatforms", Array.Empty()) + .Invoke(platformsInstance, null); + return validPlatforms.Select(p => (string)platformType.GetField("name").GetValue(p)).ToArray(); + } + } +} diff --git a/Assets/SpriteDicing/Editor/Processors/TextureSettings.cs.meta b/Assets/SpriteDicing/Editor/Processors/TextureSettings.cs.meta new file mode 100644 index 0000000..b29ee6a --- /dev/null +++ b/Assets/SpriteDicing/Editor/Processors/TextureSettings.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d59c566b8064422993c144dfb3c631be +timeCreated: 1649454642 \ No newline at end of file diff --git a/Assets/SpriteDicing/package.json b/Assets/SpriteDicing/package.json index bc01567..79c0cab 100644 --- a/Assets/SpriteDicing/package.json +++ b/Assets/SpriteDicing/package.json @@ -1,11 +1,11 @@ { "name": "com.elringus.spritedicing", - "version": "1.6.1", + "version": "1.7.0", "displayName": "SpriteDicing", - "description": "Unity extension for reusing sprite texture areas.", + "description": "Allows dicing sprite textures into atlases to eliminate identical parts.", "unity": "2019.4", "author": { "name": "Elringus", - "url": "https://elringus.me" + "url": "https://github.com/Elringus" } } diff --git a/Assets/Tests/Editor/TextureSerializerTest.cs b/Assets/Tests/Editor/TextureSerializerTest.cs index 0979242..2131927 100644 --- a/Assets/Tests/Editor/TextureSerializerTest.cs +++ b/Assets/Tests/Editor/TextureSerializerTest.cs @@ -13,6 +13,7 @@ public class TextureSerializerTest private const string tempRoot = Helpers.TextureFolderPath + "/" + tempFolder; private string basePath; + private TextureSettings textureSettings; private TextureSerializer serializer; [SetUp] @@ -20,7 +21,8 @@ public void SetUp () { AssetDatabase.CreateFolder(Helpers.TextureFolderPath, tempFolder); basePath = $"{tempRoot}/{Guid.NewGuid():N}"; - serializer = new TextureSerializer(basePath); + textureSettings = new TextureSettings(); + serializer = new TextureSerializer(basePath, textureSettings); } [TearDown] @@ -46,7 +48,7 @@ public void SerializedEqualsOriginalTexture () } [Test] - public void ImportSettingsAreApplied () + public void DefaultImportSettingsAreApplied () { var importer = GetImporter(Serialize()); AreEqual(TextureImporterType.Default, importer.textureType); @@ -56,6 +58,69 @@ public void ImportSettingsAreApplied () AreEqual(1, importer.maxTextureSize); } + [Test] + public void ExistingImportSettingsArePreserved () + { + var otherTexture = Serialize(); + var otherImporter = GetImporter(otherTexture); + otherImporter.alphaIsTransparency = false; + otherImporter.textureCompression = TextureImporterCompression.Compressed; + otherImporter.SaveAndReimport(); + + textureSettings.TryImportExisting(otherTexture); + var importer = GetImporter(Serialize()); + IsFalse(importer.alphaIsTransparency); + AreEqual(TextureImporterCompression.Compressed, importer.textureCompression); + } + + [Test] + public void ExistingPlatformSpecificSettingsArePreserved () + { + var otherPlatform = "Standalone"; + var otherTexture = Serialize(); + var otherImporter = GetImporter(otherTexture); + var otherSettings = new TextureImporterPlatformSettings { + name = otherPlatform, + overridden = true, + textureCompression = TextureImporterCompression.Compressed + }; + otherImporter.SetPlatformTextureSettings(otherSettings); + otherImporter.SaveAndReimport(); + + textureSettings.TryImportExisting(otherTexture); + var importer = GetImporter(Serialize()); + var settings = importer.GetPlatformTextureSettings(otherPlatform); + AreEqual(TextureImporterCompression.Compressed, settings.textureCompression); + } + + [Test] + public void NonOverriddenPlatformSpecificSettingsAreIgnored () + { + var otherPlatform = "Standalone"; + var otherTexture = Serialize(); + var otherImporter = GetImporter(otherTexture); + var otherSettings = new TextureImporterPlatformSettings { + name = otherPlatform, + overridden = false, + textureCompression = TextureImporterCompression.Compressed + }; + otherImporter.SetPlatformTextureSettings(otherSettings); + otherImporter.SaveAndReimport(); + + textureSettings.TryImportExisting(otherTexture); + var importer = GetImporter(Serialize()); + var settings = importer.GetPlatformTextureSettings(otherPlatform); + AreEqual(TextureImporterCompression.Uncompressed, settings.textureCompression); + } + + [Test] + public void SettingsFromInvalidObjectAreIgnored () + { + var obj = new UnityEngine.Object(); + textureSettings.TryImportExisting(obj as Texture); + DoesNotThrow(() => Serialize()); + } + [Test] public void MultipleTexturesNamedCorrectly () { diff --git a/Packages/manifest.json b/Packages/manifest.json index f24c4d8..7940abb 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -1,10 +1,10 @@ { "dependencies": { - "com.unity.modules.imgui": "1.0.0", - "com.unity.ugui": "1.0.0", "com.unity.2d.sprite": "1.0.0", - "com.unity.test-framework": "1.1.30", + "com.unity.ide.rider": "3.0.13", + "com.unity.test-framework": "1.1.31", "com.unity.testtools.codecoverage": "1.1.1", - "com.unity.ide.rider": "3.0.12" + "com.unity.ugui": "1.0.0", + "com.unity.modules.imgui": "1.0.0" } } diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 6aab311..7541a41 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -14,7 +14,7 @@ "url": "https://packages.unity.com" }, "com.unity.ide.rider": { - "version": "3.0.12", + "version": "3.0.13", "depth": 0, "source": "registry", "dependencies": { @@ -30,7 +30,7 @@ "url": "https://packages.unity.com" }, "com.unity.test-framework": { - "version": "1.1.30", + "version": "1.1.31", "depth": 0, "source": "registry", "dependencies": { diff --git a/SpriteDicing.unitypackage b/SpriteDicing.unitypackage index 2136626..f298fa2 100644 Binary files a/SpriteDicing.unitypackage and b/SpriteDicing.unitypackage differ