// Organizes all sprites by associating them with the // material they use. Returns an array list of // MaterialSpriteLists: List <MaterialSpriteList> OrganizeByMaterial(List <ISpriteAggregator> sprites) { string errString = ""; // A list of all materials List <Material> materials = new List <Material>(); // The map of materials to sprites List <MaterialSpriteList> map = new List <MaterialSpriteList>(); // The material of the sprite: Material mat; ISpriteAggregator sprite; MaterialSpriteList matSpriteList; int index; for (int i = 0; i < sprites.Count; ++i) { sprite = sprites[i]; mat = sprite.GetPackedMaterial(out errString); if (mat == null) { if (haltOnNullMaterial) { EditorUtility.DisplayDialog("ERROR", errString, "Ok"); Selection.activeGameObject = sprite.gameObject; return(null); } else { Debug.LogError(errorString); continue; } } index = materials.IndexOf(mat); // See if the material is already in our list: if (index >= 0) { matSpriteList = (MaterialSpriteList)map[index]; matSpriteList.sprites.Add(sprite); } else { materials.Add(mat); matSpriteList = new MaterialSpriteList(); matSpriteList.material = mat; matSpriteList.sprites.Add(sprite); map.Add(matSpriteList); } } return(map); }
// Assigns all frame-related information to // the sprites of an atlas: void SetFrameInfo(MaterialSpriteList msMap, AtlasTextureList texList) { SPRITE_FRAME frameInfo; ISpriteAggregator spAg; AutoSpriteBase spr; int index; for (int i = 0; i < msMap.sprites.Count; ++i) { spAg = (ISpriteAggregator)msMap.sprites[i]; // Assign each frame its UVs: for (int j = 0; j < spAg.SpriteFrames.Length; ++j) { // Validate that a texture has been selected: if (spAg.SourceTextures[j] == null) { // Set the frame size to zero to flag it // as a "null" frame: spAg.SpriteFrames[j].uvs = new Rect(0, 0, 0, 0); continue; } index = texList.textures.IndexOf(spAg.SourceTextures[j]); if (index < 0) { Debug.LogError("Error assigning frame info: frame " + j + " on sprite \"" + ((SpriteRoot)spAg).name + "\" not found in the texture list!"); continue; } frameInfo = (SPRITE_FRAME)texList.frames[index]; frameInfo.uvs = texList.uvs[index]; spAg.SpriteFrames[j].Copy(frameInfo); } spr = (AutoSpriteBase)spAg; // Update our sprite's appearance: if (spr.spriteMesh != null) { if (spr.DefaultFrame != null) { spr.SetUVs(spr.DefaultFrame.uvs); } } EditorUtility.SetDirty(spr.gameObject); } }
// Finds all textures which are to be part // of a given atlas: private AtlasTextureList BuildTextureList(MaterialSpriteList msMap) { ISpriteAggregator spr; Texture2D newTex = null; SPRITE_FRAME frameInfo = new SPRITE_FRAME(0); AtlasTextureList texList = new AtlasTextureList(); texList.material = msMap.material; // Get all the textures pointed to by the sprites: for (int i = 0; i < msMap.sprites.Count; ++i) { spr = (ISpriteAggregator)msMap.sprites[i]; spr.Aggregate(AssetDatabase.GUIDToAssetPath, AssetDatabase.LoadAssetAtPath, AssetDatabase.AssetPathToGUID); // Get the sprite ready to give us its textures if (spr.SourceTextures.Length <= 0) { Debug.LogError("Null texture reference detected on sprite \"" + ((Component)spr).name + "\"! Please verify that this was intentional."); return(null); } for (int j = 0; j < spr.SourceTextures.Length; ++j) { if (spr.SourceTextures[j] != null) { // See if the texture is already in our list: if (-1 >= texList.textures.IndexOf(spr.SourceTextures[j])) { VerifyImportSettings(spr.SourceTextures[j]); texList.textures.Add(spr.SourceTextures[j]); ProcessFrame(spr.SourceTextures[j], spr.DoNotTrimImages, ref newTex, ref frameInfo); texList.trimmedTextures.Add(newTex); texList.frames.Add(frameInfo); } } else { Debug.LogError("Null texture reference detected on sprite \"" + ((Component)spr).name + "\"! Please verify that this was intentional."); #if WARN_ON_NULL_TEXTURE Debug.LogWarning("Null texture reference detected on sprite \"" + ((Component)spr).name + "\"! Please verify that this was intentional."); #endif } } } return(texList); }
// Assigns all frame-related information to // the sprites of an atlas: void SetFrameInfo(MaterialSpriteList msMap, AtlasTextureList texList) { SPRITE_FRAME frameInfo; ISpriteAggregator spAg; int index; for (int i = 0; i < msMap.sprites.Count; ++i) { spAg = msMap.sprites[i]; // Assign each frame its UVs: for (int j = 0; j < spAg.SpriteFrames.Length; ++j) { // Validate that a texture has been selected: if (spAg.SourceTextures[j] == null) { // Set the frame size to zero to flag it // as a "null" frame: spAg.SpriteFrames[j].uvs = new Rect(0, 0, 0, 0); continue; } index = texList.textures.IndexOf(spAg.SourceTextures[j]); if (index < 0) { Debug.LogError("Error assigning frame info: frame " + j + " on object \"" + ((Component)spAg).name + "\" not found in the texture list!"); continue; } frameInfo = texList.frames[index]; frameInfo.uvs = texList.uvs[index]; spAg.SpriteFrames[j].Copy(frameInfo); } // Update our sprite's appearance: if ( !(spAg is AutoSpriteBase && ((AutoSpriteBase)spAg).spriteMesh == null) ) { if (spAg.DefaultFrame != null) { spAg.SetUVs(spAg.DefaultFrame.uvs); } } EditorUtility.SetDirty((Component)spAg); } }
// Finds all textures which are to be part // of a given atlas: AtlasTextureList BuildTextureList(MaterialSpriteList msMap) { ISpriteAggregator spr; Texture2D newTex = null; SPRITE_FRAME frameInfo = new SPRITE_FRAME(0); AtlasTextureList texList = new AtlasTextureList(); texList.material = msMap.material; // Get all the textures pointed to by the sprites: for (int i = 0; i < msMap.sprites.Count; ++i) { spr = msMap.sprites[i]; spr.Aggregate(AssetDatabase.GUIDToAssetPath, AssetDatabase.LoadAssetAtPath, AssetDatabase.AssetPathToGUID); // Get the sprite ready to give us its textures for (int j = 0; j < spr.SourceTextures.Length; ++j) { if (spr.SourceTextures[j] != null) { // See if the texture is already in our list: if (-1 >= texList.textures.IndexOf(spr.SourceTextures[j])) { VerifyImportSettings(spr.SourceTextures[j]); texList.textures.Add(spr.SourceTextures[j]); ProcessFrame(spr.SourceTextures[j], spr.DoNotTrimImages, ref newTex, ref frameInfo); texList.trimmedTextures.Add(newTex); texList.frames.Add(frameInfo); } } else { #if WARN_ON_NULL_TEXTURE Debug.LogWarning("Null texture reference detected on sprite \"" + ((Component)spr).name + "\"! Please verify that this was intentional."); #endif } } } return texList; }
// Organizes all sprites by associating them with the // material they use. Returns an array list of // MaterialSpriteLists: List<MaterialSpriteList> OrganizeByMaterial(List<ISpriteAggregator> sprites) { string errString = ""; // A list of all materials List<Material> materials = new List<Material>(); // The map of materials to sprites List<MaterialSpriteList> map = new List<MaterialSpriteList>(); // The material of the sprite: Material mat; ISpriteAggregator sprite; MaterialSpriteList matSpriteList; int index; for (int i = 0; i < sprites.Count; ++i) { sprite = sprites[i]; mat = sprite.GetPackedMaterial(out errString); if(mat == null) { if (haltOnNullMaterial) { EditorUtility.DisplayDialog("ERROR", errString, "Ok"); Selection.activeGameObject = sprite.gameObject; return null; } else { Debug.LogError(errorString); continue; } } index = materials.IndexOf(mat); // See if the material is already in our list: if (index >= 0) { matSpriteList = (MaterialSpriteList)map[index]; matSpriteList.sprites.Add(sprite); } else { materials.Add(mat); matSpriteList = new MaterialSpriteList(); matSpriteList.material = mat; matSpriteList.sprites.Add(sprite); map.Add(matSpriteList); } } return map; }
// Organizes all sprites by associating them with the // material they use. Returns an array list of // MaterialSpriteLists: List<MaterialSpriteList> OrganizeByMaterial(ArrayList sprites) { // A list of all materials ArrayList materials = new ArrayList(); // The map of materials to sprites List<MaterialSpriteList> map = new List<MaterialSpriteList>(); // The material of the sprite: Material mat; SpriteRoot sprite; MaterialSpriteList matSpriteList; int index; for (int i = 0; i < sprites.Count; ++i) { sprite = (SpriteRoot)sprites[i]; if (sprite.spriteMesh == null) { // See if it is because the sprite isn't associated // with a manager: if (sprite.managed) { // See if we can get the material // from an associated manager: if (sprite.manager != null) { mat = sprite.manager.renderer.sharedMaterial; } else // Else, no manager associated!: { EditorUtility.DisplayDialog("ERROR", "Sprite \"" + sprite.name + "\" is not associated with a SpriteManager, and can therefore not be included in the atlas build.", "Ok"); Selection.activeGameObject = sprite.gameObject; return null; } } else // Else get the material from the sprite's renderer { // as this is probably a prefab and that's why it // doesn't have a mesh: mat = sprite.renderer.sharedMaterial; } } else if (sprite.managed) { if (sprite.manager != null) { mat = sprite.manager.renderer.sharedMaterial; } else // Else, no manager associated!: { EditorUtility.DisplayDialog("ERROR", "Sprite \"" + sprite.name + "\" is not associated with a SpriteManager, and can therefore not be included in the atlas build.", "Ok"); Selection.activeGameObject = sprite.gameObject; return null; } } else mat = sprite.spriteMesh.material; index = materials.IndexOf(mat); // See if the material is already in our list: if (index >= 0) { matSpriteList = (MaterialSpriteList)map[index]; matSpriteList.sprites.Add(sprite); } else { // Validate that the sprite had a material: if (mat == null) { EditorUtility.DisplayDialog("ERROR: No material selected", "No material selected for sprite \"" + sprite.name + "\"! Please set a material and try again. Click OK to go directly to the sprite that generated this error.", "Ok"); Selection.activeGameObject = sprite.gameObject; return null; } materials.Add(mat); matSpriteList = new MaterialSpriteList(); matSpriteList.material = mat; matSpriteList.sprites.Add(sprite); map.Add(matSpriteList); } } return map; }
// Organizes all sprites by associating them with the // material they use. Returns an array list of // MaterialSpriteLists: List <MaterialSpriteList> OrganizeByMaterial(ArrayList sprites) { // A list of all materials ArrayList materials = new ArrayList(); // The map of materials to sprites List <MaterialSpriteList> map = new List <MaterialSpriteList>(); // The material of the sprite: Material mat; SpriteRoot sprite; MaterialSpriteList matSpriteList; int index; for (int i = 0; i < sprites.Count; ++i) { sprite = (SpriteRoot)sprites[i]; if (sprite.spriteMesh == null) { // See if it is because the sprite isn't associated // with a manager: if (sprite.managed) { // See if we can get the material // from an associated manager: if (sprite.manager != null) { mat = sprite.manager.renderer.sharedMaterial; } else // Else, no manager associated!: { EditorUtility.DisplayDialog("ERROR", "Sprite \"" + sprite.name + "\" is not associated with a SpriteManager, and can therefore not be included in the atlas build.", "Ok"); Selection.activeGameObject = sprite.gameObject; return(null); } } else // Else get the material from the sprite's renderer { // as this is probably a prefab and that's why it // doesn't have a mesh: mat = sprite.renderer.sharedMaterial; } } else if (sprite.managed) { if (sprite.manager != null) { mat = sprite.manager.renderer.sharedMaterial; } else // Else, no manager associated!: { EditorUtility.DisplayDialog("ERROR", "Sprite \"" + sprite.name + "\" is not associated with a SpriteManager, and can therefore not be included in the atlas build.", "Ok"); Selection.activeGameObject = sprite.gameObject; return(null); } } else { mat = sprite.spriteMesh.material; } index = materials.IndexOf(mat); // See if the material is already in our list: if (index >= 0) { matSpriteList = (MaterialSpriteList)map[index]; matSpriteList.sprites.Add(sprite); } else { // Validate that the sprite had a material: if (mat == null) { EditorUtility.DisplayDialog("ERROR: No material selected", "No material selected for sprite \"" + sprite.name + "\"! Please set a material and try again. Click OK to go directly to the sprite that generated this error.", "Ok"); Selection.activeGameObject = sprite.gameObject; return(null); } materials.Add(mat); matSpriteList = new MaterialSpriteList(); matSpriteList.material = mat; matSpriteList.sprites.Add(sprite); map.Add(matSpriteList); } } return(map); }
void OnWizardCreate() { ArrayList sprites = new ArrayList(); List <MaterialSpriteList> matSpriteMap; // List of all materials used, with their associated sprites AtlasTextureList texList; int numAtlasesBuilt = 0; // Get the path we'll use to write our atlases: assetPath = Application.dataPath + "/" + atlasFolder; FindPackableSprites(sprites); matSpriteMap = OrganizeByMaterial(sprites); // Make sure everything went okay. // If not the previous method will // already have printed an error, // so just return: if (matSpriteMap == null) { return; } // If we're only building for the selected material, // remove all but the desired material: if (doSingleMaterial) { // Unset our flag: doSingleMaterial = false; MaterialSpriteList matList = null; for (int i = 0; i < matSpriteMap.Count; ++i) { if (matSpriteMap[i].material == targetMaterial) { matList = (MaterialSpriteList)matSpriteMap[i]; break; } } // Remove all, then re-add just the one we want: matSpriteMap.Clear(); if (matList != null) { matSpriteMap.Add(matList); } else { EditorUtility.DisplayDialog("No packable sprites found.", "No packable sprites found for material \"" + targetMaterial.name + "\".\n\nTry changing the \"Scan Project Folder\" setting.", "Ok"); return; } } // Create the folder that will hold our atlases: Directory.CreateDirectory(assetPath); // Loop through each material and process its // sprites, then build its atlas before moving // to the next material. for (int i = 0; i < matSpriteMap.Count; ++i) { texList = BuildTextureList(matSpriteMap[i]); // Make sure there are textures in the list: if (texList.textures.Count < 1) { Debug.LogWarning("Warning: No textures found for material \"" + texList.material.name + "\"."); --numAtlasesBuilt; } else { BuildAtlas(texList); } // Now assign the frame info: SetFrameInfo((MaterialSpriteList)matSpriteMap[i], texList); // Save the atlas path: matSpriteMap[i].texPath = texList.texPath; texList = null; // Try to free some memory: System.GC.Collect(); #if !UNITY_IPHONE || (UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 || UNITY_3_6 || UNITY_3_7 || UNITY_3_8 || UNITY_3_9) Resources.UnloadUnusedAssets(); #endif ++numAtlasesBuilt; } #if !UNITY_IPHONE || (UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 || UNITY_3_6 || UNITY_3_7 || UNITY_3_8 || UNITY_3_9) // Make sure all changes to objects are committed to disk: //AssetDatabase.SaveAssets(); #endif // Make sure the new atlases are (re-)imported: AssetDatabase.Refresh(); // Now assign each material its atlas now that we've done a asset refresh: for (int i = 0; i < matSpriteMap.Count; ++i) { matSpriteMap[i].material.mainTexture = (Texture2D)AssetDatabase.LoadAssetAtPath(matSpriteMap[i].texPath, typeof(Texture2D)); } Debug.Log(numAtlasesBuilt + " atlases generated."); // Save our settings for next time: SaveSettings(); }