public override bool Convert(ConvertOperation convert) { bool finishConvertOp = false; List<Texture> availData = convert.Perform<Texture>().ToList(); // Generate objects foreach (Texture baseRes in availData) { if (convert.IsObjectHandled(baseRes)) continue; // Find target Resource matching the source - or create one. Material targetRes = this.FindMatchingResources<Texture,Material>(baseRes, IsMatch) .FirstOrDefault(); if (targetRes == null && convert.AllowedOperations.HasFlag(ConvertOperation.Operation.CreateRes)) { string resPath = PathHelper.GetFreePath(baseRes.FullName, Resource.GetFileExtByType<Material>()); targetRes = new Material(DrawTechnique.Mask, ColorRgba.White, baseRes); targetRes.Save(resPath); } if (targetRes == null) continue; convert.AddResult(targetRes); finishConvertOp = true; convert.MarkObjectHandled(baseRes); } return finishConvertOp; }
public override bool Convert(ConvertOperation convert) { bool finishConvertOp = false; List<BatchInfo> availData = convert.Perform<BatchInfo>().ToList(); // Generate objects foreach (BatchInfo info in availData) { if (convert.IsObjectHandled(info)) continue; // Auto-Generate Material string matName = "Material"; if (!info.MainTexture.IsExplicitNull) matName = info.MainTexture.FullName; string matPath = PathHelper.GetFreePath(matName, Resource.GetFileExtByType<Material>()); Material mat = new Material(info); mat.Save(matPath); convert.AddResult(mat); finishConvertOp = true; convert.MarkObjectHandled(info); } return finishConvertOp; }
private static bool IsMatch(Texture source, Material target) { return target.MainTexture == source; }
private void GenerateResources() { if (this.mat != null || this.texture != null || this.pixelData != null) this.ReleaseResources(); TextRenderingHint textRenderingHint; if (this.renderMode == RenderMode.MonochromeBitmap) textRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; else textRenderingHint = TextRenderingHint.AntiAliasGridFit; int cols; int rows; cols = rows = (int)Math.Ceiling(Math.Sqrt(SupportedChars.Length)); Pixmap.Layer pixelLayer = new Pixmap.Layer(MathF.RoundToInt(cols * this.internalFont.Size * 1.2f), MathF.RoundToInt(rows * this.internalFont.Height * 1.2f)); Pixmap.Layer glyphTemp; Pixmap.Layer glyphTempTypo; Bitmap bm; Bitmap measureBm = new Bitmap(1, 1); Rect[] atlas = new Rect[SupportedChars.Length]; using (Graphics measureGraphics = Graphics.FromImage(measureBm)) { Brush fntBrush = new SolidBrush(Color.Black); StringFormat formatDef = StringFormat.GenericDefault; formatDef.LineAlignment = StringAlignment.Near; formatDef.FormatFlags = 0; StringFormat formatTypo = StringFormat.GenericTypographic; formatTypo.LineAlignment = StringAlignment.Near; int x = 1; int y = 1; for (int i = 0; i < SupportedChars.Length; ++i) { string str = SupportedChars[i].ToString(CultureInfo.InvariantCulture); bool isSpace = str == " "; SizeF charSize = measureGraphics.MeasureString(str, this.internalFont, pixelLayer.Width, formatDef); // Rasterize a single glyph for rendering bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), this.internalFont.Height + 1); using (Graphics glyphGraphics = Graphics.FromImage(bm)) { glyphGraphics.Clear(Color.Transparent); glyphGraphics.TextRenderingHint = textRenderingHint; glyphGraphics.DrawString(str, this.internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatDef); } glyphTemp = new Pixmap.Layer(bm); // Rasterize a single glyph in typographic mode for metric analysis if (!isSpace) { Rectangle glyphTempBounds = glyphTemp.OpaqueBounds(); glyphTemp.SubImage(glyphTempBounds.X, 0, glyphTempBounds.Width, glyphTemp.Height); if (BodyAscentRef.Contains(SupportedChars[i])) this.bodyAscent += glyphTempBounds.Height; bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), this.internalFont.Height + 1); using (Graphics glyphGraphics = Graphics.FromImage(bm)) { glyphGraphics.Clear(Color.Transparent); glyphGraphics.TextRenderingHint = textRenderingHint; glyphGraphics.DrawString(str, this.internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatTypo); } glyphTempTypo = new Pixmap.Layer(bm); glyphTempTypo.Crop(true, false); } else { glyphTempTypo = glyphTemp; } // Update xy values if it doesn't fit anymore if (x + glyphTemp.Width + 2 > pixelLayer.Width) { x = 1; y += this.internalFont.Height + MathF.Clamp((int)MathF.Ceiling(this.internalFont.Height * 0.1875f), 3, 10); } // Memorize atlas coordinates & glyph data this.maxGlyphWidth = Math.Max(this.maxGlyphWidth, glyphTemp.Width); this.glyphs[i].width = glyphTemp.Width; this.glyphs[i].height = glyphTemp.Height; this.glyphs[i].offsetX = glyphTemp.Width - glyphTempTypo.Width; if (isSpace) { this.glyphs[i].width /= 2; this.glyphs[i].offsetX /= 2; } atlas[i].X = x; atlas[i].Y = y; atlas[i].W = glyphTemp.Width; atlas[i].H = (this.internalFont.Height + 1); // Draw it onto the font surface glyphTemp.DrawOnto(pixelLayer, BlendMode.Solid, x, y); x += glyphTemp.Width + MathF.Clamp((int)MathF.Ceiling(this.internalFont.Height * 0.125f), 2, 10); } } // White out texture except alpha channel. for (int i = 0; i < pixelLayer.Data.Length; i++) { pixelLayer.Data[i].R = 255; pixelLayer.Data[i].G = 255; pixelLayer.Data[i].B = 255; } // Determine Font properties this.height = this.internalFont.Height; this.ascent = (int)Math.Round(this.internalFont.FontFamily.GetCellAscent(this.internalFont.Style) * this.internalFont.Size / this.internalFont.FontFamily.GetEmHeight(this.internalFont.Style)); this.bodyAscent /= BodyAscentRef.Length; this.descent = (int)Math.Round(this.internalFont.FontFamily.GetCellDescent(this.internalFont.Style) * this.internalFont.GetHeight() / this.internalFont.FontFamily.GetLineSpacing(this.internalFont.Style)); this.baseLine = (int)Math.Round(this.internalFont.FontFamily.GetCellAscent(this.internalFont.Style) * this.internalFont.GetHeight() / this.internalFont.FontFamily.GetLineSpacing(this.internalFont.Style)); // Create internal Pixmap and Texture Resources this.pixelData = new Pixmap(pixelLayer); this.pixelData.Atlas = new List<Rect>(atlas); this.texture = new Texture(this.pixelData, Texture.SizeMode.Enlarge, this.IsPixelGridAligned ? TextureMagFilter.Nearest : TextureMagFilter.Linear, this.IsPixelGridAligned ? TextureMinFilter.Nearest : TextureMinFilter.LinearMipmapLinear); // Select DrawTechnique to use ContentRef<DrawTechnique> technique; if (this.renderMode == RenderMode.MonochromeBitmap) technique = DrawTechnique.Mask; else if (this.renderMode == RenderMode.GrayscaleBitmap) technique = DrawTechnique.Alpha; else if (this.renderMode == RenderMode.SmoothBitmap) technique = DrawTechnique.Alpha; else technique = DrawTechnique.SharpAlpha; // Create and configure internal BatchInfo BatchInfo matInfo = new BatchInfo(technique, ColorRgba.White, this.texture); if (technique == DrawTechnique.SharpAlpha) { matInfo.SetUniform("smoothness", this.size * 3.0f); } this.mat = new Material(matInfo); }
private void ReleaseResources() { if (this.mat != null) this.mat.Dispose(); if (this.texture != null) this.texture.Dispose(); if (this.pixelData != null) this.pixelData.Dispose(); this.mat = null; this.texture = null; this.pixelData = null; this.needsReload = true; }
private void GenerateTexMat() { if (this.material != null) this.material.Dispose(); if (this.texture != null) this.texture.Dispose(); if (this.pixelData == null) return; this.texture = new Texture(this.pixelData, TextureSizeMode.Enlarge, this.IsPixelGridAligned ? TextureMagFilter.Nearest : TextureMagFilter.Linear, this.IsPixelGridAligned ? TextureMinFilter.Nearest : TextureMinFilter.LinearMipmapLinear); // Select DrawTechnique to use ContentRef<DrawTechnique> technique; if (this.renderMode == RenderMode.MonochromeBitmap) technique = DrawTechnique.Mask; else if (this.renderMode == RenderMode.GrayscaleBitmap) technique = DrawTechnique.Alpha; else if (this.renderMode == RenderMode.SmoothBitmap) technique = DrawTechnique.Alpha; else technique = DrawTechnique.SharpAlpha; // Create and configure internal BatchInfo BatchInfo matInfo = new BatchInfo(technique, ColorRgba.White, this.texture); if (technique == DrawTechnique.SharpAlpha) { matInfo.SetUniform("smoothness", this.size * 4.0f); } this.material = new Material(matInfo); }
private void ReleaseResources() { if (this.material != null) this.material.Dispose(); if (this.texture != null) this.texture.Dispose(); if (this.pixelData != null) this.pixelData.Dispose(); this.material = null; this.texture = null; this.pixelData = null; this.glyphsDirty = true; }
private void GenerateResources() { if (this.mat != null || this.texture != null || this.pixelData != null) this.ReleaseResources(); int cols; int rows; cols = rows = (int)Math.Ceiling(Math.Sqrt(SupportedChars.Length)); Pixmap.Layer pixelLayer = new Pixmap.Layer(MathF.RoundToInt(cols * this.internalFont.Size), MathF.RoundToInt(rows * (this.internalFont.Height + 1))); Pixmap.Layer glyphTemp; Pixmap.Layer glyphTempTypo; Bitmap bm; Bitmap measureBm = new Bitmap(1, 1); Rect[] atlas = new Rect[SupportedChars.Length]; using (Graphics measureGraphics = Graphics.FromImage(measureBm)) { Brush fntBrush = new SolidBrush(Color.Black); StringFormat formatDef = StringFormat.GenericDefault; formatDef.LineAlignment = StringAlignment.Near; formatDef.FormatFlags = 0; StringFormat formatTypo = StringFormat.GenericTypographic; formatTypo.LineAlignment = StringAlignment.Near; int x = 0; int y = 0; for (int i = 0; i < SupportedChars.Length; ++i) { string str = SupportedChars[i].ToString(CultureInfo.InvariantCulture); bool isSpace = str == " "; SizeF charSize = measureGraphics.MeasureString(str, this.internalFont, pixelLayer.Width, formatDef); // Render a single glyph bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), this.internalFont.Height + 1); using (Graphics glyphGraphics = Graphics.FromImage(bm)) { glyphGraphics.Clear(Color.Transparent); glyphGraphics.TextRenderingHint = (System.Drawing.Text.TextRenderingHint)this.hint; glyphGraphics.DrawString(str, this.internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatDef); } glyphTemp = new Pixmap.Layer(bm); if (!isSpace) { Rectangle glyphTempBounds = glyphTemp.OpaqueBounds(); glyphTemp.SubImage(glyphTempBounds.X, 0, glyphTempBounds.Width, glyphTemp.Height); if (BodyAscentRef.Contains(SupportedChars[i])) this.bodyAscent += glyphTempBounds.Height; // Render a single glyph in typographic mode bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), this.internalFont.Height + 1); using (Graphics glyphGraphics = Graphics.FromImage(bm)) { glyphGraphics.Clear(Color.Transparent); glyphGraphics.TextRenderingHint = (System.Drawing.Text.TextRenderingHint)this.hint; glyphGraphics.DrawString(str, this.internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatTypo); } glyphTempTypo = new Pixmap.Layer(bm); glyphTempTypo.Crop(true, false); } else glyphTempTypo = glyphTemp; // Update xy values if it doesn't fit anymore if (x + glyphTemp.Width + 2 > pixelLayer.Width) { x = 0; y += (this.internalFont.Height + 1) + 2; } // Memorize atlas coordinates & glyph data this.maxGlyphWidth = Math.Max(this.maxGlyphWidth, glyphTemp.Width); this.glyphs[i].width = glyphTemp.Width; this.glyphs[i].height = glyphTemp.Height; this.glyphs[i].offsetX = glyphTemp.Width - glyphTempTypo.Width; if (isSpace) { this.glyphs[i].width /= 2; this.glyphs[i].offsetX /= 2; } atlas[i].X = x; atlas[i].Y = y; atlas[i].W = glyphTemp.Width; atlas[i].H = (this.internalFont.Height + 1); // Draw it onto the font surface glyphTemp.DrawOnto(pixelLayer, BlendMode.Solid, x, y); x += glyphTemp.Width + 2; } } // Adjust colors based on alpha value //for (int i = 0; i < pixelLayer.Data.Length; i++) System.Threading.Tasks.Parallel.For(0, pixelLayer.Data.Length, i => { float factor = pixelLayer.Data[i].A / 255.0f; float invFactor = 1.0f - factor; pixelLayer.Data[i].R = (byte)Math.Min(255.0f, Math.Max(0.0f, this.bgColor.R * invFactor + this.color.R * factor)); pixelLayer.Data[i].G = (byte)Math.Min(255.0f, Math.Max(0.0f, this.bgColor.G * invFactor + this.color.G * factor)); pixelLayer.Data[i].B = (byte)Math.Min(255.0f, Math.Max(0.0f, this.bgColor.B * invFactor + this.color.B * factor)); pixelLayer.Data[i].A = (byte)Math.Min(255.0f, Math.Max(0.0f, this.bgColor.A * invFactor + this.color.A * factor)); }); this.height = this.internalFont.Height; this.ascent = (int)Math.Round(this.internalFont.FontFamily.GetCellAscent(this.internalFont.Style) * this.internalFont.Size / this.internalFont.FontFamily.GetEmHeight(this.internalFont.Style)); this.bodyAscent /= BodyAscentRef.Length; this.descent = (int)Math.Round(this.internalFont.FontFamily.GetCellDescent(this.internalFont.Style) * this.internalFont.GetHeight() / this.internalFont.FontFamily.GetLineSpacing(this.internalFont.Style)); this.baseLine = (int)Math.Round(this.internalFont.FontFamily.GetCellAscent(this.internalFont.Style) * this.internalFont.GetHeight() / this.internalFont.FontFamily.GetLineSpacing(this.internalFont.Style)); bool useNearest = this.hint == RenderHint.Monochrome || !this.filtering; this.pixelData = new Pixmap(pixelLayer); this.pixelData.Atlas = new List<Rect>(atlas); this.texture = new Texture(this.pixelData, Texture.SizeMode.Enlarge, useNearest ? OpenTK.Graphics.OpenGL.TextureMagFilter.Nearest : OpenTK.Graphics.OpenGL.TextureMagFilter.Linear, useNearest ? OpenTK.Graphics.OpenGL.TextureMinFilter.Nearest : OpenTK.Graphics.OpenGL.TextureMinFilter.LinearMipmapLinear); this.mat = new Material(this.hint == RenderHint.Monochrome ? DrawTechnique.Mask : DrawTechnique.Alpha, ColorRgba.White, this.texture); }
private void GenerateMaterial() { if (this.material != null) this.material.Dispose(); if (this.texture == null) return; // Select DrawTechnique to use ContentRef<DrawTechnique> technique; if (this.renderMode == RenderMode.MonochromeBitmap) technique = DrawTechnique.Mask; else if (this.renderMode == RenderMode.GrayscaleBitmap) technique = DrawTechnique.Alpha; else if (this.renderMode == RenderMode.SmoothBitmap) technique = DrawTechnique.Alpha; else technique = DrawTechnique.SharpAlpha; // Create and configure internal BatchInfo BatchInfo matInfo = new BatchInfo(technique, ColorRgba.White, this.texture); if (technique == DrawTechnique.SharpAlpha) { matInfo.SetUniform("smoothness", this.size * 4.0f); } this.material = new Material(matInfo); }
/// <summary> /// Creates a new Material Resource based on the specified Texture, saves it and returns a reference to it. /// </summary> /// <param name="baseRes"></param> /// <returns></returns> public static ContentRef<Material> CreateFromTexture(ContentRef<Texture> baseRes) { string resPath = PathHelper.GetFreePath(baseRes.FullName, Resource.GetFileExtByType<Material>()); Material res = new Material(DrawTechnique.Mask, ColorRgba.White, baseRes); res.Save(resPath); return res; }