Example #1
0
 /// <summary>
 /// 通过skin把所有的texture打包到一个图集
 /// </summary>
 /// <returns>The repacked from skin.</returns>
 /// <param name="skin">Skin.</param>
 /// <param name="newName">New name.</param>
 /// <param name="shader">Shader.</param>
 /// <param name="outputMaterial">Output material.</param>
 /// <param name="outputTexture">Output texture.</param>
 /// <param name="maxAtlasSize">Max atlas size.</param>
 /// <param name="padding">Padding.</param>
 /// <param name="textureFormat">Texture format.</param>
 /// <param name="mipmaps">If set to <c>true</c> mipmaps.</param>
 /// <param name="materialPropertySource">Material property source.</param>
 /// <param name="clearCache">If set to <c>true</c> clear cache.</param>
 private void GetRepackedFromSkin(CombineTextureData combineTextureData, Skin skin, string newName, Shader shader, int maxAtlasSize = SpineConstValue.smallAtlasSize, int padding = SpineConstValue.atlasPadding, TextureFormat textureFormat = SpineConstValue.textureFormat, bool mipmaps = SpineConstValue.atlasMipMaps, Material materialPropertySource = null, bool clearCache = SpineConstValue.atlasClearCache)
 {
     //用CPU合并图集
     //return AtlasUtilities.GetRepackedSkin(skin, newName, shader, out outputMaterial, out outputTexture);
     //用GPU合并图集
     SpineChangeCommonTools.GetSpineRepackedSkin(combineTextureData, skin, newName, shader, maxAtlasSize, textureFormat, mipmaps, materialPropertySource, clearCache);
 }
Example #2
0
 /// <summary>
 /// 替换完attachment数据之后进行刷新
 /// </summary>
 private void UpdateRoleEquipment(SkeletonAnimation skeletonAnim, CombineTextureData combineTextureData)
 {
     //合并图集
     if (null != combineTextureData.combineCoroutine)
     {
         GameManager.Instance.StopCoroutine(combineTextureData.combineCoroutine);
     }
     combineTextureData.combineCoroutine = GameManager.Instance.StartCoroutine(TexturePackaged(skeletonAnim, combineTextureData));
 }
Example #3
0
 /// <summary>
 /// 重置
 /// </summary>
 private void ResetValue(CombineTextureData combineTextureData)
 {
     endIndex         = 0;
     beginIndex       = 0;
     currentAllWidth  = 0;
     currentAllHeight = 0;
     lineHeightList   = new List <float> ();
     combineTextureData.smallAtlasNumber = 0;
 }
Example #4
0
 private void DestroyResources(CombineTextureData combineTextureData)
 {
     if (null != combineTextureData.resultData)
     {
         if (null != combineTextureData.resultData.lastRenderTex)
         {
             RenderTexture.ReleaseTemporary(combineTextureData.resultData.lastRenderTex);
             combineTextureData.resultData.lastRenderTex.Release();
             combineTextureData.resultData.lastRenderTex = null;
         }
     }
     UnityEngine.Resources.UnloadUnusedAssets();
 }
Example #5
0
        //合并小的图集为一张大图
        private IEnumerator FinallyPackage(CombineTextureData combineTextureData, Dictionary <RenderTexture, TextureClass[]> dic, Action <PackagedTextureResult> finishCallBack)
        {
            PackagedTextureResult result          = new PackagedTextureResult();
            TextureSize           size            = GetAtlasSize(combineTextureData.smallAtlasNumber);
            MaxRectsBinPack       maxRectsBinPack = new MaxRectsBinPack(size.x, size.y, false);
            Material            material          = InitMaterial();
            RenderTexture       render            = RenderTexture.GetTemporary(size.x, size.y, 0, RenderTextureFormat.ARGB4444);
            List <TextureClass> tc = new List <TextureClass> ();

            Graphics.Blit(null, null, material, 0);
            foreach (KeyValuePair <RenderTexture, TextureClass[]> keys in dic)
            {
                RenderTexture tempTexture = keys.Key;
                Rect          rect        = maxRectsBinPack.Insert(tempTexture.width, tempTexture.height, MaxRectsBinPack.FreeRectChoiceHeuristic.RectBestAreaFit);
                //重新计算位置
                for (int i = 0; i < keys.Value.Length; i++)
                {
                    keys.Value[i].rect = new Rect(rect.x + keys.Value[i].rect.x, rect.y + keys.Value[i].rect.y, keys.Value[i].rect.width, keys.Value[i].rect.height);
                    tc.Add(keys.Value[i]);
                }
                Rect scaleRect = GetScaleRect(rect, size.x, size.y);
                material.SetTexture("_MainTex", tempTexture);
                material.SetFloat("_ScaleX", scaleRect.width);
                material.SetFloat("_ScaleY", scaleRect.height);
                material.SetFloat("_OffsetX", scaleRect.x);
                material.SetFloat("_OffsetY", scaleRect.y);
                Graphics.Blit(null, render, material, 1);
                //归还小图集RenderTexture
                RenderTexture.ReleaseTemporary(tempTexture);
                tempTexture.Release();
                tempTexture = null;
                yield return(null);
            }
            Graphics.Blit(null, null, material, 0);
            for (int i = 0; i < tc.Count; i++)
            {
                tc[i].rect = GetUVRect(GetScaleRect(tc[i].rect, size.x, size.y), tc[i].textureSize, size.x, size.y);
            }
            result.renderTexture = render;
            result.textureInfo   = tc.ToArray();
            if (null != finishCallBack)
            {
                finishCallBack.Invoke(result);
            }
        }
 /// <summary>
 /// 初始化角色的插槽和附件信息
 /// </summary>
 /// <param name="successfulCallBack">Successful call back.</param>
 /// <param name="failCallBack">Fail call back.</param>
 public void SpineInitRoleSlotAttachment(RoleAnaimationData animationData, SkeletonAnimation skeletonAnim, RoleEquipmentData tempData, CombineTextureData combineTextureData, Dictionary <int, List <string> > TempSlotAttachmentDic, List <Texture2D> destoryTextureList, Action <bool> setRoleStatus, bool isTP, bool isHide, Action <string> failCallBack = null)
 {
     if (null != setRoleStatus && isHide)
     {
         setRoleStatus.Invoke(false);
     }
     if (null != combineTextureData.initRoleCoroutine)
     {
         GameManager.Instance.StopCoroutine(combineTextureData.initRoleCoroutine);
     }
     combineTextureData.initRoleCoroutine = GameManager.Instance.StartCoroutine(spineChangeCoreLogic.InitRoleEquipment(animationData, skeletonAnim, tempData, combineTextureData, TempSlotAttachmentDic, destoryTextureList, setRoleStatus, failCallBack, isTP));
 }
 /// <summary>
 /// 角色换装
 /// </summary>
 /// <param name="slotStr">Slot string.</param>
 /// <param name="texture2D">Texture2 d.</param>
 /// <param name="successfulCallBack">Successful call back.</param>
 /// <param name="failCallBack">Fail call back.</param>
 public void SpineRoleChange(RoleAnaimationData animationData, SkeletonAnimation skeletonAnim, CombineTextureData combineTextureData, Dictionary <int, List <string> > slotAttachmentDic, RoleEquipmentData equipmentData, RoleEquipmentItem equipmentItem, bool isTexturePackaged, List <Texture2D> destoryTextureList, Action <bool> setRoleStatus, Action <string> failCallBack = null)
 {
     if (null != setRoleStatus)
     {
         setRoleStatus.Invoke(false);
     }
     System.DateTime time1 = System.DateTime.Now;
     SpineChangeDataLogic.Instance.GetRoleEquipmentObject(equipmentItem, (UnityEngine.Object o) => {
         //SpineChangeDataLogic.Instance.SaveRoleEquipmentToServerAndLocal (equipmentData, equipmentItem);
         if (null != combineTextureData.changeRoleCoroutine)
         {
             GameManager.Instance.StopCoroutine(combineTextureData.changeRoleCoroutine);
         }
         combineTextureData.changeRoleCoroutine = GameManager.Instance.StartCoroutine(spineChangeCoreLogic.Change(animationData, skeletonAnim, combineTextureData, slotAttachmentDic, o as EquipmentObject, isTexturePackaged, destoryTextureList, setRoleStatus, failCallBack));
         System.DateTime time2 = System.DateTime.Now;
         if (null != GameObject.FindObjectOfType <ChangeTest> ())
         {
             GameObject.FindObjectOfType <ChangeTest> ().text.text += "加载AB用时:" + (time2 - time1).TotalMilliseconds + "\n";
         }
     });
 }
Example #8
0
        private System.Collections.IEnumerator TexturePackaged(SkeletonAnimation skeleAnim, CombineTextureData combineTextureData)
        {
            combineTextureData.isFinished = false;
            Skin skin = new Skin(SpineConstValue.NewSkinname);

            skin.Append(skeleAnim.skeleton.data.DefaultSkin);
            System.DateTime time1 = System.DateTime.Now;
            GetRepackedFromSkin(combineTextureData, skin, SpineConstValue.NewSkinname, Shader.Find(SpineConstValue.shaderPath));
            while (!combineTextureData.isFinished)
            {
                yield return(null);
            }
            System.DateTime time2 = System.DateTime.Now;
            if (null != GameObject.FindObjectOfType <ChangeTest> ())
            {
                GameObject.FindObjectOfType <ChangeTest> ().text.text += "合并图集用时:" + (time2 - time1).TotalMilliseconds + "\n";
            }
            if (combineTextureData.isFinished)
            {
                skeleAnim.skeleton.SetSkin(combineTextureData.resultData.skin);
                skeleAnim.skeleton.data.defaultSkin = combineTextureData.resultData.skin;
                combineTextureData.resultData.self.DestroyEquipment();
                DestroyResources(combineTextureData);
            }
        }
Example #9
0
        /// <summary>
        /// 换装
        /// </summary>
        /// <returns>The change.</returns>
        /// <param name="item">装备数据</param>
        public System.Collections.IEnumerator Change(RoleAnaimationData animationData, SkeletonAnimation skeletonAnim, CombineTextureData combineTextureData, Dictionary <int, List <string> > slotAttachmentDic, EquipmentObject eo, bool isTexturePackage, List <Texture2D> destoryTextureList, Action <bool> setRoleStatus, Action <string> failCallBack, bool isCreateInit = false)
        {
            #if UNITY_ANDROID
            destoryTextureList.Add(eo.equipmentTexture_Alpha);
            destoryTextureList.Add(eo.equipmentTexture_RGB);
            #elif UNITY_IPHONE || UNITY_EDITOR
            destoryTextureList.Add(eo.equipmentTexture);
            #endif
            SpineReadJsonDataLogic.Instance.GetSpineJsonObjectDic(eo.equipmentJsonAsset);
            List <AtlasRegion>     regions = SpineChangeDataLogic.Instance.GetEquipmentAtlasRegions(eo, SpineChangeDataLogic.Instance.GetEquipmentMaterial());
            List <string>          slotAttachmentNameList = new List <string> ();
            List <AtlasRegionData> sortData = SpineCreateAttachment.Instance.GetSortRegionList(skeletonAnim, regions, slotAttachmentDic);
            //更换皮肤数据里面的Attachment字典KeyValuePair<Skin.AttachmentKeyTuple, Attachment >(换成我们自己创建的)
            for (int i = 0; i < sortData.Count; i++)
            {
                // List<int> slotIndexList = GetSlotListForSlotAttachmentDic (slotAttachmentDic, regions[i].name);
                // for (int j = 0; j < slotIndexList.Count; j++) {
                //     Attachment tempattachment = GetAttachmentByType (skeletonAnim, SpineChangeDataLogic.Instance.GetAttachmentType (skeletonAnim, slotIndexList[j] + "|" + regions[i].name), slotIndexList[j] + "|" + regions[i].name, regions[i]);
                //     if (null == tempattachment) {
                //         yield return null;
                //     }
                //     skeletonAnim.Skeleton.Data.DefaultSkin.AddAttachment (slotIndexList[j], regions[i].name, tempattachment);
                //     slotAttachmentNameList.Add (SpineChangeCoreLogic.Instance.GetSlotNameBySlotIndex (skeletonAnim, slotIndexList[j]) + "$" + tempattachment.Name);
                // }
                Attachment tempattachment = GetAttachmentByType(skeletonAnim, sortData[i].type, sortData[i].allName, sortData[i].region);
                if (null == tempattachment)
                {
                    yield return(null);
                }
                skeletonAnim.Skeleton.Data.DefaultSkin.AddAttachment(SpineChangeDataLogic.Instance.GetSlotIndexFromAllAttachmentName(sortData[i].allName), SpineChangeDataLogic.Instance.GetAttachmentFromAllAttachmnetName(sortData[i].allName), tempattachment);
                slotAttachmentNameList.Add(SpineChangeCoreLogic.Instance.GetSlotNameBySlotIndex(skeletonAnim, SpineChangeDataLogic.Instance.GetSlotIndexFromAllAttachmentName(sortData[i].allName)) + "$" + tempattachment.Name);
            }
            //替换完附件之后刷新(有的附件可以不用刷新)
            if (null == skeletonAnim)
            {
                yield break;
            }
            skeletonAnim.Skeleton.SetToSetupPose();
            System.DateTime time1 = System.DateTime.Now;
            //重组Json
            yield return(GameManager.Instance.StartCoroutine(SpineReadJsonDataLogic.Instance.CreateNewRoleJsonDic(animationData, eo.equipmentJsonAsset, slotAttachmentNameList, skeletonAnim, setRoleStatus)));

            yield return(null);

            System.DateTime time2 = System.DateTime.Now;
            if (null != GameObject.FindObjectOfType <ChangeTest> ())
            {
                GameObject.FindObjectOfType <ChangeTest> ().text.text += "重组Json的时间:" + (time2 - time1).TotalMilliseconds + "\n";
            }
            //当不是创建时change的话就判断是否合图集
            if (!isCreateInit)
            {
                if (null != roleObject)
                {
                    setRoleStatus.Invoke(true);
                }
                if (isTexturePackage)
                {
                    UpdateRoleEquipment(skeletonAnim, combineTextureData);
                }
                else
                {
                    DestroyResources(combineTextureData);
                }
            }
        }
Example #10
0
 /// <summary>
 /// 初始化角色的插槽附件
 /// </summary>
 /// <returns><c>true</c>, if role slot attachment info was inited, <c>false</c> otherwise.</returns>
 public System.Collections.IEnumerator InitRoleEquipment(RoleAnaimationData animationData, SkeletonAnimation skeletonAnim, RoleEquipmentData tempData, CombineTextureData combineTextureData, Dictionary <int, List <string> > TempSlotAttachmentDic, List <Texture2D> destoryTextureList, Action <bool> setRoleStatus, Action <string> failCallBack, bool isTP)
 {
     if (skeletonAnim == null)
     {
         if (null != failCallBack)
         {
             failCallBack.Invoke("<-初始化角色的插槽和附件信息失败->");
         }
         yield break;
     }
     System.DateTime time1 = System.DateTime.Now;
     for (int i = 0; i < tempData.RoleEquipmentItems.Count; i++)
     {
         // if(tempData.RoleEquipmentItems[i].EquipmentType == RoleEquipmentType.RoleHat || tempData.RoleEquipmentItems[i].EquipmentType == RoleEquipmentType.RoleGlasses)
         //     continue;
         EquipmentRes res = SpineChangeDataLogic.Instance.GetRoleEquipmentObject(tempData.RoleEquipmentItems[i], null);
         while (!res.isDone)
         {
             yield return(null);
         }
         combineTextureData.changeRoleCoroutine = GameManager.Instance.StartCoroutine(Change(animationData, skeletonAnim, combineTextureData, TempSlotAttachmentDic, res.GetRes(), isTP, destoryTextureList, setRoleStatus, failCallBack, true));
         yield return(combineTextureData.changeRoleCoroutine);
     }
     System.DateTime time2 = System.DateTime.Now;
     if (null != GameObject.FindObjectOfType <ChangeTest> ())
     {
         GameObject.FindObjectOfType <ChangeTest> ().text.text += "创建角色并初始化用时:" + (time2 - time1).TotalMilliseconds + "\n";
     }
     if (null != roleObject)
     {
         setRoleStatus.Invoke(true);
     }
     if (isTP)
     {
         //需要合图集
         UpdateRoleEquipment(skeletonAnim, combineTextureData);
     }
     else
     {
         DestroyResources(combineTextureData);
     }
 }
Example #11
0
        /// <summary>
        /// 通过skeletonDataAsset创建角色
        /// </summary>
        /// <returns><c>true</c>, if spine role was created, <c>false</c> otherwise.</returns>
        /// <param name="skeletonDataAsset">Skeleton data asset.</param>
        /// <param name="animationName">Animation name.</param>
        /// <param name="skinName">Skin name.</param>
        /// <param name="pos">Position.</param>
        private System.Collections.IEnumerator Create(SpineAvatarType avatarType, EquipmentObject eo, SkeletonDataAsset skeletonDataAsset, string roleGameObjectName, string animationName, string skinName, bool loop, RoleEquipmentData data, Action <Avatar> createSucCallBack, Action <string> failCallBack, Action <bool> createQueueCallBack, bool isTP)
        {
            if (skeletonDataAsset == null)
            {
                if (failCallBack != null)
                {
                    failCallBack.Invoke("<-创建角色失败->");
                }
                yield break;
            }
            GameObject roleSpine = new GameObject {
                name = roleGameObjectName
            };

            roleObject        = roleSpine;
            skeletonAnimation = SkeletonAnimation.AddToGameObject(roleSpine, skeletonDataAsset);
            skeletonAnimation.Initialize(false);
            skeletonAnimation.Skeleton.SetSkin(skinName);
            skeletonAnimation.state.SetAnimation(SpineConstValue.TrackIndex, animationName, loop);
            CreateSlotAttachmentDic(skeletonAnimation.Skeleton.Data.DefaultSkin.Attachments);
            if (null == data)
            {
                equipmentData = new RoleEquipmentData();
                equipmentData.RoleEquipmentItems = new List <RoleEquipmentItem> ();
            }
            else
            {
                equipmentData = data;
            }
            CombineTextureData combineTextureData = new CombineTextureData();

            combineTextureData.resultData = new CombineFinishedData();
            RoleAnaimationData rad = new RoleAnaimationData {
                roleJsonStr = eo.equipmentJsonAsset.text
            };
            Avatar avatar = new SpineAvatar(equipmentData, skeletonAnimation, slotAttachmentDic, rad, combineTextureData, avatarType, roleObject, eo.equipmentJsonAsset.text);

            combineTextureData.resultData.self = avatar;
            if (createSucCallBack != null)
            {
                if (null != roleSpine)
                {
                    roleSpine.SetActive(false);
                    createSucCallBack.Invoke(avatar);
                }
            }
            //初始化角色的所有服装信息
            if (equipmentData.RoleEquipmentItems.Count > 0)
            {
                if (null != combineTextureData.initRoleCoroutine)
                {
                    GameManager.Instance.StopCoroutine(combineTextureData.initRoleCoroutine);
                }
                combineTextureData.initRoleCoroutine = GameManager.Instance.StartCoroutine(InitRoleEquipment(rad, skeletonAnimation, equipmentData, combineTextureData, slotAttachmentDic, avatar.GetDestoryTextureList, roleSpine.SetActive, null, isTP));
                yield return(combineTextureData.initRoleCoroutine);
            }
            else
            {
                roleSpine.SetActive(true);
            }
            if (null != createQueueCallBack)
            {
                createQueueCallBack.Invoke(true);
            }
        }
Example #12
0
        public IEnumerator GetRenderTextureByTexturesOptimize(CombineTextureData combineTextureData, List <Spine.AtlasRegion> regions, int renderTextureSize, Action <PackagedTextureResult> finishCallBack)
        {
            ResetValue(combineTextureData);
            currentAtlasSize = renderTextureSize;
            List <TextureClass> textureList = new List <TextureClass>();
            //GetTextureClassList (textures);
            List <TextureClass> currentTextureList         = new List <TextureClass> ();
            Material            material                   = InitMaterial();
            MaxRectsBinPack     maxRectsBinPack            = new MaxRectsBinPack(currentAtlasSize, currentAtlasSize, false);
            RenderTexture       render                     = RenderTexture.GetTemporary(currentAtlasSize, currentAtlasSize, 0, RenderTextureFormat.ARGB4444);
            Dictionary <RenderTexture, TextureClass[]> dic = new Dictionary <RenderTexture, TextureClass[]> ();

            Graphics.Blit(null, null, material, 0);
            for (int i = 0; i < regions.Count; i++)
            {
                UnityEngine.Profiling.Profiler.BeginSample("SpineChange_ToTexture");
                RenderTexture regionTex = Spine.Unity.Modules.AttachmentTools.AtlasUtilities.ToTexture(regions[i]);
                UnityEngine.Profiling.Profiler.EndSample();
                textureList.Add(new TextureClass {
                    index = i, texture = regionTex, textureSize = new TextureSize {
                        x = regionTex.width, y = regionTex.height
                    }
                });
                if (!IsSuitableTexture(textureList[i].texture))
                {
                    throw new System.NotSupportedException("[--散图 " + textureList[i].texture.name + " 的大小超出单位图集的大小,请修改散图或单位图集的大小(SpineConstValue.smallAtlasSize)--]");
                }
                Rect posRect = maxRectsBinPack.Insert(textureList[i].texture.width, textureList[i].texture.height, MaxRectsBinPack.FreeRectChoiceHeuristic.RectBestAreaFit);
                if (posRect.height <= 0)
                {
                    //保存本次的图集和散图的位置信息
                    TextureClass[] array1 = new TextureClass[currentTextureList.Count];
                    currentTextureList.CopyTo(array1);
                    dic.Add(render, array1);
                    currentTextureList.Clear();
                    Graphics.Blit(null, null, material, 0);
                    //初始化参数进行下一次的合图
                    material        = InitMaterial();
                    maxRectsBinPack = new MaxRectsBinPack(currentAtlasSize, currentAtlasSize, false);
                    render          = RenderTexture.GetTemporary(currentAtlasSize, currentAtlasSize, 0, RenderTextureFormat.ARGB4444);
                    Graphics.Blit(null, null, material, 0);
                    textureList.RemoveAt(i);
                    --i;
                    combineTextureData.smallAtlasNumber++;
                    continue;
                }
                Rect scaleRect = GetScaleRect(posRect, renderTextureSize, renderTextureSize);
                material.SetTexture("_MainTex", textureList[i].texture);
                material.SetFloat("_ScaleX", scaleRect.width);
                material.SetFloat("_ScaleY", scaleRect.height);
                material.SetFloat("_OffsetX", scaleRect.x);
                material.SetFloat("_OffsetY", scaleRect.y);
                Graphics.Blit(null, render, material, 1);
                textureList[i].rect = posRect;
                currentTextureList.Add(textureList[i]);
                //卸载散图资源
                // textureList[i].texture = null;
                // UnityEngine.Resources.UnloadUnusedAssets();
                RenderTexture.ReleaseTemporary(textureList[i].texture);
                textureList[i].texture.Release();
                textureList[i].texture = null;
                yield return(null);
            }
            Graphics.Blit(null, null, material, 0);
            TextureClass[] array2 = new TextureClass[currentTextureList.Count];
            currentTextureList.CopyTo(array2);
            dic.Add(render, array2);
            if (null != combineTextureData.combineCoroutineBig)
            {
                GameManager.Instance.StopCoroutine(combineTextureData.combineCoroutineBig);
            }
            combineTextureData.combineCoroutineBig = GameManager.Instance.StartCoroutine(FinallyPackage(combineTextureData, dic, finishCallBack));
        }
        public static void GetSpineRepackedSkin(CombineTextureData combineTextureData, Skin skin, string newName, Shader shader, int maxAtlasSize, TextureFormat textureFormat, bool mipMaps, Material materialPropertySource, bool clearCache)
        {
            if (skin == null)
            {
                throw new System.NullReferenceException("Skin was null");
            }
            var skinAttachments = skin.Attachments;
            var newSkin         = new Skin(newName);

            var existingRegions     = new Dictionary <AtlasRegion, int> ();
            var regionIndexes       = new List <int> ();
            var repackedAttachments = new List <Attachment> ();
            var texturesToPack      = new List <Texture2D> ();
            var originalRegions     = new List <AtlasRegion> ();
            int newRegionIndex      = 0;

            foreach (var kvp in skinAttachments)
            {
                var newAttachment = kvp.Value.GetClone(true);
                if (IsRenderable(newAttachment))
                {
                    var region = newAttachment.GetAtlasRegion();
                    int existingIndex;
                    if (existingRegions.TryGetValue(region, out existingIndex))
                    {
                        regionIndexes.Add(existingIndex);  // Store the region index for the eventual new attachment.
                    }
                    else
                    {
                        originalRegions.Add(region);
                        //texturesToPack.Add (region.ToTexture ()); // Add the texture to the PackTextures argument
                        existingRegions.Add(region, newRegionIndex); // Add the region to the dictionary of known regions
                        regionIndexes.Add(newRegionIndex);           // Store the region index for the eventual new attachment.
                        newRegionIndex++;
                    }
                    repackedAttachments.Add(newAttachment);
                }
                var key = kvp.Key;
                newSkin.AddAttachment(key.slotIndex, key.name, newAttachment);
            }
            //合并图集
            if (null != combineTextureData.combineCoroutineSmall)
            {
                //region.ToTexture ()???
                GameManager.Instance.StopCoroutine(combineTextureData.combineCoroutineSmall);
            }
            combineTextureData.combineCoroutineSmall = GameManager.Instance.StartCoroutine(CombineTexturesTool.Instance.GetRenderTextureByTexturesOptimize(combineTextureData, originalRegions, maxAtlasSize, (PackagedTextureResult result) => {
                RenderTexture renderTexture        = result.renderTexture;
                TextureClass[] outTextureClassList = result.textureInfo;
                var newMaterial = new Material(shader);
                if (materialPropertySource != null)
                {
                    newMaterial.CopyPropertiesFromMaterial(materialPropertySource);
                    newMaterial.shaderKeywords = materialPropertySource.shaderKeywords;
                }

                newMaterial.name        = newName;
                newMaterial.mainTexture = renderTexture;
                var page  = newMaterial.ToSpineAtlasPage();
                page.name = newName;

                var repackedRegions = new List <AtlasRegion> ();
                for (int i = 0, n = originalRegions.Count; i < n; i++)
                {
                    var oldRegion = originalRegions[i];
                    var newRegion = UVRectToAtlasRegion(GetTargetRectByIndex(outTextureClassList, i), oldRegion.name, page, oldRegion.offsetX, oldRegion.offsetY, oldRegion.rotate);
                    repackedRegions.Add(newRegion);
                }

                for (int i = 0, n = repackedAttachments.Count; i < n; i++)
                {
                    var a = repackedAttachments[i];
                    a.SetRegion(repackedRegions[regionIndexes[i]]);
                }

                if (clearCache)
                {
                    AtlasUtilities.ClearCache();
                }
                if (null != combineTextureData.resultData)
                {
                    combineTextureData.resultData.skin     = null;
                    combineTextureData.resultData.material = null;
                    if (null != combineTextureData.resultData.currentRenderTex)
                    {
                        combineTextureData.resultData.lastRenderTex = combineTextureData.resultData.currentRenderTex;
                    }
                }
                combineTextureData.resultData.skin             = newSkin;
                combineTextureData.resultData.material         = newMaterial;
                combineTextureData.resultData.currentRenderTex = renderTexture;
                combineTextureData.isFinished = true;
            }));
        }