public static string BakeAtlas(GuiAtlas atlas, string fileName)
        {
            if (!AssetDatabase.Contains (atlas)) {
                return "Atlas should be saved as asset";
            }
            if (string.IsNullOrEmpty (fileName)) {
                return "Sprite folder not selected";
            }

            // cleanup.
            try {
                if (atlas.ColorTexture != null && AssetDatabase.Contains (atlas.ColorTexture)) {
                    var t = atlas.ColorTexture;
                    atlas.ColorTexture = null;
                    AssetDatabase.DeleteAsset (AssetDatabase.GetAssetPath (t));
                }
            } catch {
            }
            try {
                if (atlas.AlphaTexture != null && AssetDatabase.Contains (atlas.AlphaTexture)) {
                    var t = atlas.AlphaTexture;
                    atlas.AlphaTexture = null;
                    AssetDatabase.DeleteAsset (AssetDatabase.GetAssetPath (t));
                }
            } catch {
            }

            AssetDatabase.Refresh ();

            var sprites = new List<Texture2D> ();

            foreach (var spriteFileName in Directory.GetFiles (fileName, "*.png", SearchOption.TopDirectoryOnly)) {
                var spriteTex = new Texture2D (2, 2);
                spriteTex.LoadImage (File.ReadAllBytes (spriteFileName));
                spriteTex.Apply ();
                spriteTex.name = Path.GetFileNameWithoutExtension (spriteFileName);
                sprites.Add (spriteTex);
            }

            var atlasTex = new Texture2D (2, 2, TextureFormat.ARGB32, false);
            atlasTex.hideFlags = HideFlags.HideAndDontSave;

            Rect[] rects;

            if (sprites.Count == 1) {
                // special case, one texture
                rects = new Rect[] { new Rect (0, 0, 1f, 1f) };
                atlasTex.LoadImage (sprites[0].EncodeToPNG ());
                atlasTex.Apply ();
            } else {
                rects = atlasTex.PackTextures (sprites.ToArray (), 2, 2048);
            }

            var tex = new Texture2D (atlasTex.width, atlasTex.height, TextureFormat.RGB24, false);
            tex.hideFlags = HideFlags.HideAndDontSave;
            var srcColors = atlasTex.GetPixels32 ();
            DestroyImmediate (atlasTex);
            atlasTex = null;

            var dstAlphas = new Color32[srcColors.Length];
            Color32 c;
            for (int i = 0; i < srcColors.Length; i++) {
                c = srcColors[i];
                dstAlphas[i] = new Color32 (c.a, c.a, c.a, 255);
            }
            tex.SetPixels32 (srcColors);
            var colorData = tex.EncodeToPNG ();
            tex.SetPixels32 (dstAlphas);
            var alphaData = tex.EncodeToPNG ();
            DestroyImmediate (tex);
            tex = null;

            try {
                var srcAtlasPath = AssetDatabase.GetAssetPath (atlas);
                EditorUtility.DisplayProgressBar ("Save and import atlas data", "Color data processing...", 1f);
                var atlasPath = Path.ChangeExtension (srcAtlasPath, "color.png");
                File.WriteAllBytes (Path.Combine (Path.Combine (Application.dataPath, ".."), atlasPath), colorData);

                EditorUtility.DisplayProgressBar ("Save and import atlas data", "Alpha data processing...", 1f);
                var alphaAtlasPath = Path.ChangeExtension (srcAtlasPath, "alpha.png");
                File.WriteAllBytes (Path.Combine (Path.Combine (Application.dataPath, ".."), alphaAtlasPath), alphaData);

                EditorUtility.DisplayProgressBar ("Save and import atlas data", "Import processed data...", 1f);
                AssetDatabase.Refresh ();
                atlasTex = FixAtlasImport (atlasPath);
                atlas.ColorTexture = atlasTex;
                atlas.AlphaTexture = FixAtlasImport (alphaAtlasPath);

                var atlasSprites = new List<GuiSpriteData> (sprites.Count);
                float atlasWidth = atlasTex.width;
                float atlasHeight = atlasTex.height;
                for (int i = 0, iMax = sprites.Count; i < iMax; i++) {
                    var sprData = new GuiSpriteData ();
                    var sprName = sprites[i].name;

                    // slicing
                    var match = _slicedMask.Match (sprName.ToLowerInvariant ());
                    if (match.Success) {
                        sprName = sprName.Replace (match.Value, string.Empty);
                        sprData.BorderL = int.Parse (match.Groups["left"].Value) / atlasWidth;
                        sprData.BorderT = int.Parse (match.Groups["top"].Value) / atlasHeight;
                        sprData.BorderR = int.Parse (match.Groups["right"].Value) / atlasWidth;
                        sprData.BorderB = int.Parse (match.Groups["bottom"].Value) / atlasHeight;
                    } else {
                        sprData.BorderL = 0;
                        sprData.BorderT = 0;
                        sprData.BorderR = 0;
                        sprData.BorderB = 0;
                    }

                    sprData.Name = sprName;
                    sprData.CornerX = rects[i].x;
                    sprData.CornerY = rects[i].y;
                    sprData.CornerW = rects[i].width;
                    sprData.CornerH = rects[i].height;
                    atlasSprites.Add (sprData);
                }

                atlas.Sprites = atlasSprites.ToArray ();

                EditorUtility.SetDirty (atlas);

                AssetDatabase.SaveAssets ();
                AssetDatabase.Refresh ();

                atlas.ResetCache ();

                foreach (var panel in FindObjectsOfType<GuiPanel> ()) {
                    panel.ResetMaterialCache ();
                }
                foreach (var vis in FindObjectsOfType<GuiWidget> ()) {
                    vis.SetDirty (GuiDirtyType.Geometry);
                    EditorUtility.SetDirty (vis);
                }
            } finally {
                EditorUtility.ClearProgressBar ();

                for (var i = sprites.Count - 1; i >= 0; i--) {
                    DestroyImmediate (sprites[i]);
                    sprites.RemoveAt (i);
                }
            }

            return null;
        }
Пример #2
0
        public static string BakeAtlas(GuiAtlas atlas, string fileName)
        {
            if (!AssetDatabase.Contains(atlas))
            {
                return("Atlas should be saved as asset");
            }
            if (string.IsNullOrEmpty(fileName))
            {
                return("Sprite folder not selected");
            }

            // cleanup.
            try {
                if (atlas.ColorTexture != null && AssetDatabase.Contains(atlas.ColorTexture))
                {
                    var t = atlas.ColorTexture;
                    atlas.ColorTexture = null;
                    AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(t));
                }
            } catch {
            }
            try {
                if (atlas.AlphaTexture != null && AssetDatabase.Contains(atlas.AlphaTexture))
                {
                    var t = atlas.AlphaTexture;
                    atlas.AlphaTexture = null;
                    AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(t));
                }
            } catch {
            }

            AssetDatabase.Refresh();

            var sprites = new List <Texture2D> ();

            foreach (var spriteFileName in Directory.GetFiles(fileName, "*.png", SearchOption.TopDirectoryOnly))
            {
                var spriteTex = new Texture2D(2, 2);
                spriteTex.LoadImage(File.ReadAllBytes(spriteFileName));
                spriteTex.Apply();
                spriteTex.name = Path.GetFileNameWithoutExtension(spriteFileName);
                sprites.Add(spriteTex);
            }

            var atlasTex = new Texture2D(2, 2, TextureFormat.ARGB32, false);

            atlasTex.hideFlags = HideFlags.HideAndDontSave;

            Rect[] rects;

            if (sprites.Count == 1)
            {
                // special case, one texture
                rects = new Rect[] { new Rect(0, 0, 1f, 1f) };
                atlasTex.LoadImage(sprites[0].EncodeToPNG());
                atlasTex.Apply();
            }
            else
            {
                rects = atlasTex.PackTextures(sprites.ToArray(), 2, 2048);
            }

            var tex = new Texture2D(atlasTex.width, atlasTex.height, TextureFormat.RGB24, false);

            tex.hideFlags = HideFlags.HideAndDontSave;
            var srcColors = atlasTex.GetPixels32();

            DestroyImmediate(atlasTex);
            atlasTex = null;

            var     dstAlphas = new Color32[srcColors.Length];
            Color32 c;

            for (int i = 0; i < srcColors.Length; i++)
            {
                c            = srcColors[i];
                dstAlphas[i] = new Color32(c.a, c.a, c.a, 255);
            }
            tex.SetPixels32(srcColors);
            var colorData = tex.EncodeToPNG();

            tex.SetPixels32(dstAlphas);
            var alphaData = tex.EncodeToPNG();

            DestroyImmediate(tex);
            tex = null;

            try {
                var srcAtlasPath = AssetDatabase.GetAssetPath(atlas);
                EditorUtility.DisplayProgressBar("Save and import atlas data", "Color data processing...", 1f);
                var atlasPath = Path.ChangeExtension(srcAtlasPath, "color.png");
                File.WriteAllBytes(Path.Combine(Path.Combine(Application.dataPath, ".."), atlasPath), colorData);

                EditorUtility.DisplayProgressBar("Save and import atlas data", "Alpha data processing...", 1f);
                var alphaAtlasPath = Path.ChangeExtension(srcAtlasPath, "alpha.png");
                File.WriteAllBytes(Path.Combine(Path.Combine(Application.dataPath, ".."), alphaAtlasPath), alphaData);

                EditorUtility.DisplayProgressBar("Save and import atlas data", "Import processed data...", 1f);
                AssetDatabase.Refresh();
                atlasTex           = FixAtlasImport(atlasPath);
                atlas.ColorTexture = atlasTex;
                atlas.AlphaTexture = FixAtlasImport(alphaAtlasPath);

                var   atlasSprites = new List <GuiSpriteData> (sprites.Count);
                float atlasWidth   = atlasTex.width;
                float atlasHeight  = atlasTex.height;
                for (int i = 0, iMax = sprites.Count; i < iMax; i++)
                {
                    var sprData = new GuiSpriteData();
                    var sprName = sprites[i].name;
                    // slicing
                    var match = _slicedMask.Match(sprName.ToLowerInvariant());
                    if (match.Success)
                    {
                        sprName         = sprName.Replace(match.Value, string.Empty);
                        sprData.BorderL = int.Parse(match.Groups["left"].Value) / atlasWidth;
                        sprData.BorderT = int.Parse(match.Groups["top"].Value) / atlasHeight;
                        sprData.BorderR = int.Parse(match.Groups["right"].Value) / atlasWidth;
                        sprData.BorderB = int.Parse(match.Groups["bottom"].Value) / atlasHeight;
                    }
                    else
                    {
                        sprData.BorderL = 0;
                        sprData.BorderT = 0;
                        sprData.BorderR = 0;
                        sprData.BorderB = 0;
                    }

                    sprData.Name    = sprName;
                    sprData.CornerX = rects[i].x;
                    sprData.CornerY = rects[i].y;
                    sprData.CornerW = rects[i].width;
                    sprData.CornerH = rects[i].height;
                    atlasSprites.Add(sprData);
                }

                atlas.Sprites = atlasSprites.ToArray();

                EditorUtility.SetDirty(atlas);

                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();

                atlas.ResetCache();

                foreach (var panel in FindObjectsOfType <GuiPanel>())
                {
                    panel.ResetMaterialCache();
                }
                foreach (var vis in FindObjectsOfType <GuiWidget>())
                {
                    vis.SetDirty(GuiDirtyType.Geometry);
                    EditorUtility.SetDirty(vis);
                }
            } finally {
                EditorUtility.ClearProgressBar();

                for (var i = sprites.Count - 1; i >= 0; i--)
                {
                    DestroyImmediate(sprites[i]);
                    sprites.RemoveAt(i);
                }
            }

            return(null);
        }
 /// <summary>
 /// Fill simple sprite.
 /// </summary>
 /// <param name="mesh">Mesh.</param>
 /// <param name="width">Sprite width.</param>
 /// <param name="height">Sprite height.</param>
 /// <param name="color">Sprite color.</param>
 /// <param name="spriteData">Sprite data.</param>
 /// <param name="effect">Effect.</param>
 /// <param name="effectValue">Effect value.</param>
 /// <param name="effectColor">Effect color.</param>
 public static void FillSimpleSprite(Mesh mesh, int width, int height, Color color, GuiSpriteData spriteData,
                                      GuiFontEffect effect = GuiFontEffect.None, Vector2? effectValue = null,
                                      Color? effectColor = null)
 {
     if (mesh == null) {
         return;
     }
     PrepareBuffer (effect, effectValue, effectColor);
     if (spriteData != null) {
         var halfW = 0.5f * width;
         var halfH = 0.5f * height;
         _vRect.Set (-halfW, -halfH, width, height);
         _uvRect.Set (spriteData.CornerX, spriteData.CornerY, spriteData.CornerW, spriteData.CornerH);
         FillBuffer (ref _vRect, ref _uvRect, ref color);
     }
     GetBuffers (mesh);
 }
        /// <summary>
        /// Fill sliced / tiled sprite.
        /// </summary>
        /// <param name="mesh">Mesh.</param>
        /// <param name="width">Sprite width.</param>
        /// <param name="height">Sprite height.</param>
        /// <param name="color">Sprite color.</param>
        /// <param name="sd">Sprite data.</param>
        /// <param name="texSize">Tex size.</param>
        /// <param name="isHorTiled">Is sprite tiled horizontally.</param>
        /// <param name="isVerTiled">Is sprite tiled vertically.</param>
        /// <param name="fillCenter">Is sprite center should be filled.</param>
        public static void FillSlicedTiledSprite(
            Mesh mesh, int width, int height, Color color, GuiSpriteData sd,
            Vector2 texSize, bool isHorTiled, bool isVerTiled, bool fillCenter)
        {
            if (mesh == null) {
                return;
            }
            PrepareBuffer ();
            if (sd != null && width != 0 && height != 0) {
                var leftBorderV = (int) (sd.BorderL * texSize.x);
                var rightBorderV = (int) (sd.BorderR * texSize.x);
                var topBorderV = (int) (sd.BorderT * texSize.y);
                var bottomBorderV = (int) (sd.BorderB * texSize.y);

                if ((leftBorderV + rightBorderV) <= width && (bottomBorderV + topBorderV) <= height) {
                    var cW = sd.CenterWidth;
                    var cH = sd.CenterHeight;
                    var bR = sd.CornerX + sd.CornerW - sd.BorderR;
                    var bT = sd.CornerY + sd.CornerH - sd.BorderT;

                    var halfW = 0.5f * width;
                    var halfH = 0.5f * height;

                    if (width < 0) {
                        leftBorderV = -leftBorderV;
                        rightBorderV = -rightBorderV;
                    }

                    if (height < 0) {
                        topBorderV = -topBorderV;
                        bottomBorderV = -bottomBorderV;
                    }

                    int centerWidthV;
                    int horTileCount;

                    int centerHeightV;
                    int verTileCount;

                    if (isHorTiled) {
                        centerWidthV = (int) (cW * texSize.x);
                        if (width < 0) {
                            centerWidthV = -centerWidthV;
                        }
                        horTileCount = Mathf.Max (0, Mathf.FloorToInt ((width - leftBorderV - rightBorderV) / (float) centerWidthV));
                    } else {
                        centerWidthV = width - rightBorderV - leftBorderV;
                        horTileCount = 1;
                    }

                    if (isVerTiled) {
                        centerHeightV = (int) (cH * texSize.y);
                        if (height < 0) {
                            centerHeightV = -centerHeightV;
                        }
                        verTileCount = Mathf.Max (0, Mathf.FloorToInt ((height - bottomBorderV - topBorderV) / (float) centerHeightV));
                    } else {
                        centerHeightV = height - topBorderV - bottomBorderV;
                        verTileCount = 1;
                    }

                    // top-bottom sides
                    if (sd.BorderT > 0 || sd.BorderB > 0) {
                        _uvRect.Set (sd.CornerX + sd.BorderL, bT, cW, sd.BorderT);
                        _uvRect2.Set (sd.CornerX + sd.BorderL, sd.CornerY, cW, sd.BorderB);
                        _vRect.Set (-halfW + leftBorderV, halfH - topBorderV, centerWidthV, topBorderV);
                        _vRect2.Set (-halfW + leftBorderV, -halfH, centerWidthV, bottomBorderV);
                        for (var i = 0; i < horTileCount; i++) {
                            FillBuffer (ref _vRect, ref _uvRect, ref color);
                            FillBuffer (ref _vRect2, ref _uvRect2, ref color);
                            _vRect.x += centerWidthV;
                            _vRect2.x += centerWidthV;
                        }
                    }

                    // left-right sides
                    if (sd.BorderL > 0 || sd.BorderR > 0) {
                        _uvRect.Set (sd.CornerX, sd.CornerY + sd.BorderB, sd.BorderL, cH);
                        _uvRect2.Set (bR, sd.CornerY + sd.BorderB, sd.BorderR, cH);
                        _vRect.Set (-halfW, -halfH + bottomBorderV, leftBorderV, centerHeightV);
                        _vRect2.Set (halfW - rightBorderV, -halfH + bottomBorderV, rightBorderV, centerHeightV);
                        for (var i = 0; i < verTileCount; i++) {
                            FillBuffer (ref _vRect, ref _uvRect, ref color);
                            FillBuffer (ref _vRect2, ref _uvRect2, ref color);
                            _vRect.y += centerHeightV;
                            _vRect2.y += centerHeightV;
                        }
                    }

                    // center
                    if (fillCenter) {
                        _uvRect.Set (sd.CornerX + sd.BorderL, sd.CornerY + sd.BorderB, cW, cH);
                        _vRect.Set (0, -halfH + bottomBorderV, centerWidthV, centerHeightV);
                        for (var y = 0; y < verTileCount; y++) {
                            _vRect.x = -halfW + leftBorderV;
                            for (var x = 0; x < horTileCount; x++) {
                                FillBuffer (ref _vRect, ref _uvRect, ref color);
                                _vRect.x += centerWidthV;
                            }
                            _vRect.y += centerHeightV;
                        }
                    }

                    // left-top corner
                    if (sd.BorderL > 0 && sd.BorderT > 0) {
                        _vRect.Set (-halfW, halfH - topBorderV, leftBorderV, topBorderV);
                        _uvRect.Set (sd.CornerX, bT, sd.BorderL, sd.BorderT);
                        FillBuffer (ref _vRect, ref _uvRect, ref color);
                    }

                    // right-top corner
                    if (sd.BorderR > 0 && sd.BorderT > 0) {
                        _vRect.Set (halfW - rightBorderV, halfH - topBorderV, rightBorderV, topBorderV);
                        _uvRect.Set (bR, bT, sd.BorderR, sd.BorderT);
                        FillBuffer (ref _vRect, ref _uvRect, ref color);
                    }

                    // right-bottom corner
                    if (sd.BorderR > 0 && sd.BorderB > 0) {
                        _vRect.Set (halfW - rightBorderV, -halfH, rightBorderV, bottomBorderV);
                        _uvRect.Set (bR, sd.CornerY, sd.BorderR, sd.BorderB);
                        FillBuffer (ref _vRect, ref _uvRect, ref color);
                    }

                    // left-bottom corner
                    if (sd.BorderL > 0 && sd.BorderB > 0) {
                        _vRect.Set (-halfW, -halfH, leftBorderV, bottomBorderV);
                        _uvRect.Set (sd.CornerX, sd.CornerY, sd.BorderL, sd.BorderB);
                        FillBuffer (ref _vRect, ref _uvRect, ref color);
                    }
                }
            }
            GetBuffers (mesh);
        }
        /// <summary>
        /// Fill round-filled sprite.
        /// </summary>
        /// <param name="mesh">Mesh.</param>
        /// <param name="width">Sprite width.</param>
        /// <param name="height">Sprite height.</param>
        /// <param name="fillValue">Normalized progress of round-filling.</param>
        /// <param name="color">Sprite color.</param>
        /// <param name="spriteData">Sprite data.</param>
        /// <param name="effect">Effect.</param>
        /// <param name="effectValue">Effect value.</param>
        /// <param name="effectColor">Effect color.</param>
        public static void FillRoundFilledSprite(
            Mesh mesh, int width, int height, float fillValue, Color color, GuiSpriteData spriteData,
            GuiFontEffect effect = GuiFontEffect.None, Vector2? effectValue = null,
            Color? effectColor = null)
        {
            if (mesh == null) {
                return;
            }
            PrepareBuffer (effect, effectValue, effectColor);
            if (spriteData != null && fillValue > 0f) {
                var halfW = 0.5f * width;
                var halfH = 0.5f * height;
                _vRect.Set (-halfW, -halfH, width, height);
                _uvRect.Set (spriteData.CornerX, spriteData.CornerY, spriteData.CornerW, spriteData.CornerH);

                var uvHalfW = spriteData.CornerW * 0.5f;
                var uvHalfH = spriteData.CornerH * 0.5f;

                int i;
                for (i = 0; i < 4; i++) {
                    _uvRect.Set (
                        RoundFilledUV[i].x * uvHalfW + spriteData.CornerX,
                        RoundFilledUV[i].y * uvHalfH + spriteData.CornerY,
                        uvHalfW, uvHalfH);
                    _vRect.Set (RoundFilledV[i].x * halfW, RoundFilledV[i].y * halfH, halfW, halfH);
                    if (fillValue < (i + 1) * 0.25f) {
                        break;
                    }
                    FillBuffer (ref _vRect, ref _uvRect, ref color);
                }

                if (i < 4) {
                    fillValue = (fillValue - i * 0.25f) * 8f;
                    var needFlip = (i & 1) == 0;
                    var uv0 = new Vector2 (_uvRect.xMin, _uvRect.yMin);
                    var uv1 = new Vector2 (_uvRect.xMin, _uvRect.yMax);
                    var uv2 = new Vector2 (_uvRect.xMax, _uvRect.yMax);
                    var uv3 = new Vector2 (_uvRect.xMax, _uvRect.yMin);
                    var v0 = new Vector3 (_vRect.xMin, _vRect.yMin, 0f);
                    var v1 = new Vector3 (_vRect.xMin, _vRect.yMax, 0f);
                    var v2 = new Vector3 (_vRect.xMax, _vRect.yMax, 0f);
                    var v3 = new Vector3 (_vRect.xMax, _vRect.yMin, 0f);
                    if (needFlip) {
                        var t = uv0.y;
                        uv0.y = uv1.y;
                        uv1.y = t;
                        t = uv2.y;
                        uv2.y = uv3.y;
                        uv3.y = t;

                        t = v0.y;
                        v0.y = v1.y;
                        v1.y = t;
                        t = v2.y;
                        v2.y = v3.y;
                        v3.y = t;
                    }

                    var fvW = _vRect.width * fillValue;
                    var fvH = _vRect.height * fillValue;
                    var fuvW = _uvRect.width * fillValue;
                    var fuvH = _uvRect.height * fillValue;

                    if (fillValue >= 1f) {
                        // more than 45 degrees.
                        fvW -= _vRect.width;
                        fvH -= _vRect.height;
                        fuvW -= _uvRect.width;
                        fuvH -= _uvRect.height;
                        switch (i) {
                        case 0:
                            v1.y = _vRect.yMax - fvH;
                            uv1.y = _uvRect.yMax - fuvH;
                            break;
                        case 1:
                            v3.x = _vRect.xMin + fvW;
                            uv3.x = _uvRect.xMin + fuvW;
                            break;
                        case 2:
                            v3.y = _vRect.yMin + fvH;
                            uv3.y = _uvRect.yMin + fuvH;
                            break;
                        case 3:
                            v1.x = _vRect.xMax - fvW;
                            uv1.x = _uvRect.xMax - fuvW;
                            break;
                        }
                    } else {
                        // less than 45 degrees
                        switch (i) {
                        case 0:
                            v0.x = _vRect.xMax - fvW;
                            uv0.x = _uvRect.xMax - fuvW;
                            uv1 = uv0;
                            v1 = v0;
                            break;
                        case 1:
                            v0.y = _vRect.yMax - fvH;
                            uv0.y = _uvRect.yMax - fuvH;
                            uv3 = uv0;
                            v3 = v0;
                            break;
                        case 2:
                            v2.x = _vRect.xMin + fvW;
                            uv2.x = _uvRect.xMin + fuvW;
                            uv3 = uv2;
                            v3 = v2;
                            break;
                        case 3:
                            v2.y = _vRect.yMin + fvH;
                            uv2.y = _uvRect.yMin + fuvH;
                            uv1 = uv2;
                            v1 = v2;
                            break;
                        }
                    }

                    FillBuffer (ref v0, ref v1, ref v2, ref v3, ref uv0, ref uv1, ref uv2, ref uv3, ref color);
                }
            }
            GetBuffers (mesh);
        }