void CreateNewAtlas() { if (AtlasConfig.kUsingCopyTexture) { Texture2D tex2D = new Texture2D(mWidth, mHeight, AtlasConfig.kTextureFormat, false, true); tex2D.filterMode = FilterMode.Bilinear; //tex2D.alphaIsTransparency = true; tex2D.SetPixels32(0, 0, mWidth, mWidth, tmpColor); tex2D.Apply(false); m_tex2DList.Add(tex2D); } else { RenderTexture renderTexture = CommonUtils.CreateDyanmicAtlasRenderTexture(mWidth, mHeight, 0, AtlasConfig.kRenderTextureFormat); renderTexture.name = string.Format("DynamicAtlas {0:G} -- {0:G}", mWidth, mHeight); renderTexture.DiscardContents(true, true); Material mDefaultMaterial = new Material(Shader.Find("UI/Default")); mDefaultMaterial.mainTexture = renderTexture; m_MaterialList.Add(mDefaultMaterial); mMaterial.SetVector(mBlitParamId, new Vector4(0, 0, 1, 1)); Texture2D cleared_texture = new Texture2D(2, 2, AtlasConfig.kTextureFormat, false); Graphics.Blit(cleared_texture, renderTexture, mMaterial); m_RenderTexList.Add(renderTexture); } IntegerRectangle area = DynamicAtlasManager.Instance.AllocateRectangle(0, 0, mWidth, mHeight); List <IntegerRectangle> list = new List <IntegerRectangle>(); list.Add(area); mFreeAreasList.Add(list); }
IntegerRectangle OnMergeAreaRecursive(IntegerRectangle target, int texIndex) { List <IntegerRectangle> data = mFreeAreasList[texIndex]; IntegerRectangle mergeRect = null; foreach (var freeArea in data) { if (target.right == freeArea.x && target.y == freeArea.y && target.height == freeArea.height) //右 { mergeRect = DynamicAtlasManager.Instance.AllocateRectangle(target.x, target.y, target.width + freeArea.width, target.height); } else if (target.x == freeArea.x && target.top == freeArea.y && target.width == freeArea.width)//上 { mergeRect = DynamicAtlasManager.Instance.AllocateRectangle(target.x, target.y, target.width, target.height + freeArea.height); } else if (target.x == freeArea.right && target.y == freeArea.y && target.height == freeArea.height)//左 { mergeRect = DynamicAtlasManager.Instance.AllocateRectangle(freeArea.x, freeArea.y, freeArea.width + target.width, freeArea.height); } else if (target.x == freeArea.x && target.y == freeArea.top && target.width == freeArea.width)//下 { mergeRect = DynamicAtlasManager.Instance.AllocateRectangle(freeArea.x, freeArea.y, target.width, target.height + freeArea.height); } if (mergeRect != null) { RemoveFreeArea(texIndex, freeArea); return(mergeRect); } } if (mergeRect == null) { AddFreeArea(texIndex, target); } return(mergeRect); }
private void filterSelfSubAreas(int index) { List <IntegerRectangle> areas = mFreeAreasList[index]; for (int i = areas.Count - 1; i >= 0; i--) { IntegerRectangle filtered = areas[i]; for (int j = areas.Count - 1; j >= 0; j--) { if (i != j) { IntegerRectangle area = areas[j]; if (filtered.x >= area.x && filtered.y >= area.y && filtered.right <= area.right && filtered.top <= area.top) { DynamicAtlasManager.Instance.ReleaseRectangle(filtered); IntegerRectangle topOfStack = areas.Pop(); if (i < areas.Count) { // Move the one on the top to the freed position areas[i] = topOfStack; } break; } } } } }
public IntegerRectangle InsertArea(int width, int height, out int index) { IntegerRectangle result; bool justRightSize; IntegerRectangle freeArea = GetFreeArea(width, height, out index, out justRightSize); if (justRightSize == false) { int resultWidth = (width + mPadding) > freeArea.width ? freeArea.width : (width + mPadding); int resultHeight = (height + mPadding) > freeArea.height ? freeArea.height : (height + mPadding); result = DynamicAtlasManager.Instance.AllocateRectangle(freeArea.x, freeArea.y, resultWidth, resultHeight); if (mTopFirst) //切割此freeArea,得到新的freeArea: mNewFreeAreas { GenerateDividedAreasTopFirst(index, result, freeArea); } else { GenerateDividedAreasRightFirst(index, result, freeArea); } } else { result = DynamicAtlasManager.Instance.AllocateRectangle(freeArea.x, freeArea.y, freeArea.width, freeArea.height);; } RemoveFreeArea(index, freeArea);//回收此freeArea,无论是正好符合还是切割,都要回收 return(result); }
public void PackerTexture1() { Texture2D[] packerTexs = _texMap.Values.ToArray(); _texMap.Clear(); _mainTex = new Texture2D(_defaultWh, _defaultWh, TextureFormat.ARGB32, false); _mainTex.wrapMode = TextureWrapMode.Clamp; const int padding = 0; RectanglePacker packer = new RectanglePacker(_mainTex.width, _mainTex.height, padding); for (int i = 0; i < packerTexs.Length; i++) { packer.insertRectangle(packerTexs[i].width, packerTexs[i].height, i); } packer.packRectangles(); IntegerRectangle rect = new IntegerRectangle(); for (int i = 0; i < packer.rectangleCount; i++) { rect = packer.getRectangle(i, rect); int index = packer.getRectangleId(i); _mainTex.SetPixels32(rect.x, rect.y, rect.width, rect.height, packerTexs[index].GetPixels32()); Sprite sprite = Sprite.Create(_mainTex, new Rect(rect.x, rect.y, rect.width, rect.height), Vector2.zero, _pixelsPerUnit, 0, SpriteMeshType.FullRect); _spriteMap.Add(packerTexs[i].name, sprite); } _mainTex.Apply(); }
IntegerRectangle GetFreeArea(int width, int height, out int index, out bool justRightSize) { IntegerRectangle best = mOutsideRectangle; index = -1; justRightSize = false; int paddedWidth = width + mPadding; int paddedHeight = height + mPadding; int count = mFreeAreasList.Count; bool isFindResult = false; for (int i = 0; i < count; i++)//从第一个图集开始查找 { var item = mFreeAreasList[i]; index = i; Vector2 range = m_FindRange[index]; foreach (IntegerRectangle free in item) { if (free.x < range.x || free.y < range.y) { if (free.x < best.x && paddedWidth <= free.width && paddedHeight <= free.height) { best = free; isFindResult = true; if ((paddedWidth == free.width && free.width <= free.height && free.right < mWidth) || (paddedHeight == free.height && free.height <= free.width)) { justRightSize = true; break; } } } else { // Outside the current packed area, no padding required if (free.x < best.x && width <= free.width && height <= free.height) { best = free; isFindResult = true; if ((width == free.width && free.width <= free.height && free.right < mWidth) || (height == free.height && free.height <= free.width)) { justRightSize = true; break; } } } } if (isFindResult)//找到了就往下一个图集找了 { break; } } if (best == mOutsideRectangle) //没有找到适合的区域,那么就要申请新的图集了 { CreateNewAtlas(); index = mFreeAreasList.Count - 1; justRightSize = false;//不支持,也不允许让 图片大小直接等于图集大小 return(mFreeAreasList[index][0]); } return(best); }
private void generateDividedAreas(IntegerRectangle divider, IntegerRectangle area) { int rightDelta = area.right - divider.right; if (rightDelta > 0) { mNewFreeAreas.Add(DynamicAtlasManager.Instance.AllocateRectangle(divider.right, area.y, rightDelta, area.height)); } int leftDelta = divider.x - area.x; if (leftDelta > 0) { mNewFreeAreas.Add(DynamicAtlasManager.Instance.AllocateRectangle(area.x, area.y, leftDelta, area.height)); } int bottomDelta = area.top - divider.top; if (bottomDelta > 0) { mNewFreeAreas.Add(DynamicAtlasManager.Instance.AllocateRectangle(area.x, divider.top, area.width, bottomDelta)); } int topDelta = divider.y - area.y; if (topDelta > 0) { mNewFreeAreas.Add(DynamicAtlasManager.Instance.AllocateRectangle(area.x, area.y, area.width, topDelta)); } }
void ClearFreeAreas() { DynamicAtlas dynamicAtlas = DynamicAtlasManager.Instance.GetDynamicAtlas(_mGroup); if (AtlasConfig.kUsingCopyTexture) { List <List <IntegerRectangle> > freeLists = dynamicAtlas.GetFreeAreas(); int freeListsCount = freeLists.Count; List <Texture2D> tex2DList = dynamicAtlas.tex2DList; for (int i = 0; i < freeListsCount; i++) { var freeList = freeLists[i]; int freeListCount = freeList.Count; Texture2D dstTex = tex2DList[i]; for (int j = 0; j < freeListCount; j++) { IntegerRectangle item = freeList[j]; Color32[] colors = new Color32[item.width * item.height]; for (int k = 0; k < colors.Length; ++k) { colors[k] = Color.clear; } dstTex.SetPixels32((int)item.x, (int)item.y, item.width, item.height, colors); dstTex.Apply(); } } } else { dynamicAtlas.ClearTextureWithBlit(); } }
private Rect IntegerRectangle2Rect(IntegerRectangle integer) { Rect rect = new Rect(); rect.x = (float)integer.x / (float)TEXTURE_SIZE; rect.y = (float)integer.y / (float)TEXTURE_SIZE; rect.width = (float)integer.width / (float)TEXTURE_SIZE; rect.height = (float)integer.height / (float)TEXTURE_SIZE; return(rect); }
public bool CreateAtlas(Texture[] textures, int width = 1024, int height = 1024, int padding = 1) { bool result = false; rectangles.Clear(); dictionary.Clear(); packer.ResetAll(width, height, padding); CreateMaterial(); CreateRenderTexture(width, height); for (int i = 0; i < textures.Length; i++) { rectangles.Add(new Rect(0, 0, textures[i].width, textures[i].height)); } for (int i = 0; i < rectangles.Count; i++) { packer.insertRectangle((int)rectangles[i].width, (int)rectangles[i].height, i); } packer.packRectangles(); int index = 0; if (packer.rectangleCount > 0) { for (int j = 0; j < packer.rectangleCount; j++) { integerRect = packer.getRectangle(j, integerRect); index = packer.getRectangleId(j); if (!dictionary.ContainsKey(textures[index].name)) { Rect rect = new Rect(); rect.x = (float)integerRect.x / width; rect.y = (float)integerRect.y / height; rect.width = (float)integerRect.width / width; rect.height = (float)integerRect.height / height; dictionary.Add(textures[index].name, rect); } DrawTexture(textures[index], renderTexture, new Rect(integerRect.x, integerRect.y, integerRect.width, integerRect.height)); } result = true; } return(result); }
public IntegerRectangle AllocateRectangle(int x, int y, int width, int height) { if (mRectangleStack.Count > 0) { IntegerRectangle rectangle = mRectangleStack.Pop(); rectangle.x = x; rectangle.y = y; rectangle.width = width; rectangle.height = height; return(rectangle); } return(new IntegerRectangle(x, y, width, height)); }
bool OnMergeArea(IntegerRectangle newRect, int texIndex) { IntegerRectangle mergeRect = newRect; bool isMerged = false; while (mergeRect != null) { mergeRect = OnMergeAreaRecursive(mergeRect, texIndex); if (mergeRect != null) { isMerged = true; } } return(isMerged); }
private void generateNewFreeAreas(int index, IntegerRectangle divider) { List <IntegerRectangle> areas = mFreeAreasList[index]; for (int i = areas.Count - 1; i >= 0; i--) { IntegerRectangle area = areas[i]; if ((divider.x >= area.right || divider.right <= area.x || divider.y >= area.top || divider.top <= area.y) == false)//divider 在area里面 { generateDividedAreas(divider, area); areas.RemoveAt(i); DynamicAtlasManager.Instance.ReleaseRectangle(area); } } filterSelfSubAreas(index); }
private void generateDividedAreas(IntegerRectangle divider, IntegerRectangle area) { //int count = 0; int rightDelta = area.right - divider.right; if (rightDelta > 0) { mNewFreeAreas.Add(DynamicAtlasManager.Instance.AllocateRectangle(divider.right, area.y, rightDelta, area.height)); //count++; } int leftDelta = divider.x - area.x; if (leftDelta > 0) { mNewFreeAreas.Add(DynamicAtlasManager.Instance.AllocateRectangle(area.x, area.y, leftDelta, area.height)); //count++; } int bottomDelta = area.top - divider.top; if (bottomDelta > 0) { mNewFreeAreas.Add(DynamicAtlasManager.Instance.AllocateRectangle(area.x, divider.top, area.width, bottomDelta)); //count++; } int topDelta = divider.y - area.y; if (topDelta > 0) { mNewFreeAreas.Add(DynamicAtlasManager.Instance.AllocateRectangle(area.x, area.y, area.width, topDelta)); //count++; } //if (count == 0 && (divider.width < area.width || divider.height < area.height))//没有切割 //{ // // Only touching the area, store the area itself // mNewFreeAreas.Add(area); //} //else //{ // DynamicAtlasManager.Instance.ReleaseRectangle(area); //} }
//切割,优先上面的区域大一些 private void GenerateDividedAreasTopFirst(int index, IntegerRectangle divider, IntegerRectangle freeArea) { int rightDelta = freeArea.right - divider.right;//找到空闲区域2 if (rightDelta > 0) { IntegerRectangle area = DynamicAtlasManager.Instance.AllocateRectangle(divider.right, divider.y, rightDelta, divider.height); AddFreeArea(index, area); } int topDelta = freeArea.top - divider.top;//找到空闲区域1 if (topDelta > 0) { IntegerRectangle area = DynamicAtlasManager.Instance.AllocateRectangle(freeArea.x, divider.top, freeArea.width, topDelta); AddFreeArea(index, area); } }
public PackingAtlas(DynamicAtlasGroup group) { int length = (int)group; mWidth = length; mHeight = length; tmpColor = new Color32[length * length]; for (int k = 0; k < tmpColor.Length; ++k) { tmpColor[k] = Color.clear; } mUVXDiv = 1f / mWidth; mUVYDiv = 1f / mHeight; mOutsideRectangle = new IntegerRectangle(mWidth + 1, mWidth + 1, 0, 0); if (AtlasConfig.kUsingCopyTexture == false) { mMaterial = new Material(Shader.Find("DynamicAtlas/GraphicBlit")); mBlitParamId = Shader.PropertyToID("_DrawRect"); } CreateNewAtlas(); }
IntegerRectangle InsertArea(int width, int height, out int index) { bool justRightSize;//宽高正好是图集大小,一般不建议这样干,但是为了兼容. IntegerRectangle freeArea = GetFreeArea(width, height, out index, out justRightSize); IntegerRectangle result; mNewFreeAreas.Clear(); if (justRightSize == false) { int resultWidth = (width + mPadding) > freeArea.width ? freeArea.width : (width + mPadding); int resultHeight = (height + mPadding) > freeArea.height ? freeArea.height : (height + mPadding); result = DynamicAtlasManager.Instance.AllocateRectangle(freeArea.x, freeArea.y, resultWidth, resultHeight); generateNewFreeAreas(index, result); } else { result = DynamicAtlasManager.Instance.AllocateRectangle(freeArea.x, freeArea.y, freeArea.width, freeArea.height); } //RemoveFreeArea(index, freeArea);//回收此freeArea,无论是正好符合还是切割,都要回收 while (mNewFreeAreas.Count > 0) { AddFreeArea(index, mNewFreeAreas.Pop()); } Vector2 range = m_FindRange[index]; if (result.right > range.x)//尽量的往左,往高了找 { range.x = result.right; } if (result.top > range.y) { range.y = result.top; } m_FindRange[index] = range; return(result); }
public void ClearAtlas() { foreach (List <IntegerRectangle> items in mFreeAreasList) { while (items.Count > 0) { DynamicAtlasManager.Instance.ReleaseRectangle(items.Pop()); } items.Clear(); IntegerRectangle area = DynamicAtlasManager.Instance.AllocateRectangle(0, 0, mWidth, mHeight); items.Add(area); } int count = m_FindRange.Count; for (int i = 0; i < count; i++) { m_FindRange[i] = Vector2.zero; } foreach (var item in _usingRect) { DynamicAtlasManager.Instance.ReleaseSaveImageData(item.Value); } _usingRect.Clear(); }
private void updateRectangles() { DateTime start = DateTime.Now; const int padding = 1; if (mPacker == null) { mPacker = new RectanglePacker((int)sliderWidth.value, (int)sliderHeight.value, padding); } else { mPacker.reset((int)sliderWidth.value, (int)sliderHeight.value, padding); } for (int i = 0; i < RECTANGLE_COUNT; i++) { mPacker.insertRectangle((int)mRectangles[i].width, (int)mRectangles[i].height, i); } mPacker.packRectangles(); Clear(); DateTime end = DateTime.Now; if (mPacker.rectangleCount > 0) { packingTimeText.text = mPacker.rectangleCount + " rectangles packed in " + (end - start).Milliseconds + "ms"; IntegerRectangle rect = new IntegerRectangle(); for (int j = 0; j < mPacker.rectangleCount; j++) { rect = mPacker.getRectangle(j, rect); int index = mPacker.getRectangleId(j); Texture2D texture = textures[index]; SetTexture(texture, IntegerRectangle2Rect(rect)); } } }
private void updateRectangles() { DateTime start = DateTime.Now; const int padding = 1; if (mPacker == null) { mPacker = new RectanglePacker((int)sliderWidth.value, (int)sliderHeight.value, padding); } else { mPacker.Reset((int)sliderWidth.value, (int)sliderHeight.value, padding); } for (int i = 0; i < RECTANGLE_COUNT; i++) { mPacker.InsertRectangle((int)mRectangles[i].width, (int)mRectangles[i].height, i); } mPacker.PackRectangles(); DateTime end = DateTime.Now; if (mPacker.rectangleCount > 0) { packingTimeText.text = mPacker.rectangleCount + " rectangles packed in " + (end - start).Milliseconds + "ms"; mTexture.SetPixels32(mFillColor); IntegerRectangle rect = new IntegerRectangle(); Color32[] tmpColor; for (int j = 0; j < mPacker.rectangleCount; j++) { rect = mPacker.GetRectangle(j, rect); int size = rect.width * rect.height; tmpColor = new Color32[size]; for (int k = 0; k < size; ++k) { tmpColor[k] = Color.black; } mTexture.SetPixels32(rect.x, rect.y, rect.width, rect.height, tmpColor); int index = mPacker.GetRectangleId(j); Color color = convertHexToRGBA((uint)(0xFF171703 + (((18 * ((index + 4) % 13)) << 16) + ((31 * ((index * 3) % 8)) << 8) + 63 * (((index + 1) * 3) % 5)))); size -= 4; tmpColor = new Color32[size]; for (int k = 0; k < size; ++k) { tmpColor[k] = color; } mTexture.SetPixels32(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2, tmpColor); } mTexture.Apply(); } }
protected IEnumerator createPack(string savePath = "") { if (savePath != "") { if (deletePreviousCacheVersion && Directory.Exists(Application.persistentDataPath + "/AssetPacker/" + cacheName + "/")) { foreach (string dirPath in Directory.GetDirectories(Application.persistentDataPath + "/AssetPacker/" + cacheName + "/", "*", SearchOption.AllDirectories)) { Directory.Delete(dirPath, true); } } Directory.CreateDirectory(savePath); } List <Texture2D> textures = new List <Texture2D>(); List <string> images = new List <string>(); foreach (TextureToPack itemToRaster in itemsToRaster) { WWW loader = new WWW("file:///" + itemToRaster.file); yield return(loader); textures.Add(loader.texture); images.Add(itemToRaster.id); } int textureSize = allow4096Textures ? 4096 : 2048; List <Rect> rectangles = new List <Rect>(); for (int i = 0; i < textures.Count; i++) { if (textures[i].width > textureSize || textures[i].height > textureSize) { throw new Exception("A texture size is bigger than the sprite sheet size!"); } else { rectangles.Add(new Rect(0, 0, textures[i].width, textures[i].height)); } } const int padding = 1; int numSpriteSheet = 0; while (rectangles.Count > 0) { Texture2D texture = new Texture2D(textureSize, textureSize, TextureFormat.ARGB32, false); Color32[] fillColor = texture.GetPixels32(); for (int i = 0; i < fillColor.Length; ++i) { fillColor[i] = Color.clear; } RectanglePacker packer = new RectanglePacker(texture.width, texture.height, padding); for (int i = 0; i < rectangles.Count; i++) { packer.insertRectangle((int)rectangles[i].width, (int)rectangles[i].height, i); } packer.packRectangles(); if (packer.rectangleCount > 0) { texture.SetPixels32(fillColor); IntegerRectangle rect = new IntegerRectangle(); List <TextureAsset> textureAssets = new List <TextureAsset>(); List <Rect> garbageRect = new List <Rect>(); List <Texture2D> garabeTextures = new List <Texture2D>(); List <string> garbageImages = new List <string>(); for (int j = 0; j < packer.rectangleCount; j++) { rect = packer.getRectangle(j, rect); int index = packer.getRectangleId(j); texture.SetPixels32(rect.x, rect.y, rect.width, rect.height, textures[index].GetPixels32()); TextureAsset textureAsset = new TextureAsset(); textureAsset.x = rect.x; textureAsset.y = rect.y; textureAsset.width = rect.width; textureAsset.height = rect.height; textureAsset.name = images[index]; textureAssets.Add(textureAsset); garbageRect.Add(rectangles[index]); garabeTextures.Add(textures[index]); garbageImages.Add(images[index]); } foreach (Rect garbage in garbageRect) { rectangles.Remove(garbage); } foreach (Texture2D garbage in garabeTextures) { textures.Remove(garbage); } foreach (string garbage in garbageImages) { images.Remove(garbage); } texture.Apply(); if (savePath != "") { File.WriteAllBytes(savePath + "/data" + numSpriteSheet + ".png", texture.EncodeToPNG()); File.WriteAllText(savePath + "/data" + numSpriteSheet + ".json", JsonUtility.ToJson(new TextureAssets(textureAssets.ToArray()))); ++numSpriteSheet; } foreach (TextureAsset textureAsset in textureAssets) { mSprites.Add(textureAsset.name, Sprite.Create(texture, new Rect(textureAsset.x, textureAsset.y, textureAsset.width, textureAsset.height), Vector2.zero, pixelsPerUnit, 0, SpriteMeshType.FullRect)); } } } OnProcessCompleted.Invoke(); }
//获得最适合放texture的区域 private IntegerRectangle GetFreeArea(int width, int height, out int index, out bool justRightSize) { index = -1; justRightSize = false; if (width > mWidth || height > mHeight) { Debug.LogError("ERROR 图片尺寸大于图集大小: 图片大小为" + width + "x" + height + " 图集大小为" + mWidth + "x" + mHeight); return(null); } int paddedWidth = width + mPadding; int paddedHeight = height + mPadding; int count = mFreeAreasList.Count; IntegerRectangle tempArea = null; for (int i = 0; i < count; i++)//从第一个图集开始查找 { var item = mFreeAreasList[i]; bool isFindResult = false; foreach (var listItem in item) { IntegerRectangle area = listItem; bool isJustFullWidth = (width == area.width || width == mWidth); bool isJustFullHeight = (height == area.height || height == mHeight); bool isFitWidth = isJustFullWidth || paddedWidth <= area.width; bool isFitHeight = paddedHeight <= area.height || isJustFullHeight; if (isFitWidth && isFitHeight)//用最快的方式,找到能放进去的区域,如果宽或者高恰好等于图集的宽或者高,则没有paddling { index = i; justRightSize = (isJustFullWidth || paddedWidth == area.width) && (isJustFullHeight || paddedHeight == area.height); if (isJustFullWidth && isJustFullHeight) { return(area); } isFindResult = true; if (tempArea != null) { if (mTopFirst) { if (tempArea.height > area.height) { tempArea = area; } } else { if (tempArea.width > area.width) { tempArea = area; } } } else { tempArea = area; } } } if (isFindResult)//找到了就往下一个图集找了 { break; } } if (tempArea != null) { return(tempArea); } //没有找到适合的区域,那么就要申请新的图集了 CreateNewAtlas(); index = mFreeAreasList.Count - 1; justRightSize = false;//不支持,也不允许让 图片大小直接等于图集大小 return(mFreeAreasList[index][0]); }
void OnRenderTexture(string path, Texture2D data) { if (data == null) { GetImageData getImageData; if (mGetImageTaskDic.TryGetValue(path, out getImageData)) { if (AtlasConfig.kUsingCopyTexture) { if (getImageData.callback != null) { getImageData.callback(null, new Rect(0, 0, 0, 0), path);//完成一个任务,就回调一个任务 } } else { if (getImageData.BlitCallback != null) { getImageData.BlitCallback(null, new Rect(0, 0, 0, 0), path);//完成一个任务,就回调一个任务 } } DynamicAtlasManager.Instance.ReleaseGetImageData(getImageData); if (!mGetImageTaskDic.Remove(path)) { Debug.LogError($"无法删除GetImageData:{path}"); } } else { Debug.Log($"没有此GetImageData任务:{path}"); } return; } int index; IntegerRectangle useArea = InsertArea(data.width, data.height, out index); Rect uv = new Rect((useArea.x + offset) * mUVXDiv, (useArea.y + offset) * mUVYDiv, (useArea.width - mPadding - offset * 2) * mUVXDiv, (useArea.height - mPadding - offset * 2) * mUVYDiv); if (AtlasConfig.kUsingCopyTexture) { CopyTexture(useArea.x, useArea.y, index, data); } else { BlitTexture(useArea.x, useArea.y, index, data); } SaveImageData _SaveImageData = DynamicAtlasManager.Instance.AllocateSaveImageData(uv); _SaveImageData.texIndex = index; _SaveImageData.rectangle = useArea; _usingRect[path] = _SaveImageData; { GetImageData getImageData; if (mGetImageTaskDic.TryGetValue(path, out getImageData)) { _usingRect[path].referenceCount = _usingRect[path].referenceCount + 1; if (AtlasConfig.kUsingCopyTexture) { if (getImageData.callback != null) { Texture2D dstTex = m_tex2DList[index]; getImageData.callback(dstTex, uv, path); //完成一个任务,就回调一个任务 } } else { if (getImageData.BlitCallback != null) { Material material = m_MaterialList[index]; getImageData.BlitCallback(material, uv, path); //完成一个任务,就回调一个任务 } } DynamicAtlasManager.Instance.ReleaseGetImageData(getImageData); mGetImageTaskDic.Remove(path); } } }
protected IEnumerator createPack(string savePath = "") { if (savePath != "") { if (deletePreviousCacheVersion && Directory.Exists(Application.persistentDataPath + "/AssetPacker/" + cacheName + "/")) { foreach (string dirPath in Directory.GetDirectories(Application.persistentDataPath + "/AssetPacker/" + cacheName + "/", "*", SearchOption.AllDirectories)) { Directory.Delete(dirPath, true); } } Directory.CreateDirectory(savePath); } List <Texture2D> textures = new List <Texture2D>(); List <string> images = new List <string>(); foreach (TextureToPack itemToRaster in itemsToRaster) { Texture2D baseTexture = itemToRaster.preLoadedTexture; if (!baseTexture) { WWW loader = new WWW("file:///" + itemToRaster.file); yield return(loader); baseTexture = loader.texture; } if (itemToRaster.sliceParams != null) { TextureToPack.GridSlice sliceParams = itemToRaster.sliceParams; if (sliceParams.width > baseTexture.width || sliceParams.height > baseTexture.height) { throw new Exception(string.Format("Width and/or height of texture {0} is less than the provided slice parameters.", itemToRaster.id)); } if (!(baseTexture.width % sliceParams.width == 0 && baseTexture.height % sliceParams.height == 0)) { throw new Exception(string.Format("Width and/or height of texture {0} not a multiple of the provided slice parameters.", itemToRaster.id)); } int totalRows = baseTexture.height / sliceParams.height; int totalColumns = baseTexture.width / sliceParams.width; int textureIndex = 0; // Scan each slice left to right, top to bottom for (int rowIndex = 0; rowIndex < totalRows; ++rowIndex) { for (int columnIndex = 0; columnIndex < totalColumns; ++columnIndex) { int x = columnIndex * sliceParams.width; int y = (totalRows - rowIndex - 1) * sliceParams.height; // Starting from the top, not the bottom. Specific to GH3 sprite sheets, not nesacarily universal. Color[] pixels = baseTexture.GetPixels(x, y, sliceParams.width, sliceParams.height); Texture2D texture = new Texture2D(sliceParams.width, sliceParams.height); texture.SetPixels(pixels); texture.Apply(); textures.Add(texture); images.Add(string.Format("{0}_{1}", itemToRaster.id, textureIndex.ToString("D8"))); ++textureIndex; } } } else { textures.Add(baseTexture); images.Add(itemToRaster.id); } } int textureSize = allow4096Textures ? 4096 : 2048; List <Rect> rectangles = new List <Rect>(); for (int i = 0; i < textures.Count; i++) { if (textures[i].width > textureSize || textures[i].height > textureSize) { throw new Exception("A texture size is bigger than the sprite sheet size!"); } else { rectangles.Add(new Rect(0, 0, textures[i].width, textures[i].height)); } } const int padding = 1; int numSpriteSheet = 0; while (rectangles.Count > 0) { Texture2D texture = new Texture2D(textureSize, textureSize, TextureFormat.ARGB32, false); Color32[] fillColor = texture.GetPixels32(); for (int i = 0; i < fillColor.Length; ++i) { fillColor[i] = Color.clear; } RectanglePacker packer = new RectanglePacker(texture.width, texture.height, padding); for (int i = 0; i < rectangles.Count; i++) { packer.insertRectangle((int)rectangles[i].width, (int)rectangles[i].height, i); } packer.packRectangles(); if (packer.rectangleCount > 0) { texture.SetPixels32(fillColor); IntegerRectangle rect = new IntegerRectangle(); List <TextureAsset> textureAssets = new List <TextureAsset>(); List <Rect> garbageRect = new List <Rect>(); List <Texture2D> garabeTextures = new List <Texture2D>(); List <string> garbageImages = new List <string>(); for (int j = 0; j < packer.rectangleCount; j++) { rect = packer.getRectangle(j, rect); int index = packer.getRectangleId(j); texture.SetPixels32(rect.x, rect.y, rect.width, rect.height, textures[index].GetPixels32()); TextureAsset textureAsset = new TextureAsset(); textureAsset.x = rect.x; textureAsset.y = rect.y; textureAsset.width = rect.width; textureAsset.height = rect.height; textureAsset.name = images[index]; textureAssets.Add(textureAsset); garbageRect.Add(rectangles[index]); garabeTextures.Add(textures[index]); garbageImages.Add(images[index]); } foreach (Rect garbage in garbageRect) { rectangles.Remove(garbage); } foreach (Texture2D garbage in garabeTextures) { textures.Remove(garbage); } foreach (string garbage in garbageImages) { images.Remove(garbage); } texture.Apply(); if (savePath != "") { File.WriteAllBytes(savePath + "/data" + numSpriteSheet + ".png", texture.EncodeToPNG()); File.WriteAllText(savePath + "/data" + numSpriteSheet + ".json", JsonUtility.ToJson(new TextureAssets(textureAssets.ToArray()), true)); ++numSpriteSheet; } foreach (TextureAsset textureAsset in textureAssets) { Sprite sprite = Sprite.Create(texture, new Rect(textureAsset.x, textureAsset.y, textureAsset.width, textureAsset.height), spritePivot, pixelsPerUnit, 0, SpriteMeshType.FullRect); sprite.name = textureAsset.name; mSprites.Add(textureAsset.name, sprite); } } } OnProcessCompleted.Invoke(); }
void RemoveFreeArea(int index, IntegerRectangle data) { DynamicAtlasManager.Instance.ReleaseRectangle(data); mFreeAreasList[index].Remove(data); }
void AddFreeArea(int index, IntegerRectangle data) { List <IntegerRectangle> list = mFreeAreasList[index]; list.Add(data); }
public bool Push(string key, Texture2D texture) { if (string.IsNullOrEmpty(key)) { return(true); } if (texture == null) { return(true); } for (int i = 0; i < m_sprites.Count; i++) { m_sprites[i].index = i; m_sprites[i].color = m_texture.GetPixels((int)m_sprites[i].rect.x, (int)m_sprites[i].rect.y, (int)m_sprites[i].rect.width, (int)m_sprites[i].rect.height); } m_sprites.Add(new DynamicSprite() { key = key, index = -1, rect = new Rect(0, 0, texture.width, texture.height), color = texture.GetPixels(), }); m_packer.reset(width, height, padding); for (int i = 0; i < m_sprites.Count; i++) { m_packer.insertRectangle((int)m_sprites[i].rect.width, (int)m_sprites[i].rect.height, m_sprites[i].index); } int count = m_packer.packRectangles(); enough = m_sprites.Count > count; if (enough) { m_sprites.RemoveAt(m_sprites.FindIndex(x => x.key == key)); for (int i = 0; i < m_sprites.Count; i++) { m_sprites[i].color = null; } return(false); } else { if (texture != null) { texture = null; } if (m_texture.format != TextureFormat.RGBA32) { Object.Destroy(m_texture); m_texture = new Texture2D(width, height, TextureFormat.RGBA32, false); } m_texture.SetPixels32(m_color); IntegerRectangle rect = new IntegerRectangle(); Color32[] color; int index, id, size; for (int i = 0; i < count; i++) { rect = m_packer.getRectangle(i, rect); id = m_packer.getRectangleId(i); index = m_sprites.FindIndex(x => x.index == id); if (index != -1) { m_sprites[index].rect = new Rect(rect.x, rect.y, rect.width, rect.height); color = new Color32[m_sprites[index].color.Length]; for (int j = 0; j < m_sprites[index].color.Length; j++) { color[j] = m_sprites[index].color[j]; } } else { size = rect.width * rect.height; color = new Color32[size]; for (int j = 0; j < size; j++) { color[j] = Color.black; } } m_texture.SetPixels32(rect.x, rect.y, rect.width, rect.height, color); } for (int i = 0; i < m_sprites.Count; i++) { m_sprites[i].color = null; } if (compress) { m_texture.Compress(true); } m_texture.Apply(); return(true); } }
void OnRenderTexture(string path, Texture2D data, GetImageData imageData) { if (data == null) { for (int i = mGetImageTasks.Count - 1; i >= 0; i--) { GetImageData item = mGetImageTasks[i]; if (item.path.Equals(path)) { if (item.callback != null) { item.callback(null, new Rect(0, 0, 0, 0), path); } if (AtlasConfig.kUsingCopyTexture) { if (item.callback != null) { item.callback(null, new Rect(0, 0, 0, 0), path);//完成一个任务,就回调一个任务 } } else { if (item.BlitCallback != null) { item.BlitCallback(null, new Rect(0, 0, 0, 0), path);//完成一个任务,就回调一个任务 } } DynamicAtlasManager.Instance.ReleaseGetImageData(item); mGetImageTasks.RemoveAt(i); } } return; } int index; IntegerRectangle useArea = InsertArea(data.width, data.height, out index); Rect uv = new Rect((useArea.x + offset) * mUVXDiv, (useArea.y + offset) * mUVYDiv, (useArea.width - mPadding - offset * 2) * mUVXDiv, (useArea.height - mPadding - offset * 2) * mUVYDiv); if (AtlasConfig.kUsingCopyTexture) { CopyTexture(useArea.x, useArea.y, index, data); } else { BlitTexture(useArea.x, useArea.y, index, data); } SaveImageData _SaveImageData = DynamicAtlasManager.Instance.AllocateSaveImageData(uv); _SaveImageData.texIndex = index; _SaveImageData.rectangle = useArea; _usingRect[path] = _SaveImageData; for (int i = mGetImageTasks.Count - 1; i >= 0; i--) { GetImageData item = mGetImageTasks[i]; if (item.path.Equals(path)) { _usingRect[path].referenceCount = _usingRect[path].referenceCount + 1; if (AtlasConfig.kUsingCopyTexture) { if (item.callback != null) { Texture2D dstTex = m_tex2DList[index]; item.callback(dstTex, uv, path);//完成一个任务,就回调一个任务 } } else { if (item.BlitCallback != null) { Material material = m_MaterialList[index]; item.BlitCallback(material, uv, path);//完成一个任务,就回调一个任务 } } DynamicAtlasManager.Instance.ReleaseGetImageData(item); mGetImageTasks.RemoveAt(i); } } }
public void ReleaseRectangle(IntegerRectangle rectangle) { mRectangleStack.Add(rectangle); }
void DrawFreeArea(int index, PackingAtlas packingAtlas) { Texture2D tex2D = null; if (texList.Count < index + 1) { tex2D = new Texture2D((int)_mGroup, (int)_mGroup, TextureFormat.ARGB32, false, true); texList.Add(tex2D); if (mFillColor == null) { mFillColor = tex2D.GetPixels32(); for (int i = 0; i < mFillColor.Length; ++i) { mFillColor[i] = Color.clear; } } } else { tex2D = texList[index]; } tex2D.SetPixels32(mFillColor); if (isRefreshFreeAreas) { Color32[] tmpColor; List <IntegerRectangle> freeList = packingAtlas.GetFreeAreas()[index]; int count = freeList.Count; for (int i = 0; i < count; i++) { IntegerRectangle item = freeList[i]; int size = item.width * item.height; //---------------------------------描边,可能太费 //tmpColor = new Color32[size]; //for (int k = 0; k < size; ++k) //{ // tmpColor[k] = Color.green;//画边 //} //tex2D.SetPixels32(item.x, item.y, item.width, item.height, tmpColor); //------------------------- int outLineSize = 2; if (item.width < outLineSize * 2 || item.height < outLineSize * 2) { outLineSize = 0; } Color color = convertHexToRGBA((uint)(0xFF171703 + (((18 * ((i + 4) % 13)) << 16) + ((31 * ((i * 3) % 8)) << 8) + 63 * (((i + 1) * 3) % 5)))); color.a = 0.5f; size -= outLineSize * 4; tmpColor = new Color32[size]; for (int k = 0; k < size; ++k) { tmpColor[k] = color; } tex2D.SetPixels32(item.x + outLineSize, item.y + outLineSize, item.width - outLineSize * 2, item.height - outLineSize * 2, tmpColor); tex2D.Apply(); } } float poxX = (index + 1) * 10 + index * packingAtlas.atlasWidth * scale; GUI.DrawTexture(new Rect(poxX, formPosY, packingAtlas.atlasWidth * scale, packingAtlas.atlasHeight * scale), tex2D); }