public bool OnGui(AtlasConfiguration configuration) { using (new EditorGUILayout.VerticalScope(GUI.skin.box)) { EditorGUILayout.LabelField(@" アトラス化されたテクスチャおよび Prefab の出力設定を行います。 アトラス化作業によって変更された Prefab は同名で設定したディレクトリに出力されます。 ".Trim()); } EditorGUILayout.LabelField("グローバル設定"); using (new EditorGUI.IndentLevelScope()) { CustomField.PropertyField(this, nameof(_destination), "出力先ディレクトリ"); _name = EditorGUILayout.TextField("出力ファイル名", _name ?? configuration.GameObject.name); } EditorGUILayout.LabelField("メッシュ設定"); using (new EditorGUI.IndentLevelScope()) _isSplitByMaterialKey = EditorGUILayout.Toggle("Material Key を使用する", _isSplitByMaterialKey); EditorGUILayout.LabelField("テクスチャ設定"); using (new EditorGUI.IndentLevelScope()) _size = CustomField.EnumField("出力サイズ", _size); return(_destination != null && !string.IsNullOrWhiteSpace(_name)); }
private void DrawAtlasSettingsGUI() { _atlasWidth = (AtlasSize)EditorGUILayout.EnumPopup("Width:", _atlasWidth); _atlasHeight = (AtlasSize)EditorGUILayout.EnumPopup("Height:", _atlasHeight); _spriteAligment = (SpriteAlignment)EditorGUILayout.EnumPopup("Aligment", _spriteAligment); DrawSetBordersGUI(); }
public void OnInitialize() { if (_destination == null) { _destination = AssetDatabase.LoadAssetAtPath <DefaultAsset>(AssetDatabase.GUIDToAssetPath(DirectoryGuid)); } _isSplitByMaterialKey = false; _name = null; _size = AtlasSize.Four; }
// Revert settings public void RevertSettings( ) { int iContainerCount = m_rTextureContainers != null ? m_rTextureContainers.Length : 0; textures = new Texture2DContainer[iContainerCount]; // Deep copy for (int iContainerIndex = 0; iContainerIndex < iContainerCount; ++iContainerIndex) { textures[iContainerIndex] = new Texture2DContainer(m_rTextureContainers[iContainerIndex]); } padding = m_iPadding; maximumAtlasSize = m_eMaximumAtlasSize; EditorUtility.SetDirty(this); }
public static int ToTextureSize(this AtlasSize obj) { switch (obj) { case AtlasSize.One: return(1024); case AtlasSize.Two: return(2048); case AtlasSize.Four: return(4096); case AtlasSize.Eight: return(8192); default: throw new ArgumentOutOfRangeException(nameof(obj), obj, null); } }
// Returns the number of textures which won't fit into the atlas private int LookForOversizedTextures(Texture2DContainer[] a_rTextureContainers, int a_iPadding, AtlasSize a_eMaximumAtlasSize) { float fMaximumAtlasSize = (float)a_eMaximumAtlasSize; float fPadding = (float)a_iPadding; int iOversized = 0; if (a_rTextureContainers != null) { foreach (Texture2DContainer rTextureContainer in a_rTextureContainers) { if (rTextureContainer != null) { Texture2D rTextureToPack = rTextureContainer; if (rTextureToPack != null && (rTextureToPack.width + fPadding > fMaximumAtlasSize || rTextureToPack.height + fPadding > fMaximumAtlasSize)) { ++iOversized; } } } } return(iOversized); }
// Apply settings public bool ApplySettings(bool a_bUpdateSprites = true) { bool bSuccess; Uni2DAssetPostprocessor.Enabled = false; { int iContainerCount = textures.Length; Texture2D[] oTexturesToPack = new Texture2D[iContainerCount]; for (int iContainerIndex = 0; iContainerIndex < iContainerCount; ++iContainerIndex) { oTexturesToPack[iContainerIndex] = textures[iContainerIndex].Texture; } List <Uni2DTextureImporterSettingsPair> rTextureImporterSettings = Uni2DEditorSpriteBuilderUtils.TexturesProcessingBegin(oTexturesToPack); oTexturesToPack = null; // Look if the atlas is set properly regarding to texture sizes int iOversizedTextures = this.LookForOversizedTextures(textures, padding, maximumAtlasSize); if (iOversizedTextures == 0) { textures = this.SanitizeInputTextures(textures); iContainerCount = textures.Length; string rAtlasGUID = Uni2DEditorUtils.GetUnityAssetGUID(this); Uni2DEditorAssetTable rAssetTable = Uni2DEditorAssetTable.Instance; for (int iTextureIndex = 0, iTextureCount = m_rTextureContainers.Length; iTextureIndex < iTextureCount; ++iTextureIndex) { rAssetTable.RemoveAtlasUsingTexture(rAtlasGUID, m_rTextureContainers[iTextureIndex].GUID); } m_rTextureContainers = new Texture2DContainer[iContainerCount]; // Deep copy for (int iContainerIndex = 0; iContainerIndex < iContainerCount; ++iContainerIndex) { Texture2DContainer oTextureContainer = new Texture2DContainer(textures[iContainerIndex]); m_rTextureContainers[iContainerIndex] = oTextureContainer; rAssetTable.AddAtlasUsingTexture(rAtlasGUID, oTextureContainer.GUID); } rAssetTable.Save( ); m_iPadding = padding; m_eMaximumAtlasSize = maximumAtlasSize; bSuccess = Generate( ); if (a_bUpdateSprites) { Uni2DEditorSpriteBuilderUtils.UpdateSpriteInCurrentSceneAndResourcesAccordinglyToAtlasChange(this); } } else // Some textures can't fit { bSuccess = false; Debug.LogWarning("Uni2D could not regenerate atlas '" + (this.gameObject.name) + "' properly: " + iOversizedTextures + " texture" + (iOversizedTextures > 1 ? "s are" : " is") + " too large to fit in the atlas.", this.gameObject); } Uni2DEditorSpriteBuilderUtils.TexturesProcessingEnd(rTextureImporterSettings); } Uni2DAssetPostprocessor.Enabled = true; EditorUtility.UnloadUnusedAssets( ); return(bSuccess); }
// Returns the number of textures which won't fit into the atlas private int LookForOversizedTextures( Texture2DContainer[ ] a_rTextureContainers, int a_iPadding, AtlasSize a_eMaximumAtlasSize ) { float fMaximumAtlasSize = (float) a_eMaximumAtlasSize; float fPadding = (float) a_iPadding; int iOversized = 0; if( a_rTextureContainers != null ) { foreach( Texture2DContainer rTextureContainer in a_rTextureContainers ) { if( rTextureContainer != null ) { Texture2D rTextureToPack = rTextureContainer; if( rTextureToPack != null && ( rTextureToPack.width + fPadding > fMaximumAtlasSize || rTextureToPack.height + fPadding > fMaximumAtlasSize ) ) { ++iOversized; } } } } return iOversized; }
// Revert settings public void RevertSettings( ) { int iContainerCount = m_rTextureContainers != null ? m_rTextureContainers.Length : 0; textures = new Texture2DContainer[ iContainerCount ]; // Deep copy for( int iContainerIndex = 0; iContainerIndex < iContainerCount; ++iContainerIndex ) { textures[ iContainerIndex ] = new Texture2DContainer( m_rTextureContainers[ iContainerIndex ] ); } padding = m_iPadding; maximumAtlasSize = m_eMaximumAtlasSize; EditorUtility.SetDirty( this ); }
// Apply settings public bool ApplySettings( bool a_bUpdateSprites = true ) { bool bSuccess; Uni2DAssetPostprocessor.Enabled = false; { int iContainerCount = textures.Length; Texture2D[ ] oTexturesToPack = new Texture2D[ iContainerCount ]; for( int iContainerIndex = 0; iContainerIndex < iContainerCount; ++iContainerIndex ) { oTexturesToPack[ iContainerIndex ] = textures[ iContainerIndex ].Texture; } List<Uni2DTextureImporterSettingsPair> rTextureImporterSettings = Uni2DEditorSpriteBuilderUtils.TexturesProcessingBegin( oTexturesToPack ); oTexturesToPack = null; // Look if the atlas is set properly regarding to texture sizes int iOversizedTextures = this.LookForOversizedTextures( textures, padding, maximumAtlasSize ); if( iOversizedTextures == 0 ) { textures = this.SanitizeInputTextures( textures ); iContainerCount = textures.Length; string rAtlasGUID = Uni2DEditorUtils.GetUnityAssetGUID( this ); Uni2DEditorAssetTable rAssetTable = Uni2DEditorAssetTable.Instance; for( int iTextureIndex = 0, iTextureCount = m_rTextureContainers.Length; iTextureIndex < iTextureCount; ++iTextureIndex ) { rAssetTable.RemoveAtlasUsingTexture( rAtlasGUID, m_rTextureContainers[ iTextureIndex ].GUID ); } m_rTextureContainers = new Texture2DContainer[ iContainerCount ]; // Deep copy for( int iContainerIndex = 0; iContainerIndex < iContainerCount; ++iContainerIndex ) { Texture2DContainer oTextureContainer = new Texture2DContainer( textures[ iContainerIndex ] ); m_rTextureContainers[ iContainerIndex ] = oTextureContainer; rAssetTable.AddAtlasUsingTexture( rAtlasGUID, oTextureContainer.GUID ); } rAssetTable.Save( ); m_iPadding = padding; m_eMaximumAtlasSize = maximumAtlasSize; bSuccess = Generate( ); if( a_bUpdateSprites ) { Uni2DEditorSpriteBuilderUtils.UpdateSpriteInCurrentSceneAndResourcesAccordinglyToAtlasChange( this ); } } else // Some textures can't fit { bSuccess = false; Debug.LogWarning( "Uni2D could not regenerate atlas '" + ( this.gameObject.name ) + "' properly: " + iOversizedTextures + " texture" + ( iOversizedTextures > 1 ? "s are" : " is" ) + " too large to fit in the atlas.", this.gameObject ); } Uni2DEditorSpriteBuilderUtils.TexturesProcessingEnd( rTextureImporterSettings ); } Uni2DAssetPostprocessor.Enabled = true; EditorUtility.UnloadUnusedAssets( ); return bSuccess; }
public void RegistrationComplete() { IEnumerable <Block> blocks = RegisteredBlocks.Select(kv => kv.Value.Block); Texture2D noTexture = (Texture2D)Resources.Load("notexture"); noTexture.name = "notexture"; //Figure out what blocks will get what UV List <string> texturesToLoad = new List <string>(); foreach (Block b in blocks) { foreach (string texture in b.Data.TextureNames) { if (texture == "notexture") { continue; //Skip 'notexture' textures, because are are already going to load } //those if (!texturesToLoad.Contains(texture)) { texturesToLoad.Add(texture); } } } //Load each of the textures, make sure they are square and a power of 2 between 32 and 512. List <Texture2D> LoadedTextures = new List <Texture2D>(); List <string> NotLoadedTextures = new List <string>(); LoadedTextures.Add(noTexture); foreach (string t in texturesToLoad) { if (t == "notexture") { continue; } Texture2D loadedTexture = (Texture2D)Resources.Load(t); loadedTexture.name = t; if (loadedTexture.width != loadedTexture.height) { Debug.Log(string.Format("Texture {0} is not square!", t)); NotLoadedTextures.Add(t); continue; } if (loadedTexture.width < 32 || loadedTexture.width > 512) { Debug.Log(string.Format("Texture {0} must be a power of 2 between 32 and 512", t)); NotLoadedTextures.Add(t); continue; } if (!Mathf.IsPowerOfTwo(loadedTexture.width)) { Debug.Log(string.Format("Texture {0} must be a power of 2 between 32 and 512", t)); NotLoadedTextures.Add(t); continue; } LoadedTextures.Add(loadedTexture); } //Load and pack the textures for (int i = 32; i <= 512; i = i * 2) { IEnumerable <Texture2D> TexturesOfThisSize = LoadedTextures.Where(t => t.width == i); if (TexturesOfThisSize.Count() == 0) { continue; } //Pack them into an atlas Texture2D atlas = new Texture2D(1024, 1024, TextureFormat.ARGB32, true, false); atlas.anisoLevel = 9; atlas.mipMapBias = -.5f; atlas.filterMode = FilterMode.Point; float percent = 1f / 8f; float atlasWidth = atlas.PackTexturesWithTiling(TexturesOfThisSize.ToArray(), percent, 1024, false); atlas.Apply(true); AtlasSize thisSize = (AtlasSize)Enum.Parse(typeof(AtlasSize), "_" + i); Debug.Log("Building Atlas of size " + thisSize.ToString()); TextureAtlases[thisSize] = new TextureAtlasLookup() { Atlas = atlas, TextureNamesInThisAtlas = TexturesOfThisSize.Select(t => t.name).ToList(), CopyPercent = percent, PalleteSize = atlasWidth, }; } //Go through the loaded names and assign IDs and Blocks to them. foreach (Block b in blocks) { List <int> Ids = new List <int>(); List <AtlasSize> atlasLocations = new List <AtlasSize>(); //Find which atlas each block's texture is in for (int i = 0; i < 6; i++) { string textureName = b.Data.TextureNames[i]; //If we have a notexture or failed to load, index directly into 'notexture' if (textureName == "notexture" || NotLoadedTextures.Contains(textureName)) { Ids.Add(0); //notexture is the first texture in the 32sized array atlasLocations.Add(AtlasSize._32); continue; } //Find which atlas this texture is in AtlasSize containingAtlas = AtlasSize._32; foreach (KeyValuePair <AtlasSize, TextureAtlasLookup> kv in TextureAtlases) { if (kv.Value.TextureNamesInThisAtlas.Contains(textureName)) { containingAtlas = kv.Key; break; } } atlasLocations.Add(containingAtlas); //Find what position it's in int index = TextureAtlases[containingAtlas].TextureNamesInThisAtlas.IndexOf(textureName); Ids.Add(index); } b.Data.TextureIDs = Ids.ToArray(); Debug.Log("block:" + b.Data.DisplayName); Debug.Log("TextureIds: " + string.Join(",", b.Data.TextureIDs.Select(x => x.ToString()).ToArray())); b.Data.AtlasLocations = atlasLocations.ToArray(); } //Set up the material AtlasMaterial = (Material)Resources.Load("MCMaterial"); AtlasMaterial.SetTexture("_Atlas32", TextureAtlases[AtlasSize._32].Atlas); AtlasMaterial.SetFloat("_PERCENT", TextureAtlases[AtlasSize._32].CopyPercent); AtlasMaterial.SetFloat("_PALLETESIZE", TextureAtlases[AtlasSize._32].PalleteSize); foreach (Block b in RegisteredBlocks.Values.Select(x => x.Block)) { b.Data.RenderMaterial = AtlasMaterial; } }