├── .gitignore ├── Assets ├── Plugins.meta ├── Plugins │ ├── USplitAlpha.meta │ └── USplitAlpha │ │ ├── Editor.meta │ │ ├── Editor │ │ ├── SplitAlphaMaterialCreator.cs │ │ ├── SplitAlphaMaterialCreator.cs.meta │ │ ├── SplitAlphaReplacer.cs │ │ ├── SplitAlphaReplacer.cs.meta │ │ ├── SplitAlphaTextureCreator.cs │ │ └── SplitAlphaTextureCreator.cs.meta │ │ ├── Resources.meta │ │ └── Resources │ │ ├── Shaders.meta │ │ └── Shaders │ │ ├── Mobile-Particle-Additive_SplitAlpha.shader │ │ ├── Mobile-Particle-Additive_SplitAlpha.shader.meta │ │ ├── Mobile-Particle-Alpha_SplitAlpha.shader │ │ ├── Mobile-Particle-Alpha_SplitAlpha.shader.meta │ │ ├── Mobile-Particle-Multiply_SplitAlpha.shader │ │ ├── Mobile-Particle-Multiply_SplitAlpha.shader.meta │ │ ├── Sprite-Default_SplitAlpha.shader │ │ ├── Sprite-Default_SplitAlpha.shader.meta │ │ ├── UI-Default_SplitAlpha.shader │ │ └── UI-Default_SplitAlpha.shader.meta ├── SimpleSpritePacker.meta ├── SimpleSpritePacker │ ├── Plugins.meta │ └── Plugins │ │ ├── SimpleSpritePacker.meta │ │ └── SimpleSpritePacker │ │ ├── Changelog.txt │ │ ├── Changelog.txt.meta │ │ ├── Editor.meta │ │ ├── Editor │ │ ├── SPAtlasBuilder.cs │ │ ├── SPAtlasBuilder.cs.meta │ │ ├── SPDropWindow.cs │ │ ├── SPDropWindow.cs.meta │ │ ├── SPInstanceEditor.cs │ │ ├── SPInstanceEditor.cs.meta │ │ ├── SPReferenceReplacerWindow.cs │ │ ├── SPReferenceReplacerWindow.cs.meta │ │ ├── SPSettings.cs │ │ ├── SPSettings.cs.meta │ │ ├── SPSpriteImportData.cs │ │ ├── SPSpriteImportData.cs.meta │ │ ├── SPTools.cs │ │ └── SPTools.cs.meta │ │ ├── Scripts.meta │ │ ├── Scripts │ │ ├── SPAction.cs │ │ ├── SPAction.cs.meta │ │ ├── SPActionType.cs │ │ ├── SPActionType.cs.meta │ │ ├── SPInstance.cs │ │ ├── SPInstance.cs.meta │ │ ├── SPSpriteInfo.cs │ │ ├── SPSpriteInfo.cs.meta │ │ ├── UITexturePacker.cs │ │ └── UITexturePacker.cs.meta │ │ ├── readme.txt │ │ └── readme.txt.meta ├── Tests.meta ├── Tests │ ├── ItemAtlas.asset │ ├── ItemAtlas.asset.meta │ ├── ItemAtlas.png │ ├── ItemAtlas.png.meta │ ├── ItemAtlasUI.mat │ ├── ItemAtlasUI.mat.meta │ ├── ItemAtlas_SpriteDefault.mat │ ├── ItemAtlas_SpriteDefault.mat.meta │ ├── ItemAtlas_UIDefault.mat │ ├── ItemAtlas_UIDefault.mat.meta │ ├── PackableSprites.meta │ ├── PackableSprites │ │ ├── T_Bracer.png │ │ ├── T_Bracer.png.meta │ │ ├── T_Runestone_Blue.png │ │ ├── T_Runestone_Blue.png.meta │ │ ├── T_Scroll.png │ │ ├── T_Scroll.png.meta │ │ ├── T_Sword.png │ │ └── T_Sword.png.meta │ ├── Test A with alpha.mat │ ├── Test A with alpha.mat.meta │ ├── Test A with alpha.png │ ├── Test A with alpha.png.meta │ ├── Test B with alpha UI.mat │ ├── Test B with alpha UI.mat.meta │ ├── Test B with alpha.png │ ├── Test B with alpha.png.meta │ ├── Test.unity │ ├── Test.unity.meta │ ├── _alpha.meta │ └── _alpha │ │ ├── ItemAtlas.png │ │ ├── ItemAtlas.png.meta │ │ ├── Test A with alpha.png │ │ ├── Test A with alpha.png.meta │ │ ├── Test B with alpha.png │ │ └── Test B with alpha.png.meta ├── UBootstrap.SpriteCollection.meta ├── UBootstrap.SpriteCollection │ ├── Plugins.meta │ └── Plugins │ │ ├── Editor.meta │ │ ├── Editor │ │ ├── SpriteCollectionEditor.cs │ │ └── SpriteCollectionEditor.cs.meta │ │ ├── Scripts.meta │ │ └── Scripts │ │ ├── SpriteCollection.cs │ │ ├── SpriteCollection.cs.meta │ │ ├── SpriteCollectionManager.cs │ │ └── SpriteCollectionManager.cs.meta ├── USingleton.meta └── USingleton │ ├── Plugins.meta │ └── Plugins │ ├── USingleton.meta │ └── USingleton │ ├── GameSingleton.cs │ ├── GameSingleton.cs.meta │ ├── SceneSingleton.cs │ └── SceneSingleton.cs.meta ├── LICENSE ├── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset └── UnityConnectSettings.asset ├── imgs ├── example1.png ├── example2.png └── example3.png ├── index.js ├── p.json ├── package.json ├── readme.md └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | 8 | # Autogenerated VS/MD solution and project files 9 | ExportedObj/ 10 | *.csproj 11 | *.unityproj 12 | *.sln 13 | *.suo 14 | *.tmp 15 | *.user 16 | *.userprefs 17 | *.pidb 18 | *.booproj 19 | *.svd 20 | 21 | 22 | # Unity3D generated meta files 23 | *.pidb.meta 24 | 25 | # Unity3D Generated File On Crash Reports 26 | sysinfo.txt 27 | 28 | # Builds 29 | *.apk 30 | *.unitypackage 31 | 32 | node_modules 33 | UnityPackageManager 34 | -------------------------------------------------------------------------------- /Assets/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 10568fededd874cf2810429467f11c00 3 | folderAsset: yes 4 | timeCreated: 1508832245 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 06190da7cc24b4b1192372aeea70f855 3 | folderAsset: yes 4 | timeCreated: 1508832287 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 50817f26cac9b4933bc37e3e4651be68 3 | folderAsset: yes 4 | timeCreated: 1508755159 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Editor/SplitAlphaMaterialCreator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | using System.IO; 6 | 7 | namespace USplitAlpha 8 | { 9 | public class SplitAlphaMaterialCreator 10 | { 11 | private static readonly string PNGSuffix = ".png"; 12 | private static readonly string MatSuffix = ".mat"; 13 | private static readonly string StarPng = "*.png"; 14 | private static readonly string StarMat = "*.mat"; 15 | 16 | [MenuItem ("Assets/USplitAlpha/Create Base Particle Materials", false, 100)] 17 | public static void CreateBaseParticleSplitAlphaMaterial () 18 | { 19 | Dictionary splitAlphaShaderNames = new Dictionary (); 20 | splitAlphaShaderNames.Add ("_Ad", "SplitAlpha/Mobile/Particles/Additive"); 21 | splitAlphaShaderNames.Add ("_Al", "SplitAlpha/Mobile/Particles/Alpha Blended"); 22 | splitAlphaShaderNames.Add ("_Mu", "SplitAlpha/Mobile/Particles/Multiply"); 23 | 24 | CreateSplitAlphaMaterial (splitAlphaShaderNames); 25 | } 26 | 27 | [MenuItem ("Assets/USplitAlpha/Create Base Particle Materials", true)] 28 | private static bool ValidateCreateBaseParticleSplitAlphaMaterial () 29 | { 30 | return Selection.activeObject is Texture2D; 31 | } 32 | 33 | [MenuItem ("Assets/USplitAlpha/Create UIDefault Material", false, 101)] 34 | private static void CreateUIDefaultSplitAlphaMaterial () 35 | { 36 | Dictionary splitAlphaShaderNames = new Dictionary (); 37 | splitAlphaShaderNames.Add ("_UIDefault", "SplitAlpha/UI/Default"); 38 | 39 | CreateSplitAlphaMaterial (splitAlphaShaderNames); 40 | } 41 | 42 | [MenuItem ("Assets/USplitAlpha/Create UIDefault Material", true)] 43 | private static bool ValidateCreateUIDefaultSplitAlphaMaterial () 44 | { 45 | return Selection.activeObject is Texture2D; 46 | } 47 | 48 | [MenuItem ("Assets/USplitAlpha/Create Sprite Default Material", false, 102)] 49 | private static void CreateSpriteDefaultSplitAlphaMaterial () 50 | { 51 | Dictionary splitAlphaShaderNames = new Dictionary (); 52 | splitAlphaShaderNames.Add ("_SpriteDefault", "SplitAlpha/Sprites/Default"); 53 | 54 | CreateSplitAlphaMaterial (splitAlphaShaderNames); 55 | } 56 | 57 | [MenuItem ("Assets/USplitAlpha/Create Sprite Default Material", true)] 58 | private static bool ValidateCreateSpriteDefaultSplitAlphaMaterial () 59 | { 60 | return Selection.activeObject is Texture2D; 61 | } 62 | 63 | public static void CreateSplitAlphaMaterial (Dictionary splitAlphaShaderNames) 64 | { 65 | HashSet selectedObjectPaths = new HashSet (); 66 | 67 | foreach (var assetGUID in Selection.assetGUIDs) { 68 | var assetPath = AssetDatabase.GUIDToAssetPath (assetGUID); 69 | if (AssetDatabase.IsValidFolder (assetPath)) { 70 | selectedObjectPaths.UnionWith (Directory.GetFiles (assetPath, StarPng, SearchOption.AllDirectories)); 71 | } else if (assetPath.EndsWith (PNGSuffix)) { 72 | selectedObjectPaths.Add (assetPath); 73 | } 74 | } 75 | 76 | foreach (var path in selectedObjectPaths) { 77 | string materialPath = System.IO.Path.GetDirectoryName (path); 78 | string materialName = System.IO.Path.GetFileNameWithoutExtension (path); 79 | Texture2D mainTexture = AssetDatabase.LoadAssetAtPath (path); 80 | var alphaTexturePath = SplitAlphaTextureCreator.GetAlphaTextureAssetPath (path); 81 | Texture2D alphaTexture = AssetDatabase.LoadAssetAtPath (alphaTexturePath); 82 | 83 | foreach (string shaderName in splitAlphaShaderNames.Keys) { 84 | CreateSplitAlphaMaterial (splitAlphaShaderNames [shaderName], materialPath + "/" + materialName + shaderName + ".mat", mainTexture, alphaTexture); 85 | } 86 | } 87 | } 88 | 89 | private static void CreateSplitAlphaMaterial (string shaderName, string path, Texture2D mainTexture, Texture2D alphaTexture) 90 | { 91 | AssetDatabase.DeleteAsset (path); 92 | Material adMaterial = new Material (Shader.Find (shaderName)); 93 | adMaterial.SetTexture ("_MainTex", mainTexture); 94 | adMaterial.SetTexture ("_AlphaTex", alphaTexture); 95 | AssetDatabase.CreateAsset (adMaterial, path); 96 | } 97 | 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Editor/SplitAlphaMaterialCreator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c313e9e12661b4836b71c43d002efe0f 3 | timeCreated: 1508994000 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Editor/SplitAlphaReplacer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | namespace USplitAlpha 7 | { 8 | public class SplitAlphaReplacer 9 | { 10 | public static void Apply (Material m) 11 | { 12 | var texture = m.GetTexture ("_MainTex"); 13 | if (texture == null || !(texture is Texture2D)) { 14 | Debug.LogErrorFormat ("{0}::{1} Make sure material have main texture!", "SplitAlphaReplacer", "Apply"); 15 | return; 16 | } 17 | 18 | var alphaTexturePath = SplitAlphaTextureCreator.GetAlphaTextureAssetPath (AssetDatabase.GetAssetPath (texture)); 19 | Texture2D alphaTexture = AssetDatabase.LoadAssetAtPath (alphaTexturePath); 20 | if (alphaTexture == null) { 21 | Debug.LogErrorFormat ("{0}::{1} Cannot Find Alpha texture at {2}!", "SplitAlphaReplacer", "Apply", alphaTexturePath); 22 | return; 23 | } 24 | m.SetTexture ("_AlphaTex", alphaTexture); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Editor/SplitAlphaReplacer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad3460fe526ad4ae69d80cffa094d69c 3 | timeCreated: 1508994000 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Editor/SplitAlphaTextureCreator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | using System.IO; 6 | using System.Linq; 7 | 8 | namespace USplitAlpha 9 | { 10 | public class SplitAlphaTextureCreator : AssetPostprocessor 11 | { 12 | public static readonly string AlphaFolderSuffix = "_alpha"; 13 | public static readonly TextureCompressionQuality CompressionQuality = TextureCompressionQuality.Normal; 14 | 15 | 16 | private static readonly string PNGSuffix = ".png"; 17 | private static readonly string MatSuffix = ".mat"; 18 | private static readonly string StarPng = "*.png"; 19 | private static readonly string StarMat = "*.mat"; 20 | private static readonly string AssetsDir = "Assets"; 21 | private static readonly string Android = "Android"; 22 | private static readonly string iPhone = "iPhone"; 23 | 24 | private static bool _isRevert = false; 25 | private static string _currentTexturePath; 26 | 27 | [MenuItem ("Assets/USplitAlpha/Apply", false, 1)] 28 | private static void MenuItem_ApplySplitAlphaToSelectedTexture () 29 | { 30 | _ApplySplitAlphaToSelectedTexture (false); 31 | } 32 | 33 | [MenuItem ("Assets/USplitAlpha/Revert", false, 2)] 34 | private static void MenuItem_RevertSplitAlphaToSelectedTexture () 35 | { 36 | _ApplySplitAlphaToSelectedTexture (true); 37 | } 38 | 39 | private static void _ApplySplitAlphaToSelectedTexture (bool isRevert) 40 | { 41 | 42 | HashSet selectedObjectPaths = new HashSet (); 43 | 44 | foreach (var assetGUID in Selection.assetGUIDs) { 45 | var assetPath = AssetDatabase.GUIDToAssetPath (assetGUID); 46 | if (AssetDatabase.IsValidFolder (assetPath)) { 47 | selectedObjectPaths.UnionWith (Directory.GetFiles (assetPath, StarPng, SearchOption.AllDirectories)); 48 | selectedObjectPaths.UnionWith (Directory.GetFiles (assetPath, StarMat, SearchOption.AllDirectories)); 49 | } else if (assetPath.EndsWith (PNGSuffix) || assetPath.EndsWith (MatSuffix)) { 50 | selectedObjectPaths.Add (assetPath); 51 | } 52 | } 53 | 54 | var filteredObjectPaths = selectedObjectPaths.Where (x => !_IsAlphaTexture (x)).ToList (); 55 | 56 | var total = selectedObjectPaths.Count; 57 | var index = 0; 58 | foreach (var path in selectedObjectPaths) { 59 | index++; 60 | var progressText = string.Format ("[{0}/{1}] : {2}", index, total, path); 61 | if (EditorUtility.DisplayCancelableProgressBar ( 62 | "Applying Alpha", progressText, (float)index / total)) { 63 | break; 64 | } 65 | if (path.EndsWith (PNGSuffix)) { 66 | ApplySplitAlphaToTexture (path, isRevert); 67 | } else { 68 | ApplySplitAlphaToMaterial (path, isRevert); 69 | } 70 | 71 | } 72 | 73 | Resources.UnloadUnusedAssets (); 74 | AssetDatabase.Refresh (); 75 | UnityEditor.EditorUtility.ClearProgressBar (); 76 | } 77 | 78 | public static bool ApplySplitAlphaToMaterial (string path, bool isRevert = false) 79 | { 80 | if (string.IsNullOrEmpty (path)) { 81 | Debug.LogError (string.Format ("ApplySplitAlphaToMaterial: path is null or empty of [{0}]", path)); 82 | return false; 83 | } 84 | 85 | Material m = AssetDatabase.LoadAssetAtPath (path); 86 | 87 | if (m == null) { 88 | Debug.LogError (string.Format ("ApplySplitAlphaToMaterial: Material is null or empty of [{0}]", path)); 89 | return false; 90 | } 91 | 92 | SplitAlphaReplacer.Apply (m); 93 | 94 | return true; 95 | } 96 | 97 | public static bool ApplySplitAlphaToTexture (string path, bool isRevert = false) 98 | { 99 | if (string.IsNullOrEmpty (path)) { 100 | Debug.LogError (string.Format ("ApplySplitAlphaToTexture: path is null or empty of [{0}]", path)); 101 | return false; 102 | } 103 | 104 | if (_IsAlphaTexture (path)) { 105 | return false; 106 | } 107 | 108 | _isRevert = isRevert; 109 | _currentTexturePath = path; 110 | 111 | AssetDatabase.ImportAsset (path, ImportAssetOptions.ForceUpdate | ImportAssetOptions.DontDownloadFromCacheServer); 112 | AssetDatabase.SaveAssets (); 113 | _currentTexturePath = null; 114 | AssetDatabase.ImportAsset (path, ImportAssetOptions.ForceUpdate | ImportAssetOptions.DontDownloadFromCacheServer); 115 | 116 | return true; 117 | } 118 | 119 | private static bool _IsAlphaTexture (string path) 120 | { 121 | string directoryName = Path.GetDirectoryName (path); 122 | if (!directoryName.EndsWith ("/" + AlphaFolderSuffix)) { 123 | return false; 124 | } 125 | return true; 126 | } 127 | 128 | public override int GetPostprocessOrder () 129 | { 130 | return -9999; 131 | } 132 | 133 | void OnPreprocessTexture () 134 | { 135 | if (string.IsNullOrEmpty (_currentTexturePath)) { 136 | return; 137 | } 138 | 139 | var importer = (assetImporter as TextureImporter); 140 | 141 | if (_currentTexturePath == importer.assetPath) { 142 | _SetTrueColorFormat (importer); 143 | importer.isReadable |= !_isRevert; 144 | } 145 | } 146 | 147 | void OnPostprocessTexture (Texture2D texture) 148 | { 149 | var importer = (assetImporter as TextureImporter); 150 | 151 | if (_currentTexturePath != importer.assetPath && _IsAlphaTexture (importer.assetPath)) { 152 | if (!_isRevert) { 153 | _SetIOSAndAndroidRGB4 (importer, CompressionQuality); 154 | } 155 | } else if (_currentTexturePath == importer.assetPath) { 156 | if (!_isRevert) { 157 | Texture2D alphaTexture = _CreateAlphaTexture (texture, importer); 158 | 159 | if (alphaTexture != null) { 160 | AssetDatabase.ImportAsset (AssetDatabase.GetAssetPath (alphaTexture), ImportAssetOptions.ForceUpdate | ImportAssetOptions.DontDownloadFromCacheServer); 161 | _SetIOSAndAndroidRGB4 (importer, CompressionQuality); 162 | } else { 163 | _SetTrueColorFormat (importer); 164 | } 165 | } else { 166 | _DeleteAlphaTexture (GetAlphaTextureFilePath (importer.assetPath)); 167 | } 168 | } 169 | } 170 | 171 | private static Texture2D _CreateAlphaTexture (Texture2D texture, TextureImporter textureImporter) 172 | { 173 | if (texture == null) { 174 | Debug.LogError (string.Format ("{0}::{1} Texture is null!", "SplitAlphaTextureCreator", "CreateAlphaTexture")); 175 | return null; 176 | } 177 | 178 | if (!textureImporter.isReadable) { 179 | Debug.LogError (string.Format ("{0}::{1} Texture must be readwrite enabled: {2}", "SplitAlphaTextureCreator", "CreateAlphaTexture", textureImporter.assetPath)); 180 | return null; 181 | } 182 | 183 | if (!_IsPOTAndMultipleOf4 (texture.width) || !_IsPOTAndMultipleOf4 (texture.height)) { 184 | Debug.LogError (string.Format ("{0}::{1} Only textures with width/height being POT and multiple of 4 can be used: {2}", "SplitAlphaTextureCreator", "CreateAlphaTexture", textureImporter.assetPath)); 185 | return null; 186 | } 187 | 188 | string savedPath = GetAlphaTextureFilePath (textureImporter.assetPath); 189 | Texture2D alphaTexture = _CreateRawAlphaTexture (texture); 190 | _SaveAlphaTexture (alphaTexture, savedPath); 191 | 192 | return alphaTexture; 193 | } 194 | 195 | public static string GetAlphaTextureFilePath (string assetPath) 196 | { 197 | string sourcePath = assetPath.Replace (AssetsDir, Application.dataPath); 198 | string sourceDirPath = Path.GetDirectoryName (sourcePath); 199 | string sourceFileName = Path.GetFileNameWithoutExtension (sourcePath); 200 | string alphaFileName = sourceFileName + PNGSuffix; 201 | return Path.Combine (Path.Combine (sourceDirPath, AlphaFolderSuffix), alphaFileName); 202 | } 203 | 204 | public static string GetAlphaTextureAssetPath (string assetPath) 205 | { 206 | string sourcePath = assetPath; 207 | string sourceDirPath = Path.GetDirectoryName (sourcePath); 208 | string sourceFileName = Path.GetFileNameWithoutExtension (sourcePath); 209 | string alphaFileName = sourceFileName + PNGSuffix; 210 | return Path.Combine (Path.Combine (sourceDirPath, AlphaFolderSuffix), alphaFileName); 211 | } 212 | 213 | private static Texture2D _CreateRawAlphaTexture (Texture2D texture) 214 | { 215 | var alphaTexture = new Texture2D (texture.width, texture.height, TextureFormat.RGB24, false); 216 | alphaTexture.wrapMode = TextureWrapMode.Clamp; 217 | 218 | var pixels = texture.GetPixels (); 219 | for (int i = 0; i < pixels.Length; i++) { 220 | var a = pixels [i].a; 221 | pixels [i] = new Color (a, a, a); 222 | } 223 | alphaTexture.SetPixels (pixels); 224 | 225 | return alphaTexture; 226 | } 227 | 228 | private static void _SaveAlphaTexture (Texture2D texture, string filePath) 229 | { 230 | FileInfo fileInfo = new FileInfo (filePath); 231 | 232 | if (!fileInfo.Directory.Exists) { 233 | fileInfo.Directory.Create (); 234 | } 235 | var bytes = texture.EncodeToPNG (); 236 | File.WriteAllBytes (filePath, bytes); 237 | } 238 | 239 | private static void _DeleteAlphaTexture (string filePath) 240 | { 241 | File.Delete (filePath); 242 | string dirPath = Path.GetDirectoryName (filePath); 243 | 244 | string[] filePaths = Directory.GetFiles (dirPath, StarPng, SearchOption.AllDirectories); 245 | if (filePaths.Length == 0) { 246 | Directory.Delete (dirPath, true); 247 | } 248 | } 249 | 250 | private static bool _IsPOTAndMultipleOf4 (int size) 251 | { 252 | return size >= 4 && ((size & (size - 1)) == 0); 253 | } 254 | 255 | private static void _SetTrueColorFormat (TextureImporter textureImporter) 256 | { 257 | textureImporter.ClearPlatformTextureSettings (Android); 258 | textureImporter.ClearPlatformTextureSettings (iPhone); 259 | TextureImporterPlatformSettings platformTextureSettings; 260 | 261 | platformTextureSettings = textureImporter.GetDefaultPlatformTextureSettings (); 262 | platformTextureSettings.format = TextureImporterFormat.RGBA32; 263 | platformTextureSettings.overridden = true; 264 | 265 | textureImporter.SetPlatformTextureSettings (platformTextureSettings); 266 | 267 | textureImporter.alphaSource = TextureImporterAlphaSource.FromInput; 268 | textureImporter.maxTextureSize = 2048; 269 | textureImporter.generateCubemap = TextureImporterGenerateCubemap.None; 270 | textureImporter.npotScale = TextureImporterNPOTScale.None; 271 | textureImporter.mipmapEnabled = false; 272 | } 273 | 274 | public static void _SetIOSAndAndroidRGB4 (TextureImporter textureImporter, TextureCompressionQuality compressionQuality) 275 | { 276 | int cq = (int)compressionQuality; 277 | 278 | TextureImporterPlatformSettings platformTextureSettings; 279 | platformTextureSettings = textureImporter.GetPlatformTextureSettings (Android); 280 | platformTextureSettings.format = TextureImporterFormat.ETC_RGB4; 281 | platformTextureSettings.compressionQuality = cq; 282 | platformTextureSettings.overridden = true; 283 | textureImporter.SetPlatformTextureSettings (platformTextureSettings); 284 | 285 | platformTextureSettings = textureImporter.GetPlatformTextureSettings (iPhone); 286 | platformTextureSettings.format = TextureImporterFormat.PVRTC_RGB4; 287 | platformTextureSettings.compressionQuality = cq; 288 | platformTextureSettings.overridden = true; 289 | textureImporter.SetPlatformTextureSettings (platformTextureSettings); 290 | 291 | platformTextureSettings = textureImporter.GetDefaultPlatformTextureSettings (); 292 | platformTextureSettings.format = TextureImporterFormat.RGB24; 293 | platformTextureSettings.overridden = true; 294 | textureImporter.SetPlatformTextureSettings (platformTextureSettings); 295 | 296 | textureImporter.alphaSource = TextureImporterAlphaSource.None; 297 | textureImporter.mipmapEnabled = false; 298 | } 299 | 300 | } 301 | } -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Editor/SplitAlphaTextureCreator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 350e68ca8c8d14b45bcff2d7ac1854ce 3 | timeCreated: 1508776084 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Resources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 08f7d0ab2f4c54430835944f41d88fbf 3 | folderAsset: yes 4 | timeCreated: 1508869847 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Resources/Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4f8d5ffa3921a4a7297a34edfe5509bb 3 | folderAsset: yes 4 | timeCreated: 1508820075 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Resources/Shaders/Mobile-Particle-Additive_SplitAlpha.shader: -------------------------------------------------------------------------------- 1 | // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 | 3 | // Simplified Additive Particle shader. Differences from regular Additive Particle one: 4 | // - no Tint color 5 | // - no Smooth particle support 6 | // - no AlphaTest 7 | // - no ColorMask 8 | 9 | Shader "SplitAlpha/Mobile/Particles/Additive" { 10 | Properties { 11 | _MainTex ("Particle Texture", 2D) = "white" {} 12 | _AlphaTex ("External Alpha", 2D) = "white" {} 13 | } 14 | 15 | Category { 16 | Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" } 17 | Blend SrcAlpha One 18 | Cull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) } 19 | 20 | SubShader 21 | { 22 | Pass 23 | { 24 | CGPROGRAM 25 | #pragma vertex vert 26 | #pragma fragment frag 27 | #pragma target 2.0 28 | 29 | #include "UnityCG.cginc" 30 | 31 | sampler2D _MainTex; 32 | sampler2D _AlphaTex; 33 | 34 | struct appdata_t 35 | { 36 | float4 vertex : POSITION; 37 | float4 color : COLOR; 38 | float2 texcoord : TEXCOORD0; 39 | }; 40 | 41 | struct v2f 42 | { 43 | float4 pos : SV_POSITION; 44 | fixed4 color : COLOR; 45 | float2 texcoord : TEXCOORD0; 46 | }; 47 | 48 | v2f vert(appdata_t v) 49 | { 50 | v2f o; 51 | 52 | o.pos = UnityObjectToClipPos(v.vertex); 53 | o.texcoord = v.texcoord; 54 | o.color = v.color; 55 | 56 | return o; 57 | } 58 | 59 | fixed4 frag(v2f i) : SV_Target 60 | { 61 | fixed4 c = tex2D (_MainTex, i.texcoord); 62 | fixed4 alpha = tex2D (_AlphaTex, i.texcoord); 63 | c.a = alpha.r; 64 | c *= i.color; 65 | 66 | return c; 67 | } 68 | 69 | ENDCG 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Resources/Shaders/Mobile-Particle-Additive_SplitAlpha.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: df70ad3df505a4d14bad7e11f1fb187b 3 | timeCreated: 1508831153 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Resources/Shaders/Mobile-Particle-Alpha_SplitAlpha.shader: -------------------------------------------------------------------------------- 1 | // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 | 3 | // Simplified Alpha Blended Particle shader. Differences from regular Alpha Blended Particle one: 4 | // - no Tint color 5 | // - no Smooth particle support 6 | // - no AlphaTest 7 | // - no ColorMask 8 | 9 | Shader "SplitAlpha/Mobile/Particles/Alpha Blended" { 10 | Properties { 11 | _MainTex ("Particle Texture", 2D) = "white" {} 12 | _AlphaTex ("External Alpha", 2D) = "white" {} 13 | } 14 | 15 | Category { 16 | Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" } 17 | Blend SrcAlpha OneMinusSrcAlpha 18 | Cull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) } 19 | 20 | SubShader 21 | { 22 | Pass 23 | { 24 | CGPROGRAM 25 | #pragma vertex vert 26 | #pragma fragment frag 27 | #pragma target 2.0 28 | 29 | #include "UnityCG.cginc" 30 | 31 | sampler2D _MainTex; 32 | sampler2D _AlphaTex; 33 | 34 | struct appdata_t 35 | { 36 | float4 vertex : POSITION; 37 | float4 color : COLOR; 38 | float2 texcoord : TEXCOORD0; 39 | }; 40 | 41 | struct v2f 42 | { 43 | float4 pos : SV_POSITION; 44 | fixed4 color : COLOR; 45 | float2 texcoord : TEXCOORD0; 46 | }; 47 | 48 | v2f vert(appdata_t v) 49 | { 50 | v2f o; 51 | 52 | o.pos = UnityObjectToClipPos(v.vertex); 53 | o.texcoord = v.texcoord; 54 | o.color = v.color; 55 | 56 | return o; 57 | } 58 | 59 | fixed4 frag(v2f i) : SV_Target 60 | { 61 | fixed4 c = tex2D (_MainTex, i.texcoord); 62 | fixed4 alpha = tex2D (_AlphaTex, i.texcoord); 63 | c.a = alpha.r; 64 | c *= i.color; 65 | 66 | return c; 67 | } 68 | 69 | ENDCG 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Resources/Shaders/Mobile-Particle-Alpha_SplitAlpha.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9ab87f9ded0af4656897074f2abcbb1d 3 | timeCreated: 1508831523 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Resources/Shaders/Mobile-Particle-Multiply_SplitAlpha.shader: -------------------------------------------------------------------------------- 1 | Shader "SplitAlpha/Mobile/Particles/Multiply" { 2 | Properties { 3 | _MainTex ("Particle Texture", 2D) = "white" {} 4 | _AlphaTex ("External Alpha", 2D) = "white" {} 5 | } 6 | 7 | Category { 8 | Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" } 9 | Blend Zero SrcColor 10 | Cull Off Lighting Off ZWrite Off Fog { Color (1,1,1,1) } 11 | 12 | BindChannels { 13 | Bind "Color", color 14 | Bind "Vertex", vertex 15 | Bind "TexCoord", texcoord 16 | } 17 | 18 | SubShader 19 | { 20 | Pass 21 | { 22 | CGPROGRAM 23 | #pragma vertex vert 24 | #pragma fragment frag 25 | #pragma target 2.0 26 | 27 | #include "UnityCG.cginc" 28 | 29 | sampler2D _MainTex; 30 | sampler2D _AlphaTex; 31 | 32 | struct appdata_t 33 | { 34 | float4 vertex : POSITION; 35 | float4 color : COLOR; 36 | float2 texcoord : TEXCOORD0; 37 | }; 38 | 39 | struct v2f 40 | { 41 | float4 pos : SV_POSITION; 42 | fixed4 color : COLOR; 43 | float2 texcoord : TEXCOORD0; 44 | }; 45 | 46 | v2f vert(appdata_t v) 47 | { 48 | v2f o; 49 | 50 | o.pos = UnityObjectToClipPos(v.vertex); 51 | o.texcoord = v.texcoord; 52 | o.color = v.color; 53 | 54 | return o; 55 | } 56 | 57 | fixed4 frag(v2f i) : SV_Target 58 | { 59 | fixed4 c = tex2D (_MainTex, i.texcoord); 60 | fixed4 alpha = tex2D (_AlphaTex, i.texcoord); 61 | c.a = alpha.r; 62 | c *= i.color; 63 | 64 | c = lerp(half4(1,1,1,1), c, c.a); 65 | 66 | return c; 67 | } 68 | 69 | ENDCG 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Resources/Shaders/Mobile-Particle-Multiply_SplitAlpha.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5f6fe37a910fe4a6ebc53e4ea8739921 3 | timeCreated: 1508828554 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Resources/Shaders/Sprite-Default_SplitAlpha.shader: -------------------------------------------------------------------------------- 1 | Shader "SplitAlpha/Sprites/Default" 2 | { 3 | Properties 4 | { 5 | _MainTex ("Sprite Texture", 2D) = "white" {} 6 | _AlphaTex ("External Alpha", 2D) = "white" {} 7 | _Color ("Tint", Color) = (1,1,1,1) 8 | [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 9 | } 10 | 11 | SubShader 12 | { 13 | Tags 14 | { 15 | "Queue"="Transparent" 16 | "IgnoreProjector"="True" 17 | "RenderType"="Transparent" 18 | "PreviewType"="Plane" 19 | "CanUseSpriteAtlas"="True" 20 | } 21 | 22 | Cull Off 23 | Lighting Off 24 | ZWrite Off 25 | Blend One OneMinusSrcAlpha 26 | 27 | Pass 28 | { 29 | CGPROGRAM 30 | #pragma vertex vert 31 | #pragma fragment frag 32 | #pragma target 2.0 33 | #pragma multi_compile _ PIXELSNAP_ON 34 | 35 | #include "UnityCG.cginc" 36 | 37 | fixed4 _Color; 38 | sampler2D _MainTex; 39 | sampler2D _AlphaTex; 40 | 41 | struct appdata_t 42 | { 43 | float4 vertex : POSITION; 44 | float4 color : COLOR; 45 | float2 texcoord : TEXCOORD0; 46 | }; 47 | 48 | struct v2f 49 | { 50 | float4 pos : SV_POSITION; 51 | fixed4 color : COLOR; 52 | float2 texcoord : TEXCOORD0; 53 | }; 54 | 55 | v2f vert(appdata_t v) 56 | { 57 | v2f o; 58 | 59 | o.pos = UnityObjectToClipPos(v.vertex); 60 | o.texcoord = v.texcoord; 61 | o.color = v.color * _Color; 62 | 63 | #ifdef PIXELSNAP_ON 64 | o.pos = UnityPixelSnap (o.pos); 65 | #endif 66 | 67 | return o; 68 | } 69 | 70 | fixed4 frag(v2f i) : SV_Target 71 | { 72 | fixed4 c = tex2D (_MainTex, i.texcoord); 73 | fixed4 alpha = tex2D (_AlphaTex, i.texcoord); 74 | c.a = alpha.r; 75 | c *= i.color; 76 | c.rgb *= c.a; 77 | return c; 78 | } 79 | ENDCG 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Resources/Shaders/Sprite-Default_SplitAlpha.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1c854f6787e724274b328c8394275290 3 | timeCreated: 1508752497 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Resources/Shaders/UI-Default_SplitAlpha.shader: -------------------------------------------------------------------------------- 1 | Shader "SplitAlpha/UI/Default" 2 | { 3 | Properties 4 | { 5 | _MainTex ("Sprite Texture", 2D) = "white" {} 6 | _AlphaTex("External Texture", 2D) = "white" {} 7 | _Color ("Tint", Color) = (1,1,1,1) 8 | 9 | _StencilComp ("Stencil Comparison", Float) = 8 10 | _Stencil ("Stencil ID", Float) = 0 11 | _StencilOp ("Stencil Operation", Float) = 0 12 | _StencilWriteMask ("Stencil Write Mask", Float) = 255 13 | _StencilReadMask ("Stencil Read Mask", Float) = 255 14 | 15 | _ColorMask ("Color Mask", Float) = 15 16 | 17 | [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0 18 | } 19 | 20 | SubShader 21 | { 22 | Tags 23 | { 24 | "Queue"="Transparent" 25 | "IgnoreProjector"="True" 26 | "RenderType"="Transparent" 27 | "PreviewType"="Plane" 28 | "CanUseSpriteAtlas"="True" 29 | } 30 | 31 | Stencil 32 | { 33 | Ref [_Stencil] 34 | Comp [_StencilComp] 35 | Pass [_StencilOp] 36 | ReadMask [_StencilReadMask] 37 | WriteMask [_StencilWriteMask] 38 | } 39 | 40 | Cull Off 41 | Lighting Off 42 | ZWrite Off 43 | ZTest [unity_GUIZTestMode] 44 | Blend SrcAlpha OneMinusSrcAlpha 45 | ColorMask [_ColorMask] 46 | 47 | Pass 48 | { 49 | CGPROGRAM 50 | #pragma vertex vert 51 | #pragma fragment frag 52 | #pragma target 2.0 53 | 54 | #include "UnityCG.cginc" 55 | #include "UnityUI.cginc" 56 | 57 | #pragma multi_compile __ UNITY_UI_ALPHACLIP 58 | 59 | fixed4 _Color; 60 | fixed4 _TextureSampleAdd; 61 | float4 _ClipRect; 62 | sampler2D _MainTex; 63 | sampler2D _AlphaTex; 64 | 65 | struct appdata_t 66 | { 67 | float4 vertex : POSITION; 68 | float4 color : COLOR; 69 | float2 texcoord : TEXCOORD0; 70 | }; 71 | 72 | struct v2f 73 | { 74 | float4 pos : SV_POSITION; 75 | fixed4 color : COLOR; 76 | float2 texcoord : TEXCOORD0; 77 | float4 worldPosition : TEXCOORD1; 78 | }; 79 | 80 | v2f vert(appdata_t v) 81 | { 82 | v2f o; 83 | o.worldPosition = v.vertex; 84 | o.pos = UnityObjectToClipPos(o.worldPosition); 85 | 86 | o.texcoord = v.texcoord; 87 | 88 | #ifdef UNITY_HALF_TEXEL_OFFSET 89 | o.pos.xy += (_ScreenParams.zw-1.0) * float2(-1,1) * o.pos.w; 90 | #endif 91 | 92 | o.color = v.color * _Color; 93 | return o; 94 | } 95 | 96 | fixed4 frag(v2f i) : SV_Target 97 | { 98 | fixed4 color = UnityGetUIDiffuseColor(i.texcoord, _MainTex, _AlphaTex, _TextureSampleAdd) * i.color; 99 | 100 | color.a *= UnityGet2DClipping(i.worldPosition.xy, _ClipRect); 101 | 102 | #ifdef UNITY_UI_ALPHACLIP 103 | clip (color.a - 0.001); 104 | #endif 105 | 106 | return color; 107 | } 108 | ENDCG 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Assets/Plugins/USplitAlpha/Resources/Shaders/UI-Default_SplitAlpha.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9506af562f4894988a33949bf7187531 3 | timeCreated: 1508750364 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 358011f482a5749e592fb86b8bd4809c 3 | folderAsset: yes 4 | timeCreated: 1508833881 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e2b16ed471bc47e1824b08506224283 3 | folderAsset: yes 4 | timeCreated: 1501648432 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9c426d2eb7dd148ad90fcb11e2dd2099 3 | folderAsset: yes 4 | timeCreated: 1501648415 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Changelog.txt: -------------------------------------------------------------------------------- 1 | Version 1.8: 2 | - Added automatic texture format correction. 3 | - Improved the sprite referrence replacement. 4 | 5 | Version 1.7: 6 | - Source sprite reference replacing tool will now also set the values of structs. 7 | - Source sprite reference replacing tool will now target only prefabs if the target is Project. 8 | 9 | Version 1.6: 10 | - Greatly improved source sprite reference replacing speed. 11 | 12 | Version 1.5: 13 | - Extended the source sprite reference replacing tool. 14 | 15 | Version 1.4: 16 | - Added source sprite reference replacing tool. 17 | 18 | Version 1.3: 19 | - Simple Sprite Packer no longer prevents building. 20 | 21 | Version 1.2: 22 | - Improved MaxRects packing performance be pre-estimating the texture size (Provided by Vrvyus). 23 | 24 | Version 1.1: 25 | - Fixed packing issue when the source is Sprite of type Multiple. 26 | - Inspector will no Repaint when settings are changed in the SPSettings window. -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Changelog.txt.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1bb77079aeed59d44acc7ba4b70212e8 3 | TextScriptImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4b6b777d2dae3ad44b4f8e140fe5017c 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPAtlasBuilder.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using SimpleSpritePacker; 4 | using SimpleSpritePackerEditor; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | namespace SimpleSpritePackerEditor 9 | { 10 | public class SPAtlasBuilder { 11 | 12 | private SPInstance m_Instance; 13 | 14 | // Constructor 15 | public SPAtlasBuilder(SPInstance instance) 16 | { 17 | this.m_Instance = instance; 18 | } 19 | 20 | public static int CompareBySize(SPSpriteInfo a, SPSpriteInfo b) 21 | { 22 | // A is null b is not b is greater so put it at the front of the list 23 | if (a == null && b != null) return 1; 24 | 25 | // A is not null b is null a is greater so put it at the front of the list 26 | if (a != null && b == null) return -1; 27 | 28 | // Get the total pixels used for each sprite 29 | float aPixels = a.sizeForComparison.x * a.sizeForComparison.y; 30 | float bPixels = b.sizeForComparison.x * b.sizeForComparison.y; 31 | 32 | if (aPixels > bPixels) return -1; 33 | else if (aPixels < bPixels) return 1; 34 | return 0; 35 | } 36 | 37 | /// 38 | /// Rebuilds the atlas texture. 39 | /// 40 | public void RebuildAtlas() 41 | { 42 | if (this.m_Instance == null) 43 | { 44 | Debug.LogError("SPAtlasBuilder failed to rebuild the atlas, reason: Sprite Packer Instance reference is null."); 45 | return; 46 | } 47 | 48 | if (this.m_Instance.texture == null) 49 | { 50 | Debug.LogWarning("Sprite Packer failed to rebuild the atlas, please make sure the atlas texture reference is set."); 51 | return; 52 | } 53 | 54 | // Make the atlas texture readable 55 | if (SPTools.TextureSetReadWriteEnabled(this.m_Instance.texture, true, false)) 56 | { 57 | // Get a list with the current sprites and applied actions 58 | List spriteInfoList = this.m_Instance.GetSpriteListWithAppliedActions(); 59 | 60 | // Get the source textures asset paths 61 | string[] sourceTexturePaths = this.CollectSourceTextureAssetPaths(spriteInfoList); 62 | 63 | // Make the source textures readable 64 | if (!this.SetAssetsReadWriteEnabled(sourceTexturePaths, true)) 65 | { 66 | Debug.LogError("Sprite Packer failed to make one or more of the source texture readable, please do it manually."); 67 | return; 68 | } 69 | 70 | // Make sure all the textures have the correct texture format 71 | this.CorrectTexturesFormat(spriteInfoList); 72 | 73 | // If we are using max rects packing, sort the sprite info list by size 74 | if (this.m_Instance.packingMethod == SPInstance.PackingMethod.MaxRects) 75 | { 76 | spriteInfoList.Sort(CompareBySize); 77 | } 78 | 79 | // Temporary textures array 80 | Texture2D[] textures = new Texture2D[spriteInfoList.Count]; 81 | 82 | // Create an array to contain the sprite import data 83 | SPSpriteImportData[] spritesImportData = new SPSpriteImportData[spriteInfoList.Count]; 84 | 85 | // Populate the textures and names arrays 86 | int ia = 0; 87 | foreach (SPSpriteInfo si in spriteInfoList) 88 | { 89 | // Temporary texture 90 | Texture2D texture = null; 91 | 92 | // Prepare the sprite import data 93 | SPSpriteImportData importData = new SPSpriteImportData(); 94 | 95 | // Prepare the sprite name 96 | importData.name = "Sprite_" + ia.ToString(); 97 | 98 | if (si.targetSprite != null) 99 | { 100 | importData.name = si.targetSprite.name; 101 | } 102 | else if (si.source != null && (si.source is Texture2D || si.source is Sprite)) 103 | { 104 | if (si.source is Texture2D) importData.name = (si.source as Texture2D).name; 105 | else importData.name = (si.source as Sprite).name; 106 | } 107 | 108 | // Prepare texture 109 | // In case the source texture is missing, rebuild from the already existing sprite 110 | if (si.source == null && si.targetSprite != null) 111 | { 112 | // Copy the sprite into the temporary texture 113 | texture = new Texture2D((int)si.targetSprite.rect.width, (int)si.targetSprite.rect.height, TextureFormat.ARGB32, false); 114 | Color[] pixels = si.targetSprite.texture.GetPixels((int)si.targetSprite.rect.x, 115 | (int)si.targetSprite.rect.y, 116 | (int)si.targetSprite.rect.width, 117 | (int)si.targetSprite.rect.height); 118 | texture.SetPixels(pixels); 119 | texture.Apply(); 120 | } 121 | // Handle texture source 122 | else if (si.source is Texture2D) 123 | { 124 | // Get as texture 125 | Texture2D sourceTex = si.source as Texture2D; 126 | 127 | // Check if we have as source texture 128 | if (sourceTex != null) 129 | { 130 | // Copy the source texture into the temp one 131 | texture = new Texture2D(sourceTex.width, sourceTex.height, TextureFormat.ARGB32, false); 132 | Color[] pixels = sourceTex.GetPixels(0, 0, sourceTex.width, sourceTex.height); 133 | texture.SetPixels(pixels); 134 | texture.Apply(); 135 | 136 | // Transfer the sprite data 137 | importData.border = Vector4.zero; 138 | importData.alignment = this.m_Instance.defaultPivot; 139 | importData.pivot = this.m_Instance.defaultCustomPivot; 140 | } 141 | } 142 | // Handle sprite source 143 | else if (si.source is Sprite) 144 | { 145 | // Get as sprite 146 | Sprite sourceSprite = si.source as Sprite; 147 | 148 | // Make sure we have the sprite 149 | if (sourceSprite != null) 150 | { 151 | // Copy the sprite into the temporary texture 152 | texture = new Texture2D((int)sourceSprite.rect.width, (int)sourceSprite.rect.height, TextureFormat.ARGB32, false); 153 | Color[] pixels = sourceSprite.texture.GetPixels((int)sourceSprite.rect.x, 154 | (int)sourceSprite.rect.y, 155 | (int)sourceSprite.rect.width, 156 | (int)sourceSprite.rect.height); 157 | texture.SetPixels(pixels); 158 | texture.Apply(); 159 | 160 | // Transfer the sprite data 161 | importData.border = sourceSprite.border; 162 | importData.alignment = SpriteAlignment.Custom; 163 | importData.pivot = new Vector2( (0f - sourceSprite.bounds.center.x / sourceSprite.bounds.extents.x / 2 + 0.5f), 164 | (0f - sourceSprite.bounds.center.y / sourceSprite.bounds.extents.y / 2 + 0.5f)); 165 | } 166 | } 167 | 168 | // Save the new texture into our array 169 | textures[ia] = (texture != null) ? texture : new Texture2D(1, 1); 170 | 171 | // Set the sprite import data 172 | spritesImportData[ia] = importData; 173 | 174 | // Increase the indexer 175 | ia++; 176 | } 177 | 178 | // Make the source textures assets non readable 179 | if (SPTools.GetEditorPrefBool(SPTools.Settings_DisableReadWriteEnabled)) 180 | this.SetAssetsReadWriteEnabled(sourceTexturePaths, false); 181 | 182 | // Clear the source textures asset paths 183 | System.Array.Clear(sourceTexturePaths, 0, sourceTexturePaths.Length); 184 | 185 | // Create a temporary texture for the packing 186 | Texture2D tempTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false); 187 | 188 | // UV coords array 189 | Rect[] uvs; 190 | 191 | // Pack the textures into the temporary 192 | if (this.m_Instance.packingMethod == SPInstance.PackingMethod.Unity) 193 | { 194 | uvs = tempTexture.PackTextures(textures, this.m_Instance.padding, this.m_Instance.maxSize); 195 | } 196 | else 197 | { 198 | uvs = UITexturePacker.PackTextures(tempTexture, textures, this.m_Instance.padding, this.m_Instance.maxSize); 199 | 200 | // Check if packing failed 201 | if (uvs == null) 202 | { 203 | Debug.LogError("Sprite Packer texture packing failed, the textures might be exceeding the specified maximum size."); 204 | return; 205 | } 206 | } 207 | 208 | // Import and Configure the texture atlas (also disables Read/Write) 209 | SPTools.ImportAndConfigureAtlasTexture(this.m_Instance.texture, tempTexture, uvs, spritesImportData); 210 | 211 | // Clear the current sprite info list 212 | this.m_Instance.ClearSprites(); 213 | 214 | // Clear the actions list 215 | this.m_Instance.ClearActions(); 216 | 217 | // Destroy the textures from the temporary textures array 218 | for (int ib = 0; ib < textures.Length; ib++) 219 | UnityEngine.Object.DestroyImmediate(textures[ib]); 220 | 221 | // Destroy the temporary texture 222 | UnityEngine.Object.DestroyImmediate(tempTexture); 223 | 224 | // Convert the temporary sprite info into array 225 | SPSpriteInfo[] spriteInfoArray = spriteInfoList.ToArray(); 226 | 227 | // Clear the temporary sprite info list 228 | spriteInfoList.Clear(); 229 | 230 | // Apply the new sprite reff to the sprite info and add the sprite info to the sprites list 231 | for (int i = 0; i < spriteInfoArray.Length; i++) 232 | { 233 | SPSpriteInfo info = spriteInfoArray[i]; 234 | 235 | if (info.targetSprite == null) 236 | info.targetSprite = SPTools.LoadSprite(this.m_Instance.texture, spritesImportData[i].name); 237 | 238 | // Add to the instance sprite info list 239 | this.m_Instance.AddSprite(info); 240 | } 241 | 242 | // Clear the sprites import data array 243 | System.Array.Clear(spritesImportData, 0, spritesImportData.Length); 244 | 245 | // Set dirty 246 | EditorUtility.SetDirty(this.m_Instance); 247 | } 248 | else 249 | { 250 | Debug.LogError("Sprite Packer failed to make the atlas texture readable, please do it manually."); 251 | } 252 | } 253 | 254 | /// 255 | /// Collects the source textures asset paths. 256 | /// 257 | /// The source texture asset paths. 258 | /// Sprite info list. 259 | protected string[] CollectSourceTextureAssetPaths(List spriteInfoList) 260 | { 261 | List texturePaths = new List(); 262 | 263 | // Add the textures from the sprite info list into our textures list 264 | foreach (SPSpriteInfo spriteInfo in spriteInfoList) 265 | { 266 | string path = string.Empty; 267 | 268 | // No source but present target sprite 269 | if (spriteInfo.source == null && spriteInfo.targetSprite != null) 270 | { 271 | path = SPTools.GetAssetPath(spriteInfo.targetSprite.texture); 272 | } 273 | // Texture source 274 | else if (spriteInfo.source is Texture2D) 275 | { 276 | path = SPTools.GetAssetPath(spriteInfo.source as Texture2D); 277 | } 278 | // Sprite source 279 | else if (spriteInfo.source is Sprite) 280 | { 281 | path = SPTools.GetAssetPath((spriteInfo.source as Sprite).texture); 282 | } 283 | 284 | if (!string.IsNullOrEmpty(path)) 285 | { 286 | if (!texturePaths.Contains(path)) 287 | texturePaths.Add(path); 288 | } 289 | } 290 | 291 | return texturePaths.ToArray(); 292 | } 293 | 294 | /// 295 | /// Sets the assets read write enabled. 296 | /// 297 | /// true, if assets read write enabled was set, false otherwise. 298 | /// Asset paths. 299 | /// If set to true enabled. 300 | protected bool SetAssetsReadWriteEnabled(string[] assetPaths, bool enabled) 301 | { 302 | bool success = true; 303 | 304 | // Make the assets readable 305 | foreach (string assetPath in assetPaths) 306 | { 307 | // Make the texture readable 308 | if (!SPTools.AssetSetReadWriteEnabled(assetPath, enabled, false)) 309 | { 310 | Debug.LogWarning("Sprite Packer failed to set Read/Write state (" + enabled.ToString() + ") on asset: " + assetPath); 311 | success = false; 312 | } 313 | } 314 | 315 | // Return the result 316 | return success; 317 | } 318 | 319 | /// 320 | /// Corrects the textures format. 321 | /// 322 | /// Sprite info list. 323 | protected void CorrectTexturesFormat(List spriteInfoList) 324 | { 325 | if (spriteInfoList == null || spriteInfoList.Count == 0) 326 | return; 327 | 328 | foreach (SPSpriteInfo spriteInfo in spriteInfoList) 329 | { 330 | Texture2D texture = null; 331 | 332 | // No source but present target sprite 333 | if (spriteInfo.source == null && spriteInfo.targetSprite != null) 334 | { 335 | texture = spriteInfo.targetSprite.texture; 336 | } 337 | // Texture source 338 | else if (spriteInfo.source is Texture2D) 339 | { 340 | texture = (spriteInfo.source as Texture2D); 341 | } 342 | // Sprite source 343 | else if (spriteInfo.source is Sprite) 344 | { 345 | texture = (spriteInfo.source as Sprite).texture; 346 | } 347 | 348 | if (texture != null) 349 | { 350 | // Make sure it's the correct format 351 | if (texture.format != TextureFormat.ARGB32 && 352 | texture.format != TextureFormat.RGBA32 && 353 | texture.format != TextureFormat.BGRA32 && 354 | texture.format != TextureFormat.RGB24 && 355 | texture.format != TextureFormat.Alpha8 && 356 | texture.format != TextureFormat.DXT1 && 357 | texture.format != TextureFormat.DXT5) 358 | { 359 | // Get the texture asset path 360 | string assetPath = SPTools.GetAssetPath(texture); 361 | 362 | // Set new texture format 363 | if (!SPTools.AssetSetFormat(assetPath, TextureImporterFormat.ARGB32)) 364 | { 365 | Debug.LogWarning("Sprite Packer failed to set texture format ARGB32 on asset: " + assetPath); 366 | } 367 | } 368 | } 369 | } 370 | } 371 | } 372 | } -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPAtlasBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 405b51c6728877443a9b52a87d6f0d5a 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPDropWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections; 4 | using SimpleSpritePacker; 5 | 6 | namespace SimpleSpritePackerEditor 7 | { 8 | public class SPDropWindow : EditorWindow 9 | { 10 | private static Color green = new Color(0.345f, 0.625f, 0.370f, 1f); 11 | private SPInstance m_Instance; 12 | 13 | [MenuItem ("Window/Simple Sprite Packer/Drag and Drop Window")] 14 | public static void ShowWindow() 15 | { 16 | EditorWindow.GetWindow(typeof(SPDropWindow)); 17 | } 18 | 19 | protected void OnEnable() 20 | { 21 | this.titleContent = new GUIContent("SP Drop"); 22 | 23 | if (EditorPrefs.HasKey(SPTools.Settings_SavedInstanceIDKey)) 24 | { 25 | string instancePath = AssetDatabase.GetAssetPath(EditorPrefs.GetInt(SPTools.Settings_SavedInstanceIDKey, 0)); 26 | 27 | if (!string.IsNullOrEmpty(instancePath)) 28 | { 29 | this.m_Instance = AssetDatabase.LoadAssetAtPath(instancePath, typeof(SPInstance)) as SPInstance; 30 | } 31 | } 32 | } 33 | 34 | protected void OnGUI() 35 | { 36 | EditorGUIUtility.labelWidth = 100f; 37 | 38 | GUILayout.BeginVertical(); 39 | GUILayout.Space(8f); 40 | 41 | GUI.changed = false; 42 | this.m_Instance = EditorGUILayout.ObjectField("Sprite Packer", this.m_Instance, typeof(SPInstance), false) as SPInstance; 43 | if (GUI.changed) 44 | { 45 | // Save the instance id 46 | EditorPrefs.SetInt(SPTools.Settings_SavedInstanceIDKey, (this.m_Instance == null) ? 0 : this.m_Instance.GetInstanceID()); 47 | } 48 | 49 | GUILayout.Space(4f); 50 | 51 | if (this.m_Instance == null) 52 | { 53 | EditorGUILayout.HelpBox("Please set the sprite packer instance reference in order to use this feature.", MessageType.Info); 54 | } 55 | else 56 | { 57 | Event evt = Event.current; 58 | Rect drop_area = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); 59 | GUIStyle boxStyle = new GUIStyle(GUI.skin.box); 60 | boxStyle.alignment = TextAnchor.MiddleCenter; 61 | GUI.color = SPDropWindow.green; 62 | GUI.Box(drop_area, "Add Sprite (Drop Here)", boxStyle); 63 | GUI.color = Color.white; 64 | 65 | switch (evt.type) 66 | { 67 | case EventType.DragUpdated: 68 | case EventType.DragPerform: 69 | { 70 | if (!drop_area.Contains(evt.mousePosition)) 71 | return; 72 | 73 | DragAndDrop.visualMode = DragAndDropVisualMode.Copy; 74 | 75 | if (evt.type == EventType.DragPerform) 76 | { 77 | DragAndDrop.AcceptDrag(); 78 | 79 | Object[] filtered = SPTools.FilterResourcesForAtlasImport(DragAndDrop.objectReferences); 80 | 81 | // Disallow miltiple sprites of the same source, if set so 82 | if (!SPTools.GetEditorPrefBool(SPTools.Settings_AllowMuliSpritesOneSource)) 83 | { 84 | // Additional filtering specific to the instance 85 | for (int i = 0; i < filtered.Length; i++) 86 | { 87 | if (this.m_Instance.sprites.Find(s => s.source == filtered[i]) != null) 88 | { 89 | Debug.LogWarning("A sprite with source \"" + SimpleSpritePackerEditor.SPTools.GetAssetPath(filtered[i]) + "\" already exists in the atlas, consider changing the Sprite Packer settings to allow multiple sprites from the same source."); 90 | System.Array.Clear(filtered, i, 1); 91 | } 92 | } 93 | } 94 | 95 | // Types are handled internally 96 | this.m_Instance.QueueAction_AddSprites(filtered); 97 | 98 | Selection.activeObject = this.m_Instance; 99 | //EditorPrefs.SetBool(SPTools.Settings_ShowSpritesKeys, false); 100 | } 101 | break; 102 | } 103 | } 104 | } 105 | 106 | GUILayout.EndVertical(); 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPDropWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dec0cbd899c8b5b4ca8f59e9ca0f2942 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPInstanceEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using SimpleSpritePacker; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | 7 | namespace SimpleSpritePackerEditor 8 | { 9 | [CustomEditor(typeof(SPInstance))] 10 | public class SPInstanceEditor : Editor { 11 | 12 | private SPInstance m_SPInstance; 13 | private SPAtlasBuilder m_AtlasBuilder; 14 | 15 | private static Color green = new Color(0.345f, 0.625f, 0.370f, 1f); 16 | private static Color red = new Color(0.779f, 0.430f, 0.430f, 1f); 17 | private static Color spriteBoxNormalColor = new Color(0.897f, 0.897f, 0.897f, 1f); 18 | private static Color spriteBoxHighlightColor = new Color(0.798f, 0.926f, 0.978f, 1f); 19 | 20 | private Vector2 scrollViewOffset = Vector2.zero; 21 | private int m_SelectedSpriteInstanceID = 0; 22 | 23 | private GUIStyle boxStyle; 24 | private GUIStyle paddingStyle; 25 | 26 | protected void OnEnable() 27 | { 28 | this.m_SPInstance = this.target as SPInstance; 29 | this.m_AtlasBuilder = new SPAtlasBuilder(this.m_SPInstance); 30 | 31 | SPTools.PrepareDefaultEditorPrefs(); 32 | 33 | this.boxStyle = new GUIStyle(EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).box); 34 | this.paddingStyle = new GUIStyle(); 35 | this.paddingStyle.padding = new RectOffset(3, 3, 3, 3); 36 | } 37 | 38 | protected void OnDisable() 39 | { 40 | this.m_AtlasBuilder = null; 41 | this.m_SPInstance = null; 42 | } 43 | 44 | public override void OnInspectorGUI() 45 | { 46 | this.serializedObject.Update(); 47 | EditorGUILayout.PropertyField(this.serializedObject.FindProperty("m_Texture"), new GUIContent("Atlas Texture")); 48 | EditorGUILayout.Space(); 49 | EditorGUILayout.PropertyField(this.serializedObject.FindProperty("m_Padding"), new GUIContent("Packing Padding")); 50 | this.MaxSizePopup(this.serializedObject.FindProperty("m_MaxSize"), "Packing Max Size"); 51 | EditorGUILayout.PropertyField(this.serializedObject.FindProperty("m_PackingMethod")); 52 | EditorGUILayout.Space(); 53 | EditorGUILayout.PropertyField(this.serializedObject.FindProperty("m_DefaultPivot")); 54 | 55 | if ((SpriteAlignment)this.serializedObject.FindProperty("m_DefaultPivot").enumValueIndex != SpriteAlignment.Custom) 56 | GUI.enabled = false; 57 | 58 | EditorGUILayout.PropertyField(this.serializedObject.FindProperty("m_DefaultCustomPivot"), new GUIContent("Default Cus. Pivot")); 59 | 60 | GUI.enabled = true; 61 | 62 | this.serializedObject.ApplyModifiedProperties(); 63 | 64 | EditorGUILayout.Space(); 65 | this.DrawCurrentSprites(); 66 | EditorGUILayout.Space(); 67 | if (this.m_SPInstance.pendingActions.Count > 0) 68 | { 69 | this.DrawActionButtons(); 70 | EditorGUILayout.Space(); 71 | } 72 | this.DrawPendingActions(); 73 | EditorGUILayout.Space(); 74 | this.DrawActionButtons(); 75 | EditorGUILayout.Space(); 76 | this.DropAreaGUI(); 77 | } 78 | 79 | private void DrawActionButtons() 80 | { 81 | // Get a rect for the buttons 82 | Rect controlRect = EditorGUILayout.GetControlRect(); 83 | 84 | // Clear Actions Button 85 | controlRect.width = (controlRect.width / 2f) - 6f; 86 | 87 | if (this.m_SPInstance.pendingActions.Count == 0) 88 | GUI.enabled = false; 89 | 90 | if (GUI.Button(controlRect, "Clear Actions", EditorStyles.miniButton)) 91 | { 92 | this.m_SPInstance.ClearActions(); 93 | } 94 | GUI.enabled = true; 95 | 96 | // Rebuild Button 97 | controlRect.x = controlRect.width + 24f; 98 | 99 | if (GUI.Button(controlRect, "Rebuild Atlas", EditorStyles.miniButton)) 100 | { 101 | this.m_AtlasBuilder.RebuildAtlas(); 102 | } 103 | } 104 | 105 | private void MaxSizePopup(SerializedProperty property, string label) 106 | { 107 | string[] names = new string[8] { "32", "64", "128", "256", "512", "1024", "2048", "4096" }; 108 | int[] sizes = new int[8] { 32, 64, 128, 256, 512, 1024, 2048, 4096 }; 109 | 110 | GUI.changed = false; 111 | int size = EditorGUILayout.IntPopup(label, property.intValue, names, sizes); 112 | 113 | if (GUI.changed) 114 | { 115 | property.intValue = size; 116 | } 117 | } 118 | 119 | private void DrawCurrentSprites() 120 | { 121 | if (this.m_SPInstance == null) 122 | return; 123 | 124 | Rect controlRect = EditorGUILayout.GetControlRect(); 125 | GUI.Label(controlRect, "Sprites (" + this.m_SPInstance.sprites.Count.ToString() + ")", EditorStyles.boldLabel); 126 | 127 | GUI.Label(new Rect(controlRect.width - 120f, controlRect.y, 70f, 20f), "Scrollview"); 128 | 129 | GUI.changed = false; 130 | bool sv = GUI.Toggle(new Rect(controlRect.width - 55f, controlRect.y + 1f, 20f, 20f), EditorPrefs.GetBool(SPTools.Settings_UseScrollViewKey), " "); 131 | if (GUI.changed) 132 | { 133 | EditorPrefs.SetBool(SPTools.Settings_UseScrollViewKey, sv); 134 | } 135 | 136 | GUI.Label(new Rect(controlRect.width - 40f, controlRect.y, 40f, 20f), "Show"); 137 | 138 | GUI.changed = false; 139 | bool ss = GUI.Toggle(new Rect(controlRect.width - 2f, controlRect.y + 1f, 20f, 20f), EditorPrefs.GetBool(SPTools.Settings_ShowSpritesKey), " "); 140 | if (GUI.changed) 141 | { 142 | EditorPrefs.SetBool(SPTools.Settings_ShowSpritesKey, ss); 143 | } 144 | 145 | if (EditorPrefs.GetBool(SPTools.Settings_ShowSpritesKey)) 146 | { 147 | if (this.m_SPInstance.sprites.Count == 0) 148 | { 149 | this.DrawMessage("The atlas does not contain sprites."); 150 | return; 151 | } 152 | 153 | EditorGUILayout.BeginVertical(this.boxStyle); 154 | 155 | if (EditorPrefs.GetBool(SPTools.Settings_UseScrollViewKey)) 156 | { 157 | this.scrollViewOffset = EditorGUILayout.BeginScrollView(this.scrollViewOffset, GUILayout.Height(EditorPrefs.GetFloat(SPTools.Settings_ScrollViewHeightKey))); 158 | } 159 | 160 | if (EditorPrefs.GetBool(SPTools.Settings_UseSpriteThumbsKey)) 161 | { 162 | this.DrawSpritesWithThumbs(); 163 | } 164 | else 165 | { 166 | this.DrawSpritesSimple(); 167 | } 168 | 169 | if (EditorPrefs.GetBool(SPTools.Settings_UseScrollViewKey)) 170 | { 171 | EditorGUILayout.EndScrollView(); 172 | } 173 | 174 | EditorGUILayout.EndVertical(); 175 | } 176 | } 177 | 178 | private Color c; 179 | 180 | private void DrawSpritesWithThumbs() 181 | { 182 | // Get a copy of the sprites list 183 | List sprites = this.m_SPInstance.copyOfSprites; 184 | sprites.Sort(); 185 | 186 | EditorGUILayout.BeginHorizontal(); 187 | GUILayout.Space(6f); 188 | EditorGUILayout.BeginVertical(); 189 | 190 | RectOffset padding = this.paddingStyle.padding; 191 | RectOffset thumbnailPadding = new RectOffset(6, 6, 6, 3); 192 | float thumbnailMaxHeight = EditorPrefs.GetFloat(SPTools.Settings_ThumbsHeightKey); 193 | float labelHeight = 20f; 194 | float selectedExtensionHeight = 27f; 195 | 196 | GUIStyle labelStyle = new GUIStyle(EditorStyles.label); 197 | labelStyle.fontStyle = FontStyle.Normal; 198 | labelStyle.alignment = TextAnchor.MiddleCenter; 199 | 200 | // Draw the sprites 201 | foreach (SPSpriteInfo info in sprites) 202 | { 203 | bool isSelected = this.IsSelected(info.GetHashCode()); 204 | Color boxColor = (isSelected ? SPInstanceEditor.spriteBoxHighlightColor : SPInstanceEditor.spriteBoxNormalColor); 205 | 206 | GUILayout.Space(6f); 207 | EditorGUILayout.BeginHorizontal(this.paddingStyle); 208 | 209 | if (info.targetSprite != null) 210 | { 211 | // Determine the control height 212 | float thumbnailHeight = (info.targetSprite.rect.height > thumbnailMaxHeight) ? thumbnailMaxHeight : info.targetSprite.rect.height; 213 | 214 | // Apply the thumb padding to the height 215 | float thumbnailHeightWithPadding = thumbnailHeight + thumbnailPadding.top + thumbnailPadding.bottom; 216 | 217 | // Generate a working rect for the control 218 | Rect controlRect = GUILayoutUtility.GetRect(0.0f, (thumbnailHeightWithPadding + labelHeight + (isSelected ? (selectedExtensionHeight + padding.top) : 0f)), GUILayout.ExpandWidth(true)); 219 | 220 | // Determine the click rect 221 | Rect clickRect = new Rect(controlRect.x, controlRect.y, controlRect.width, (controlRect.height - (isSelected ? (selectedExtensionHeight + padding.top) : 0f))); 222 | 223 | // Sprite box background 224 | GUI.color = boxColor; 225 | GUI.Box(new Rect(controlRect.x - padding.left, controlRect.y - padding.top, controlRect.width + (padding.left + padding.right), controlRect.height + (padding.top + padding.bottom)), "", this.boxStyle); 226 | GUI.color = Color.white; 227 | 228 | // Draw the thumbnail 229 | if (info.targetSprite.texture != null) 230 | this.DrawThumbnail(info, thumbnailHeight, controlRect, thumbnailPadding); 231 | 232 | // Draw the sprite name label 233 | GUI.Label(new Rect(controlRect.x, (controlRect.y + thumbnailHeightWithPadding + 1f), controlRect.width, labelHeight), info.targetSprite.name + " (" + info.targetSprite.rect.width + "x" + info.targetSprite.rect.height + ")", labelStyle); 234 | 235 | // Remove button 236 | if (GUI.Button(new Rect((controlRect.width - 9f), (controlRect.y + thumbnailHeightWithPadding + 2f), 18f, 18f), "X")) 237 | { 238 | this.m_SPInstance.QueueAction_RemoveSprite(info); 239 | } 240 | // Detect sprite clicks 241 | else if (Event.current.type == EventType.MouseUp && clickRect.Contains(Event.current.mousePosition)) 242 | { 243 | EditorGUIUtility.PingObject(info.targetSprite); 244 | 245 | // Remove the focus of the focused control 246 | GUI.FocusControl(""); 247 | 248 | // Set as selected 249 | if (!isSelected) this.SetSelected(info.GetHashCode()); 250 | } 251 | 252 | // Draw the selected extension 253 | if (isSelected) 254 | { 255 | Rect extensionRect = new Rect((controlRect.x - padding.left), 256 | (controlRect.y + thumbnailHeightWithPadding + labelHeight + padding.top), 257 | (controlRect.width + (padding.left + padding.right)), 258 | selectedExtensionHeight); 259 | 260 | // Box that looks like a separator 261 | if (Event.current.type == EventType.Repaint) 262 | { 263 | GUI.color = boxColor; 264 | this.boxStyle.Draw(new Rect(extensionRect.x, extensionRect.y, extensionRect.width, 1f), GUIContent.none, 0); 265 | GUI.color = Color.white; 266 | } 267 | 268 | // Draw the source label 269 | GUI.Label(new Rect(extensionRect.x + padding.left + 2f, extensionRect.y + padding.top + 3f, 60f, 20f), "Source:", EditorStyles.label); 270 | 271 | Rect sourceFieldRect = new Rect((extensionRect.x + 60f), (extensionRect.y + padding.top + 3f), (extensionRect.width - 66f), 18f); 272 | 273 | // Draw the sprite source field 274 | EditorGUI.BeginChangeCheck(); 275 | Object source = EditorGUI.ObjectField(sourceFieldRect, info.source, typeof(Object), false); 276 | if (EditorGUI.EndChangeCheck()) 277 | this.m_SPInstance.ChangeSpriteSource(info, source); 278 | } 279 | } 280 | 281 | EditorGUILayout.EndHorizontal(); 282 | } 283 | GUILayout.Space(6f); 284 | 285 | EditorGUILayout.EndVertical(); 286 | GUILayout.Space(6f); 287 | EditorGUILayout.EndHorizontal(); 288 | } 289 | 290 | private void DrawThumbnail(SPSpriteInfo info, float height, Rect controlRect, RectOffset padding) 291 | { 292 | // Calculate the sprite rect inside the texture 293 | Rect spriteRect = new Rect(info.targetSprite.textureRect.x / info.targetSprite.texture.width, 294 | info.targetSprite.textureRect.y / info.targetSprite.texture.height, 295 | info.targetSprite.textureRect.width / info.targetSprite.texture.width, 296 | info.targetSprite.textureRect.height / info.targetSprite.texture.height); 297 | 298 | // Get the original sprite size 299 | Vector2 spriteSize = new Vector2(info.targetSprite.rect.width, info.targetSprite.rect.height); 300 | 301 | // Determine the max size of the thumb 302 | Vector2 thumbMaxSize = new Vector2((controlRect.width - (padding.left + padding.right)), height); 303 | 304 | // Clamp the sprite size based on max width and height of the control 305 | if (spriteSize.x > thumbMaxSize.x) 306 | { 307 | spriteSize *= thumbMaxSize.x / spriteSize.x; 308 | } 309 | if (spriteSize.y > thumbMaxSize.y) 310 | { 311 | spriteSize *= thumbMaxSize.y / spriteSize.y; 312 | } 313 | 314 | // Prepare the rect for the texture draw 315 | Rect thumbRect = new Rect(0f, 0f, spriteSize.x, spriteSize.y); 316 | 317 | // Position in the middle of the control rect 318 | thumbRect.x = controlRect.x + ((controlRect.width - spriteSize.x) / 2f); 319 | thumbRect.y = controlRect.y + padding.top + ((height - spriteSize.y) / 2f); 320 | 321 | // Draw the thumbnail 322 | GUI.DrawTextureWithTexCoords(thumbRect, info.targetSprite.texture, spriteRect, true); 323 | } 324 | 325 | private void DrawSpritesSimple() 326 | { 327 | // Get a copy of the sprites list 328 | List sprites = this.m_SPInstance.copyOfSprites; 329 | sprites.Sort(); 330 | 331 | // Draw the sprites 332 | foreach (SPSpriteInfo info in sprites) 333 | { 334 | EditorGUILayout.Space(); 335 | EditorGUILayout.BeginHorizontal(); 336 | GUILayout.Space(8f); 337 | 338 | if (info.targetSprite != null) 339 | { 340 | EditorGUILayout.ObjectField(info.targetSprite, typeof(Sprite), false, GUILayout.Height(20f)); 341 | } 342 | else 343 | { 344 | EditorGUILayout.TextField("Missing sprite reference"); 345 | } 346 | 347 | // Remove button 348 | if (GUILayout.Button("X", GUILayout.Width(20f))) 349 | { 350 | this.m_SPInstance.QueueAction_RemoveSprite(info); 351 | } 352 | 353 | GUILayout.Space(6f); 354 | EditorGUILayout.EndHorizontal(); 355 | } 356 | EditorGUILayout.Space(); 357 | } 358 | 359 | private void DrawPendingActions() 360 | { 361 | if (this.m_SPInstance == null) 362 | return; 363 | 364 | EditorGUILayout.LabelField("Pending Actions", EditorStyles.boldLabel); 365 | 366 | float labelWidth = 90f; 367 | 368 | if (this.m_SPInstance.pendingActions.Count == 0) 369 | { 370 | this.DrawMessage("There are no pending actions."); 371 | return; 372 | } 373 | 374 | EditorGUILayout.BeginVertical(); 375 | 376 | List unqueueList = new List(); 377 | 378 | // Draw the actions 379 | foreach (SPAction action in this.m_SPInstance.pendingActions) 380 | { 381 | switch (action.actionType) 382 | { 383 | case SPAction.ActionType.Sprite_Add: 384 | { 385 | GUI.color = SPInstanceEditor.green; 386 | EditorGUILayout.BeginHorizontal(this.boxStyle); 387 | GUI.color = Color.white; 388 | 389 | EditorGUILayout.LabelField("Add Sprite", GUILayout.Width(labelWidth)); 390 | EditorGUILayout.ObjectField(action.resource, action.resource.GetType(), false); 391 | 392 | // Remove action button 393 | if (GUILayout.Button("X", GUILayout.Width(20f))) 394 | { 395 | unqueueList.Add(action); 396 | } 397 | 398 | EditorGUILayout.EndHorizontal(); 399 | break; 400 | } 401 | case SPAction.ActionType.Sprite_Remove: 402 | { 403 | GUI.color = SPInstanceEditor.red; 404 | EditorGUILayout.BeginHorizontal(this.boxStyle); 405 | GUI.color = Color.white; 406 | 407 | EditorGUILayout.LabelField("Remove Sprite", GUILayout.Width(labelWidth)); 408 | EditorGUILayout.ObjectField(action.spriteInfo.targetSprite, typeof(Sprite), false); 409 | 410 | // Remove action button 411 | if (GUILayout.Button("X", GUILayout.Width(20f))) 412 | { 413 | unqueueList.Add(action); 414 | } 415 | 416 | EditorGUILayout.EndHorizontal(); 417 | break; 418 | } 419 | } 420 | } 421 | 422 | // Unqueue actions in the list 423 | foreach (SPAction a in unqueueList) 424 | { 425 | this.m_SPInstance.UnqueueAction(a); 426 | } 427 | 428 | EditorGUILayout.EndVertical(); 429 | EditorGUILayout.Space(); 430 | } 431 | 432 | private void DropAreaGUI() 433 | { 434 | Event evt = Event.current; 435 | Rect drop_area = GUILayoutUtility.GetRect(0.0f, 50.0f, GUILayout.ExpandWidth(true)); 436 | this.boxStyle.alignment = TextAnchor.MiddleCenter; 437 | GUI.color = SPInstanceEditor.green; 438 | GUI.Box(drop_area, "Add Sprite (Drop Here)", this.boxStyle); 439 | GUI.color = Color.white; 440 | 441 | switch (evt.type) 442 | { 443 | case EventType.DragUpdated: 444 | case EventType.DragPerform: 445 | { 446 | if (!drop_area.Contains(evt.mousePosition)) 447 | return; 448 | 449 | DragAndDrop.visualMode = DragAndDropVisualMode.Copy; 450 | 451 | if (evt.type == EventType.DragPerform) 452 | { 453 | DragAndDrop.AcceptDrag(); 454 | 455 | Object[] filtered = SPTools.FilterResourcesForAtlasImport(DragAndDrop.objectReferences); 456 | 457 | // Disallow miltiple sprites of the same source, if set so 458 | if (!SPTools.GetEditorPrefBool(SPTools.Settings_AllowMuliSpritesOneSource)) 459 | { 460 | // Additional filtering specific to the instance 461 | for (int i = 0; i < filtered.Length; i++) 462 | { 463 | if (this.m_SPInstance.sprites.Find(s => s.source == filtered[i]) != null) 464 | { 465 | Debug.LogWarning("A sprite with source \"" + SimpleSpritePackerEditor.SPTools.GetAssetPath(filtered[i]) + "\" already exists in the atlas, consider changing the Sprite Packer settings to allow multiple sprites from the same source."); 466 | System.Array.Clear(filtered, i, 1); 467 | } 468 | } 469 | } 470 | 471 | // Types are handled internally 472 | this.m_SPInstance.QueueAction_AddSprites(filtered); 473 | } 474 | break; 475 | } 476 | } 477 | } 478 | 479 | private void DrawMessage(string message) 480 | { 481 | Rect rect = GUILayoutUtility.GetRect(0.0f, 25.0f, GUILayout.ExpandWidth(true)); 482 | this.boxStyle.alignment = TextAnchor.MiddleCenter; 483 | GUI.Box(rect, message, this.boxStyle); 484 | } 485 | 486 | private bool IsSelected(int id) 487 | { 488 | return (this.m_SelectedSpriteInstanceID == id); 489 | } 490 | 491 | private void SetSelected(int id) 492 | { 493 | this.m_SelectedSpriteInstanceID = id; 494 | base.Repaint(); 495 | } 496 | 497 | private static string GetSavePath() 498 | { 499 | string path = "Assets"; 500 | Object obj = Selection.activeObject; 501 | 502 | if (obj != null) 503 | { 504 | path = AssetDatabase.GetAssetPath(obj.GetInstanceID()); 505 | 506 | if (path.Length > 0) 507 | { 508 | if (!System.IO.Directory.Exists(path)) 509 | { 510 | string[] pathParts = path.Split("/"[0]); 511 | pathParts[pathParts.Length - 1] = ""; 512 | path = string.Join("/", pathParts); 513 | } 514 | } 515 | } 516 | 517 | return EditorUtility.SaveFilePanelInProject("Sprite Packer", "Sprite Packer", "asset", "Create a new sprite packer instance.", path); 518 | } 519 | 520 | [MenuItem("Assets/Create/Sprite Packer")] 521 | public static void CreateInstance() 522 | { 523 | string assetPath = GetSavePath(); 524 | 525 | if (string.IsNullOrEmpty(assetPath)) 526 | return; 527 | 528 | // Create the sprite packer instance 529 | SPInstance asset = ScriptableObject.CreateInstance("SPInstance") as SPInstance; 530 | AssetDatabase.CreateAsset(asset, AssetDatabase.GenerateUniqueAssetPath(assetPath)); 531 | AssetDatabase.Refresh(); 532 | 533 | // Save the instance id in the editor prefs 534 | EditorPrefs.SetInt(SPTools.Settings_SavedInstanceIDKey, asset.GetInstanceID()); 535 | 536 | // Repaint the SPDropWindow 537 | EditorWindow.GetWindow(typeof(SPDropWindow)).Repaint(); 538 | 539 | // Get a name for the texture 540 | string texturePath = assetPath.Replace(".asset", ".png"); 541 | 542 | // Create blank texture 543 | if (SPTools.CreateBlankTexture(texturePath, true)) 544 | { 545 | // Set the texture reff in the sprite packer instance 546 | asset.texture = AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)) as Texture2D; 547 | } 548 | 549 | // Focus on the new sprite packer 550 | EditorUtility.FocusProjectWindow(); 551 | Selection.activeObject = asset; 552 | } 553 | } 554 | } -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPInstanceEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 91274e902efcc1d49a437799c96a9f63 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPReferenceReplacerWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using UnityEditor.SceneManagement; 4 | using System.Collections; 5 | using SimpleSpritePacker; 6 | 7 | namespace SimpleSpritePackerEditor 8 | { 9 | public class SPReferenceReplacerWindow : EditorWindow 10 | { 11 | public enum ReplaceMode : int 12 | { 13 | SourceWithAtlas, 14 | AtlasWithSource 15 | } 16 | 17 | public enum TargetMode : int 18 | { 19 | CurrentScene = 0, 20 | ProjectOnly = 1, 21 | CurrentSceneAndProject = 2, 22 | AllScenes = 3, 23 | AllScenesAndProject = 4, 24 | } 25 | 26 | private SPInstance m_Instance; 27 | private TargetMode m_TargetMode = TargetMode.AllScenesAndProject; 28 | private ReplaceMode m_ReplaceMode = ReplaceMode.SourceWithAtlas; 29 | 30 | private static RectOffset padding = new RectOffset(10, 10, 10, 10); 31 | public static string PrefsKey_TargetMode = "SPRefReplacer_TargetMode"; 32 | public static string PrefsKey_SpriteRenderersOnly = "SPRefReplacer_SpriteRenderersOnly"; 33 | 34 | [MenuItem ("Window/Simple Sprite Packer/Reference Replacer Tool")] 35 | public static void ShowWindow() 36 | { 37 | EditorWindow.GetWindow(typeof(SPReferenceReplacerWindow)); 38 | } 39 | 40 | protected void OnEnable() 41 | { 42 | this.titleContent = new GUIContent("SP Reference Replacer"); 43 | 44 | if (EditorPrefs.HasKey(SPTools.Settings_SavedInstanceIDKey)) 45 | { 46 | string instancePath = AssetDatabase.GetAssetPath(EditorPrefs.GetInt(SPTools.Settings_SavedInstanceIDKey, 0)); 47 | 48 | if (!string.IsNullOrEmpty(instancePath)) 49 | { 50 | this.m_Instance = AssetDatabase.LoadAssetAtPath(instancePath, typeof(SPInstance)) as SPInstance; 51 | } 52 | } 53 | 54 | // Default prefs 55 | if (!EditorPrefs.HasKey(SPReferenceReplacerWindow.PrefsKey_TargetMode)) 56 | { 57 | EditorPrefs.SetInt(SPReferenceReplacerWindow.PrefsKey_TargetMode, (int)this.m_TargetMode); 58 | } 59 | 60 | // Load target mode setting 61 | this.m_TargetMode = (TargetMode)EditorPrefs.GetInt(SPReferenceReplacerWindow.PrefsKey_TargetMode); 62 | } 63 | 64 | protected void OnGUI() 65 | { 66 | EditorGUIUtility.labelWidth = 100f; 67 | 68 | GUILayout.BeginVertical(); 69 | GUILayout.Space((float)SPReferenceReplacerWindow.padding.top); 70 | GUILayout.BeginHorizontal(); 71 | GUILayout.Space((float)SPReferenceReplacerWindow.padding.left); 72 | GUILayout.BeginVertical(); 73 | 74 | GUI.changed = false; 75 | this.m_Instance = EditorGUILayout.ObjectField("Sprite Packer", this.m_Instance, typeof(SPInstance), false) as SPInstance; 76 | if (GUI.changed) 77 | { 78 | // Save the instance id 79 | EditorPrefs.SetInt(SPTools.Settings_SavedInstanceIDKey, (this.m_Instance == null) ? 0 : this.m_Instance.GetInstanceID()); 80 | } 81 | 82 | GUILayout.Space(6f); 83 | 84 | GUILayout.BeginVertical(GUI.skin.box); 85 | GUILayout.Space(6f); 86 | 87 | GUILayout.BeginHorizontal(); 88 | GUILayout.Space(6f); 89 | 90 | EditorGUILayout.LabelField("Replace mode", GUILayout.Width(130f)); 91 | this.m_ReplaceMode = (ReplaceMode)EditorGUILayout.EnumPopup(this.m_ReplaceMode); 92 | 93 | GUILayout.Space(6f); 94 | GUILayout.EndHorizontal(); 95 | 96 | GUILayout.BeginHorizontal(); 97 | GUILayout.Space(6f); 98 | 99 | EditorGUI.BeginChangeCheck(); 100 | EditorGUILayout.LabelField("Replace references in", GUILayout.Width(130f)); 101 | this.m_TargetMode = (TargetMode)EditorGUILayout.EnumPopup(this.m_TargetMode); 102 | if (EditorGUI.EndChangeCheck()) 103 | { 104 | EditorPrefs.SetInt(SPReferenceReplacerWindow.PrefsKey_TargetMode, (int)this.m_TargetMode); 105 | } 106 | 107 | GUILayout.Space(6f); 108 | GUILayout.EndHorizontal(); 109 | 110 | GUILayout.BeginHorizontal(); 111 | GUILayout.Space(6f); 112 | GUI.changed = false; 113 | bool spriteRenderersOnly = GUILayout.Toggle(EditorPrefs.GetBool(SPReferenceReplacerWindow.PrefsKey_SpriteRenderersOnly), " Replace references in Sprite Renderers only ?"); 114 | if (GUI.changed) 115 | { 116 | EditorPrefs.SetBool(SPReferenceReplacerWindow.PrefsKey_SpriteRenderersOnly, spriteRenderersOnly); 117 | } 118 | GUILayout.Space(6f); 119 | GUILayout.EndHorizontal(); 120 | 121 | GUILayout.Space(6f); 122 | GUILayout.EndVertical(); 123 | 124 | GUILayout.Space(6f); 125 | 126 | if (this.m_Instance == null) 127 | { 128 | EditorGUILayout.HelpBox("Please set the sprite packer instance reference in order to use this feature.", MessageType.Info); 129 | } 130 | else 131 | { 132 | if (GUILayout.Button("Replace")) 133 | { 134 | int replacedCount = 0; 135 | 136 | switch (this.m_TargetMode) 137 | { 138 | case TargetMode.CurrentScene: 139 | { 140 | replacedCount += SPTools.ReplaceReferencesInScene(this.m_Instance.copyOfSprites, this.m_ReplaceMode, spriteRenderersOnly); 141 | break; 142 | } 143 | case TargetMode.ProjectOnly: 144 | { 145 | replacedCount += SPTools.ReplaceReferencesInProject(this.m_Instance.copyOfSprites, this.m_ReplaceMode, spriteRenderersOnly); 146 | break; 147 | } 148 | case TargetMode.CurrentSceneAndProject: 149 | { 150 | replacedCount += SPTools.ReplaceReferencesInProject(this.m_Instance.copyOfSprites, this.m_ReplaceMode, spriteRenderersOnly); 151 | replacedCount += SPTools.ReplaceReferencesInScene(this.m_Instance.copyOfSprites, this.m_ReplaceMode, spriteRenderersOnly); 152 | break; 153 | } 154 | case TargetMode.AllScenes: 155 | { 156 | replacedCount += SPTools.ReplaceReferencesInAllScenes(this.m_Instance.copyOfSprites, this.m_ReplaceMode, spriteRenderersOnly, false); 157 | break; 158 | } 159 | case TargetMode.AllScenesAndProject: 160 | { 161 | replacedCount += SPTools.ReplaceReferencesInProject(this.m_Instance.copyOfSprites, this.m_ReplaceMode, spriteRenderersOnly); 162 | replacedCount += SPTools.ReplaceReferencesInScene(this.m_Instance.copyOfSprites, this.m_ReplaceMode, spriteRenderersOnly); 163 | #if UNITY_5_3_OR_NEWER 164 | EditorSceneManager.SaveOpenScenes(); 165 | #else 166 | EditorApplication.SaveScene(); 167 | #endif 168 | replacedCount += SPTools.ReplaceReferencesInAllScenes(this.m_Instance.copyOfSprites, this.m_ReplaceMode, spriteRenderersOnly, true); 169 | break; 170 | } 171 | } 172 | 173 | EditorUtility.DisplayDialog("Reference Replacer", "Replaced references count: " + replacedCount.ToString(), "Okay"); 174 | } 175 | } 176 | 177 | GUILayout.EndVertical(); 178 | GUILayout.Space((float)SPReferenceReplacerWindow.padding.right); 179 | GUILayout.EndHorizontal(); 180 | GUILayout.Space((float)SPReferenceReplacerWindow.padding.bottom); 181 | GUILayout.EndVertical(); 182 | } 183 | } 184 | } -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPReferenceReplacerWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d027e050df27cbf42b84283c006d7761 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPSettings.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using SimpleSpritePacker; 4 | using System.Collections; 5 | 6 | namespace SimpleSpritePackerEditor 7 | { 8 | public class SPSettings : EditorWindow 9 | { 10 | private static RectOffset padding = new RectOffset(10, 10, 10, 10); 11 | 12 | protected void OnEnable() 13 | { 14 | this.titleContent = new GUIContent("SP Settings"); 15 | } 16 | 17 | protected void OnGUI() 18 | { 19 | GUILayout.BeginVertical(); 20 | GUILayout.Space((float)SPSettings.padding.top); 21 | GUILayout.BeginHorizontal(); 22 | GUILayout.Space((float)SPSettings.padding.left); 23 | GUILayout.BeginVertical(); 24 | 25 | GUILayout.Label("General", EditorStyles.boldLabel); 26 | 27 | GUILayout.BeginVertical(GUI.skin.box); 28 | GUILayout.Space(6f); 29 | 30 | GUILayout.BeginHorizontal(); 31 | GUILayout.Space(6f); 32 | GUI.changed = false; 33 | bool drwe = GUILayout.Toggle(EditorPrefs.GetBool(SPTools.Settings_DisableReadWriteEnabled), " Disable Read/Write Enabled of the source textures after packing ?"); 34 | if (GUI.changed) 35 | { 36 | EditorPrefs.SetBool(SPTools.Settings_DisableReadWriteEnabled, drwe); 37 | } 38 | GUILayout.Space(6f); 39 | GUILayout.EndHorizontal(); 40 | 41 | GUILayout.Space(6f); 42 | 43 | GUILayout.BeginHorizontal(); 44 | GUILayout.Space(6f); 45 | GUI.changed = false; 46 | bool amsos = GUILayout.Toggle(EditorPrefs.GetBool(SPTools.Settings_AllowMuliSpritesOneSource), " Allow multiple sprites from the same source ?"); 47 | if (GUI.changed) 48 | { 49 | EditorPrefs.SetBool(SPTools.Settings_AllowMuliSpritesOneSource, amsos); 50 | } 51 | GUILayout.Space(6f); 52 | GUILayout.EndHorizontal(); 53 | 54 | GUILayout.Space(6f); 55 | GUILayout.EndVertical(); 56 | 57 | GUILayout.Label("Layout", EditorStyles.boldLabel); 58 | 59 | GUILayout.BeginVertical(GUI.skin.box); 60 | GUILayout.Space(6f); 61 | 62 | GUILayout.BeginHorizontal(); 63 | GUILayout.Space(6f); 64 | GUI.changed = false; 65 | bool ust = GUILayout.Toggle(EditorPrefs.GetBool(SPTools.Settings_UseSpriteThumbsKey), " Use sprite thumbs ?"); 66 | if (GUI.changed) 67 | { 68 | EditorPrefs.SetBool(SPTools.Settings_UseSpriteThumbsKey, ust); 69 | this.InvokeRepaint(); 70 | } 71 | GUILayout.Space(6f); 72 | GUILayout.EndHorizontal(); 73 | 74 | GUILayout.Space(6f); 75 | 76 | GUILayout.BeginHorizontal(); 77 | GUILayout.Space(6f); 78 | GUILayout.Label("Thumbs Max Height: " + EditorPrefs.GetFloat(SPTools.Settings_ThumbsHeightKey).ToString(), GUILayout.Width(150f)); 79 | GUI.changed = false; 80 | float th = GUILayout.HorizontalSlider(EditorPrefs.GetFloat(SPTools.Settings_ThumbsHeightKey), 20f, 200f, GUILayout.ExpandWidth(true)); 81 | if (GUI.changed) 82 | { 83 | EditorPrefs.SetFloat(SPTools.Settings_ThumbsHeightKey, Mathf.Round(th)); 84 | this.InvokeRepaint(); 85 | } 86 | GUILayout.Space(6f); 87 | GUILayout.EndHorizontal(); 88 | 89 | GUILayout.Space(6f); 90 | 91 | GUILayout.BeginHorizontal(); 92 | GUILayout.Space(6f); 93 | GUI.changed = false; 94 | bool ssv = GUILayout.Toggle(EditorPrefs.GetBool(SPTools.Settings_UseScrollViewKey), " Use scroll view for sprites ?"); 95 | if (GUI.changed) 96 | { 97 | EditorPrefs.SetBool(SPTools.Settings_UseScrollViewKey, ssv); 98 | this.InvokeRepaint(); 99 | } 100 | GUILayout.Space(6f); 101 | GUILayout.EndHorizontal(); 102 | 103 | GUILayout.Space(6f); 104 | 105 | GUILayout.BeginHorizontal(); 106 | GUILayout.Space(6f); 107 | GUILayout.Label("Scroll View Height: " + EditorPrefs.GetFloat(SPTools.Settings_ScrollViewHeightKey).ToString(), GUILayout.Width(150f)); 108 | GUI.changed = false; 109 | float svs = GUILayout.HorizontalSlider(EditorPrefs.GetFloat(SPTools.Settings_ScrollViewHeightKey), 40f, 500f, GUILayout.ExpandWidth(true)); 110 | if (GUI.changed) 111 | { 112 | EditorPrefs.SetFloat(SPTools.Settings_ScrollViewHeightKey, Mathf.Round(svs)); 113 | this.InvokeRepaint(); 114 | } 115 | GUILayout.Space(6f); 116 | GUILayout.EndHorizontal(); 117 | 118 | GUILayout.Space(6f); 119 | GUILayout.EndVertical(); 120 | 121 | GUILayout.EndVertical(); 122 | GUILayout.Space((float)SPSettings.padding.right); 123 | GUILayout.EndHorizontal(); 124 | GUILayout.Space((float)SPSettings.padding.bottom); 125 | GUILayout.EndVertical(); 126 | } 127 | 128 | private void InvokeRepaint() 129 | { 130 | // Only repaint if the selected object is a sprite packer 131 | if (Selection.activeObject is SPInstance) 132 | { 133 | // Repaint by setting it dirty 134 | EditorUtility.SetDirty(Selection.activeObject); 135 | } 136 | } 137 | 138 | [MenuItem ("Window/Simple Sprite Packer/Settings")] 139 | public static void ShowWindow() 140 | { 141 | EditorWindow.GetWindow(typeof(SPSettings)); 142 | } 143 | } 144 | } -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPSettings.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 834053f710394e84cbbcb230fccf9dd8 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPSpriteImportData.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | namespace SimpleSpritePackerEditor 5 | { 6 | [System.Serializable] 7 | public struct SPSpriteImportData 8 | { 9 | public string name; 10 | public Vector4 border; 11 | public SpriteAlignment alignment; 12 | public Vector2 pivot; 13 | } 14 | } -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPSpriteImportData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e6816e8f3f4d9e84ab772fd204152c95 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Editor/SPTools.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 874e9b467a74f6c46927577d9b98f6f8 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2240ec96a6998374888a4ed0b2a664b7 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Scripts/SPAction.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | namespace SimpleSpritePacker 5 | { 6 | [System.Serializable] 7 | public class SPAction 8 | { 9 | public enum ActionType 10 | { 11 | Sprite_Add, 12 | Sprite_Remove, 13 | } 14 | 15 | public ActionType actionType; 16 | public UnityEngine.Object resource; 17 | public SPSpriteInfo spriteInfo; 18 | } 19 | } -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Scripts/SPAction.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2bb2187fc3c69344c9c77644a2644f12 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Scripts/SPActionType.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace SimpleSpritePacker 4 | { 5 | [System.Serializable] 6 | public enum SPActionType 7 | { 8 | Sprite_Add, 9 | Sprite_Remove, 10 | } 11 | } -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Scripts/SPActionType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 36392a9543a7af94b8c007af11983c88 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Scripts/SPInstance.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | #if UNITY_EDITOR 5 | using UnityEditor; 6 | #endif 7 | 8 | namespace SimpleSpritePacker 9 | { 10 | public class SPInstance : ScriptableObject { 11 | 12 | public enum PackingMethod 13 | { 14 | MaxRects, 15 | Unity 16 | } 17 | 18 | [SerializeField] private Texture2D m_Texture; 19 | [SerializeField] private int m_Padding = 1; 20 | [SerializeField] private int m_MaxSize = 4096; 21 | [SerializeField] private PackingMethod m_PackingMethod = PackingMethod.MaxRects; 22 | [SerializeField] private SpriteAlignment m_DefaultPivot = SpriteAlignment.Center; 23 | [SerializeField] private Vector2 m_DefaultCustomPivot = new Vector2(0.5f, 0.5f); 24 | 25 | [SerializeField] private List m_Sprites = new List(); 26 | [SerializeField] private List m_PendingActions = new List(); 27 | 28 | /// 29 | /// Gets or sets the atlas texture. 30 | /// 31 | /// The texture. 32 | public Texture2D texture 33 | { 34 | get { return this.m_Texture; } 35 | set 36 | { 37 | this.m_Texture = value; 38 | #if UNITY_EDITOR 39 | EditorUtility.SetDirty(this); 40 | #endif 41 | } 42 | } 43 | 44 | /// 45 | /// Gets or sets the packing padding. 46 | /// 47 | /// The padding. 48 | public int padding 49 | { 50 | get { return this.m_Padding; } 51 | set 52 | { 53 | this.m_Padding = value; 54 | #if UNITY_EDITOR 55 | EditorUtility.SetDirty(this); 56 | #endif 57 | } 58 | } 59 | 60 | /// 61 | /// Gets or sets the max packing size. 62 | /// 63 | /// The size of the max. 64 | public int maxSize 65 | { 66 | get { return this.m_MaxSize; } 67 | set 68 | { 69 | this.m_MaxSize = value; 70 | #if UNITY_EDITOR 71 | EditorUtility.SetDirty(this); 72 | #endif 73 | } 74 | } 75 | 76 | /// 77 | /// Gets or sets the packing method. 78 | /// 79 | /// The packing method. 80 | public PackingMethod packingMethod 81 | { 82 | get { return this.m_PackingMethod; } 83 | set 84 | { 85 | this.m_PackingMethod = value; 86 | #if UNITY_EDITOR 87 | EditorUtility.SetDirty(this); 88 | #endif 89 | } 90 | } 91 | 92 | /// 93 | /// Gets or sets the default pivot. 94 | /// 95 | /// The default pivot. 96 | public SpriteAlignment defaultPivot 97 | { 98 | get { return this.m_DefaultPivot; } 99 | set 100 | { 101 | this.m_DefaultPivot = value; 102 | #if UNITY_EDITOR 103 | EditorUtility.SetDirty(this); 104 | #endif 105 | } 106 | } 107 | 108 | /// 109 | /// Gets or sets the default custom pivot. 110 | /// 111 | /// The default custom pivot. 112 | public Vector2 defaultCustomPivot 113 | { 114 | get { return this.m_DefaultCustomPivot; } 115 | set 116 | { 117 | this.m_DefaultCustomPivot = value; 118 | #if UNITY_EDITOR 119 | EditorUtility.SetDirty(this); 120 | #endif 121 | } 122 | } 123 | 124 | /// 125 | /// Gets the list of sprites. 126 | /// 127 | /// The sprites. 128 | public List sprites 129 | { 130 | get { return this.m_Sprites; } 131 | } 132 | 133 | /// 134 | /// Gets a copy of the list of sprites. 135 | /// 136 | /// The copy of sprites. 137 | public List copyOfSprites 138 | { 139 | get 140 | { 141 | List list = new List(); 142 | foreach (SPSpriteInfo i in this.m_Sprites) 143 | list.Add(i); 144 | return list; 145 | } 146 | } 147 | 148 | /// 149 | /// Gets the list of pending actions. 150 | /// 151 | /// The pending actions. 152 | public List pendingActions 153 | { 154 | get { return this.m_PendingActions; } 155 | } 156 | 157 | /// 158 | /// Changes the sprite source. 159 | /// 160 | /// Sprite info. 161 | /// New source. 162 | public void ChangeSpriteSource(SPSpriteInfo spriteInfo, Object newSource) 163 | { 164 | // Validate the new source 165 | if (newSource == null) 166 | { 167 | spriteInfo.source = null; 168 | } 169 | else if (newSource is Texture2D || newSource is Sprite) 170 | { 171 | spriteInfo.source = newSource; 172 | } 173 | 174 | #if UNITY_EDITOR 175 | EditorUtility.SetDirty(this); 176 | #endif 177 | } 178 | 179 | /// 180 | /// Queues add sprite action. 181 | /// 182 | /// Resource. 183 | public void QueueAction_AddSprite(Object resource) 184 | { 185 | if (resource is Texture2D || resource is Sprite) 186 | { 187 | // Check if that sprite is already added to the queue 188 | if (this.m_PendingActions.Find(a => (a.actionType == SPAction.ActionType.Sprite_Add && a.resource == resource)) != null) 189 | return; 190 | 191 | SPAction action = new SPAction(); 192 | action.actionType = SPAction.ActionType.Sprite_Add; 193 | action.resource = resource; 194 | this.m_PendingActions.Add(action); 195 | } 196 | } 197 | 198 | /// 199 | /// Queues add sprites action. 200 | /// 201 | /// Resources. 202 | public void QueueAction_AddSprites(Object[] resources) 203 | { 204 | foreach (Object resource in resources) 205 | { 206 | this.QueueAction_AddSprite(resource); 207 | } 208 | } 209 | 210 | /// 211 | /// Queues remove sprite action. 212 | /// 213 | /// Sprite info. 214 | public void QueueAction_RemoveSprite(SPSpriteInfo spriteInfo) 215 | { 216 | if (spriteInfo == null) 217 | return; 218 | 219 | if (!this.m_Sprites.Contains(spriteInfo)) 220 | return; 221 | 222 | // Check if that sprite is already added to the queue 223 | if (this.m_PendingActions.Find(a => (a.actionType == SPAction.ActionType.Sprite_Remove && a.spriteInfo == spriteInfo)) != null) 224 | return; 225 | 226 | SPAction action = new SPAction(); 227 | action.actionType = SPAction.ActionType.Sprite_Remove; 228 | action.spriteInfo = spriteInfo; 229 | this.m_PendingActions.Add(action); 230 | } 231 | 232 | /// 233 | /// Unqueues action. 234 | /// 235 | /// Action. 236 | public void UnqueueAction(SPAction action) 237 | { 238 | if (this.m_PendingActions.Contains(action)) 239 | this.m_PendingActions.Remove(action); 240 | } 241 | 242 | /// 243 | /// Gets the a list of add sprite actions. 244 | /// 245 | /// The add sprite actions. 246 | protected List GetAddSpriteActions() 247 | { 248 | List actions = new List(); 249 | 250 | foreach (SPAction action in this.m_PendingActions) 251 | { 252 | if (action.actionType == SPAction.ActionType.Sprite_Add) 253 | { 254 | actions.Add(action); 255 | } 256 | } 257 | 258 | return actions; 259 | } 260 | 261 | /// 262 | /// Gets a list of remove sprite actions. 263 | /// 264 | /// The remove sprite actions. 265 | protected List GetRemoveSpriteActions() 266 | { 267 | List actions = new List(); 268 | 269 | foreach (SPAction action in this.m_PendingActions) 270 | { 271 | if (action.actionType == SPAction.ActionType.Sprite_Remove) 272 | { 273 | actions.Add(action); 274 | } 275 | } 276 | 277 | return actions; 278 | } 279 | 280 | /// 281 | /// Clears the current sprites collection data. 282 | /// 283 | public void ClearSprites() 284 | { 285 | this.m_Sprites.Clear(); 286 | } 287 | 288 | /// 289 | /// Adds sprite to the sprite collection. 290 | /// 291 | /// Sprite info. 292 | public void AddSprite(SPSpriteInfo spriteInfo) 293 | { 294 | if (spriteInfo != null) 295 | this.m_Sprites.Add(spriteInfo); 296 | } 297 | 298 | /// 299 | /// Clears the current actions. 300 | /// 301 | public void ClearActions() 302 | { 303 | this.m_PendingActions.Clear(); 304 | } 305 | 306 | /// 307 | /// Gets a sprite list with applied actions. 308 | /// 309 | /// The sprite list with applied actions. 310 | public List GetSpriteListWithAppliedActions() 311 | { 312 | // Create temporary sprite info list 313 | List spriteInfoList = new List(); 314 | 315 | // Add the current sprites 316 | foreach (SPSpriteInfo si in this.m_Sprites) 317 | spriteInfoList.Add(si); 318 | 319 | // Apply the remove actions 320 | foreach (SPAction ra in this.GetRemoveSpriteActions()) 321 | { 322 | if (spriteInfoList.Contains(ra.spriteInfo)) 323 | spriteInfoList.Remove(ra.spriteInfo); 324 | } 325 | 326 | // Apply the add actions 327 | foreach (SPAction asa in this.GetAddSpriteActions()) 328 | { 329 | SPSpriteInfo si = new SPSpriteInfo(); 330 | si.source = asa.resource; 331 | spriteInfoList.Add(si); 332 | } 333 | 334 | // return the list 335 | return spriteInfoList; 336 | } 337 | } 338 | } -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Scripts/SPInstance.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b6c88e76926c9a64b92874e628e03a83 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Scripts/SPSpriteInfo.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System; 3 | 4 | namespace SimpleSpritePacker 5 | { 6 | [System.Serializable] 7 | public class SPSpriteInfo : IComparable 8 | { 9 | /// 10 | /// The source texture or sprite. 11 | /// 12 | public UnityEngine.Object source; 13 | 14 | /// 15 | /// The target sprite (the one in the atlas). 16 | /// 17 | public Sprite targetSprite; 18 | 19 | /// 20 | /// Gets the name of the sprite. 21 | /// 22 | /// The name. 23 | public string name 24 | { 25 | get 26 | { 27 | if (this.targetSprite != null) 28 | { 29 | return this.targetSprite.name; 30 | } 31 | else if (this.source != null) 32 | { 33 | return this.source.name; 34 | } 35 | 36 | // Default 37 | return string.Empty; 38 | } 39 | } 40 | 41 | /// 42 | /// Gets the sprite size used for comparison. 43 | /// 44 | /// The size for comparison. 45 | public Vector2 sizeForComparison 46 | { 47 | get 48 | { 49 | if (this.source != null) 50 | { 51 | if (this.source is Texture2D) 52 | { 53 | return new Vector2((this.source as Texture2D).width, (this.source as Texture2D).height); 54 | } 55 | else if (this.source is Sprite) 56 | { 57 | return (this.source as Sprite).rect.size; 58 | } 59 | } 60 | else if (this.targetSprite != null) 61 | { 62 | return this.targetSprite.rect.size; 63 | } 64 | 65 | // Default 66 | return Vector2.zero; 67 | } 68 | } 69 | 70 | public int CompareTo(SPSpriteInfo other) 71 | { 72 | return this.name.CompareTo(other.name); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Scripts/SPSpriteInfo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 57359e436a2768c498d5a65bb44f73e9 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Scripts/UITexturePacker.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Based on the Public Domain MaxRectsBinPack.cpp source by Jukka Jylänki 3 | https://github.com/juj/RectangleBinPack/ 4 | 5 | Ported to C# by Sven Magnus 6 | This version is also public domain - do whatever you want with it. 7 | */ 8 | using UnityEngine; 9 | using System.Collections; 10 | using System.Collections.Generic; 11 | 12 | public class UITexturePacker 13 | { 14 | public int binWidth = 0; 15 | public int binHeight = 0; 16 | public bool allowRotations; 17 | 18 | public List usedRectangles = new List(); 19 | public List freeRectangles = new List(); 20 | 21 | public enum FreeRectChoiceHeuristic 22 | { 23 | RectBestShortSideFit, //< -BSSF: Positions the rectangle against the short side of a free rectangle into which it fits the best. 24 | RectBestLongSideFit, //< -BLSF: Positions the rectangle against the long side of a free rectangle into which it fits the best. 25 | RectBestAreaFit, //< -BAF: Positions the rectangle into the smallest free rect into which it fits. 26 | RectBottomLeftRule, //< -BL: Does the Tetris placement. 27 | RectContactPointRule //< -CP: Choosest the placement where the rectangle touches other rects as much as possible. 28 | }; 29 | 30 | public UITexturePacker (int width, int height, bool rotations) 31 | { 32 | Init(width, height, rotations); 33 | } 34 | 35 | public void Init (int width, int height, bool rotations) 36 | { 37 | binWidth = width; 38 | binHeight = height; 39 | allowRotations = rotations; 40 | 41 | Rect n = new Rect(); 42 | n.x = 0; 43 | n.y = 0; 44 | n.width = width; 45 | n.height = height; 46 | 47 | usedRectangles.Clear(); 48 | 49 | freeRectangles.Clear(); 50 | freeRectangles.Add(n); 51 | } 52 | 53 | private struct Storage 54 | { 55 | public Rect rect; 56 | public bool paddingX; 57 | public bool paddingY; 58 | } 59 | 60 | public static Rect[] PackTextures (Texture2D texture, Texture2D[] textures, int padding, int maxSize) 61 | { 62 | int area = 0; 63 | for ( int i = 0; i < textures.Length; i++ ) 64 | { 65 | if (textures[i] != null) 66 | area += (textures[i].width * textures[i].height); 67 | } 68 | int startW = 4; 69 | int startH = 4; 70 | while ( startW * startH < area ) 71 | { 72 | if ( startW <= startH ) startW *= 2; 73 | else startH *= 2; 74 | } 75 | if ( startW > maxSize || startH > maxSize ) return null; 76 | 77 | return PackTextures( texture, textures, startW, startH, padding, maxSize ); 78 | } 79 | 80 | public static Rect[] PackTextures (Texture2D texture, Texture2D[] textures, int width, int height, int padding, int maxSize) 81 | { 82 | if (width > maxSize && height > maxSize) 83 | return null; 84 | 85 | if (width > maxSize || height > maxSize) 86 | { 87 | int temp = width; 88 | width = height; 89 | height = temp; 90 | } 91 | 92 | UITexturePacker bp = new UITexturePacker(width, height, false); 93 | Storage[] storage = new Storage[textures.Length]; 94 | 95 | for (int i = 0; i < textures.Length; i++) 96 | { 97 | Texture2D tex = textures[i]; 98 | if (!tex) continue; 99 | 100 | Rect rect = new Rect(); 101 | 102 | int xPadding = 1; 103 | int yPadding = 1; 104 | 105 | for (xPadding = 1; xPadding >= 0; --xPadding) 106 | { 107 | for (yPadding = 1; yPadding >= 0; --yPadding) 108 | { 109 | rect = bp.Insert(tex.width + (xPadding * padding), tex.height + (yPadding * padding), 110 | UITexturePacker.FreeRectChoiceHeuristic.RectBestAreaFit); 111 | if (rect.width != 0 && rect.height != 0) break; 112 | 113 | // After having no padding if it still doesn't fit -- increase texture size. 114 | else if (xPadding == 0 && yPadding == 0) 115 | { 116 | return PackTextures(texture, textures, width * (width <= height ? 2 : 1), 117 | height * (height < width ? 2 : 1), padding, maxSize); 118 | } 119 | } 120 | if (rect.width != 0 && rect.height != 0) break; 121 | } 122 | 123 | storage[i] = new Storage(); 124 | storage[i].rect = rect; 125 | storage[i].paddingX = (xPadding != 0); 126 | storage[i].paddingY = (yPadding != 0); 127 | } 128 | 129 | texture.Resize(width, height); 130 | texture.SetPixels(new Color[width * height]); 131 | 132 | // The returned rects 133 | Rect[] rects = new Rect[textures.Length]; 134 | 135 | for (int i = 0; i < textures.Length; i++) 136 | { 137 | Texture2D tex = textures[i]; 138 | if (!tex) continue; 139 | 140 | Rect rect = storage[i].rect; 141 | int xPadding = (storage[i].paddingX ? padding : 0); 142 | int yPadding = (storage[i].paddingY ? padding : 0); 143 | Color[] colors = tex.GetPixels(); 144 | 145 | // Would be used to rotate the texture if need be. 146 | if (rect.width != tex.width + xPadding) 147 | { 148 | Color[] newColors = tex.GetPixels(); 149 | 150 | for (int x = 0; x < rect.width; x++) 151 | { 152 | for (int y = 0; y < rect.height; y++) 153 | { 154 | int prevIndex = ((int)rect.height - (y + 1)) + x * (int)tex.width; 155 | newColors[x + y * (int)rect.width] = colors[prevIndex]; 156 | } 157 | } 158 | 159 | colors = newColors; 160 | } 161 | 162 | texture.SetPixels((int)rect.x, (int)rect.y, (int)rect.width - xPadding, (int)rect.height - yPadding, colors); 163 | rect.x /= width; 164 | rect.y /= height; 165 | rect.width = (rect.width - xPadding) / width; 166 | rect.height = (rect.height - yPadding) / height; 167 | rects[i] = rect; 168 | } 169 | texture.Apply(); 170 | 171 | return rects; 172 | } 173 | 174 | public Rect Insert (int width, int height, FreeRectChoiceHeuristic method) 175 | { 176 | Rect newNode = new Rect(); 177 | int score1 = 0; // Unused in this function. We don't need to know the score after finding the position. 178 | int score2 = 0; 179 | switch (method) 180 | { 181 | case FreeRectChoiceHeuristic.RectBestShortSideFit: newNode = FindPositionForNewNodeBestShortSideFit(width, height, ref score1, ref score2); break; 182 | case FreeRectChoiceHeuristic.RectBottomLeftRule: newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2); break; 183 | case FreeRectChoiceHeuristic.RectContactPointRule: newNode = FindPositionForNewNodeContactPoint(width, height, ref score1); break; 184 | case FreeRectChoiceHeuristic.RectBestLongSideFit: newNode = FindPositionForNewNodeBestLongSideFit(width, height, ref score2, ref score1); break; 185 | case FreeRectChoiceHeuristic.RectBestAreaFit: newNode = FindPositionForNewNodeBestAreaFit(width, height, ref score1, ref score2); break; 186 | } 187 | 188 | if (newNode.height == 0) 189 | return newNode; 190 | 191 | int numRectanglesToProcess = freeRectangles.Count; 192 | for (int i = 0; i < numRectanglesToProcess; ++i) 193 | { 194 | if (SplitFreeNode(freeRectangles[i], ref newNode)) 195 | { 196 | freeRectangles.RemoveAt(i); 197 | --i; 198 | --numRectanglesToProcess; 199 | } 200 | } 201 | 202 | PruneFreeList(); 203 | 204 | usedRectangles.Add(newNode); 205 | return newNode; 206 | } 207 | 208 | public void Insert (List rects, List dst, FreeRectChoiceHeuristic method) 209 | { 210 | dst.Clear(); 211 | 212 | while (rects.Count > 0) 213 | { 214 | int bestScore1 = int.MaxValue; 215 | int bestScore2 = int.MaxValue; 216 | int bestRectIndex = -1; 217 | Rect bestNode = new Rect(); 218 | 219 | for (int i = 0; i < rects.Count; ++i) 220 | { 221 | int score1 = 0; 222 | int score2 = 0; 223 | Rect newNode = ScoreRect((int)rects[i].width, (int)rects[i].height, method, ref score1, ref score2); 224 | 225 | if (score1 < bestScore1 || (score1 == bestScore1 && score2 < bestScore2)) 226 | { 227 | bestScore1 = score1; 228 | bestScore2 = score2; 229 | bestNode = newNode; 230 | bestRectIndex = i; 231 | } 232 | } 233 | 234 | if (bestRectIndex == -1) 235 | return; 236 | 237 | PlaceRect(bestNode); 238 | rects.RemoveAt(bestRectIndex); 239 | } 240 | } 241 | 242 | void PlaceRect (Rect node) 243 | { 244 | int numRectanglesToProcess = freeRectangles.Count; 245 | for (int i = 0; i < numRectanglesToProcess; ++i) 246 | { 247 | if (SplitFreeNode(freeRectangles[i], ref node)) 248 | { 249 | freeRectangles.RemoveAt(i); 250 | --i; 251 | --numRectanglesToProcess; 252 | } 253 | } 254 | 255 | PruneFreeList(); 256 | 257 | usedRectangles.Add(node); 258 | } 259 | 260 | Rect ScoreRect (int width, int height, FreeRectChoiceHeuristic method, ref int score1, ref int score2) 261 | { 262 | Rect newNode = new Rect(); 263 | score1 = int.MaxValue; 264 | score2 = int.MaxValue; 265 | switch (method) 266 | { 267 | case FreeRectChoiceHeuristic.RectBestShortSideFit: newNode = FindPositionForNewNodeBestShortSideFit(width, height, ref score1, ref score2); break; 268 | case FreeRectChoiceHeuristic.RectBottomLeftRule: newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2); break; 269 | case FreeRectChoiceHeuristic.RectContactPointRule: newNode = FindPositionForNewNodeContactPoint(width, height, ref score1); 270 | score1 = -score1; // Reverse since we are minimizing, but for contact point score bigger is better. 271 | break; 272 | case FreeRectChoiceHeuristic.RectBestLongSideFit: newNode = FindPositionForNewNodeBestLongSideFit(width, height, ref score2, ref score1); break; 273 | case FreeRectChoiceHeuristic.RectBestAreaFit: newNode = FindPositionForNewNodeBestAreaFit(width, height, ref score1, ref score2); break; 274 | } 275 | 276 | // Cannot fit the current rectangle. 277 | if (newNode.height == 0) 278 | { 279 | score1 = int.MaxValue; 280 | score2 = int.MaxValue; 281 | } 282 | 283 | return newNode; 284 | } 285 | 286 | /// Computes the ratio of used surface area. 287 | public float Occupancy () 288 | { 289 | ulong usedSurfaceArea = 0; 290 | for (int i = 0; i < usedRectangles.Count; ++i) 291 | usedSurfaceArea += (uint)usedRectangles[i].width * (uint)usedRectangles[i].height; 292 | 293 | return (float)usedSurfaceArea / (binWidth * binHeight); 294 | } 295 | 296 | Rect FindPositionForNewNodeBottomLeft (int width, int height, ref int bestY, ref int bestX) 297 | { 298 | Rect bestNode = new Rect(); 299 | //memset(bestNode, 0, sizeof(Rect)); 300 | 301 | bestY = int.MaxValue; 302 | 303 | for (int i = 0; i < freeRectangles.Count; ++i) 304 | { 305 | // Try to place the rectangle in upright (non-flipped) orientation. 306 | if (freeRectangles[i].width >= width && freeRectangles[i].height >= height) 307 | { 308 | int topSideY = (int)freeRectangles[i].y + height; 309 | if (topSideY < bestY || (topSideY == bestY && freeRectangles[i].x < bestX)) 310 | { 311 | bestNode.x = freeRectangles[i].x; 312 | bestNode.y = freeRectangles[i].y; 313 | bestNode.width = width; 314 | bestNode.height = height; 315 | bestY = topSideY; 316 | bestX = (int)freeRectangles[i].x; 317 | } 318 | } 319 | if (allowRotations && freeRectangles[i].width >= height && freeRectangles[i].height >= width) 320 | { 321 | int topSideY = (int)freeRectangles[i].y + width; 322 | if (topSideY < bestY || (topSideY == bestY && freeRectangles[i].x < bestX)) 323 | { 324 | bestNode.x = freeRectangles[i].x; 325 | bestNode.y = freeRectangles[i].y; 326 | bestNode.width = height; 327 | bestNode.height = width; 328 | bestY = topSideY; 329 | bestX = (int)freeRectangles[i].x; 330 | } 331 | } 332 | } 333 | return bestNode; 334 | } 335 | 336 | Rect FindPositionForNewNodeBestShortSideFit (int width, int height, ref int bestShortSideFit, ref int bestLongSideFit) 337 | { 338 | Rect bestNode = new Rect(); 339 | //memset(&bestNode, 0, sizeof(Rect)); 340 | 341 | bestShortSideFit = int.MaxValue; 342 | 343 | for (int i = 0; i < freeRectangles.Count; ++i) 344 | { 345 | // Try to place the rectangle in upright (non-flipped) orientation. 346 | if (freeRectangles[i].width >= width && freeRectangles[i].height >= height) 347 | { 348 | int leftoverHoriz = Mathf.Abs((int)freeRectangles[i].width - width); 349 | int leftoverVert = Mathf.Abs((int)freeRectangles[i].height - height); 350 | int shortSideFit = Mathf.Min(leftoverHoriz, leftoverVert); 351 | int longSideFit = Mathf.Max(leftoverHoriz, leftoverVert); 352 | 353 | if (shortSideFit < bestShortSideFit || (shortSideFit == bestShortSideFit && longSideFit < bestLongSideFit)) 354 | { 355 | bestNode.x = freeRectangles[i].x; 356 | bestNode.y = freeRectangles[i].y; 357 | bestNode.width = width; 358 | bestNode.height = height; 359 | bestShortSideFit = shortSideFit; 360 | bestLongSideFit = longSideFit; 361 | } 362 | } 363 | 364 | if (allowRotations && freeRectangles[i].width >= height && freeRectangles[i].height >= width) 365 | { 366 | int flippedLeftoverHoriz = Mathf.Abs((int)freeRectangles[i].width - height); 367 | int flippedLeftoverVert = Mathf.Abs((int)freeRectangles[i].height - width); 368 | int flippedShortSideFit = Mathf.Min(flippedLeftoverHoriz, flippedLeftoverVert); 369 | int flippedLongSideFit = Mathf.Max(flippedLeftoverHoriz, flippedLeftoverVert); 370 | 371 | if (flippedShortSideFit < bestShortSideFit || (flippedShortSideFit == bestShortSideFit && flippedLongSideFit < bestLongSideFit)) 372 | { 373 | bestNode.x = freeRectangles[i].x; 374 | bestNode.y = freeRectangles[i].y; 375 | bestNode.width = height; 376 | bestNode.height = width; 377 | bestShortSideFit = flippedShortSideFit; 378 | bestLongSideFit = flippedLongSideFit; 379 | } 380 | } 381 | } 382 | return bestNode; 383 | } 384 | 385 | Rect FindPositionForNewNodeBestLongSideFit (int width, int height, ref int bestShortSideFit, ref int bestLongSideFit) 386 | { 387 | Rect bestNode = new Rect(); 388 | //memset(&bestNode, 0, sizeof(Rect)); 389 | 390 | bestLongSideFit = int.MaxValue; 391 | 392 | for (int i = 0; i < freeRectangles.Count; ++i) 393 | { 394 | // Try to place the rectangle in upright (non-flipped) orientation. 395 | if (freeRectangles[i].width >= width && freeRectangles[i].height >= height) 396 | { 397 | int leftoverHoriz = Mathf.Abs((int)freeRectangles[i].width - width); 398 | int leftoverVert = Mathf.Abs((int)freeRectangles[i].height - height); 399 | int shortSideFit = Mathf.Min(leftoverHoriz, leftoverVert); 400 | int longSideFit = Mathf.Max(leftoverHoriz, leftoverVert); 401 | 402 | if (longSideFit < bestLongSideFit || (longSideFit == bestLongSideFit && shortSideFit < bestShortSideFit)) 403 | { 404 | bestNode.x = freeRectangles[i].x; 405 | bestNode.y = freeRectangles[i].y; 406 | bestNode.width = width; 407 | bestNode.height = height; 408 | bestShortSideFit = shortSideFit; 409 | bestLongSideFit = longSideFit; 410 | } 411 | } 412 | 413 | if (allowRotations && freeRectangles[i].width >= height && freeRectangles[i].height >= width) 414 | { 415 | int leftoverHoriz = Mathf.Abs((int)freeRectangles[i].width - height); 416 | int leftoverVert = Mathf.Abs((int)freeRectangles[i].height - width); 417 | int shortSideFit = Mathf.Min(leftoverHoriz, leftoverVert); 418 | int longSideFit = Mathf.Max(leftoverHoriz, leftoverVert); 419 | 420 | if (longSideFit < bestLongSideFit || (longSideFit == bestLongSideFit && shortSideFit < bestShortSideFit)) 421 | { 422 | bestNode.x = freeRectangles[i].x; 423 | bestNode.y = freeRectangles[i].y; 424 | bestNode.width = height; 425 | bestNode.height = width; 426 | bestShortSideFit = shortSideFit; 427 | bestLongSideFit = longSideFit; 428 | } 429 | } 430 | } 431 | return bestNode; 432 | } 433 | 434 | Rect FindPositionForNewNodeBestAreaFit (int width, int height, ref int bestAreaFit, ref int bestShortSideFit) 435 | { 436 | Rect bestNode = new Rect(); 437 | //memset(&bestNode, 0, sizeof(Rect)); 438 | 439 | bestAreaFit = int.MaxValue; 440 | 441 | for (int i = 0; i < freeRectangles.Count; ++i) 442 | { 443 | int areaFit = (int)freeRectangles[i].width * (int)freeRectangles[i].height - width * height; 444 | 445 | // Try to place the rectangle in upright (non-flipped) orientation. 446 | if (freeRectangles[i].width >= width && freeRectangles[i].height >= height) 447 | { 448 | int leftoverHoriz = Mathf.Abs((int)freeRectangles[i].width - width); 449 | int leftoverVert = Mathf.Abs((int)freeRectangles[i].height - height); 450 | int shortSideFit = Mathf.Min(leftoverHoriz, leftoverVert); 451 | 452 | if (areaFit < bestAreaFit || (areaFit == bestAreaFit && shortSideFit < bestShortSideFit)) 453 | { 454 | bestNode.x = freeRectangles[i].x; 455 | bestNode.y = freeRectangles[i].y; 456 | bestNode.width = width; 457 | bestNode.height = height; 458 | bestShortSideFit = shortSideFit; 459 | bestAreaFit = areaFit; 460 | } 461 | } 462 | 463 | if (allowRotations && freeRectangles[i].width >= height && freeRectangles[i].height >= width) 464 | { 465 | int leftoverHoriz = Mathf.Abs((int)freeRectangles[i].width - height); 466 | int leftoverVert = Mathf.Abs((int)freeRectangles[i].height - width); 467 | int shortSideFit = Mathf.Min(leftoverHoriz, leftoverVert); 468 | 469 | if (areaFit < bestAreaFit || (areaFit == bestAreaFit && shortSideFit < bestShortSideFit)) 470 | { 471 | bestNode.x = freeRectangles[i].x; 472 | bestNode.y = freeRectangles[i].y; 473 | bestNode.width = height; 474 | bestNode.height = width; 475 | bestShortSideFit = shortSideFit; 476 | bestAreaFit = areaFit; 477 | } 478 | } 479 | } 480 | return bestNode; 481 | } 482 | 483 | /// Returns 0 if the two intervals i1 and i2 are disjoint, or the length of their overlap otherwise. 484 | int CommonIntervalLength (int i1start, int i1end, int i2start, int i2end) 485 | { 486 | if (i1end < i2start || i2end < i1start) 487 | return 0; 488 | return Mathf.Min(i1end, i2end) - Mathf.Max(i1start, i2start); 489 | } 490 | 491 | int ContactPointScoreNode (int x, int y, int width, int height) 492 | { 493 | int score = 0; 494 | 495 | if (x == 0 || x + width == binWidth) 496 | score += height; 497 | if (y == 0 || y + height == binHeight) 498 | score += width; 499 | 500 | for (int i = 0; i < usedRectangles.Count; ++i) 501 | { 502 | if (usedRectangles[i].x == x + width || usedRectangles[i].x + usedRectangles[i].width == x) 503 | score += CommonIntervalLength((int)usedRectangles[i].y, (int)usedRectangles[i].y + (int)usedRectangles[i].height, y, y + height); 504 | if (usedRectangles[i].y == y + height || usedRectangles[i].y + usedRectangles[i].height == y) 505 | score += CommonIntervalLength((int)usedRectangles[i].x, (int)usedRectangles[i].x + (int)usedRectangles[i].width, x, x + width); 506 | } 507 | return score; 508 | } 509 | 510 | Rect FindPositionForNewNodeContactPoint (int width, int height, ref int bestContactScore) 511 | { 512 | Rect bestNode = new Rect(); 513 | //memset(&bestNode, 0, sizeof(Rect)); 514 | 515 | bestContactScore = -1; 516 | 517 | for (int i = 0; i < freeRectangles.Count; ++i) 518 | { 519 | // Try to place the rectangle in upright (non-flipped) orientation. 520 | if (freeRectangles[i].width >= width && freeRectangles[i].height >= height) 521 | { 522 | int score = ContactPointScoreNode((int)freeRectangles[i].x, (int)freeRectangles[i].y, width, height); 523 | if (score > bestContactScore) 524 | { 525 | bestNode.x = (int)freeRectangles[i].x; 526 | bestNode.y = (int)freeRectangles[i].y; 527 | bestNode.width = width; 528 | bestNode.height = height; 529 | bestContactScore = score; 530 | } 531 | } 532 | if (allowRotations && freeRectangles[i].width >= height && freeRectangles[i].height >= width) 533 | { 534 | int score = ContactPointScoreNode((int)freeRectangles[i].x, (int)freeRectangles[i].y, height, width); 535 | if (score > bestContactScore) 536 | { 537 | bestNode.x = (int)freeRectangles[i].x; 538 | bestNode.y = (int)freeRectangles[i].y; 539 | bestNode.width = height; 540 | bestNode.height = width; 541 | bestContactScore = score; 542 | } 543 | } 544 | } 545 | return bestNode; 546 | } 547 | 548 | bool SplitFreeNode (Rect freeNode, ref Rect usedNode) 549 | { 550 | // Test with SAT if the rectangles even intersect. 551 | if (usedNode.x >= freeNode.x + freeNode.width || usedNode.x + usedNode.width <= freeNode.x || 552 | usedNode.y >= freeNode.y + freeNode.height || usedNode.y + usedNode.height <= freeNode.y) 553 | return false; 554 | 555 | if (usedNode.x < freeNode.x + freeNode.width && usedNode.x + usedNode.width > freeNode.x) 556 | { 557 | // New node at the top side of the used node. 558 | if (usedNode.y > freeNode.y && usedNode.y < freeNode.y + freeNode.height) 559 | { 560 | Rect newNode = freeNode; 561 | newNode.height = usedNode.y - newNode.y; 562 | freeRectangles.Add(newNode); 563 | } 564 | 565 | // New node at the bottom side of the used node. 566 | if (usedNode.y + usedNode.height < freeNode.y + freeNode.height) 567 | { 568 | Rect newNode = freeNode; 569 | newNode.y = usedNode.y + usedNode.height; 570 | newNode.height = freeNode.y + freeNode.height - (usedNode.y + usedNode.height); 571 | freeRectangles.Add(newNode); 572 | } 573 | } 574 | 575 | if (usedNode.y < freeNode.y + freeNode.height && usedNode.y + usedNode.height > freeNode.y) 576 | { 577 | // New node at the left side of the used node. 578 | if (usedNode.x > freeNode.x && usedNode.x < freeNode.x + freeNode.width) 579 | { 580 | Rect newNode = freeNode; 581 | newNode.width = usedNode.x - newNode.x; 582 | freeRectangles.Add(newNode); 583 | } 584 | 585 | // New node at the right side of the used node. 586 | if (usedNode.x + usedNode.width < freeNode.x + freeNode.width) 587 | { 588 | Rect newNode = freeNode; 589 | newNode.x = usedNode.x + usedNode.width; 590 | newNode.width = freeNode.x + freeNode.width - (usedNode.x + usedNode.width); 591 | freeRectangles.Add(newNode); 592 | } 593 | } 594 | 595 | return true; 596 | } 597 | 598 | void PruneFreeList () 599 | { 600 | for (int i = 0; i < freeRectangles.Count; ++i) 601 | for (int j = i + 1; j < freeRectangles.Count; ++j) 602 | { 603 | if (IsContainedIn(freeRectangles[i], freeRectangles[j])) 604 | { 605 | freeRectangles.RemoveAt(i); 606 | --i; 607 | break; 608 | } 609 | if (IsContainedIn(freeRectangles[j], freeRectangles[i])) 610 | { 611 | freeRectangles.RemoveAt(j); 612 | --j; 613 | } 614 | } 615 | } 616 | 617 | bool IsContainedIn (Rect a, Rect b) 618 | { 619 | return a.x >= b.x && a.y >= b.y 620 | && a.x + a.width <= b.x + b.width 621 | && a.y + a.height <= b.y + b.height; 622 | } 623 | } 624 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/Scripts/UITexturePacker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d819fab663aad9540887c6698db7a2e6 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/readme.txt: -------------------------------------------------------------------------------- 1 | Simple Sprite Packer v1.8 by ChoMPI 2 | 3 | How to Use? 4 | - Right click in the Project view the go to Create -> Sprite Packer. 5 | - From there on just drag and drop graphics and hit the Rebuild Atlas button. -------------------------------------------------------------------------------- /Assets/SimpleSpritePacker/Plugins/SimpleSpritePacker/readme.txt.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e9bb9dbef1a6546e293579a2bf077394 3 | timeCreated: 1486820919 4 | licenseType: Free 5 | TextScriptImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6d072f9da4e4d4803a1a4dfd2774eb8a 3 | folderAsset: yes 4 | timeCreated: 1508832321 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Tests/ItemAtlas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/ItemAtlas.asset -------------------------------------------------------------------------------- /Assets/Tests/ItemAtlas.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9f47235c249af4471bbd9dc2fef5f91c 3 | timeCreated: 1508833995 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 11400000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Tests/ItemAtlas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/ItemAtlas.png -------------------------------------------------------------------------------- /Assets/Tests/ItemAtlas.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad5641faf3e554d45a035ca3d78c24c8 3 | timeCreated: 1508869866 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: 7 | 21300000: T_Bracer 8 | 21300002: T_Scroll 9 | 21300004: T_Sword 10 | 21300006: T_Runestone_Blue 11 | serializedVersion: 4 12 | mipmaps: 13 | mipMapMode: 0 14 | enableMipMap: 0 15 | sRGBTexture: 1 16 | linearTexture: 0 17 | fadeOut: 0 18 | borderMipMap: 0 19 | mipMapFadeDistanceStart: 1 20 | mipMapFadeDistanceEnd: 3 21 | bumpmap: 22 | convertToNormalMap: 0 23 | externalNormalMap: 0 24 | heightScale: 0.25 25 | normalMapFilter: 0 26 | isReadable: 1 27 | grayScaleToAlpha: 0 28 | generateCubemap: 6 29 | cubemapConvolution: 0 30 | seamlessCubemap: 0 31 | textureFormat: 1 32 | maxTextureSize: 2048 33 | textureSettings: 34 | filterMode: 0 35 | aniso: 4 36 | mipBias: -1 37 | wrapMode: 1 38 | nPOTScale: 0 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 2 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 47 | spritePixelsToUnits: 100 48 | alphaUsage: 0 49 | alphaIsTransparency: 1 50 | spriteTessellationDetail: -1 51 | textureType: 8 52 | textureShape: 1 53 | maxTextureSizeSet: 0 54 | compressionQualitySet: 0 55 | textureFormatSet: 0 56 | platformSettings: 57 | - buildTarget: DefaultTexturePlatform 58 | maxTextureSize: 2048 59 | textureFormat: 3 60 | textureCompression: 1 61 | compressionQuality: 50 62 | crunchedCompression: 0 63 | allowsAlphaSplitting: 0 64 | overridden: 1 65 | - buildTarget: Standalone 66 | maxTextureSize: 2048 67 | textureFormat: 5 68 | textureCompression: 1 69 | compressionQuality: 50 70 | crunchedCompression: 0 71 | allowsAlphaSplitting: 0 72 | overridden: 0 73 | - buildTarget: Android 74 | maxTextureSize: 2048 75 | textureFormat: 34 76 | textureCompression: 1 77 | compressionQuality: 50 78 | crunchedCompression: 0 79 | allowsAlphaSplitting: 0 80 | overridden: 1 81 | - buildTarget: iPhone 82 | maxTextureSize: 2048 83 | textureFormat: 32 84 | textureCompression: 1 85 | compressionQuality: 50 86 | crunchedCompression: 0 87 | allowsAlphaSplitting: 0 88 | overridden: 1 89 | spriteSheet: 90 | serializedVersion: 2 91 | sprites: 92 | - serializedVersion: 2 93 | name: T_Bracer 94 | rect: 95 | serializedVersion: 2 96 | x: 0 97 | y: 0 98 | width: 51 99 | height: 51 100 | alignment: 9 101 | pivot: {x: 0.5, y: 0.5} 102 | border: {x: 0, y: 0, z: 0, w: 0} 103 | outline: [] 104 | tessellationDetail: -1 105 | - serializedVersion: 2 106 | name: T_Scroll 107 | rect: 108 | serializedVersion: 2 109 | x: 0 110 | y: 52 111 | width: 51 112 | height: 51 113 | alignment: 9 114 | pivot: {x: 0.5, y: 0.5} 115 | border: {x: 0, y: 0, z: 0, w: 0} 116 | outline: [] 117 | tessellationDetail: -1 118 | - serializedVersion: 2 119 | name: T_Sword 120 | rect: 121 | serializedVersion: 2 122 | x: 52 123 | y: 0 124 | width: 51 125 | height: 51 126 | alignment: 9 127 | pivot: {x: 0.5, y: 0.5} 128 | border: {x: 0, y: 0, z: 0, w: 0} 129 | outline: [] 130 | tessellationDetail: -1 131 | - serializedVersion: 2 132 | name: T_Runestone_Blue 133 | rect: 134 | serializedVersion: 2 135 | x: 52 136 | y: 52 137 | width: 51 138 | height: 51 139 | alignment: 9 140 | pivot: {x: 0.5, y: 0.5} 141 | border: {x: 0, y: 0, z: 0, w: 0} 142 | outline: [] 143 | tessellationDetail: -1 144 | outline: [] 145 | spritePackingTag: 146 | userData: 147 | assetBundleName: 148 | assetBundleVariant: 149 | -------------------------------------------------------------------------------- /Assets/Tests/ItemAtlasUI.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/ItemAtlasUI.mat -------------------------------------------------------------------------------- /Assets/Tests/ItemAtlasUI.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0ad183c761556445a810cd90573bf7d3 3 | timeCreated: 1508834097 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Tests/ItemAtlas_SpriteDefault.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/ItemAtlas_SpriteDefault.mat -------------------------------------------------------------------------------- /Assets/Tests/ItemAtlas_SpriteDefault.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 68df029ebc2254dd18b4b46231c11979 3 | timeCreated: 1511324960 4 | licenseType: Free 5 | NativeFormatImporter: 6 | externalObjects: {} 7 | mainObjectFileID: 2100000 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Assets/Tests/ItemAtlas_UIDefault.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/ItemAtlas_UIDefault.mat -------------------------------------------------------------------------------- /Assets/Tests/ItemAtlas_UIDefault.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 079f27c222ab04da4b0c0ba5994fb674 3 | timeCreated: 1511325788 4 | licenseType: Free 5 | NativeFormatImporter: 6 | externalObjects: {} 7 | mainObjectFileID: 2100000 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Assets/Tests/PackableSprites.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 88309b1b712264e0fbe3668d577db366 3 | folderAsset: yes 4 | timeCreated: 1508833738 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Tests/PackableSprites/T_Bracer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/PackableSprites/T_Bracer.png -------------------------------------------------------------------------------- /Assets/Tests/PackableSprites/T_Bracer.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 89cdaa1fc53fd4bc6907058e72803f4e 3 | timeCreated: 1508837511 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 1 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: 1 34 | nPOTScale: 0 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 1 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 1 46 | spriteTessellationDetail: -1 47 | textureType: 8 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: 4 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 1 61 | - buildTarget: Standalone 62 | maxTextureSize: 2048 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | spriteSheet: 70 | serializedVersion: 2 71 | sprites: [] 72 | outline: [] 73 | spritePackingTag: 74 | userData: 75 | assetBundleName: 76 | assetBundleVariant: 77 | -------------------------------------------------------------------------------- /Assets/Tests/PackableSprites/T_Runestone_Blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/PackableSprites/T_Runestone_Blue.png -------------------------------------------------------------------------------- /Assets/Tests/PackableSprites/T_Runestone_Blue.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bd7795649e7794c718874f81699f0315 3 | timeCreated: 1508837511 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 1 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: 1 34 | nPOTScale: 0 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 1 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 1 46 | spriteTessellationDetail: -1 47 | textureType: 8 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: 4 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 1 61 | - buildTarget: Standalone 62 | maxTextureSize: 2048 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | spriteSheet: 70 | serializedVersion: 2 71 | sprites: [] 72 | outline: [] 73 | spritePackingTag: 74 | userData: 75 | assetBundleName: 76 | assetBundleVariant: 77 | -------------------------------------------------------------------------------- /Assets/Tests/PackableSprites/T_Scroll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/PackableSprites/T_Scroll.png -------------------------------------------------------------------------------- /Assets/Tests/PackableSprites/T_Scroll.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8ca66ce16e42a4c939ec31de63e6274c 3 | timeCreated: 1508837511 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 1 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: 1 34 | nPOTScale: 0 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 1 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 1 46 | spriteTessellationDetail: -1 47 | textureType: 8 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: 4 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 1 61 | - buildTarget: Standalone 62 | maxTextureSize: 2048 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | spriteSheet: 70 | serializedVersion: 2 71 | sprites: [] 72 | outline: [] 73 | spritePackingTag: 74 | userData: 75 | assetBundleName: 76 | assetBundleVariant: 77 | -------------------------------------------------------------------------------- /Assets/Tests/PackableSprites/T_Sword.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/PackableSprites/T_Sword.png -------------------------------------------------------------------------------- /Assets/Tests/PackableSprites/T_Sword.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 13ab6fe15688b498dafe1b275a6318e2 3 | timeCreated: 1508837511 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 1 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: 1 34 | nPOTScale: 0 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 1 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 1 46 | spriteTessellationDetail: -1 47 | textureType: 8 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: 4 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 1 61 | - buildTarget: Standalone 62 | maxTextureSize: 2048 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | spriteSheet: 70 | serializedVersion: 2 71 | sprites: [] 72 | outline: [] 73 | spritePackingTag: 74 | userData: 75 | assetBundleName: 76 | assetBundleVariant: 77 | -------------------------------------------------------------------------------- /Assets/Tests/Test A with alpha.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/Test A with alpha.mat -------------------------------------------------------------------------------- /Assets/Tests/Test A with alpha.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fe3abc4485cb148e7abfed93392a53fd 3 | timeCreated: 1508834178 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Tests/Test A with alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/Test A with alpha.png -------------------------------------------------------------------------------- /Assets/Tests/Test A with alpha.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e2a2c34172afa4986a161c69ef46139e 3 | timeCreated: 1508834214 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 1 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: 1 34 | nPOTScale: 0 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 1 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 0 45 | alphaIsTransparency: 1 46 | spriteTessellationDetail: -1 47 | textureType: 8 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: 3 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 1 61 | - buildTarget: Standalone 62 | maxTextureSize: 2048 63 | textureFormat: 3 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | - buildTarget: Android 70 | maxTextureSize: 2048 71 | textureFormat: 34 72 | textureCompression: 1 73 | compressionQuality: 50 74 | crunchedCompression: 0 75 | allowsAlphaSplitting: 0 76 | overridden: 1 77 | - buildTarget: iPhone 78 | maxTextureSize: 2048 79 | textureFormat: 32 80 | textureCompression: 1 81 | compressionQuality: 50 82 | crunchedCompression: 0 83 | allowsAlphaSplitting: 0 84 | overridden: 1 85 | spriteSheet: 86 | serializedVersion: 2 87 | sprites: [] 88 | outline: [] 89 | spritePackingTag: 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /Assets/Tests/Test B with alpha UI.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/Test B with alpha UI.mat -------------------------------------------------------------------------------- /Assets/Tests/Test B with alpha UI.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 757df61a7133c4d52b0e222730ed9fe1 3 | timeCreated: 1508834178 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 2100000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Tests/Test B with alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/Test B with alpha.png -------------------------------------------------------------------------------- /Assets/Tests/Test B with alpha.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 11f88a5fb431b4eb9beb8d0663887483 3 | timeCreated: 1508837524 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 1 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: 1 34 | nPOTScale: 0 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 1 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 0 45 | alphaIsTransparency: 1 46 | spriteTessellationDetail: -1 47 | textureType: 8 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: 3 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 1 61 | - buildTarget: Standalone 62 | maxTextureSize: 2048 63 | textureFormat: 3 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | - buildTarget: Android 70 | maxTextureSize: 2048 71 | textureFormat: 34 72 | textureCompression: 1 73 | compressionQuality: 50 74 | crunchedCompression: 0 75 | allowsAlphaSplitting: 0 76 | overridden: 1 77 | - buildTarget: iPhone 78 | maxTextureSize: 2048 79 | textureFormat: 32 80 | textureCompression: 1 81 | compressionQuality: 50 82 | crunchedCompression: 0 83 | allowsAlphaSplitting: 0 84 | overridden: 1 85 | spriteSheet: 86 | serializedVersion: 2 87 | sprites: [] 88 | outline: [] 89 | spritePackingTag: 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /Assets/Tests/Test.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/Test.unity -------------------------------------------------------------------------------- /Assets/Tests/Test.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 916cb1f0ab1aa40a8b0fed689a41eff6 3 | timeCreated: 1508832329 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Tests/_alpha.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: faad5fd989443408189d84d73f8b3751 3 | folderAsset: yes 4 | timeCreated: 1508834039 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Tests/_alpha/ItemAtlas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/_alpha/ItemAtlas.png -------------------------------------------------------------------------------- /Assets/Tests/_alpha/ItemAtlas.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 458d3dbefaf564152a555267c3c0359c 3 | timeCreated: 1508869866 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | externalObjects: {} 8 | serializedVersion: 4 9 | mipmaps: 10 | mipMapMode: 0 11 | enableMipMap: 0 12 | sRGBTexture: 1 13 | linearTexture: 0 14 | fadeOut: 0 15 | borderMipMap: 0 16 | mipMapsPreserveCoverage: 0 17 | alphaTestReferenceValue: 0.5 18 | mipMapFadeDistanceStart: 1 19 | mipMapFadeDistanceEnd: 3 20 | bumpmap: 21 | convertToNormalMap: 0 22 | externalNormalMap: 0 23 | heightScale: 0.25 24 | normalMapFilter: 0 25 | isReadable: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -1 37 | wrapU: 1 38 | wrapV: 1 39 | wrapW: 1 40 | nPOTScale: 0 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 1 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 49 | spritePixelsToUnits: 100 50 | alphaUsage: 0 51 | alphaIsTransparency: 1 52 | spriteTessellationDetail: -1 53 | textureType: 8 54 | textureShape: 1 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - buildTarget: DefaultTexturePlatform 60 | maxTextureSize: 2048 61 | resizeAlgorithm: 0 62 | textureFormat: 3 63 | textureCompression: 1 64 | compressionQuality: 50 65 | crunchedCompression: 0 66 | allowsAlphaSplitting: 0 67 | overridden: 1 68 | - buildTarget: Android 69 | maxTextureSize: 2048 70 | resizeAlgorithm: 0 71 | textureFormat: 34 72 | textureCompression: 1 73 | compressionQuality: 50 74 | crunchedCompression: 0 75 | allowsAlphaSplitting: 0 76 | overridden: 1 77 | - buildTarget: iPhone 78 | maxTextureSize: 2048 79 | resizeAlgorithm: 0 80 | textureFormat: 32 81 | textureCompression: 1 82 | compressionQuality: 50 83 | crunchedCompression: 0 84 | allowsAlphaSplitting: 0 85 | overridden: 1 86 | spriteSheet: 87 | serializedVersion: 2 88 | sprites: [] 89 | outline: [] 90 | physicsShape: [] 91 | spritePackingTag: 92 | userData: 93 | assetBundleName: 94 | assetBundleVariant: 95 | -------------------------------------------------------------------------------- /Assets/Tests/_alpha/Test A with alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/_alpha/Test A with alpha.png -------------------------------------------------------------------------------- /Assets/Tests/_alpha/Test A with alpha.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3b57f72fc81ac451f8dea3507d568c54 3 | timeCreated: 1508834210 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | externalObjects: {} 8 | serializedVersion: 4 9 | mipmaps: 10 | mipMapMode: 0 11 | enableMipMap: 0 12 | sRGBTexture: 1 13 | linearTexture: 0 14 | fadeOut: 0 15 | borderMipMap: 0 16 | mipMapsPreserveCoverage: 0 17 | alphaTestReferenceValue: 0.5 18 | mipMapFadeDistanceStart: 1 19 | mipMapFadeDistanceEnd: 3 20 | bumpmap: 21 | convertToNormalMap: 0 22 | externalNormalMap: 0 23 | heightScale: 0.25 24 | normalMapFilter: 0 25 | isReadable: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -1 37 | wrapU: 1 38 | wrapV: 1 39 | wrapW: 1 40 | nPOTScale: 0 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 1 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 49 | spritePixelsToUnits: 100 50 | alphaUsage: 0 51 | alphaIsTransparency: 1 52 | spriteTessellationDetail: -1 53 | textureType: 8 54 | textureShape: 1 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - buildTarget: DefaultTexturePlatform 60 | maxTextureSize: 2048 61 | resizeAlgorithm: 0 62 | textureFormat: 3 63 | textureCompression: 1 64 | compressionQuality: 50 65 | crunchedCompression: 0 66 | allowsAlphaSplitting: 0 67 | overridden: 1 68 | - buildTarget: Android 69 | maxTextureSize: 2048 70 | resizeAlgorithm: 0 71 | textureFormat: 34 72 | textureCompression: 1 73 | compressionQuality: 50 74 | crunchedCompression: 0 75 | allowsAlphaSplitting: 0 76 | overridden: 1 77 | - buildTarget: iPhone 78 | maxTextureSize: 2048 79 | resizeAlgorithm: 0 80 | textureFormat: 32 81 | textureCompression: 1 82 | compressionQuality: 50 83 | crunchedCompression: 0 84 | allowsAlphaSplitting: 0 85 | overridden: 1 86 | spriteSheet: 87 | serializedVersion: 2 88 | sprites: [] 89 | outline: [] 90 | physicsShape: [] 91 | spritePackingTag: 92 | userData: 93 | assetBundleName: 94 | assetBundleVariant: 95 | -------------------------------------------------------------------------------- /Assets/Tests/_alpha/Test B with alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/Assets/Tests/_alpha/Test B with alpha.png -------------------------------------------------------------------------------- /Assets/Tests/_alpha/Test B with alpha.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f1b1a3913635d4e83bc1ae5a565cfab0 3 | timeCreated: 1508834242 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | externalObjects: {} 8 | serializedVersion: 4 9 | mipmaps: 10 | mipMapMode: 0 11 | enableMipMap: 0 12 | sRGBTexture: 1 13 | linearTexture: 0 14 | fadeOut: 0 15 | borderMipMap: 0 16 | mipMapsPreserveCoverage: 0 17 | alphaTestReferenceValue: 0.5 18 | mipMapFadeDistanceStart: 1 19 | mipMapFadeDistanceEnd: 3 20 | bumpmap: 21 | convertToNormalMap: 0 22 | externalNormalMap: 0 23 | heightScale: 0.25 24 | normalMapFilter: 0 25 | isReadable: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -1 37 | wrapU: 1 38 | wrapV: 1 39 | wrapW: 1 40 | nPOTScale: 0 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 1 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 49 | spritePixelsToUnits: 100 50 | alphaUsage: 0 51 | alphaIsTransparency: 1 52 | spriteTessellationDetail: -1 53 | textureType: 8 54 | textureShape: 1 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - buildTarget: DefaultTexturePlatform 60 | maxTextureSize: 2048 61 | resizeAlgorithm: 0 62 | textureFormat: 3 63 | textureCompression: 1 64 | compressionQuality: 50 65 | crunchedCompression: 0 66 | allowsAlphaSplitting: 0 67 | overridden: 1 68 | - buildTarget: Android 69 | maxTextureSize: 2048 70 | resizeAlgorithm: 0 71 | textureFormat: 34 72 | textureCompression: 1 73 | compressionQuality: 50 74 | crunchedCompression: 0 75 | allowsAlphaSplitting: 0 76 | overridden: 1 77 | - buildTarget: iPhone 78 | maxTextureSize: 2048 79 | resizeAlgorithm: 0 80 | textureFormat: 32 81 | textureCompression: 1 82 | compressionQuality: 50 83 | crunchedCompression: 0 84 | allowsAlphaSplitting: 0 85 | overridden: 1 86 | spriteSheet: 87 | serializedVersion: 2 88 | sprites: [] 89 | outline: [] 90 | physicsShape: [] 91 | spritePackingTag: 92 | userData: 93 | assetBundleName: 94 | assetBundleVariant: 95 | -------------------------------------------------------------------------------- /Assets/UBootstrap.SpriteCollection.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6a740803024f40f3936e7c93bd6bd5d 3 | folderAsset: yes 4 | timeCreated: 1508832971 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/UBootstrap.SpriteCollection/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e3150252cdac4b80877f50547706472 3 | folderAsset: yes 4 | timeCreated: 1495791921 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/UBootstrap.SpriteCollection/Plugins/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0ca7fc5aa14b04f658ae910df96fd122 3 | folderAsset: yes 4 | timeCreated: 1495792178 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/UBootstrap.SpriteCollection/Plugins/Editor/SpriteCollectionEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.IO; 4 | 5 | namespace UBootstrap.Editor 6 | { 7 | [CustomEditor (typeof(SpriteCollection))] 8 | public class SpriteCollectionEditor : UnityEditor.Editor 9 | { 10 | private SerializedProperty folderName, texture, sprites; 11 | 12 | protected virtual void OnEnable () 13 | { 14 | folderName = serializedObject.FindProperty ("folderName"); 15 | texture = serializedObject.FindProperty ("texture"); 16 | sprites = serializedObject.FindProperty ("sprites"); 17 | } 18 | 19 | override public void OnInspectorGUI () 20 | { 21 | SpriteCollection component = (SpriteCollection)target; 22 | EditorGUILayout.BeginHorizontal (); 23 | EditorGUILayout.PropertyField (folderName); 24 | 25 | float reloadWidth = GUI.skin.label.CalcSize (new GUIContent ("Reload")).x + 20; 26 | if (GUILayout.Button ("Reload", GUILayout.Width (reloadWidth))) { 27 | // Debug.Log (this.GetType ().Name + "::OnInspectorGUI Load pngs from " + component.folderName); 28 | string[] spritePaths = Directory.GetFiles (Application.dataPath + "/" + component.folderName, "*.png", SearchOption.TopDirectoryOnly); 29 | component.sprites.Clear (); 30 | 31 | string spritePath = string.Empty; 32 | for (int i = 0; i < spritePaths.Length; i++) { 33 | var index = spritePaths [i].IndexOf ("/Assets") + 1; 34 | spritePath = spritePaths [i].Substring (index); 35 | var items = AssetDatabase.LoadAllAssetsAtPath (spritePath); 36 | foreach (var item in items) { 37 | if (item is Sprite) { 38 | component.sprites.Add ((Sprite)item); 39 | } 40 | } 41 | 42 | } 43 | } 44 | 45 | EditorGUILayout.EndHorizontal (); 46 | 47 | EditorGUILayout.BeginHorizontal (); 48 | EditorGUILayout.PropertyField (texture); 49 | if (GUILayout.Button ("Reload", GUILayout.Width (reloadWidth))) { 50 | component.sprites.Clear (); 51 | string spritePath = AssetDatabase.GetAssetPath (component.texture); 52 | var index = spritePath.IndexOf ("/Assets") + 1; 53 | spritePath = spritePath.Substring (index); 54 | var items = AssetDatabase.LoadAllAssetsAtPath (spritePath); 55 | foreach (var item in items) { 56 | if (item is Sprite) { 57 | component.sprites.Add ((Sprite)item); 58 | } 59 | } 60 | 61 | } 62 | EditorGUILayout.EndHorizontal (); 63 | 64 | EditorGUILayout.PropertyField (sprites, true); 65 | serializedObject.ApplyModifiedProperties (); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /Assets/UBootstrap.SpriteCollection/Plugins/Editor/SpriteCollectionEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ae27dfb0d243e4fa7a63373584023d74 3 | timeCreated: 1495793306 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/UBootstrap.SpriteCollection/Plugins/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f94eee0eff3d54e4689e52df365344b6 3 | folderAsset: yes 4 | timeCreated: 1495792175 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/UBootstrap.SpriteCollection/Plugins/Scripts/SpriteCollection.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace UBootstrap 6 | { 7 | public class SpriteCollection : MonoBehaviour 8 | { 9 | public List sprites = new List (); 10 | public string collectionName; 11 | public string folderName; 12 | public Texture2D texture; 13 | 14 | void Awake () 15 | { 16 | } 17 | 18 | void OnDestroy () 19 | { 20 | } 21 | 22 | public Sprite GetSprite (int index) 23 | { 24 | if (index >= 0 && index < sprites.Count) { 25 | return sprites [index]; 26 | } 27 | 28 | return null; 29 | } 30 | 31 | public Sprite GetSprite (string spriteName) 32 | { 33 | foreach (Sprite sprite in sprites) { 34 | if (sprite != null && sprite.name == spriteName) { 35 | return sprite; 36 | } 37 | } 38 | return null; 39 | } 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /Assets/UBootstrap.SpriteCollection/Plugins/Scripts/SpriteCollection.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0dedbb2c4d92042a8bd360c05a36092b 3 | timeCreated: 1495792880 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/UBootstrap.SpriteCollection/Plugins/Scripts/SpriteCollectionManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using USingleton; 5 | 6 | namespace UBootstrap 7 | { 8 | public class SpriteCollectionManager : GameSingleton 9 | { 10 | List AllCollections = new List (); 11 | 12 | public SpriteCollection GetCollection (string collectionName) 13 | { 14 | var collection = AllCollections.Find (c => c.collectionName == collectionName); 15 | 16 | if (collection == null) { 17 | collection = (Resources.Load (collectionName) as GameObject).GetComponent (); 18 | collection.collectionName = collectionName; 19 | AllCollections.Add (collection); 20 | } 21 | 22 | return collection; 23 | } 24 | 25 | /// 26 | /// This remove the collection from our internal List, 27 | /// however, it does not DESTROY the prefab. To really unload the prefab, we have 28 | /// to call Resources.UnloadUnusedAssets. This is a heavy call, so try to call it 29 | /// in appropriate places. 30 | /// 31 | /// Collection name. 32 | public void DestroyCollection (string collectionName) 33 | { 34 | var collection = AllCollections.Find (c => c.collectionName == collectionName); 35 | if (collection != null) { 36 | AllCollections.Remove (collection); 37 | } 38 | } 39 | 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /Assets/UBootstrap.SpriteCollection/Plugins/Scripts/SpriteCollectionManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dad46f1253f3a4fab9b7351530507c11 3 | timeCreated: 1495792560 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/USingleton.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 51b34253f533a4153858ac7ca238816d 3 | folderAsset: yes 4 | timeCreated: 1508832971 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/USingleton/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f57c9c29a26c943829602fa7dcd6de8b 3 | folderAsset: yes 4 | timeCreated: 1494325656 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/USingleton/Plugins/USingleton.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dfa675a745a5e4e8cb3a58b5412c3a38 3 | folderAsset: yes 4 | timeCreated: 1494325662 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/USingleton/Plugins/USingleton/GameSingleton.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Assertions; 3 | 4 | namespace USingleton 5 | { 6 | /// 7 | /// Game singleton will be initialized once in the game. It persists when scenes are loaded and reloaded 8 | /// It is recommended to replaced MonoBehaviour with your BaseBehaviour class 9 | /// 10 | public class GameSingleton : MonoBehaviour where T : GameSingleton 11 | { 12 | private static T instance; 13 | 14 | public static T Instance { 15 | get { 16 | Assert.IsNotNull (instance, "Instance is null. Please call CreateInstance first!"); 17 | return instance; 18 | } 19 | } 20 | 21 | public static T CreateInstance () 22 | { 23 | if (instance != null) { 24 | Assert.IsNull (instance, "Instance is not null. Please call CreateInstance once only"); 25 | return instance; 26 | } 27 | 28 | GameObject go = new GameObject (typeof(T).Name); 29 | instance = go.AddComponent (); 30 | 31 | instance.OnCreated (); 32 | 33 | DontDestroyOnLoad (go); 34 | 35 | return instance; 36 | } 37 | 38 | protected virtual void OnDestroy () 39 | { 40 | instance = null; 41 | } 42 | 43 | protected virtual void OnCreated () 44 | { 45 | } 46 | 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /Assets/USingleton/Plugins/USingleton/GameSingleton.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dc7e94c06970f4333960d67b36e3270c 3 | timeCreated: 1494325768 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/USingleton/Plugins/USingleton/SceneSingleton.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Assertions; 3 | 4 | namespace USingleton 5 | { 6 | /// 7 | /// Scene singleton will be initialized once per scene. It does not persist when scenes are loaded and reloaded 8 | /// It is recommended to replaced MonoBehaviour with your BaseBehaviour class 9 | /// 10 | public class SceneSingleton : MonoBehaviour where T : SceneSingleton 11 | { 12 | private static T instance; 13 | 14 | public static T Instance { 15 | get { 16 | if (instance == null) { 17 | instance = FindObjectOfType (); 18 | 19 | Assert.IsNotNull (instance, "Instance should not be null. You must call this in the correct scene setup"); 20 | } 21 | 22 | return instance; 23 | } 24 | } 25 | 26 | protected virtual void OnDestroy () 27 | { 28 | instance = null; 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /Assets/USingleton/Plugins/USingleton/SceneSingleton.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 907f6ee66f5a14294be1bca5e1bc55d3 3 | timeCreated: 1495595249 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Ha.Minh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/ClusterInputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2017.2.0f3 2 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/ProjectSettings/UnityConnectSettings.asset -------------------------------------------------------------------------------- /imgs/example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/imgs/example1.png -------------------------------------------------------------------------------- /imgs/example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/imgs/example2.png -------------------------------------------------------------------------------- /imgs/example3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/USplitAlpha/57347789370df9cde513463c15c58efa01a30bc1/imgs/example3.png -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var mkdirp = require('mkdirp'); 2 | var path = require('path'); 3 | var ncp = require('ncp'); 4 | 5 | // Don't run this if the original folder where we run `yarn install` is the same as the current folder 6 | var topLvlPackage = path.relative("" + process.env.DIR, __dirname) == "" 7 | if (topLvlPackage) { 8 | return; 9 | } 10 | 11 | var assetDir = 'Assets'; 12 | var project = require('./p.json'); 13 | 14 | for (var i = 0, l = project.assets.length; i < l; i++) { 15 | var file = project.assets[i]; 16 | var src = path.join(__dirname, assetDir, file); 17 | var dir = path.join(__dirname, '..', '..', assetDir, file); 18 | var parentDir = path.dirname(dir); 19 | 20 | // Create folder if missing 21 | mkdirp(parentDir, function(_src, _dir, err) { 22 | if (err) { 23 | console.error(err) 24 | process.exit(1); 25 | } 26 | 27 | // Copy files 28 | ncp(_src, _dir, function(err) { 29 | if (err) { 30 | console.error(err); 31 | process.exit(1); 32 | } 33 | }); 34 | }.bind(this, src, dir)); 35 | } 36 | -------------------------------------------------------------------------------- /p.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets": [ 3 | "Plugins/USplitAlpha" 4 | ] 5 | } 6 | 7 | 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "USplitAlpha", 3 | "version": "0.0.5", 4 | "description": "USplitAlpha is a library that helps you apply Split Alpha texture to both Android and iOS easily", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js", 8 | "Assets" 9 | ], 10 | "scripts": { 11 | "postinstall": "node index.js", 12 | "unity": "rm -fr node_modules && DIR=`pwd` yarn install --flat --prod --verbose" 13 | }, 14 | "dependencies": { 15 | "minimist": "ssh://github.com/substack/minimist.git#0.0.8", 16 | "mkdirp": "ssh://github.com/substack/node-mkdirp.git#0.5.1", 17 | "ncp": "ssh://github.com/AvianFlu/ncp.git#v2.0.0" 18 | }, 19 | "devDependencies": { 20 | "UBootstrap.SpriteCollection": "ssh://github.com/minhhh/UBootstrap.SpriteCollection#v0.0.3", 21 | "SimpleSpritePacker": "ssh://github.com/minhhh/SimpleSpritePacker#v0.0.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # USplitAlpha 2 | 3 | > Split Alpha channel for Android and iOS 4 | 5 | According to a survey ([Unity Texture compression and optimization](http://minhhh.github.io/posts/unity-texture-compression-and-optimization)) about various different texture formats in Unity, `ETC1` and Split Alpha channel provides the best build size and memory footprint. As mentioned [here](https://feedback.unity3d.com/suggestions/pvrtc-rgb-4bit-plus-alpha-split-texture-compression-dot-dot-dot), Unity currently does not support SplitAlpha on iOS and there was a bug that makes it not work on UI in older versions. 6 | 7 | `USplitAlpha` is a library that helps you apply Split Alpha texture to both Android and iOS easily. On Android it uses `ETC1 RGB4bit` both main texture and alpha texture. On iOS is uses `PVRTC RGB4bit`. 8 | 9 | The inspiration for this library is drawn from [https://github.com/keijiro/unity-alphamask](https://github.com/keijiro/unity-alphamask) and [Unity、Mobile端末向けの画一的なテクスチャ圧縮方法](https://web.archive.org/web/20160726041743/http://developers.mobage.jp/blog/texture-compression) 10 | 11 | ## Usage 12 | To apply USplitAlpha into your project, there are 3 main steps: 13 | 14 | 1. Create Split Alpha textures from the original textures 15 | 2. Create materials that uses Split Alpha 16 | 3. Apply materials to `UI Image`, `UI Raw Image` or `Sprite`. 17 | 18 | **Step 1: Create Split Alpha textures from the original textures** 19 | 20 | 1. Preconditions: 21 | * The texture that you wish to create alpha channel for must have width and height being power of two and multiple of 4. Note that the texture does NOT have to be squared. 22 | * The texture must also be `png`. If you have a `psd`, please convert it to `png` first. 23 | * The texture must not be packed by Unity SpritePacker, i.e. no packing tag 24 | 2. In the `Project` view, right-click on the texture. Select `USplitAlpha>Apply`. This will generate an alpha channel texture and put it in a folder called `_alpha` in the same folder as the original texture After that, both the original texture and the alpha texture import settings will be changed to using `ETC1 RGB4bit` and `PVRTC RGB4bit` on Android and iOS, respectively. 25 | 26 | ![example 1](/imgs/example1.png) 27 | 28 | **Step 2: Create Material that uses Split Alpha** 29 | 30 | 1. Create a new material 31 | 2. Set the material's shader to one of the shaders in `Plugins/USplitAlpha/Shaders`. For instance, use `SplitAlpha/Sprites/Default` shader if you want to apply to Sprites. 32 | 3. The material's shader will have 2 texture fields: `Sprite Texture` and `External Alpha` (the names might vary slightly according to shaders). Set the original texture to `Sprite Texture` and the alpha mask texture `External Alpha` 33 | 34 | ![example 2](/imgs/example2.png) 35 | 36 | **Step 3: Apply material to UI Image, UI Raw Image or Sprite** 37 | 38 | 1. Apply the material created in step 2 to the appropriate elements. For `UI Image` and `UI Raw Image`, use `SplitAlpha/UI/Default`. For `Sprites`, use `SplitAlpha/Sprites/Default`. For mobile particles, use `SplitAlpha/Mobile/Particles/Additive` or `SplitAlpha/Mobile/Particles/Multiply` or `SplitAlpha/Mobile/Particles/Alpha Blended` 39 | 2. Set the correct sprite. For `RawImage` you don't have to set anything. For `UI Image` and `Sprite`, you have to choose a sprite inside the original texture. Most of the time, you would want to create the material from an Atlas so that you can batch multiple `UI Image` and `Sprites` to save draw call. 40 | 41 | ![example 3](/imgs/example3.png) 42 | 43 | **Bonus 1: Batch create split alpha texture** 44 | 45 | You can actually select several textures and/or folders then choose `USplitAlpha>Apply`. This will create split alpha textures for all of the `png` files in all subfolders recursively. 46 | 47 | **Bonus 2: Revert split alpha textures** 48 | 49 | You can actually select several textures and/or folders then choose `USplitAlpha>Revert` to revert the textures to their original settings without split alpha. All of the split alpha textures will be removed and folders `_alpha` as well if they are empty. 50 | 51 | **Bonus 3: Create texture Atlas** 52 | 53 | I use the plugin `SimpleSpritePacker` to create texture atlas from NPOT sprites. You can also use other external tools such as TexturePacker to create atlases. 54 | 55 | **Bonus 4: Loading from AssetBundle** 56 | 57 | You can simply put all the textures and materials in AssetBundle and load them from server. Only thing to note is after you load the material, you will have to re-set the shader of the material like so: 58 | 59 | ``` 60 | material.shader = Shader.Find (material.shader.name); 61 | ``` 62 | 63 | **Bonus 5: Loading atlas from AssetBundle** 64 | 65 | You cannot put Atlas packed by Unity's SpritePacker and load it back, that's why we have to use manual Atlas. Then, loading sprites by name from an Atlas loaded from AssetBundle is trivial You can use a solution such as [UBootstrap.SpriteCollection](https://github.com/minhhh/UBootstrap.SpriteCollection) to do it. 66 | 67 | ### Create SplitAlpha Materials 68 | 69 | 1. Select one or more Textures in the **Project** view 70 | 2. Right click and select `USplitAlpha > Create ... Materials` 71 | 3. You can create 3 basic particle materials: Additive, Alpha Blended and Multiply or SpriteDefault, or UIDefault 72 | 73 | ### Examples 74 | You can find all examples in the scene `Assets/Tests/Test` 75 | 76 | 1. `Test A with alpha` uses a material with a single sprite texture 77 | 2. `Test B with alpha UI RawImage` uses a material with a raw texture 78 | 3. `Test B with alpha UI` uses the same material as `Test B with alpha UI RawImage` 79 | 4. `Batchable UI Image 1`, `..2`, etc. uses `ItemAtlasUI` material created from `ItemAtlas`. This allows to use the same material for many UI Images and allow them to batch 80 | 5. `BatchableSprite 1`, `..2`, etc. is similar to `Batchable UI Image 1`, except that the shader is replaced by `SplitAlpha/Sprites/Default` 81 | 82 | ### Support Shaders 83 | Currently, there are 5 Split Alpha shaders corresponding to 5 original shaders: 84 | 85 | 1. `UI/Default`: `SplitAlpha/UI/Default` 86 | 1. `Sprites/Default`: `SplitAlpha/Sprites/Default` 87 | 1. `Mobile/Particles/Additive`: `SplitAlpha/Mobile/Particles/Additive` 88 | 1. `Mobile/Particles/Multiply`: `SplitAlpha/Mobile/Particles/Multiply` 89 | 1. `Mobile/Particles/Alpha Blended`: `SplitAlpha/Mobile/Particles/Alpha Blended` 90 | 91 | The code for the ogiginal shaders was taken from Unity then modified to support Split Alpha. Extending SplitAlpha support to other shaders is straightforward. 92 | 93 | ## Future Improvements 94 | 95 | Obviously, the workflow so far is a little laborious. You have to create split alpha textures by hand, create materials by hand, apply material to UI elements by hand. There are so many improvements that can be made to automate all of these tasks better. In fact, all of these improvements have been implemented and applied to production but I cannot share the code. 96 | 97 | **Improvement 1: Put hard-coded configurable parameters in global settings** 98 | 99 | Currently, the compression quality is hard-coded. We should put all configurable parameters in a single ScriptableObject. 100 | 101 | **Improvement 2: Make it work with Unity SpritePacker** 102 | 103 | This is quite straightforward. When you create split alpha texture, you have to copy all settings from the original texture `TextureImporter`, except for the packing tag. You will add a prefix or suffix to the original packing tag instead. Then you have to change `PackerPolicy` by creating a custom `PackerPolicy`, so that the generated Atlas will use `ETC1 RGB4bit` or `PVRTC RGB4bit` compression. 104 | 105 | **Improvement 3: Automatic material creation** 106 | 107 | This is how you implement: 108 | 109 | 1. Create a lookup table to replace normal shader by a split alpha one. For instance, `UI/Default` will be replaced by `SplitAlpha/UI/Default`, and so on. 110 | 2. Create Helper Component (MonoBehaviour) for different visual elements, such as `UIRawImageSplitAlpha`, `UIImageSplitAlpha`, `SpriteRendererSplitAlpha`, `MeshRendererSplitAlpha` and so on. 111 | 3. Helper Components will operate in 2 modes: Editor mode and Play Mode. 112 | 4. In Editor Mode, Helper Component will create a dummy material, set the correct shader by searching for matching shader in the lookup table in step 1. Then Helper Component will set the original texture and alpha texture correspondingly. Finally, Helper Component will set the dummy material so that the element is displying correctly in Edit Mode. 113 | 5. In Play Mode, Helper Component will create shared static material instead of dummy material. This is done so that multiple component using the same original texture will also share the same Split Alpha material. One thing to note is that sprites that are packed with Unity's SpritePacker using packing tag can also work. 114 | 115 | Now you can simply assign sprites to different visual elements, then set all of those sprites to use the same packing tag and voila, all your visual elements can batch and use Split Alpha. However, this approach can NOT work with AssetBundle. 116 | 117 | **Improvement 4: Add Helper Component to GameObject automatically** 118 | 119 | There is still one manual step that you have to do in **Improvement 1**, that is adding the correct MonoBehaviour to the correct GameObject. We can automate this step like so: 120 | 121 | 1. Create a tool that allows you to select several objects, prefabs, or scenes, recursively. 122 | 2. Make an Apply function that search for certain Components in those GameObjects, Prefabs, or Scenes. The Components can be `UIImage`, `UIRawImage`, `SpriteRenderer`, `MeshRenderer` or other custom renderer. 123 | 3. Add the corresponding `UIImageSplitAlpha`, `UIRawImageSplitAlpha`, `SpriteRendererSplitAlpha`, `MeshRendererSplitAlpha` or other custom components. 124 | 125 | Also add a Revert function to revert the change easily. 126 | 127 | **Improvement 5: Create Split Alpha material automatically** 128 | 129 | Create a tool so that users only have to set the main texture, the alpha texture will be filled in automatically by searching in `_alpha` folder. This is DONE. 130 | 131 | **Improvement 6: Reduce the size of Alpha mask** 132 | 133 | If the alpha mask of a texture is very simple, for instance, it's mostly white pixels or smooth gradation, then it can be downsized to 1/4 or 1/16 of the area of original texture. Then it can be used by expanding it with a bilinear filter. 134 | 135 | 136 | ## Install 137 | 138 | To include USplitAlpha into your project, you can copy `Assets/Plugins/USplitAlpha` to your project folder. Alternatively, you can use `npm` method of package management described [here](https://github.com/minhhh/UBootstrap). 139 | 140 | ## Changelog 141 | 142 | **0.0.5** 143 | 144 | * Add create materials from selected textures 145 | 146 | **0.0.4** 147 | 148 | * Add Apply function for Material 149 | 150 | **0.0.3** 151 | 152 | * Add `SplitAlphaReplacer` for Material 153 | 154 | **0.0.2** 155 | 156 | * Create namespace `USplitAlpha` 157 | * Improve readme 158 | 159 | **0.0.1** 160 | 161 | * Initial commit 162 | 163 |
164 | 165 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "SimpleSpritePacker@ssh://github.com/minhhh/SimpleSpritePacker#v0.0.1": 6 | version "0.0.1" 7 | resolved "ssh://github.com/minhhh/SimpleSpritePacker#a1bb114ccd8685dfa1fb04fb47e1392b5fcbd656" 8 | dependencies: 9 | minimist "ssh://github.com/substack/minimist.git#0.0.8" 10 | mkdirp "ssh://github.com/substack/node-mkdirp.git#0.5.1" 11 | ncp "ssh://github.com/AvianFlu/ncp.git#v2.0.0" 12 | 13 | "UBootstrap.Core@ssh://github.com/minhhh/UBootstrap.Core#v0.0.19": 14 | version "0.0.19" 15 | resolved "ssh://github.com/minhhh/UBootstrap.Core#aa559ab07189d52f10d8efaf9272d6e08e078d69" 16 | dependencies: 17 | minimist "ssh://github.com/substack/minimist.git#0.0.8" 18 | mkdirp "ssh://github.com/substack/node-mkdirp.git#0.5.1" 19 | ncp "ssh://github.com/AvianFlu/ncp.git#v2.0.0" 20 | 21 | "UBootstrap.SpriteCollection@ssh://github.com/minhhh/UBootstrap.SpriteCollection#v0.0.3": 22 | version "0.0.3" 23 | resolved "ssh://github.com/minhhh/UBootstrap.SpriteCollection#c5374a0049ead63edc19716bd3a5b462539f3283" 24 | dependencies: 25 | minimist "ssh://github.com/substack/minimist.git#0.0.8" 26 | mkdirp "ssh://github.com/substack/node-mkdirp.git#0.5.1" 27 | ncp "ssh://github.com/AvianFlu/ncp.git#v2.0.0" 28 | unity-singleton "ssh://github.com/minhhh/unity-singleton#v0.0.2" 29 | 30 | minimist@0.0.8, "minimist@ssh://github.com/substack/minimist.git#0.0.8": 31 | version "0.0.8" 32 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 33 | 34 | "mkdirp@ssh://github.com/substack/node-mkdirp.git#0.5.1": 35 | version "0.5.1" 36 | resolved "ssh://github.com/substack/node-mkdirp.git#d4eff0f06093aed4f387e88e9fc301cb76beedc7" 37 | dependencies: 38 | minimist "0.0.8" 39 | 40 | "ncp@ssh://github.com/AvianFlu/ncp.git#v2.0.0": 41 | version "2.0.0" 42 | resolved "ssh://github.com/AvianFlu/ncp.git#93c7c6c719e2a4944dc09a16178b09aef428cdf0" 43 | 44 | "unity-singleton@ssh://github.com/minhhh/unity-singleton#v0.0.2": 45 | version "0.0.2" 46 | resolved "ssh://github.com/minhhh/unity-singleton#4c9b467dd0cd0aeca45685c35865cd68947b2339" 47 | dependencies: 48 | minimist "ssh://github.com/substack/minimist.git#0.0.8" 49 | mkdirp "ssh://github.com/substack/node-mkdirp.git#0.5.1" 50 | ncp "ssh://github.com/AvianFlu/ncp.git#v2.0.0" 51 | --------------------------------------------------------------------------------