protected override void Start() { _DKumaGenerator = GameObject.Find("DKUMAGenerator").GetComponent <DKUMAGenerator>(); // umaGenerator.umaData.cleanTextures(); materialDefinitionList = new List <DKUMAData.MaterialDefinition>(); //Update atlas area can be handled here DKUMAData.MaterialDefinition tempMaterialDefinition = new DKUMAData.MaterialDefinition(); DKSlotData[] slots = umaGenerator.umaData.umaRecipe.slotDataList; if (slots == null) { Debug.LogError(umaGenerator.umaData.gameObject.name + " can not be generated : the Slot list is umpty. Verify your Elements configuration."); } else if (slots.Length > 0) { for (int i = 0; i < slots.Length; i++) { if (slots[i] != null && slots[i].overlayList.Count != 0) { tempMaterialDefinition = new DKUMAData.MaterialDefinition(); tempMaterialDefinition.baseTexture = slots[i].overlayList[0].textureList; tempMaterialDefinition.baseColor = slots[i].overlayList[0].color; tempMaterialDefinition.materialSample = slots[i].materialSample; tempMaterialDefinition.overlays = new DKUMAData.textureData[slots[i].overlayList.Count - 1]; tempMaterialDefinition.overlayColors = new Color32[tempMaterialDefinition.overlays.Length]; tempMaterialDefinition.rects = new Rect[tempMaterialDefinition.overlays.Length]; tempMaterialDefinition.channelMask = new Color32[tempMaterialDefinition.overlays.Length + 1][]; tempMaterialDefinition.channelAdditiveMask = new Color32[tempMaterialDefinition.overlays.Length + 1][]; tempMaterialDefinition.channelMask[0] = slots[i].overlayList[0].channelMask; tempMaterialDefinition.channelAdditiveMask[0] = slots[i].overlayList[0].channelAdditiveMask; tempMaterialDefinition.slotData = slots[i]; for (int overlayID = 0; overlayID < slots[i].overlayList.Count - 1; overlayID++) { tempMaterialDefinition.overlays[overlayID] = new DKUMAData.textureData(); tempMaterialDefinition.rects[overlayID] = slots[i].overlayList[overlayID + 1].rect; tempMaterialDefinition.overlays[overlayID].textureList = slots[i].overlayList[overlayID + 1].textureList; tempMaterialDefinition.overlayColors[overlayID] = slots[i].overlayList[overlayID + 1].color; tempMaterialDefinition.channelMask[overlayID + 1] = slots[i].overlayList[overlayID + 1].channelMask; tempMaterialDefinition.channelAdditiveMask[overlayID + 1] = slots[i].overlayList[overlayID + 1].channelAdditiveMask; } materialDefinitionList.Add(tempMaterialDefinition); } } } if (_DKumaGenerator.usePRO && UnityEditorInternal.InternalEditorUtility.HasPro()) { textureProcessPROCoroutine = new DK_RPG_TextureProcessPROCoroutine(); } else { textureProcessIndieCoroutine = new DK_RPG_TextureProcessIndieCoroutine(); } packTexture = new MaxRectsBinPack(_DKumaGenerator.atlasResolution, _DKumaGenerator.atlasResolution, false); }
public void Execute(object parameter) { mpm.FB_UI_Atlas.Sprites.Clear(); mpm.Rectangles.Clear(); mpm.FB_UI_Atlas.Fonts.Clear(); FontSettings fontSettings = new FontSettings(); MaxRectsBinPack binPack = new MaxRectsBinPack((int)mpm.TextureWidth, (int)mpm.TextureHeight, false); //fontsize 20 mpm.FontSystem.GenerateFont(mpm.Rectangles, mpm.FB_UI_Atlas.Fonts, binPack, fontSettings); //fontsize 40 fontSettings = new FontSettings() { FontSize = 40 }; mpm.FontSystem.GenerateFont(mpm.Rectangles, mpm.FB_UI_Atlas.Fonts, binPack, fontSettings); AtlasHelper.GenAtlas(binPack, mpm.Rectangles, mpm.FB_UI_Atlas.Sprites, mpm.ImageFolder, mpm.ImageExtensions, mpm.TextureWidth, mpm.TextureHeight); }
public DynamicAtlas(int width, int height, string name, HeuristicMethod method = HeuristicMethod.RectBestShortSideFit) { Texture = new Texture2D(width, height, TextureFormat.RGBA32, false); Texture.name = name; this.method = method; rectsPack = new MaxRectsBinPack(width, height, false); names = new List <string>(); }
private void SubLayoutCells(ref float maxHeight, List <PUTableCell> cellsToAdd, MaxRectsBinPack.FreeRectChoiceHeuristic heuristic) { RectTransform contentRectTransform = contentObject.transform as RectTransform; float blockHeight = 2048.0f; float baseY = maxHeight; if (cellsToAdd [0].IsHeader()) { PUTableCell cell = cellsToAdd [0]; cellsToAdd.RemoveAt(0); cell.puGameObject.rectTransform.anchoredPosition = new Vector2(0, -baseY); baseY += cell.puGameObject.rectTransform.sizeDelta.y; } // The MaxRects packer works by being given a canvas (width/height) to fit all rectangles in // For us to use this and allow arbitrary height, we give it a rect the size of the visible // scroll area, fill it up, and then repeat until we run out of cells. int bail = 500; while (cellsToAdd.Count > 0 && bail > 0) { MaxRectsBinPack packer = new MaxRectsBinPack((int)contentRectTransform.rect.width, (int)blockHeight, false); for (int i = cellsToAdd.Count - 1; i >= 0; i--) { PUTableCell cell = cellsToAdd [i]; LORect packedRect; if (packer.Insert((int)cell.puGameObject.rectTransform.sizeDelta.x, (int)cell.puGameObject.rectTransform.sizeDelta.y, heuristic, cell.puGameObject.rectTransform, out packedRect)) { packedRect.y += baseY; cell.puGameObject.rectTransform.anchoredPosition = new Vector2(packedRect.x, -packedRect.y); if ((packedRect.y + packedRect.height) > maxHeight) { maxHeight = (packedRect.y + packedRect.height); } cellsToAdd.RemoveAt(i); } } if (expandToFill) { packer.ExpandRectsToFill((int)contentRectTransform.rect.width, (maxHeight - baseY)); } baseY = maxHeight; bail--; } if (bail == 0) { Debug.Log("Warning: PUGridTable layout failed to place all cells"); } }
public TextureAtlas(int size, string name = null) { texture = new Texture2D(size, size); if (name != null) texture.name = name; else texture.name = Guid.NewGuid().ToString(); pack = new MaxRectsBinPack(size, size, false); rects = new Dictionary<int, Rect>(); }
public TextureAtlas(int size, string name = null) { texture = new Texture2D(size, size); if (name != null) { texture.name = name; } else { texture.name = Guid.NewGuid().ToString(); } pack = new MaxRectsBinPack(size, size, false); rects = new Dictionary <int, Rect>(); }
void CopyOri(List <rectData> _ori, string atlasName) { if (_ori == null || _ori.Count == 0) { //Debug.Log("完成"); return; } List <Rect> rc = new List <Rect>(); foreach (var item in _ori) { rc.Add(item.rect); } List <rectData> _surplus = new List <rectData>(); List <rectData> mItemp = new List <rectData>(); // 图集组合优化: 一个图集,固定size,源图片中选择最佳组合,最大化利用图集size MaxRectsBinPack temp = new MaxRectsBinPack(1024, 1024, false); temp.insert2(rc, new List <Rect>(), inputReactDic[InputKey]); for (int i = 0; i < _ori.Count; i++) { Rect rect = temp.usedRectangles[i]; rectData data = new rectData(); data = _ori[i]; if (rect == new Rect()) { _surplus.Add(data); } else { data.rect = rect; mItemp.Add(data); } } if (mItemp.Count != 0) { histDic.Add((atlasName + "_" + (++key)).ToString(), mItemp); CopyOri(_surplus, atlasName); } else { foreach (var item in _surplus) { Debug.LogError("图片大于1024相素 : " + item.key); //NGUIDebug.Log("图片大于1024相素 : " + item.key); } } }
//合并小的图集为一张大图 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); } }
public void GenerateFont(ObservableCollection <System.Windows.UIElement> list, ObservableCollection <FontModel> fontList, MaxRectsBinPack maxRectsBinPack, FontSettings fontSettings) { _FontSettings = fontSettings; _MaxRectsBinPack = maxRectsBinPack; _fontList = fontList; _uiElemetList = list; string message = ""; bool result = checkBeforeRender(ref message); if (!result) { MessageBox.Show(message); return; } AsynDisplayImage(); }
protected override void OnInitialize() { base.OnInitialize(); var scale = 100d; var rectCount = 500; rectSizes = Enumerable.Range(0, rectCount) .Select(p => new vec2((float)(rand.NextDouble() * scale), (float)(rand.NextDouble() * scale))) .Where(p => 0 != (int)p.x && 0 != (int)p.y) .ToArray(); rects = new Rect[rectCount]; var totalWidth = 1024; var extraWidth = 128; maxRectsBinPack = new MaxRectsBinPack(totalWidth, totalWidth, true); for (var i = 0; i < rectSizes.Length; i++) { var rect = rectSizes[i]; rects[i] = maxRectsBinPack.Insert((int)rect.x, (int)rect.y, MaxRectsBinPack.FreeRectChoiceHeuristic.RectBestLongSideFit); while (rects[i].width == 0) { maxRectsBinPack.freeRectangles.Add(new Rect { x = totalWidth, y = 0, width = extraWidth, height = totalWidth + extraWidth }); maxRectsBinPack.freeRectangles.Add(new Rect { x = 0, y = totalWidth, width = totalWidth, height = extraWidth }); totalWidth += extraWidth; rects[i] = maxRectsBinPack.Insert((int)rect.x, (int)rect.y, MaxRectsBinPack.FreeRectChoiceHeuristic.RectBestLongSideFit); } } }
public Bitmap test_draw(ObservableCollection <System.Windows.UIElement> list, ObservableCollection <FontModel> fontList, MaxRectsBinPack binPack, string alphabet, FontSettings fontSettings) { alphabet = alphabet.Replace("\n", ""); alphabet = alphabet.Replace("\r", ""); Library library = new Library(); Face face = library.NewFace(fontSettings.FontName, 0); // Find the largest glyph bounding rectangle // Rect glyphRect = getGlyphRect(face, alphabet); //int glyphWidth = (int)Math.Ceiling(glyphRect.Width) + 4 * fontSettings.OutlineWidth; //int glyphHeight = (int)Math.Ceiling(glyphRect.Height) + 4 * fontSettings.OutlineWidth; int glyphWidth = 18 + 4 * fontSettings.OutlineWidth; int glyphHeight = 18 + 4 * fontSettings.OutlineWidth; //add new font FontModel newFont = new FontModel() { Id = (ushort)fontSettings.FontSize, size = fontSettings.FontSize, lineheight = glyphHeight, // 22, spacelength = (int)(glyphWidth * 0.6f), //todo ? baseline = 0, kerning = -0.5f, monowidth = fontSettings.FontSize + 1, letterspacing = 0, rangeFrom = alphabet[0], rangeTo = alphabet[alphabet.Length - 1] }; fontList.Add(newFont); Bitmap bmp = new Bitmap((int)Math.Ceiling((double)fontSettings.ImageWidth), (int)Math.Ceiling((double)fontSettings.ImageHeight)); Graphics g = Graphics.FromImage(bmp); g.Clear(fontSettings.BgColor); //g.Clear(Color.Black);q int x = 0, y = 0; for (int i = 0; i < alphabet.ToCharArray().Length; i++) { string currentChar0 = alphabet.ToCharArray()[i].ToString(); uint glyphIndex = face.GetCharIndex(uchar2code(currentChar0)); if (fontSettings.FontSize <= 14) { face.SetPixelSizes((uint)0, (uint)fontSettings.FontSize); face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); face.Glyph.RenderGlyph(RenderMode.Normal); } else { face.SetCharSize(0, fontSettings.FontSize, 0, 72); face.LoadGlyph(glyphIndex, LoadFlags.ForceAutohint, LoadTarget.Lcd); face.Glyph.RenderGlyph(RenderMode.Lcd); } //Get character alignment float left = (float)face.Glyph.Metrics.HorizontalBearingX; float right = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width; float top = (float)face.Glyph.Metrics.HorizontalBearingY; float bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height; float FHT = fontSettings.FontSize; int FHD = (int)Math.Ceiling(FHT); int kx = x + face.Glyph.BitmapLeft; int ky = (int)Math.Round((float)y + (FHD - face.Glyph.BitmapTop)); ////Select render mode (1 times or 2 times) //if (this.grender_mode == "freetype_nearestneighbor") //{ // face.SetCharSize(0, this.fontHeight * 2, 0, 72); // face.LoadGlyph(glyphIndex, LoadFlags.ForceAutohint, LoadTarget.Lcd); // face.Glyph.RenderGlyph(RenderMode.Lcd); // FTBitmap ftbmp = face.Glyph.Bitmap; // if (ftbmp.Width == 0) // { // x += this.tile_width; // if (x + this.tile_width > this.image_width) // { // x = 0; // y += this.tile_height; // } // continue; // } // Bitmap tmpBmp = ftbmp.ToGdipBitmap(this.penColor); // tmpBmp = kPasteImage(tmpBmp, tile_width * 2, tile_height * 2, (int)face.Glyph.BitmapLeft, // (int)Math.Round(((float)this.fontHeight * 2 - face.Glyph.BitmapTop))); // Bitmap cBmp = kResizeImage(tmpBmp, tmpBmp.Width / 2, tmpBmp.Height / 2, System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor); // Bitmap nBmp = gray2alpha(cBmp); // cBmp.Dispose(); // g.DrawImageUnscaled(nBmp, x + FontSettings.relativePositionX, y + FontSettings.relativePositionY); // nBmp.Dispose(); //} //else if (this.grender_mode == "freetype_HighQualityBicubic") //{ // face.SetCharSize(0, this.fontHeight * 2, 0, 72); // face.LoadGlyph(glyphIndex, LoadFlags.ForceAutohint, LoadTarget.Lcd); // face.Glyph.RenderGlyph(RenderMode.Lcd); // FTBitmap ftbmp = face.Glyph.Bitmap; // if (ftbmp.Width == 0) // { // x += this.tile_width; // if (x + this.tile_width > this.image_width) // { // x = 0; // y += this.tile_height; // } // continue; // } // Bitmap tmpBmp = ftbmp.ToGdipBitmap(this.penColor); // tmpBmp = kPasteImage(tmpBmp, tile_width * 2, tile_height * 2, (int)face.Glyph.BitmapLeft, // (int)Math.Round(((float)this.fontHeight * 2 - face.Glyph.BitmapTop))); // Bitmap cBmp = kResizeImage(tmpBmp, tmpBmp.Width / 2, tmpBmp.Height / 2, System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic); // Bitmap nBmp = gray2alpha(cBmp); // cBmp.Dispose(); // g.DrawImageUnscaled(nBmp, x + FontSettings.relativePositionX, y + FontSettings.relativePositionY); // nBmp.Dispose(); //} //else if (this.grender_mode == "freetype_drawtwice") //{ // face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); // face.Glyph.RenderGlyph(RenderMode.Normal); // FTBitmap ftbmp = face.Glyph.Bitmap; // if (ftbmp.Width == 0) // { // x += this.tile_width; // if (x + this.tile_width > this.image_width) // { // x = 0; // y += this.tile_height; // } // continue; // } // Bitmap cBmp = ftbmp.ToGdipBitmap(this.penColor); // Bitmap sBmp = ftbmp.ToGdipBitmap(this.shadowColor); // Bitmap nBmp = gray2alpha(cBmp); // cBmp.Dispose(); // g.DrawImageUnscaled(sBmp, kx + FontSettings.relativePositionX + 1, ky + FontSettings.relativePositionY + 1);//draw twice // g.DrawImageUnscaled(nBmp, kx + FontSettings.relativePositionX, ky + FontSettings.relativePositionY); // cBmp.Dispose(); // nBmp.Dispose(); //} //else if (this.grender_mode == "freeyype_nosmoothing") //{ // face.SetPixelSizes((uint)0, (uint)this.fontHeight); // face.LoadGlyph(glyphIndex, LoadFlags.Monochrome, LoadTarget.Mono); // face.Glyph.RenderGlyph(RenderMode.Mono); // FTBitmap ftbmp = face.Glyph.Bitmap; // if (ftbmp.Width == 0) // { // x += this.tile_width; // if (x + this.tile_width > this.image_width) // { // x = 0; // y += this.tile_height; // } // continue; // } // Bitmap cBmp = ftbmp.ToGdipBitmap(this.penColor); // g.DrawImageUnscaled(cBmp, kx + FontSettings.relativePositionX, ky + FontSettings.relativePositionY); // cBmp.Dispose(); //} // int tile_width = 24; //int tile_height = FontSettings.iFontHeight;//24; ////else ////{ FTBitmap ftbmp = face.Glyph.Bitmap; // if (ftbmp.Width == 0) // { // x += tile_width; // if (x + tile_width > this.image_width) // { // x = 0; // y += tile_height; // } // continue; // } Bitmap cBmp = ftbmp.ToGdipBitmap(fontSettings.PenColor); Bitmap nBmp = gray2alpha(cBmp); Rect newPos = binPack.Insert(cBmp.Width, cBmp.Height, MaxRectsBinPack.FreeRectChoiceHeuristic.RectBottomLeftRule); //DebugRectangle System.Windows.Shapes.Rectangle testRect = new System.Windows.Shapes.Rectangle { Stroke = System.Windows.Media.Brushes.LightGreen, StrokeThickness = 0 }; ImageBrush ib = new ImageBrush(); // cBmp.MakeTransparent(); cBmp.Dispose(); var source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(nBmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()); nBmp.Dispose(); ib.ImageSource = source; testRect.Fill = ib; testRect.Width = newPos.Width; testRect.Height = newPos.Height; Canvas.SetLeft(testRect, newPos.Left); Canvas.SetTop(testRect, newPos.Top); list.Add(testRect); Glyph newGlyph = new Glyph() { X = (int)Math.Ceiling(newPos.Left), Y = (int)Math.Ceiling(newPos.Top), width = (int)Math.Ceiling(newPos.Width), height = (int)Math.Ceiling(newPos.Height) }; newFont.SetGlyph(currentChar0, newGlyph); //if(glyphIndex == 33) //{ //} // Construct KerningData for (int j = 0; j < alphabet.ToCharArray().Length; j++) { string left_Char0 = alphabet.ToCharArray()[j].ToString(); uint left_glyphIndex = face.GetCharIndex(uchar2code(left_Char0)); //if (left_glyphIndex == 45) //{ //} //char c1 = mAlphabet[i]; //FT_UInt c1Index = FT_Get_Char_Index(face, c1); var delta = face.GetKerning(left_glyphIndex, glyphIndex, KerningMode.Default); // KerningData kd = new KerningData(kern_currentChar0, currentChar0, delta.X.ToInt32() >> 6, 0, delta.Y.ToInt32() >> 6, 0); if (left_glyphIndex == 0 || delta.X == 0) //no kerning { continue; } Kerning newKerning = new Kerning(); newKerning.RightGlyphID = left_glyphIndex; newKerning.KerningValue = delta.X.ToInt32() >> 6; newFont.SetKerning(left_Char0, newKerning); } newFont.SetVerticalOffset(currentChar0, ky); //cBmp.Dispose(); //g.DrawImageUnscaled(nBmp, (int)Math.Ceiling(newPos.X) + fontSettings.relativePositionX, (int)Math.Ceiling(newPos.Y) + fontSettings.relativePositionY); //// g.DrawImageUnscaled(nBmp, kx + FontSettings.relativePositionX, ky + FontSettings.relativePositionY); //nBmp.Dispose(); } g.Dispose(); library.Dispose(); return(bmp); }
private void button_Click(object sender, RoutedEventArgs e) { try { var mpm = ((AtlasModel)this.DataContext); mpm.Sprites.Clear(); mpm.Rectangles.Clear(); // mpm.Fonts.Clear(); // FontSettings fontSettings = new FontSettings(); MaxRectsBinPack binPack = new MaxRectsBinPack((int)mpm.TextureWidth, (int)mpm.TextureHeight, false); System.Drawing.Image image = System.Drawing.Image.FromFile(@"F:\Projekte\coop\XGame\_devFolder\Work\UI\Button_test-export.png");//mpm.AngelcodeFontFile); Rect newPos = binPack.Insert(image.Width, image.Height, MaxRectsBinPack.FreeRectChoiceHeuristic.RectBestLongSideFit); foreach (var fontModel in mpm.Fonts) { foreach (FontData character in fontModel.Items) { character.Glyph.X += (int)newPos.X; character.Glyph.Y += (int)newPos.Y; } } Rectangle testRect = new Rectangle { Stroke = Brushes.LightBlue, StrokeThickness = 0 }; ImageBrush ib = new ImageBrush(); BitmapImage bmi = new BitmapImage(new Uri(@"F:\Projekte\coop\XGame\_devFolder\Work\UI\Button_test-export.png", UriKind.Absolute)); ib.ImageSource = bmi; testRect.Fill = ib; testRect.Width = newPos.Width; testRect.Height = newPos.Height; Canvas.SetLeft(testRect, newPos.Left); Canvas.SetTop(testRect, newPos.Top); mpm.Rectangles.Add(testRect); //mpm.FontSystem.GenerateFont(mpm.Rectangles, // mpm.Fonts, // binPack, // fontSettings); //fontSettings = new FontSettings() //{ // FontSize = 40 //}; //mpm.FontSystem.GenerateFont(mpm.Rectangles, // mpm.FB_UI_Atlas.Fonts, // binPack, // fontSettings); AtlasHelper.GenAtlas(binPack, mpm.Rectangles, mpm.Sprites, mpm.ImageFolder, mpm.ImageExtensions, mpm.TextureWidth, mpm.TextureHeight); RenderTargetBitmap renderBitmap = new RenderTargetBitmap( (int)canvas.Width, (int)canvas.Height, 96d, 96d, PixelFormats.Pbgra32); // needed otherwise the image output is black canvas.Measure(new Size((int)canvas.Width, (int)canvas.Height)); canvas.Arrange(new Rect(new Size((int)canvas.Width, (int)canvas.Height))); renderBitmap.Render(canvas); //JpegBitmapEncoder encoder = new JpegBitmapEncoder(); PngBitmapEncoder encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(renderBitmap)); using (FileStream file = File.Create(((AtlasModel)this.DataContext).FB_UI_Atlas.TextureName)) { encoder.Save(file); } var fbData = mpm.FB_UI_Atlas.CreateFBData(); //@"F:\Projekte\coop\XGame\data\dbData\UI\TestAtlas.fbbin" using (FileStream fileStream = new FileStream(mpm.TargetFbbinFile, FileMode.Create)) { // Write the data to the file, byte by byte. for (int i = 0; i < fbData._fbData.Length; i++) { fileStream.WriteByte(fbData._fbData[i]); } // Set the stream position to the beginning of the file. fileStream.Seek(0, SeekOrigin.Begin); // Read and verify the data. for (int i = 0; i < fileStream.Length; i++) { if (fbData._fbData[i] != fileStream.ReadByte()) { Console.WriteLine("Error writing data."); return; } } Console.WriteLine("The data was written to {0} " + "and verified.", fileStream.Name); } } catch (Exception ex) { } }
private static Rect[] PackTextures(Texture2D texture, Texture2D[] sprites, int padding, int width, int height, int maxSize, bool forceSquare) { if ((width > maxSize && height < maxSize) || (height > maxSize && width < maxSize)) { width = height = maxSize; } if (width > maxSize || height > maxSize) { throw new InvalidOperationException("Packed sprites exceed maximum atlas size"); } if (forceSquare) { var max = Mathf.Max(width, height); width = max; height = max; } else if (height > width) { int temp = width; width = height; height = temp; } MaxRectsBinPack bp = new MaxRectsBinPack(width, height, false); Rect[] rects = new Rect[sprites.Length]; for (int i = 0; i < sprites.Length; i++) { Texture2D sprite = sprites[i]; var spriteWidth = sprite.width + padding; var spriteHeight = sprite.height + padding; var packingMethodConfig = (dfTexturePacker.dfTexturePackingMethod)EditorPrefs.GetInt("DaikonForge.AtlasPackingMethod", (int)dfTexturePacker.dfTexturePackingMethod.RectBestAreaFit); Rect rect = bp.Insert( spriteWidth, spriteHeight, packingMethodConfig ); // If the rect could not be packed into the current dimensions, // increase the texture size. if (rect.width == 0 || rect.height == 0) { return(PackTextures(texture, sprites, padding, (width <= height ? width << 1 : width), (height < width ? height << 1 : height), maxSize, forceSquare)); } rects[i] = rect; } // Check for max size if (width > maxSize || height > maxSize) { throw new InvalidOperationException("Packed sprites exceed maximum atlas size"); } texture.Resize(width, height); texture.SetPixels(new Color[width * height]); var extrudeEdges = EditorPrefs.GetBool("DaikonForge.AtlasExtrudeSprites", false) && padding > 0; for (int i = 0; i < sprites.Length; i++) { Texture2D sprite = sprites[i]; Rect rect = rects[i]; Color[] colors = sprite.GetPixels(); #region Edge extrusion coded provided by Mistale - http: //www.daikonforge.com/dfgui/forums/topic/dilate-texture-atlas/ // Dilate border if padding is set if (extrudeEdges) { int w = (int)sprite.width; int h = (int)sprite.height; int xStart = (int)rect.x; int yStart = (int)rect.y; int xStop = xStart + w - 1; int yStop = yStart + h - 1; Color[] wColors; int halfPadding = (int)(padding / 2f); // Top border wColors = sprite.GetPixels(0, 0, sprite.width, 1); for (int p = 0; p < halfPadding && yStart - p >= 1; p++) { texture.SetPixels(xStart, yStart - p - 1, sprite.width, 1, wColors); } // Bottom border wColors = sprite.GetPixels(0, sprite.height - 1, sprite.width, 1); for (int p = 0; p < halfPadding && yStop + p < texture.height - 1; p++) { texture.SetPixels(xStart, yStop + p + 1, sprite.width, 1, wColors); } // Left border wColors = sprite.GetPixels(0, 0, 1, sprite.height); for (int p = 0; p < halfPadding && xStart - p >= 1; p++) { texture.SetPixels(xStart - p - 1, yStart, 1, sprite.height, wColors); } // Right border wColors = sprite.GetPixels(sprite.width - 1, 0, 1, sprite.height); for (int p = 0; p < halfPadding && xStop + p < texture.width - 1; p++) { texture.SetPixels(xStop + p + 1, yStart, 1, sprite.height, wColors); } } #endregion texture.SetPixels( (int)rect.x, (int)rect.y, (int)sprite.width, (int)sprite.height, colors ); rects[i] = new Rect( rect.x / width, rect.y / height, (rect.width - padding) / width, (rect.height - padding) / height ); } return(rects); }
internal static void GenAtlas(List <string> paths) { List <Image> textures = new List <Image>(); double size = 0; foreach (var path in paths) { Image a = Image.Load(path); size += a.Width * a.Height; textures.Add(a); } size = Math.Sqrt(size) * 1.5; Rectangle[] rects = new Rectangle[textures.Count]; MaxRectsBinPack bp = new MaxRectsBinPack((int)size, (int)size, false); for (int i = 0; i < textures.Count; i++) { Rectangle rect = bp.Insert(textures[i].Width, textures[i].Height, MaxRectsBinPack.FreeRectChoiceHeuristic.RectBestAreaFit); if (rect.Width == 0 || rect.Height == 0) { Logger.LogError("The mystery error we thought impossible..."); return; } rects[i] = rect; } Vector2i MaxSize = new Vector2i(); foreach (var rect in rects) { if (rect.X + rect.Width > MaxSize.X) { MaxSize.X = rect.X + rect.Width; } if (rect.Y + rect.Height > MaxSize.Y) { MaxSize.Y = rect.Y + rect.Height; } } Atlas = new Image <Rgba32>(MaxSize.X, MaxSize.Y); for (int i = 0; i < rects.Length; i++) { Vector4 coord = new Vector4( (float)rects[i].X / Atlas.Width, 1.0f - (float)rects[i].Y / Atlas.Height, (float)(rects[i].X + rects[i].Width) / Atlas.Width, 1.0f - ((float)(rects[i].Y + rects[i].Height) / Atlas.Height) ); AtlasCoords.TryAdd(paths[i], coord); Atlas.Mutate(o => o.DrawImage(textures[i], new SixLabors.ImageSharp.Point(rects[i].X, rects[i].Y), 1f)); } Atlas.Mutate(o => o.Flip(FlipMode.Vertical)); Atlas.SaveAsPng("pain_and_suffering_sequel.png"); }
static void Main(string[] args) { int binWidth = 128, binHeight = 128; // 128 128 30 20 50 20 10 80 90 20 90 20 RectSize[] rectSizes = { new RectSize(30, 20), new RectSize(50, 20), new RectSize(10, 80), new RectSize(90, 20), new RectSize(90, 20) }; Console.WriteLine("### MaxRectsBinPack ###"); MaxRectsBinPack maxRectsBinPack = new MaxRectsBinPack(); maxRectsBinPack.Init(binWidth, binHeight); foreach (var rectSize in rectSizes) { Rect rect = maxRectsBinPack.Insert(rectSize, new MaxRectsBinPack.Option() { Method = MaxRectsBinPack.FreeRectChoiceHeuristic.RectBestAreaFit }); if (0 != rect.Height) { Console.WriteLine($"Rect -> {rect}, Free space left={maxRectsBinPack.FreeSpaceLeft}"); } else { Console.WriteLine($"Failed!-> {rectSize}"); } } Console.WriteLine("### GuillotineBinPack ###"); GuillotineBinPack binGuillotine = new GuillotineBinPack(); binGuillotine.Init(binWidth, binHeight); foreach (var rectSize in rectSizes) { Rect rect = binGuillotine.Insert(rectSize, new GuillotineBinPack.Option() { Merge = true, FreeRectChoice = GuillotineBinPack.FreeRectChoiceHeuristic.RectBestAreaFit, GuillotineSplit = GuillotineBinPack.GuillotineSplitHeuristic.SplitLongerAxis }); if (0 != rect.Height) { Console.WriteLine($"Rect -> {rect}, Free space left={binGuillotine.FreeSpaceLeft}"); } else { Console.WriteLine($"Failed!-> {rectSize}"); } } Console.WriteLine("### ShelfBinPack ###"); ShelfBinPack shelfBinPack = new ShelfBinPack { UseWasteMap = true }; shelfBinPack.Init(binWidth, binHeight); foreach (var rectSize in rectSizes) { Rect rect = shelfBinPack.Insert(rectSize, new ShelfBinPack.Option() { Method = ShelfBinPack.ShelfChoiceHeuristic.ShelfBestAreaFit }); if (0 != rect.Height) { Console.WriteLine($"Rect -> {rect}, Free space left= {shelfBinPack.FreeSpaceLeft}"); } else { Console.WriteLine($"Failed!-> {rectSize}"); } } Console.WriteLine("### ShelfNextFitBinPack ###"); ShelfNextFitBinPack shelfNextFitBinPack = new ShelfNextFitBinPack(); shelfNextFitBinPack.Init(binWidth, binHeight); foreach (var rectSize in rectSizes) { Rect rect = shelfNextFitBinPack.Insert(rectSize, new OptionNone()); if (0 != rect.Width) { Console.WriteLine($"Rect -> {rect}, Free space left={shelfNextFitBinPack.FreeSpaceLeft}"); } else { Console.WriteLine($"Failed!-> {rectSize}"); } } Console.WriteLine("### SkylineBinPack ###"); SkylineBinPack skylineBinPack = new SkylineBinPack(); skylineBinPack.Init(binWidth, binHeight); foreach (var rectSize in rectSizes) { Rect rect = skylineBinPack.Insert(rectSize, new SkylineBinPack.Option() { Method = SkylineBinPack.LevelChoiceHeuristic.LevelBottomLeft }); if (0 != rect.Height) { Console.WriteLine($"Rect -> {rect}, Free space left= {skylineBinPack.FreeSpaceLeft}"); } else { Console.WriteLine($"Failed! -> {rectSize}"); } } }
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)); }
private static Rect[] PackTextures( Texture2D texture, Texture2D[] sprites, int padding, int width, int height, int maxSize, bool forceSquare ) { if( ( width > maxSize && height < maxSize ) || ( height > maxSize && width < maxSize ) ) { width = height = maxSize; } if( width > maxSize || height > maxSize ) throw new InvalidOperationException( "Packed sprites exceed maximum atlas size" ); if( forceSquare ) { var max = Mathf.Max( width, height ); width = max; height = max; } else if( height > width ) { int temp = width; width = height; height = temp; } MaxRectsBinPack bp = new MaxRectsBinPack( width, height, false ); Rect[] rects = new Rect[ sprites.Length ]; for( int i = 0; i < sprites.Length; i++ ) { Texture2D sprite = sprites[ i ]; var spriteWidth = sprite.width + padding; var spriteHeight = sprite.height + padding; var packingMethodConfig = (dfTexturePacker.dfTexturePackingMethod)EditorPrefs.GetInt( "DaikonForge.AtlasPackingMethod", (int)dfTexturePacker.dfTexturePackingMethod.RectBestAreaFit ); Rect rect = bp.Insert( spriteWidth, spriteHeight, packingMethodConfig ); // If the rect could not be packed into the current dimensions, // increase the texture size. if( rect.width == 0 || rect.height == 0 ) { return PackTextures( texture, sprites, padding, ( width <= height ? width << 1 : width ), ( height < width ? height << 1 : height ), maxSize, forceSquare ); } rects[ i ] = rect; } // Check for max size if( width > maxSize || height > maxSize ) throw new InvalidOperationException( "Packed sprites exceed maximum atlas size" ); texture.Resize( width, height ); texture.SetPixels( new Color[ width * height ] ); var extrudeEdges = EditorPrefs.GetBool( "DaikonForge.AtlasExtrudeSprites", false ) && padding > 0; for( int i = 0; i < sprites.Length; i++ ) { Texture2D sprite = sprites[ i ]; Rect rect = rects[ i ]; Color[] colors = sprite.GetPixels(); #region Edge extrusion coded provided by Mistale - http://www.daikonforge.com/dfgui/forums/topic/dilate-texture-atlas/ // Dilate border if padding is set if( extrudeEdges ) { int w = (int)sprite.width; int h = (int)sprite.height; int xStart = (int)rect.x; int yStart = (int)rect.y; int xStop = xStart + w - 1; int yStop = yStart + h - 1; Color[] wColors; int halfPadding = (int)( padding / 2f ); // Top border wColors = sprite.GetPixels( 0, 0, sprite.width, 1 ); for( int p = 0; p < halfPadding && yStart - p >= 1; p++ ) texture.SetPixels( xStart, yStart - p - 1, sprite.width, 1, wColors ); // Bottom border wColors = sprite.GetPixels( 0, sprite.height - 1, sprite.width, 1 ); for( int p = 0; p < halfPadding && yStop + p < texture.height - 1; p++ ) texture.SetPixels( xStart, yStop + p + 1, sprite.width, 1, wColors ); // Left border wColors = sprite.GetPixels( 0, 0, 1, sprite.height ); for( int p = 0; p < halfPadding && xStart - p >= 1; p++ ) texture.SetPixels( xStart - p - 1, yStart, 1, sprite.height, wColors ); // Right border wColors = sprite.GetPixels( sprite.width - 1, 0, 1, sprite.height ); for( int p = 0; p < halfPadding && xStop + p < texture.width - 1; p++ ) texture.SetPixels( xStop + p + 1, yStart, 1, sprite.height, wColors ); } #endregion texture.SetPixels( (int)rect.x, (int)rect.y, (int)sprite.width, (int)sprite.height, colors ); rects[ i ] = new Rect( rect.x / width, rect.y / height, ( rect.width - padding ) / width, ( rect.height - padding ) / height ); } return rects; }
private static Rect[] PackTextures( Texture2D texture, Texture2D[] sprites, int padding, int width, int height, int maxSize ) { if( ( width > maxSize && height < maxSize ) || ( height > maxSize && width < maxSize ) ) { width = height = maxSize; } if( width > maxSize || height > maxSize ) throw new InvalidOperationException( "Packed sprites exceed maximum atlas size" ); if( height > width ) { int temp = width; width = height; height = temp; } MaxRectsBinPack bp = new MaxRectsBinPack( width, height, false ); Rect[] rects = new Rect[ sprites.Length ]; for( int i = 0; i < sprites.Length; i++ ) { Texture2D sprite = sprites[ i ]; var spriteWidth = sprite.width + padding; var spriteHeight = sprite.height + padding; Rect rect = bp.Insert( spriteWidth, spriteHeight, MaxRectsBinPack.FreeRectChoiceHeuristic.RectBestAreaFit ); // If the rect could not be packed into the current dimensions, // increase the texture size. if( rect.width == 0 || rect.height == 0 ) { return PackTextures( texture, sprites, padding, ( width <= height ? width << 1 : width ), ( height < width ? height << 1 : height ), maxSize ); } rects[ i ] = rect; } // Check for max size if( width > maxSize || height > maxSize ) throw new InvalidOperationException( "Packed sprites exceed maximum atlas size" ); texture.Resize( width, height ); texture.SetPixels( new Color[ width * height ] ); for( int i = 0; i < sprites.Length; i++ ) { Texture2D sprite = sprites[ i ]; Rect rect = rects[ i ]; Color[] colors = sprite.GetPixels(); texture.SetPixels( (int)rect.x, (int)rect.y, (int)sprite.width, (int)sprite.height, colors ); rects[ i ] = new Rect( rect.x / width, rect.y / height, ( rect.width - padding ) / width, ( rect.height - padding ) / height ); } return rects; }