Пример #1
0
    public void OnGroupAtlases(BuildTarget target, UnityEditor.Sprites.PackerJob job,
                               int[] textureImporterInstanceIDs)
    {
        List <Entry> entries = new List <Entry>();

        foreach (int instanceID in textureImporterInstanceIDs)
        {
            TextureImporter ti = EditorUtility.InstanceIDToObject(instanceID) as TextureImporter;

            TextureFormat desiredFormat;
            ColorSpace    colorSpace;
            int           compressionQuality;
            ti.ReadTextureImportInstructions(target, out desiredFormat, out colorSpace, out compressionQuality);

            TextureImporterSettings tis = new TextureImporterSettings();
            ti.ReadTextureSettings(tis);

            Sprite[] sprites =
                AssetDatabase.LoadAllAssetRepresentationsAtPath(ti.assetPath)
                .Select(x => x as Sprite)
                .Where(x => x != null)
                .ToArray();
            foreach (Sprite sprite in sprites)
            {
                Entry entry = new Entry();
                entry.sprite              = sprite;
                entry.settings.format     = desiredFormat;
                entry.settings.colorSpace = colorSpace;
                // Use Compression Quality for Grouping later only for Compressed Formats. Otherwise leave it Empty.
                entry.settings.compressionQuality = IsCompressedFormat(desiredFormat) ? compressionQuality : 0;
                entry.settings.filterMode         = Enum.IsDefined(typeof(FilterMode), ti.filterMode)
                    ? ti.filterMode
                    : FilterMode.Bilinear;
                entry.settings.maxWidth  = 2048;
                entry.settings.maxHeight = 2048;

                entry.settings.generateMipMaps = ti.mipmapEnabled;
                entry.settings.enableRotation  = AllowRotationFlipping;
                if (ti.mipmapEnabled)
                {
                    entry.settings.paddingPower = kDefaultPaddingPower;
                }
                else
                {
                    entry.settings.paddingPower = (uint)EditorSettings.spritePackerPaddingPower;
                }
#if ENABLE_ANDROID_ATLAS_ETC1_COMPRESSION
                entry.settings.allowsAlphaSplitting = ti.GetAllowsAlphaSplitting();
#endif //ENABLE_ANDROID_ATLAS_ETC1_COMPRESSION

                entry.atlasName   = ParseAtlasName(ti.spritePackingTag);
                entry.packingMode = GetPackingMode(ti.spritePackingTag, tis.spriteMeshType);
                entry.anisoLevel  = ti.anisoLevel;

                entries.Add(entry);
            }

            Resources.UnloadAsset(ti);
        }

        // First split sprites into groups based on atlas name
        var atlasGroups =
            from e in entries
            group e by e.atlasName;
        foreach (var atlasGroup in atlasGroups)
        {
            int page = 0;

            // Then split those groups into smaller groups based on texture settings
            var settingsGroups =
                from t in atlasGroup
                group t by t.settings;
            foreach (var settingsGroup in settingsGroups)
            {
                string atlasName = atlasGroup.Key;
                if (settingsGroups.Count() > 1)
                {
                    atlasName += string.Format(" (Group {0})", page);
                }

                UnityEditor.Sprites.AtlasSettings settings = settingsGroup.Key;
                settings.anisoLevel = 1;
                // Use the highest aniso level from all entries in this atlas
                if (settings.generateMipMaps)
                {
                    foreach (Entry entry in settingsGroup)
                    {
                        if (entry.anisoLevel > settings.anisoLevel)
                        {
                            settings.anisoLevel = entry.anisoLevel;
                        }
                    }
                }

                // 需要分离alpha通道的情况
                if (TextureUtility.IsTransparent(settings.format))
                {
                    if (!CustomAtlasConfig.ShouldKeepAlpha(atlasName))
                    {
                        if (CustomAtlasConfig.ShouldUseOutputAtlasTexture(atlasName))
                        {
                            settings.format = TextureFormat.RGB24;
                        }
                        else
                        {
                            settings.format = TextureUtility.TransparentToNoTransparentFormat(settings.format);
                        }
                    }
                }

                job.AddAtlas(atlasName, settings);
                foreach (Entry entry in settingsGroup)
                {
                    job.AssignToAtlas(atlasName, entry.sprite, entry.packingMode, SpritePackingRotation.None);
                }

                ++page;
            }
        }
    }
    private static void WriteSpritesRenderData(List <AtlasEntry> atlasEntries)
    {
        if (atlasEntries == null)
        {
            return;
        }

        foreach (var atlasEntry in atlasEntries)
        {
            foreach (var spriteEntry in atlasEntry.SpriteEntries)
            {
                var spr = spriteEntry.Sprite;
                var so  = new SerializedObject(spr);

                // 是否使用导出的贴图文件
                string    atlasName = spriteEntry.AtlasName;
                Texture2D atlasTexture;
                if (CustomAtlasConfig.ShouldUseOutputAtlasTexture(atlasName))
                {
                    atlasTexture = atlasEntry.OutputTexture;
                }
                else
                {
                    atlasTexture = atlasEntry.Texture;
                }
                var alphaTexture = spriteEntry.AlphaTexture;

                // 获取散图属性
                var rect              = so.FindProperty("m_Rect").rectValue;
                var pivot             = so.FindProperty("m_Pivot").vector2Value;
                var pixelsToUnits     = so.FindProperty("m_PixelsToUnits").floatValue;
                var tightRect         = so.FindProperty("m_RD.textureRect").rectValue;
                var originSettingsRaw = so.FindProperty("m_RD.settingsRaw").intValue;

                // 散图(tight)在散图(full rect)中的位置和宽高
                var tightOffset = new Vector2(tightRect.x, tightRect.y);
                var tightWidth  = tightRect.width;
                var tightHeight = tightRect.height;

                // 计算散图(full rect)在图集中的rect和offset
                var fullRectInAtlas = GetTextureFullRectInAtlas(atlasTexture,
                                                                spriteEntry.Uvs, spriteEntry.AtlasUvs);
                var fullRectOffsetInAtlas = new Vector2(fullRectInAtlas.x, fullRectInAtlas.y);

                // 计算散图(tight)在图集中的rect
                var tightRectInAtlas = new Rect(fullRectInAtlas.x + tightOffset.x,
                                                fullRectInAtlas.y + tightOffset.y, tightWidth, tightHeight);

                // 计算uvTransform
                // x: Pixels To Unit X
                // y: 中心点在图集中的位置X
                // z: Pixels To Unit Y
                // w: 中心点在图集中的位置Y
                var uvTransform = new Vector4(
                    pixelsToUnits,
                    rect.width * pivot.x + fullRectOffsetInAtlas.x,
                    pixelsToUnits,
                    rect.height * pivot.y + fullRectOffsetInAtlas.y);

                // 计算settings
                // 0位:packed。1表示packed,0表示不packed
                // 1位:SpritePackingMode。0表示tight,1表示rectangle
                // 2-5位:SpritePackingRotation。0表示不旋转,1表示水平翻转,2表示竖直翻转,3表示180度旋转,4表示90度旋转
                // 6位:SpriteMeshType。0表示full rect,1表示tight
                // 67 = SpriteMeshType(tight) + SpritePackingMode(rectangle) + packed
                var settingsRaw = 67;

                // 写入RenderData
                so.FindProperty("m_RD.texture").objectReferenceValue      = atlasTexture;
                so.FindProperty("m_RD.alphaTexture").objectReferenceValue = alphaTexture;
                so.FindProperty("m_RD.textureRect").rectValue             = tightRectInAtlas;
                so.FindProperty("m_RD.textureRectOffset").vector2Value    = tightOffset;
                so.FindProperty("m_RD.atlasRectOffset").vector2Value      = fullRectOffsetInAtlas;
                so.FindProperty("m_RD.settingsRaw").intValue     = settingsRaw;
                so.FindProperty("m_RD.uvTransform").vector4Value = uvTransform;
                so.ApplyModifiedProperties();

                // 备份原数据,用于恢复
                spriteEntry.OriginTextureRect = tightRect;
                spriteEntry.OriginSettingsRaw = originSettingsRaw;
            }
        }
    }