public Text(FontSize size, string text, Vector3 color, BMFont.Justification justification = BMFont.Justification.Left) { this.Justification = justification; this.font = FontFromSize(size); this.String = text; this.Color = color; }
Vector4 outlineColor = new Vector4(1.0f, 0.0f, 0.0f, 0.6f); //alpha => 0:disabled 1:enabled protected override void initVulkan() { base.initVulkan(); cmds = cmdPool.AllocateCommandBuffer(swapChain.ImageCount); font = new BMFont(vke.samples.Utils.GetDataFile("font.fnt")); vbo = new GPUBuffer <float> (dev, VkBufferUsageFlags.VertexBuffer | VkBufferUsageFlags.TransferDst, 1024); ibo = new GPUBuffer <ushort> (dev, VkBufferUsageFlags.IndexBuffer | VkBufferUsageFlags.TransferDst, 2048); descriptorPool = new DescriptorPool(dev, 1, new VkDescriptorPoolSize(VkDescriptorType.UniformBuffer), new VkDescriptorPoolSize(VkDescriptorType.CombinedImageSampler) ); dsLayout = new DescriptorSetLayout(dev, 0, new VkDescriptorSetLayoutBinding(0, VkShaderStageFlags.Vertex, VkDescriptorType.UniformBuffer), new VkDescriptorSetLayoutBinding(1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler)); using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount4, false)) { cfg.Layout = new PipelineLayout(dev, dsLayout); cfg.Layout.AddPushConstants(new VkPushConstantRange(VkShaderStageFlags.Fragment, (uint)Marshal.SizeOf <Vector4> () * 2)); cfg.RenderPass = new RenderPass(dev, swapChain.ColorFormat, cfg.Samples); cfg.blendAttachments[0] = new VkPipelineColorBlendAttachmentState( true, VkBlendFactor.One, VkBlendFactor.OneMinusSrcAlpha, VkBlendOp.Add, VkBlendFactor.One, VkBlendFactor.Zero); cfg.AddVertexBinding(0, 5 * sizeof(float)); cfg.AddVertexAttributes(0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat); cfg.AddShader(dev, VkShaderStageFlags.Vertex, "#shaders.main.vert.spv"); cfg.AddShader(dev, VkShaderStageFlags.Fragment, "#shaders.main.frag.spv"); pipeline = new GraphicPipeline(cfg); } uboMats = new HostBuffer(dev, VkBufferUsageFlags.UniformBuffer, matrices); uboMats.Map(); //permanent map descriptorSet = descriptorPool.Allocate(dsLayout); fontTexture = font.GetPageTexture(0, presentQueue, cmdPool); fontTexture.CreateView(); fontTexture.CreateSampler(); fontTexture.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; DescriptorSetWrites dsUpdate = new DescriptorSetWrites(descriptorSet, dsLayout); dsUpdate.Write(dev, uboMats.Descriptor, fontTexture.Descriptor); generateText("Vulkan", out HostBuffer <Vertex> staggingVbo, out HostBuffer <ushort> staggingIbo); PrimaryCommandBuffer cmd = cmdPool.AllocateAndStart(VkCommandBufferUsageFlags.OneTimeSubmit); staggingVbo.CopyTo(cmd, vbo); staggingIbo.CopyTo(cmd, ibo); presentQueue.EndSubmitAndWait(cmd); staggingVbo.Dispose(); staggingIbo.Dispose(); UpdateFrequency = 10; }
/// <summary> /// Reload the font data. /// </summary> static public void Load(BMFont font, string name, byte[] bytes) { font.Clear(); if (bytes != null) { ByteReader reader = new ByteReader(bytes); char[] separator = new char[] { ' ' }; while (reader.canRead) { string line = reader.ReadLine(); if (string.IsNullOrEmpty(line)) { break; } string[] split = line.Split(separator, System.StringSplitOptions.RemoveEmptyEntries); int len = split.Length; if (split[0] == "char") { // Expected data style: // char id=13 x=506 y=62 width=3 height=3 xoffset=-1 yoffset=50 xadvance=0 page=0 chnl=15 int channel = (len > 10) ? GetInt(split[10]) : 15; if (len > 9 && GetInt(split[9]) > 0) { Debug.LogError("Your font was exported with more than one texture. Only one texture is supported by NGUI.\n" + "You need to re-export your font, enlarging the texture's dimensions until everything fits into just one texture."); break; } if (len > 8) { int id = GetInt(split[1]); BMGlyph glyph = font.GetGlyph(id, true); if (glyph != null) { glyph.x = GetInt(split[2]); glyph.y = GetInt(split[3]); glyph.width = GetInt(split[4]); glyph.height = GetInt(split[5]); glyph.offsetX = GetInt(split[6]); glyph.offsetY = GetInt(split[7]); glyph.advance = GetInt(split[8]); glyph.channel = channel; } else { Debug.Log("Char: " + split[1] + " (" + id + ") is NULL"); } } else { Debug.LogError("Unexpected number of entries for the 'char' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "kerning") { // Expected data style: // kerning first=84 second=244 amount=-5 if (len > 3) { int first = GetInt(split[1]); int second = GetInt(split[2]); int amount = GetInt(split[3]); BMGlyph glyph = font.GetGlyph(second, true); if (glyph != null) { glyph.SetKerning(first, amount); } } else { Debug.LogError("Unexpected number of entries for the 'kerning' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "common") { // Expected data style: // common lineHeight=64 base=51 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=1 redChnl=4 greenChnl=4 blueChnl=4 if (len > 5) { font.charSize = GetInt(split[1]); font.baseOffset = GetInt(split[2]); font.texWidth = GetInt(split[3]); font.texHeight = GetInt(split[4]); int pages = GetInt(split[5]); if (pages != 1) { Debug.LogError("Font '" + name + "' must be created with only 1 texture, not " + pages); break; } } else { Debug.LogError("Unexpected number of entries for the 'common' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "page") { // Expected data style: // page id=0 file="textureName.png" if (len > 2) { font.spriteName = GetString(split[2]).Replace("\"", ""); font.spriteName = font.spriteName.Replace(".png", ""); font.spriteName = font.spriteName.Replace(".tga", ""); } } else if (split[0] == "symbol") { // Expected data style: // symbol sequence=(A) x=172 y=140 width=20 height=20 if (len > 5) { // BMSymbol symbol = font.GetSymbol(GetString(split[1]), true); // symbol.x = GetInt(split[2]); // symbol.y = GetInt(split[3]); // symbol.width = GetInt(split[4]); // symbol.height = GetInt(split[5]); } } } } }
public static void BMFontCreat() { string txtPath = string.Empty; string texturePath = string.Empty; string[] guids = Selection.assetGUIDs; if (guids.Length != 2) { Debug.Log("please select fontImage and fontText!"); return; } Font mFont = new Font(); TextAsset mText = null; Material material = new Material(Shader.Find("GUI/Text Shader")); for (int i = 0; i < guids.Length; i++) { string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]); int index = assetPath.ToString().IndexOf("Assets"); string modPath = assetPath.ToString().Remove(0, index); modPath = modPath.Replace("\\", "/"); if (assetPath.Contains("txt"))//txt { txtPath = modPath; mText = (TextAsset)AssetDatabase.LoadAssetAtPath(modPath, typeof(TextAsset)); } else//png { texturePath = modPath; TextureImporter texImport = AssetImporter.GetAtPath(modPath) as TextureImporter; texImport.textureFormat = TextureImporterFormat.AutomaticTruecolor; texImport.textureType = TextureImporterType.Image; texImport.wrapMode = TextureWrapMode.Clamp; AssetDatabase.ImportAsset(modPath); material.mainTexture = (Texture)AssetDatabase.LoadAssetAtPath(modPath, typeof(Texture)); } } if (mText == null || material == null) return; mFont.name = mText.name; material.name = mText.name; BMFont mbFont = new BMFont(); BMFontReader.Load(mbFont, mText.name, mText.bytes); CharacterInfo[] characterInfo = new CharacterInfo[mbFont.glyphs.Count]; for (int j = 0; j < mbFont.glyphs.Count; j++) { BMGlyph bmInfo = mbFont.glyphs[j]; CharacterInfo info = new CharacterInfo(); info.index = bmInfo.index; info.uv.x = (float)bmInfo.x / (float)mbFont.texWidth; info.uv.y = 1 - (float)bmInfo.y / (float)mbFont.texHeight; info.uv.width = (float)bmInfo.width / (float)mbFont.texWidth; info.uv.height = -1f * (float)bmInfo.height / (float)mbFont.texHeight; info.vert.x = (float)bmInfo.offsetX; info.vert.y = 0f; info.vert.width = (float)bmInfo.width; info.vert.height = (float)bmInfo.height; info.width = (float)bmInfo.advance; characterInfo[j] = info; } mFont.characterInfo = characterInfo; mFont.material = material; string newFontPath = txtPath.Replace("txt", "fontsettings"); string newMatrilPath = txtPath.Replace("txt", "mat"); AssetDatabase.CreateAsset(material, newMatrilPath); AssetDatabase.CreateAsset(mFont, newFontPath); AssetDatabase.Refresh(); }
{ public static void BatchCreateArtistFont() { string dirName = ""; string fntname = EditorUtils.SelectObjectPathInfo(ref dirName).Split('.')[0]; Debug.Log(fntname); Debug.Log(dirName); string fntFileName = dirName + fntname + ".fnt"; Font CustomFont = new Font(); { AssetDatabase.CreateAsset(CustomFont, dirName + fntname + ".fontsettings"); AssetDatabase.SaveAssets(); } TextAsset BMFontText = null; { BMFontText = AssetDatabase.LoadAssetAtPath(fntFileName, typeof(TextAsset)) as TextAsset; } BMFont mbFont = new BMFont(); BMFontReader.Load(mbFont, BMFontText.name, BMFontText.bytes); // 借用NGUI封装的读取类 CharacterInfo[] characterInfo = new CharacterInfo[mbFont.glyphs.Count]; for (int i = 0; i < mbFont.glyphs.Count; i++) { BMGlyph bmInfo = mbFont.glyphs[i]; CharacterInfo info = new CharacterInfo(); info.index = bmInfo.index; info.uv.x = (float)bmInfo.x / (float)mbFont.texWidth; info.uv.y = 1 - (float)bmInfo.y / (float)mbFont.texHeight; info.uv.width = (float)bmInfo.width / (float)mbFont.texWidth; info.uv.height = -1f * (float)bmInfo.height / (float)mbFont.texHeight; info.vert.x = (float)bmInfo.offsetX; info.vert.y = (float)bmInfo.offsetY; info.vert.width = (float)bmInfo.width; info.vert.height = (float)bmInfo.height; info.width = (float)bmInfo.advance; characterInfo[i] = info; } CustomFont.characterInfo = characterInfo; string textureFilename = dirName + mbFont.spriteName + ".png"; Material mat = null; { Shader shader = Shader.Find("Transparent/Diffuse"); mat = new Material(shader); Texture tex = AssetDatabase.LoadAssetAtPath(textureFilename, typeof(Texture)) as Texture; mat.SetTexture("_MainTex", tex); AssetDatabase.CreateAsset(mat, dirName + fntname + ".mat"); AssetDatabase.SaveAssets(); } CustomFont.material = mat; //AssetDatabase.SaveAssets(); SerializedObject so = new SerializedObject(CustomFont); so.ApplyModifiedProperties(); }
/// <summary> /// Reload the font data. /// </summary> static public void Load(BMFont font, string name, byte[] bytes) { font.Clear(); if (bytes != null) { ByteReader reader = new ByteReader(bytes); char[] separator = new char[] { ' ' }; while (reader.canRead) { string line = reader.ReadLine(); if (string.IsNullOrEmpty(line)) { break; } string[] split = line.Split(separator, System.StringSplitOptions.RemoveEmptyEntries); if (split[0] == "char") { // Expected data style: // char id=13 x=506 y=62 width=3 height=3 xoffset=-1 yoffset=50 xadvance=0 page=0 chnl=15 if (split.Length > 8) { int id = GetInt(split[1]); BMGlyph glyph = font.GetGlyph(id, true); if (glyph != null) { glyph.x = GetInt(split[2]); glyph.y = GetInt(split[3]); glyph.width = GetInt(split[4]); glyph.height = GetInt(split[5]); glyph.offsetX = GetInt(split[6]); glyph.offsetY = GetInt(split[7]); glyph.advance = GetInt(split[8]); } else { Debug.Log("Char: " + split[1] + " (" + id + ") is NULL"); } } else { Debug.LogError("Unexpected number of entries for the 'char' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "kerning") { // Expected data style: // kerning first=84 second=244 amount=-5 if (split.Length > 3) { int first = GetInt(split[1]); int second = GetInt(split[2]); int amount = GetInt(split[3]); BMGlyph glyph = font.GetGlyph(second, true); if (glyph != null) { glyph.SetKerning(first, amount); } } else { Debug.LogError("Unexpected number of entries for the 'kerning' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "common") { // Expected data style: // common lineHeight=64 base=51 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=1 redChnl=4 greenChnl=4 blueChnl=4 if (split.Length > 5) { font.charSize = GetInt(split[1]); font.baseOffset = GetInt(split[2]); font.texWidth = GetInt(split[3]); font.texHeight = GetInt(split[4]); int pages = GetInt(split[5]); if (pages != 1) { Debug.LogError("Font '" + name + "' must be created with only 1 texture, not " + pages); break; } } else { Debug.LogError("Unexpected number of entries for the 'common' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "page") { // Expected data style: // page id=0 file="textureName.png" if (split.Length > 2) { font.spriteName = GetString(split[2]).Replace("\"", ""); font.spriteName = font.spriteName.Replace(".png", ""); font.spriteName = font.spriteName.Replace(".tga", ""); } } } } }
{ public static void BatchCreateArtistFont() { string dirName = ""; string fntname = EditorUtils.SelectObjectPathInfo(ref dirName).Split('.')[0]; string fntFileName = dirName + fntname + ".fnt"; Font CustomFont = new Font(); AssetDatabase.CreateAsset(CustomFont, dirName + fntname + ".fontsettings"); TextAsset BMFontText = AssetDatabase.LoadAssetAtPath(fntFileName, typeof(TextAsset)) as TextAsset; BMFont mbFont = new BMFont(); BMFontReader.Load(mbFont, BMFontText.name, BMFontText.bytes); // 借用NGUI封装的读取类 CharacterInfo[] characterInfo = new CharacterInfo[mbFont.glyphs.Count]; for (int i = 0; i < mbFont.glyphs.Count; i++) { BMGlyph bmInfo = mbFont.glyphs[i]; CharacterInfo info = new CharacterInfo(); info.index = bmInfo.index; Rect rect = new Rect(); rect.x = bmInfo.x / (float)mbFont.texWidth; rect.y = 1 - bmInfo.y / (float)mbFont.texHeight; rect.width = bmInfo.width / (float)mbFont.texWidth; rect.height = -1 * bmInfo.height / (float)mbFont.texHeight; info.uvBottomLeft = new Vector2(rect.xMin, rect.yMin); info.uvBottomRight = new Vector2(rect.xMax, rect.yMin); info.uvTopLeft = new Vector2(rect.xMin, rect.yMax); info.uvTopRight = new Vector2(rect.xMax, rect.yMax); rect = new Rect(); rect.x = bmInfo.offsetX; rect.y = bmInfo.offsetY; rect.width = bmInfo.width; rect.height = bmInfo.height; info.minX = (int)rect.xMin; info.maxX = (int)rect.xMax; info.minY = (int)rect.yMax; info.maxY = (int)rect.yMin; info.advance = bmInfo.advance; characterInfo[i] = info; } CustomFont.characterInfo = characterInfo; string textureFilename = dirName + mbFont.spriteName + ".png"; Shader shader = Shader.Find("Sprites/Default"); Material mat = new Material(shader); Texture tex = AssetDatabase.LoadAssetAtPath(textureFilename, typeof(Texture)) as Texture; mat.SetTexture("_MainTex", tex); AssetDatabase.CreateAsset(mat, dirName + fntname + ".mat"); AssetDatabase.SaveAssets(); CustomFont.material = mat; AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); }
public static void BatchCreateArtistFont() { string dirName = ""; string fntname = EditorUtils.SelectObjectPathInfo(ref dirName).Split('.')[0]; Debug.Log(fntname); Debug.Log(dirName); string fntFileName = dirName + fntname + ".fnt"; Font CustomFont = new Font(); { AssetDatabase.CreateAsset(CustomFont, dirName + fntname + ".fontsettings"); AssetDatabase.SaveAssets(); } TextAsset BMFontText = null; { BMFontText = AssetDatabase.LoadAssetAtPath(fntFileName, typeof(TextAsset)) as TextAsset; } //Debug.Log(BMFontText.ToString().Replace("\"", "\'")); Debug.Log(BMFontText.text); JsonString js = JsonMapper.ToObject <JsonString>(BMFontText.text); //JsonString js = JsonUtility.FromJson<JsonString>(BMFontText.text); Debug.Log(js.file); BMFont mbFont = new BMFont(); BMFontReader.Load(mbFont, BMFontText.name, BMFontText.bytes); // 借用NGUI封装的读取类 CharacterInfo[] characterInfo = new CharacterInfo[mbFont.glyphs.Count]; for (int i = 0; i < mbFont.glyphs.Count; i++) { BMGlyph bmInfo = mbFont.glyphs[i]; CharacterInfo info = new CharacterInfo(); info.index = bmInfo.index; Rect r = new Rect(); r.x = (float)bmInfo.x / (float)mbFont.texWidth; r.y = 1 - (float)bmInfo.y / (float)mbFont.texHeight; r.width = (float)bmInfo.width / (float)mbFont.texWidth; r.height = -1f * (float)bmInfo.height / (float)mbFont.texHeight; info.uvBottomLeft = new Vector2(r.xMin, r.yMin); info.uvBottomRight = new Vector2(r.xMax, r.yMin); info.uvTopLeft = new Vector2(r.xMin, r.yMax); info.uvTopRight = new Vector2(r.xMax, r.yMax); //info.uv.x = (float)bmInfo.x / (float)mbFont.texWidth; //info.uv.y = 1 - (float)bmInfo.y / (float)mbFont.texHeight; //info.uv.width = (float)bmInfo.width / (float)mbFont.texWidth; //info.uv.height = -1f * (float)bmInfo.height / (float)mbFont.texHeight; r.x = (float)bmInfo.offsetX; r.y = (float)bmInfo.offsetY; r.width = (float)bmInfo.width; r.height = (float)bmInfo.height; //info.vert.x = (float)bmInfo.offsetX; //info.vert.y = (float)bmInfo.offsetY; //info.vert.width = (float)bmInfo.width; //info.vert.height = (float)bmInfo.height; info.minX = (int)r.xMin; info.maxX = (int)r.xMax; info.minY = (int)r.yMax; info.maxY = (int)r.yMin; info.advance = (int)bmInfo.advance; characterInfo[i] = info; } CustomFont.characterInfo = characterInfo; string textureFilename = dirName + mbFont.spriteName + ".png"; Material mat = null; { Shader shader = Shader.Find("Transparent/Diffuse"); mat = new Material(shader); Texture tex = AssetDatabase.LoadAssetAtPath(textureFilename, typeof(Texture)) as Texture; mat.SetTexture("_MainTex", tex); AssetDatabase.CreateAsset(mat, dirName + fntname + ".mat"); AssetDatabase.SaveAssets(); } CustomFont.material = mat; }
public void Draw(SmartSpriteBatch spriteBatch, bool showDebug) { BMFont font = Solids.Instance.AssetLibrary.GetFont("consolas"); if (font != null) { if (showDebug) { var bounds = spriteBatch.GraphicsDevice.Viewport.Bounds; spriteBatch.DrawSolidRectangle(new FloatRectangle(0, 0, bounds.Width, (int)(bounds.Height * 0.8f)), Color.CornflowerBlue * 0.75f); } var scale = new Vector2(0.75f, 0.75f); int mxh = 0; int mxw = 0; foreach (var i in DebugObjects) { var r = font.MeasureString(i.CurrentText) * scale; if (r.X > mxw) { mxw = (int)r.X; } if (r.Y > mxh) { mxh = (int)r.Y; } } int width = 100 + mxw + 20; if (showDebug) { spriteBatch.DrawSolidRectangle(new FloatRectangle(spriteBatch.GraphicsDevice.Viewport.Bounds.Width - (int)width - 20, 2, (int)width, (int)mxh * DebugObjects.Count), Color.Black); } int ct = 0; float mx = 1; if (showDebug && false) { Vector2 fontscale = new Vector2(0.4f, 0.4f); int ps = 50; font.DrawText(spriteBatch, new Vector2(10, 20), "Key", Color.White, fontscale); font.DrawText(spriteBatch, new Vector2(300, 20), "Runs", Color.White, fontscale); font.DrawText(spriteBatch, new Vector2(450, 20), "Avg", Color.White, fontscale); font.DrawText(spriteBatch, new Vector2(600, 20), "Min", Color.White, fontscale); font.DrawText(spriteBatch, new Vector2(750, 20), "Max", Color.White, fontscale); font.DrawText(spriteBatch, new Vector2(900, 20), "Total", Color.White, fontscale); foreach (KeyValuePair <string, BenchMarkDetails> benchMarkDetailse in BenchMarkProvider.BenchMarks) { font.DrawText(spriteBatch, new Vector2(10, ps), benchMarkDetailse.Key, Color.White, new Vector2(0.5f, 0.5f)); font.DrawText(spriteBatch, new Vector2(300, ps), benchMarkDetailse.Value.NumberOfTimesRun.ToString(), Color.White, fontscale); font.DrawText(spriteBatch, new Vector2(450, ps), benchMarkDetailse.Value.AverageTime.ToString("c"), Color.White, fontscale); font.DrawText(spriteBatch, new Vector2(600, ps), benchMarkDetailse.Value.ShortestTime.ToString("c"), Color.White, fontscale); font.DrawText(spriteBatch, new Vector2(750, ps), benchMarkDetailse.Value.LongestTime.ToString("c"), Color.White, fontscale); font.DrawText(spriteBatch, new Vector2(900, ps), benchMarkDetailse.Value.TotalTime.ToString("c"), Color.White, fontscale); ps = ps + 30; } } if (showDebug && true) { Vector2 fontscale = new Vector2(0.4f, 0.4f); int ps = 50 + (BreezeDebug.ConsoleHistory.Count * 30); if (ps > 700) { ps = 700; } foreach (string history in BreezeDebug.ConsoleHistory) { if (ps > 0) { font.DrawText(spriteBatch, new Vector2(10, ps), history, Color.White, new Vector2(0.5f, 0.5f)); ps = ps - 30; } } } if (false) { foreach (var i in DebugObjects) { if (showDebug) { font.DrawText(spriteBatch, new Vector2(spriteBatch.GraphicsDevice.Viewport.Bounds.Width - width - 10, mxh * ct), i.CurrentText, Color.White, scale); if (Solids.Instance.FrameCounter.CurrentFramesPerSecond > 59) { if (pointer % 500 == 0) { mx = Math.Max(i.HistoricValues.Max(), 1); if (mx > i.MXValue) { i.MXValue = mx; } else { i.MXValue = i.MXValue * 0.995f; } } mx = i.MXValue; int xct = 0; for (int x = pointer; x < pointer + 49; x++) { float h1 = (i.HistoricValues[x % 50] / mx) * mxh; float h2 = (i.HistoricValues[(x + 1) % 50] / mx) * mxh; int ps = spriteBatch.GraphicsDevice.Viewport.Bounds.Width - 90 + (xct * 2); spriteBatch.DrawLine(new Vector2(ps, h1 + (ct * mxh)), new Vector2(ps + 2, h2 + (ct * mxh)), Color.White); xct++; } } ct++; } i.HistoricValues[pointer % 50] = i.CurrentValue; } } pointer++; } }
public static void BMFontCreate(string txtPath, string pngPath, string tempName) { TextAsset mText = (TextAsset)AssetDatabase.LoadAssetAtPath(txtPath, typeof(TextAsset)); TextureImporter texImport = AssetImporter.GetAtPath(pngPath) as TextureImporter; texImport.textureCompression = TextureImporterCompression.Uncompressed; texImport.textureType = TextureImporterType.Default; texImport.wrapMode = TextureWrapMode.Clamp; texImport.mipmapEnabled = false; texImport.isReadable = false; AssetDatabase.ImportAsset(pngPath); Material material = new Material(Shader.Find("GUI/Text Shader")); material.mainTexture = (Texture)AssetDatabase.LoadAssetAtPath(pngPath, typeof(Texture)); Font mFont = new Font(); if (mText == null || material == null) { return; } mFont.name = mText.name; material.name = mText.name; BMFont mbFont = new BMFont(); BMFontReader.Load(mbFont, mText.name, mText.bytes); CharacterInfo[] characterInfo = new CharacterInfo[mbFont.glyphs.Count]; for (int j = 0; j < mbFont.glyphs.Count; j++) { BMGlyph bmInfo = mbFont.glyphs[j]; CharacterInfo info = new CharacterInfo(); info.index = bmInfo.index; info.uv.x = (float)bmInfo.x / (float)mbFont.texWidth; info.uv.y = 1 - (float)bmInfo.y / (float)mbFont.texHeight; info.uv.width = (float)bmInfo.width / (float)mbFont.texWidth; info.uv.height = -1f * (float)bmInfo.height / (float)mbFont.texHeight; info.vert.x = (float)bmInfo.offsetX; info.vert.y = 0f; info.vert.width = (float)bmInfo.width; info.vert.height = (float)bmInfo.height; info.width = (float)bmInfo.advance; //此处使用新版生成图片字导致文字间隔增大,可以将Tracking属性调为负,但是会导致输入图片字的坐标显示错乱 //否则只能修改图片 所以这里不做修改 忽略上面的警告信息 //float uvX = (float)bmInfo.x / (float)mbFont.texWidth; //float uvY = 1 - (float)bmInfo.y / (float)mbFont.texHeight; //float uvWidth = (float)bmInfo.width / (float)mbFont.texWidth; //float uvHeight = -1f * (float)bmInfo.height / (float)mbFont.texHeight; //info.uvBottomLeft = new Vector2(uvX, uvY); //info.uvBottomRight = new Vector2(uvX + uvWidth, uvY); //info.uvTopLeft = new Vector2(uvX, uvY + uvHeight); //info.uvTopRight = new Vector2(uvX + uvWidth, uvY + uvHeight); //info.minX = bmInfo.x; //info.maxX = bmInfo.x + bmInfo.width; //info.minY = bmInfo.y + bmInfo.height; //info.maxY = bmInfo.y; //info.advance = bmInfo.advance; characterInfo[j] = info; } mFont.characterInfo = characterInfo; mFont.material = material; string newFontPath = txtPath.Replace("txt", "fontsettings"); string newMatrilPath = txtPath.Replace("txt", "mat"); string tempFontPath = string.Format("Assets/{0}.fontsettings", tempName); string tempMatPath = string.Format("Assets/{0}.mat", tempName); AssetDatabase.CreateAsset(material, tempMatPath); AssetDatabase.CreateAsset(mFont, tempFontPath); File.Copy(Application.dataPath.Replace("Assets", tempFontPath), Application.dataPath.Replace("Assets", newFontPath), true); File.Copy(Application.dataPath.Replace("Assets", tempMatPath), Application.dataPath.Replace("Assets", newMatrilPath), true); AssetDatabase.DeleteAsset(tempFontPath); AssetDatabase.DeleteAsset(tempMatPath); AssetDatabase.Refresh(); Font f = AssetDatabase.LoadAssetAtPath <Font>(newFontPath); Material m = AssetDatabase.LoadAssetAtPath <Material>(newMatrilPath); f.material = m; AssetDatabase.Refresh(); }
private static void TextKeyDown(UICamera camera, UIInput input, UnityEngine.Event @event, UILabel label) { if (input == UIUnityEvents.lastInput && camera == UIUnityEvents.lastInputCamera) { UIUnityEvents.lastLabel = label; TextEditor textEditor = null; if (!UIUnityEvents.GetTextEditor(out textEditor)) { return; } if (!UIUnityEvents.GetKeyboardControl()) { Debug.Log(string.Concat("Did not ", @event)); return; } bool flag = false; if (!UIUnityEvents.TextEditorHandleEvent(@event, textEditor)) { KeyCode keyCode = @event.keyCode; if (keyCode == KeyCode.Tab) { return; } if (keyCode == KeyCode.None) { char chr = @event.character; if (chr == '\t') { return; } bool flag1 = false; flag1 = chr == '\n'; if (flag1 && !input.inputMultiline && [email protected]) { UIUnityEvents.submit = true; } else if (label.font) { BMFont bMFont = label.font.bmFont; BMFont bMFont1 = bMFont; if (bMFont != null) { if (flag1 || chr != 0 && bMFont1.ContainsGlyph(chr)) { textEditor.Insert(chr); flag = true; } else if (chr == 0) { if (Input.compositionString.Length > 0) { textEditor.ReplaceSelection(string.Empty); flag = true; } @event.Use(); } } } } } else { @event.Use(); flag = true; } UIUnityEvents.TextSharedEnd(flag, textEditor, @event); } }
public static Sprite[] Create(float x, float y, string text, BMFont font, BMFontShader shader) { return(Create(new Vector3(x, y, 0), text, font, shader)); }
public void Render(Size screenSize, BMFont font) { //_renderer.SetViewPort(0, 0, 428, 240); _activeRoom.Render(_renderer, screenSize, _cameraPos, font); }
//public static void Main(string[] args) public static void Main() { Glut.glutInit(); Glut.glutInitDisplayMode(Glut.GLUT_DOUBLE | Glut.GLUT_DEPTH | Glut.GLUT_MULTISAMPLE); // multisampling makes things beautiful! Glut.glutInitWindowSize(width, height); Glut.glutCreateWindow("OpenGL Tutorial"); Glut.glutIdleFunc(OnRenderFrame); Glut.glutDisplayFunc(OnDisplay); Glut.glutKeyboardFunc(OnKeyboardDown); Glut.glutKeyboardUpFunc(OnKeyboardUp); Glut.glutCloseFunc(OnClose); Glut.glutReshapeFunc(OnReshape); // add our mouse callbacks for this tutorial Glut.glutMouseFunc(OnMouse); Glut.glutMotionFunc(OnMove); Gl.Enable(EnableCap.DepthTest); Gl.Enable(EnableCap.Blend); Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); // create our shader program program = new ShaderProgram(VertexShader, FragmentShader); // create our camera camera = new Camera(new Vector3(0, 0, 10), Quaternion.Identity); camera.SetDirection(new Vector3(0, 0, -1)); // set up the projection and view matrix program.Use(); program["projection_matrix"].SetValue(Matrix4.CreatePerspectiveFieldOfView(0.45f, (float)width / height, 0.1f, 1000f)); //program["view_matrix"].SetValue(Matrix4.LookAt(new Vector3(0, 0, 10), Vector3.Zero, Vector3.Up)); program["light_direction"].SetValue(new Vector3(0, 0, 1)); program["enable_lighting"].SetValue(lighting); program["normalTexture"].SetValue(1); program["enable_mapping"].SetValue(normalMapping); brickDiffuse = new Texture("AlternatingBrick-ColorMap.png"); brickNormals = new Texture("AlternatingBrick-NormalMap.png"); Vector3[] vertices = new Vector3[] { new Vector3(1, 1, -1), new Vector3(-1, 1, -1), new Vector3(-1, 1, 1), new Vector3(1, 1, 1), // top new Vector3(1, -1, 1), new Vector3(-1, -1, 1), new Vector3(-1, -1, -1), new Vector3(1, -1, -1), // bottom new Vector3(1, 1, 1), new Vector3(-1, 1, 1), new Vector3(-1, -1, 1), new Vector3(1, -1, 1), // front face new Vector3(1, -1, -1), new Vector3(-1, -1, -1), new Vector3(-1, 1, -1), new Vector3(1, 1, -1), // back face new Vector3(-1, 1, 1), new Vector3(-1, 1, -1), new Vector3(-1, -1, -1), new Vector3(-1, -1, 1), // left new Vector3(1, 1, -1), new Vector3(1, 1, 1), new Vector3(1, -1, 1), new Vector3(1, -1, -1) }; cube = new VBO <Vector3>(vertices); Vector2[] uvs = new Vector2[] { new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1) }; cubeUV = new VBO <Vector2>(uvs); List <uint> triangles = new List <uint>(); for (uint i = 0; i < 6; i++) { triangles.Add(i * 4); triangles.Add(i * 4 + 1); triangles.Add(i * 4 + 2); triangles.Add(i * 4); triangles.Add(i * 4 + 2); triangles.Add(i * 4 + 3); } cubeTriangles = new VBO <uint>(triangles.ToArray(), BufferTarget.ElementArrayBuffer); Vector3[] normals = Geometry.CalculateNormals(vertices, triangles.ToArray()); cubeNormals = new VBO <Vector3>(normals); Vector3[] tangents = CalculateTangents(vertices, normals, triangles.ToArray(), uvs); cubeTangents = new VBO <Vector3>(tangents); // load the bitmap font for this tutorial font = new BMFont("font24.fnt", "font24.png"); fontProgram = new ShaderProgram(BMFont.FontVertexSource, BMFont.FontFragmentSource); fontProgram.Use(); fontProgram["ortho_matrix"].SetValue(Matrix4.CreateOrthographic(width, height, 0, 1000)); fontProgram["color"].SetValue(new Vector3(1, 1, 1)); information = font.CreateString(fontProgram, "OpenGL C# Tutorial 15"); watch = System.Diagnostics.Stopwatch.StartNew(); Glut.glutMainLoop(); }
/// <summary> /// Reload the font data. /// </summary> public static void Load(BMFont font, string name, byte[] bytes) { font.Clear(); if (bytes != null) { BmByteReader reader = new BmByteReader(bytes); char[] separator = new char[] { ' ' }; while (reader.canRead) { string line = reader.ReadLine(); if (string.IsNullOrEmpty(line)) break; string[] split = line.Split(separator, System.StringSplitOptions.RemoveEmptyEntries); int len = split.Length; if (split[0] == "char") { // Expected data style: // char id=13 x=506 y=62 width=3 height=3 xoffset=-1 yoffset=50 xadvance=0 page=0 chnl=15 int channel = (len > 10) ? GetInt(split[10]) : 15; if (len > 9 && GetInt(split[9]) > 0) { Debug.LogError("Your font was exported with more than one texture. Only one texture is supported by NGUI.\n" + "You need to re-export your font, enlarging the texture's dimensions until everything fits into just one texture."); break; } if (len > 8) { int id = GetInt(split[1]); BMGlyph glyph = font.GetGlyph(id, true); if (glyph != null) { glyph.x = GetInt(split[2]); glyph.y = GetInt(split[3]); glyph.width = GetInt(split[4]); glyph.height = GetInt(split[5]); glyph.offsetX = GetInt(split[6]); glyph.offsetY = GetInt(split[7]); glyph.advance = GetInt(split[8]); glyph.channel = channel; } else Debug.Log("Char: " + split[1] + " (" + id + ") is NULL"); } else { Debug.LogError("Unexpected number of entries for the 'char' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "kerning") { // Expected data style: // kerning first=84 second=244 amount=-5 if (len > 3) { int first = GetInt(split[1]); int second = GetInt(split[2]); int amount = GetInt(split[3]); BMGlyph glyph = font.GetGlyph(second, true); if (glyph != null) glyph.SetKerning(first, amount); } else { Debug.LogError("Unexpected number of entries for the 'kerning' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "common") { // Expected data style: // common lineHeight=64 base=51 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=1 redChnl=4 greenChnl=4 blueChnl=4 if (len > 5) { font.charSize = GetInt(split[1]); font.baseOffset = GetInt(split[2]); font.texWidth = GetInt(split[3]); font.texHeight = GetInt(split[4]); int pages = GetInt(split[5]); if (pages != 1) { Debug.LogError("Font '" + name + "' must be created with only 1 texture, not " + pages); break; } } else { Debug.LogError("Unexpected number of entries for the 'common' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "page") { // Expected data style: // page id=0 file="textureName.png" if (len > 2) { font.spriteName = GetString(split[2]).Replace("\"", ""); font.spriteName = font.spriteName.Replace(".png", ""); font.spriteName = font.spriteName.Replace(".tga", ""); } } } } }
public static Vector2 DrawFontAsset( SmartSpriteBatch spriteBatch, ScreenAbstractor screen, float opacity, string text, Color?fontColor, FloatRectangle?position, float fontSize, float?lineHeight, string fontName, bool pseudoAntiAlias, bool wordWrap, FontJustification justification, float fontMargin, Thickness margin = null, Color?outlineColor = null, FloatRectangle?clip = null, Texture2D bgTexture = null, Vector2?scrollOffset = null, int?caretPos = null, bool multiLine = false, Rectangle?scissorRect = null) { if (position == null) { return(Vector2.Zero); } if (string.IsNullOrWhiteSpace(text)) { return(Vector2.Zero); } List <string> textValues = new List <string> { text }; if (multiLine) { textValues = text.ToList(); } if (fontSize == 0) { fontSize = 24; } float lHeight = fontSize * 1.25f; if (lineHeight.HasValue) { lHeight = lineHeight.Value; } float translatedBaseSize = screen.Translate(new Vector2(1f, 1f)).Y; float fontSizeRatio = (translatedBaseSize / 1080f); float translatedFontSize = fontSizeRatio * fontSize; FontFamily fontFamily = Solids.Instance.Fonts.Fonts[fontName]; if (fontFamily == null) { return(Vector2.Zero); } string currentKey = translatedFontSize.ToString() + fontFamily.ToString(); BMFont myFont = fontFamily.GetFont((int)translatedFontSize); Vector2 sizeOfI = myFont.MeasureString("Igj'#" + FontSystem.MDL2Symbols.Download.AsChar()); float translatedWidth = screen.Translate(position).Value.Width; float wordWrapWidth = translatedWidth; if (margin != null) { wordWrapWidth = wordWrapWidth - screen.Translate(new Vector2(margin.Left + margin.Right, 0)).X; position = new FloatRectangle(position.Value.X, position.Value.Y + margin.Top, position.Value.Width, position.Value.Height); } Vector2 size = myFont.MeasureString(text); float scale = translatedFontSize / sizeOfI.Y; if (wordWrap && multiLine) { List <string> lines = textValues.ToList(); textValues = new List <string>(); string reconstructedLine = ""; foreach (string line in lines) { string[] words = line.Split(' '); for (int i = 0; i < words.Length; i++) { string withoutCurrentWord = reconstructedLine; reconstructedLine = reconstructedLine + words[i] + " "; Vector2 wwSize = myFont.MeasureString(reconstructedLine); if (wwSize.X * scale > wordWrapWidth) { textValues.Add(withoutCurrentWord); reconstructedLine = ""; i = i - 1; } } } textValues.Add(reconstructedLine); } float ulHeight = lHeight / translatedBaseSize; Vector2 calcSize = Vector2.Zero; for (int i = 0; i < textValues.Count; i++) { FloatRectangle positionValue = new FloatRectangle(position.Value.X, position.Value.Y + (ulHeight * i), position.Value.Width, ulHeight); FloatRectangle fontPos = new FloatRectangle(positionValue.X, positionValue.Y + fontMargin, positionValue.Width, positionValue.Height - (fontMargin * 2f)); string textValue = textValues[i]; FloatRectangle?tclip = screen.Translate(clip); FloatRectangle positionRectangle = new FloatRectangle(); FloatRectangle translatedPosition = screen.Translate(fontPos).Value; if (tclip.HasValue) { if (translatedPosition.Right < tclip.Value.X || translatedPosition.X > tclip.Value.Right) { return(Vector2.Zero); } } if (string.IsNullOrWhiteSpace(fontName)) { return(Vector2.Zero); } float width = size.X * scale; switch (justification) { case FontJustification.Left: { positionRectangle = new FloatRectangle(translatedPosition.X, translatedPosition.Y, width, translatedPosition.Height); break; } case FontJustification.Right: { positionRectangle = new FloatRectangle(translatedPosition.Right - width, translatedPosition.Y, width, translatedPosition.Height); break; } case FontJustification.Center: { positionRectangle = new FloatRectangle(translatedPosition.X + (translatedPosition.Width / 2f) - (width / 2f), translatedPosition.Y, width, translatedPosition.Height); break; } } if (caretPos != null) { using (new SmartSpriteBatchManager(Solids.Instance.SpriteBatch, scissorRect: tclip)) { float actualCarotPos = (width / text.Length) * caretPos.Value; float oppax = (DateTime.Now.Millisecond % 250) / 250f; spriteBatch.DrawLine( new Vector2(positionRectangle.X + actualCarotPos, positionRectangle.Y), new Vector2(positionRectangle.X + actualCarotPos, positionRectangle.Bottom), Color.White * oppax, tclip, 1f); } } Rectangle source = new Rectangle(0, 0, (int)size.X, (int)size.Y); tclip = tclip?.Clamp(scissorRect); (Rectangle position, Rectangle? source)translator = TextureHelpers.GetAdjustedDestAndSourceAfterClip(positionRectangle, source, tclip); Solids.Instance.SpriteBatch.Scissor = tclip.ToRectangle(); Rectangle tmp = Solids.Instance.Bounds; if (tclip.HasValue) { tmp = tclip.Clamp(scissorRect).ToRectangle; } Solids.Instance.SpriteBatch.Scissor = tmp; using (new SmartSpriteBatchManager(Solids.Instance.SpriteBatch)) { if ((pseudoAntiAlias || outlineColor.HasValue)) { Color?cl = fontColor * opacity * 0.3f; if (outlineColor.HasValue) { cl = outlineColor.Value * opacity; } for (int y = -1; y <= 1; y = y + 2) { for (int x = -1; x <= 1; x = x + 2) { myFont.DrawText(Solids.Instance.SpriteBatch, translator.position.X + x, translator.position.Y + y, textValue, cl, scale); } } } myFont.DrawText(Solids.Instance.SpriteBatch, translator.position.X, translator.position.Y, textValue, fontColor * opacity, scale); calcSize = new Vector2(position.Value.Width, calcSize.Y + lHeight); } Solids.Instance.SpriteBatch.Scissor = null; } float actHeight = screen.Untranslate(calcSize.Y); if (margin != null) { calcSize.Y = calcSize.Y + margin.Bottom; } return(new Vector2(position.Value.Width, actHeight)); }
public static void BMFontCreat() { string txtPath = string.Empty; string texturePath = string.Empty; string[] guids = Selection.assetGUIDs; if (guids.Length != 2) { Debug.Log("please select fontImage and fontText!"); return; } Font mFont = new Font(); TextAsset mText = null; Material material = new Material(Shader.Find("GUI/Text Shader")); for (int i = 0; i < guids.Length; i++) { string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]); int index = assetPath.ToString().IndexOf("Assets"); string modPath = assetPath.ToString().Remove(0, index); modPath = modPath.Replace("\\", "/"); if (assetPath.Contains("txt"))//txt { txtPath = modPath; mText = (TextAsset)AssetDatabase.LoadAssetAtPath(modPath, typeof(TextAsset)); } else//png { texturePath = modPath; TextureImporter texImport = AssetImporter.GetAtPath(modPath) as TextureImporter; texImport.textureFormat = TextureImporterFormat.AutomaticTruecolor; texImport.textureType = TextureImporterType.Image; texImport.wrapMode = TextureWrapMode.Clamp; AssetDatabase.ImportAsset(modPath); material.mainTexture = (Texture)AssetDatabase.LoadAssetAtPath(modPath, typeof(Texture)); } } if (mText == null || material == null) { return; } mFont.name = mText.name; material.name = mText.name; BMFont mbFont = new BMFont(); BMFontReader.Load(mbFont, mText.name, mText.bytes); CharacterInfo[] characterInfo = new CharacterInfo[mbFont.glyphs.Count]; for (int j = 0; j < mbFont.glyphs.Count; j++) { BMGlyph bmInfo = mbFont.glyphs[j]; CharacterInfo info = new CharacterInfo(); info.index = bmInfo.index; info.uv.x = (float)bmInfo.x / (float)mbFont.texWidth; info.uv.y = 1 - (float)bmInfo.y / (float)mbFont.texHeight; info.uv.width = (float)bmInfo.width / (float)mbFont.texWidth; info.uv.height = -1f * (float)bmInfo.height / (float)mbFont.texHeight; info.vert.x = (float)bmInfo.offsetX; info.vert.y = 0f; info.vert.width = (float)bmInfo.width; info.vert.height = (float)bmInfo.height; info.width = (float)bmInfo.advance; characterInfo[j] = info; } mFont.characterInfo = characterInfo; mFont.material = material; string newFontPath = txtPath.Replace("txt", "fontsettings"); string newMatrilPath = txtPath.Replace("txt", "mat"); AssetDatabase.CreateAsset(material, newMatrilPath); AssetDatabase.CreateAsset(mFont, newFontPath); AssetDatabase.Refresh(); }
private void TryAdd() { try { string name = (nameTextBox.Text.Trim().Equals(string.Empty) ? "New Game Object" : nameTextBox.Text); GameObject obj = new GameObject(); switch (itemListBox.SelectedIndex) { case 1: obj = new Sprite(); break; case 2: obj = new AnimatedSprite(); break; case 3: obj = new Tileset(); break; case 4: obj = new AudioObject(); break; case 5: obj = new BMFont(); break; case 6: obj = new ParticleEmitter(); break; } obj.Name = name; DragDropTreeViewItem insertedItem; if (addToSelectedCheckBox.IsChecked == true) { if (targetObject == null) { SceneManager.ActiveScene.GameObjects.Add(obj); } else { targetObject.Children.Add(obj); } insertedItem = EditorHandler.SceneTreeView.AddNode(target as DragDropTreeViewItem, obj, EditorHandler.SceneTreeView.GameObjectImageSource(obj)); } else { SceneManager.ActiveScene.GameObjects.Add(obj); insertedItem = EditorHandler.SceneTreeView.AddNode(null, obj, EditorHandler.SceneTreeView.GameObjectImageSource(obj)); } EditorHandler.SelectedGameObjects.Clear(); EditorHandler.SelectedGameObjects.Add(obj); EditorHandler.ChangeSelectedObjects(); this.Close(); } catch (System.Exception ex) { MessageBox.Show(ex.Message, "Error!", MessageBoxButton.OK, MessageBoxImage.Error); } }
public libGUI(RenderWindow RWind) { Controls = new List <Control>(); MouseHeldControls = new Dictionary <Key, Control>(); LoadSkin("content/textures/gui_elements/standard"); RWind.OnMouseMove += (W, X, Y) => { MousePos = new Vector2(X, W.WindowHeight - Y); OnMouseMoveEventArgs Evt = new OnMouseMoveEventArgs(this, MousePos); for (int i = Controls.Count - 1; i >= 0; i--) { // for (int i = 0; i < Controls.Count; i++) { Control C = Controls[i]; C.OnMouseMove(Evt); if (Evt.Consumed) { break; } } }; RWind.OnKey += (W, Key, Scancode, Pressed, Repeat, Mods) => { bool IsMouse = Key >= Key.MouseButton1 && Key <= Key.MouseButton8; OnKeyEventArgs Evt = new OnKeyEventArgs(this, MousePos, Pressed, Key); if (IsMouse) { bool ClickedOnAny = false; Control ClickedRootControl = null; for (int i = 0; i < Controls.Count; i++) { // for (int i = Controls.Count - 1; i >= 0; i--) { Control C = Controls[i]; if (C.IsInside(MousePos)) { Control Ctrl = C.GetRecursiveClientAreaChildAt(MousePos) ?? C; ClickControl(Ctrl, Key, Pressed); ClickedOnAny = true; ClickedRootControl = C; } } if (ClickedRootControl != null) { BringToFront(ClickedRootControl); } if (!ClickedOnAny) { ClickControl(null, Key, Pressed); } } for (int i = Controls.Count - 1; i >= 0; i--) { //for (int i = 0; i < Controls.Count; i++) { Control C = Controls[i]; C.OnKey(Evt); if (Evt.Consumed) { break; } } }; DefaultFont = new BMFont("content/fonts/proggy_clean_16.fnt"); ((BMFont)DefaultFont).LoadTextures("content/textures", TextureFilter.Linear); DebugFont = new BMFont("content/fonts/proggy_small_16.fnt"); ((BMFont)DebugFont).LoadTextures("content/textures", TextureFilter.Linear); AnonPro16 = new BMFont("content/fonts/anonymous_pro_16.fnt"); AnonPro16.LoadTextures("content/textures", TextureFilter.Linear); AnonPro32 = new BMFont("content/fonts/anonymous_pro_32.fnt"); AnonPro32.LoadTextures("content/textures", TextureFilter.Linear); }
public static void DrawText(float x, float y, string text, BMFont font, BMFontShader fontShader, Camera camera) { DrawSpriteCollection(BatchExecution.DrawElements, 1, ImText.Create(x, y, text, font, fontShader), camera); }
// public override void OnInspectorGUI () // { // if(GUILayout.Button("Create Custom Font")) // { // CustomFontCreator creator = target as CustomFontCreator; // Debug.Log ("Create Custom Font: " + target.name); // // if(creator._FntSettings == null) // { // Debug.LogError ("No fnt file configured"); // return; // } // // CreateBMPFont (creator._FntSettings); // } // // base.OnInspectorGUI (); // } public static void CreateBMPFont(TextAsset fntSetting) { // TextAsset fntSetting = creator._FntSettings; // 公共路径 string path = AssetDatabase.GetAssetPath(fntSetting); var idx = path.LastIndexOf("/"); Debug.Assert(idx >= 0); string basePath = path.Substring(0, idx); Debug.Log("Path: " + basePath); // 公共文件名:去掉后缀后的名字 var fileName = path.Substring(idx + 1); var extIdx = fileName.LastIndexOf("."); if (extIdx >= 0) { fileName = fileName.Substring(0, extIdx); } Debug.Log("File Name: " + fileName); Debug.Assert(basePath.Length > 0 && fileName.Length > 0); BMFont bmfont = getBMFontInfo(fntSetting); if (bmfont == null) { Debug.Log("Invalid .fnt file"); return; } var texturePath = basePath + "/" + bmfont.spriteName + ".png"; Debug.Log("Texture Path: " + texturePath); var fntTexture = AssetDatabase.LoadAssetAtPath <Texture> (texturePath); if (fntTexture == null) { Debug.LogError("Can't find texture at target path"); return; } string materialPath = basePath + "/" + fileName + "M.mat"; Material fntMaterial = AssetDatabase.LoadAssetAtPath <Material> (materialPath); if (fntMaterial == null) { fntMaterial = createFontMaterial(materialPath, fntTexture); // EditorUtility.SetDirty(fntMaterial); } string fntPath = basePath + "/" + fileName + "U.fontsettings"; Font fnt = AssetDatabase.LoadAssetAtPath <Font> (fntPath); if (fnt == null) { fnt = createCustomFnt(fntPath, fntMaterial); } var charInfos = retriveCharInfos(bmfont); fnt.characterInfo = charInfos; // FIXME: #BUG# 关闭Unity后,自定义字体数据消失 (charInfos) EditorUtility.SetDirty(fntMaterial); EditorUtility.SetDirty(fnt); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); }
static void CreateMyFont() { if (Selection.objects == null) { return; } if (Selection.objects.Length == 0) { Debug.LogWarning("没有选中fnt文件,或者图片文件"); return; } //至少需要保证选中文件的目录下面有fnt文件,否则不会生成字体 Font m_myFont = null; TextAsset m_data = null; string filePath = ""; Material mat = null; Texture2D tex = null; bool bln = false; //不管选中fnt、png、mat、fontsettings其中的任何一个,都可以创建字体 foreach (UnityEngine.Object o in Selection.objects) { if (o.GetType() == typeof(TextAsset)) { m_data = o as TextAsset; bln = true; } else if (o.GetType() == typeof(Material)) { mat = o as Material; bln = true; } else if (o.GetType() == typeof(Texture2D)) { tex = o as Texture2D; bln = true; } else if (o.GetType() == typeof(Font)) { m_myFont = o as Font; bln = true; } if (bln) { filePath = AssetDatabase.GetAssetPath(o); filePath = filePath.Substring(0, filePath.LastIndexOf('.')); } } //获取fnt文件,我们在这里加一次判断,为了可以直接选择图片也能导出字体 string dataPathName = filePath + ".fnt"; if (m_data == null) { m_data = ( TextAsset )AssetDatabase.LoadAssetAtPath(dataPathName, typeof(TextAsset)); } if (m_data != null) { string matPathName = filePath + ".mat"; string fontPathName = filePath + ".fontsettings"; string texPathName = filePath + ".png"; //获取图片,如果没有图片,不影响,可以生成之后,再手动设置 if (tex == null) { tex = ( Texture2D )AssetDatabase.LoadAssetAtPath(texPathName, typeof(Texture2D)); } if (tex == null) { Debug.LogWarning("没找到图片,或者图片名称和fnt文件名称不匹配"); } //获取材质,如果没有则创建对应名字的材质 if (mat == null) { mat = ( Material )AssetDatabase.LoadAssetAtPath(matPathName, typeof(Material)); } if (mat == null) { mat = new Material(Shader.Find("GUI/Text Shader")); AssetDatabase.CreateAsset(mat, matPathName); } else { mat.shader = Shader.Find("GUI/Text Shader"); } mat.SetTexture("_MainTex", tex); //获取font文件,如果没有则创建对应名字的font文件 if (m_myFont == null) { m_myFont = ( Font )AssetDatabase.LoadAssetAtPath(fontPathName, typeof(Font)); } if (m_myFont == null) { m_myFont = new Font(); AssetDatabase.CreateAsset(m_myFont, fontPathName); } m_myFont.material = mat; BMFont mbFont = new BMFont(); //借助NGUI的类,读取字体fnt文件信息,可以不用自己去解析了 BMFontReader.Load(mbFont, m_data.name, m_data.bytes); CharacterInfo[] characterInfo = new CharacterInfo[mbFont.glyphs.Count]; for (int i = 0; i < mbFont.glyphs.Count; i++) { BMGlyph bmInfo = mbFont.glyphs[i]; CharacterInfo info = new CharacterInfo(); //设置ascii码 info.index = bmInfo.index; //设置字符映射到材质上的坐标 info.uvBottomLeft = new Vector2(( float )bmInfo.x / mbFont.texWidth, 1f - ( float )(bmInfo.y + bmInfo.height) / mbFont.texHeight); info.uvBottomRight = new Vector2(( float )(bmInfo.x + bmInfo.width) / mbFont.texWidth, 1f - ( float )(bmInfo.y + bmInfo.height) / mbFont.texHeight); info.uvTopLeft = new Vector2(( float )bmInfo.x / mbFont.texWidth, 1f - ( float )(bmInfo.y) / mbFont.texHeight); info.uvTopRight = new Vector2(( float )(bmInfo.x + bmInfo.width) / mbFont.texWidth, 1f - ( float )(bmInfo.y) / mbFont.texHeight); //设置字符顶点的偏移位置和宽高 info.minX = bmInfo.offsetX; info.minY = -bmInfo.offsetY - bmInfo.height; info.maxX = bmInfo.offsetX + bmInfo.width; info.maxY = -bmInfo.offsetY; //设置字符的宽度 info.advance = bmInfo.advance; characterInfo[i] = info; } m_myFont.characterInfo = characterInfo; EditorUtility.SetDirty(m_myFont); //设置变更过的资源 EditorUtility.SetDirty(mat); //设置变更过的资源 AssetDatabase.SaveAssets(); //保存变更的资源 AssetDatabase.Refresh(); //刷新资源,貌似在Mac上不起作用 //由于上面fresh之后在编辑器中依然没有刷新,所以暂时想到这个方法, //先把生成的字体导出成一个包,然后再重新导入进来,这样就可以直接刷新了 //这是在Mac上遇到的,不知道Windows下面会不会出现,如果不出现可以把下面这一步注释掉 AssetDatabase.ExportPackage(fontPathName, "temp.unitypackage"); AssetDatabase.DeleteAsset(fontPathName); AssetDatabase.ImportPackage("temp.unitypackage", true); AssetDatabase.Refresh(); Debug.Log("创建字体成功"); } else { Debug.LogWarning("没有找到fnt文件,或者文件名称和图片名称不匹配"); } }
protected virtual void DrawXNA(float totalSeconds) { GLEx gl = process.GL; if (gl != null) { if (!process.Next()) { return; } if (isScale) { gl.Scale(LSystem.scaleWidth, LSystem.scaleHeight); } int repaintMode = process.GetRepaintMode(); switch (repaintMode) { case Screen.SCREEN_BITMAP_REPAINT: gl.Reset(clear); if (process.GetX() == 0 && process.GetY() == 0) { gl.DrawTexture(process.GetBackground(), 0, 0); } else { gl.DrawTexture(process.GetBackground(), process.GetX(), process.GetY()); } break; case Screen.SCREEN_COLOR_REPAINT: LColor c = process.GetColor(); if (c != null) { gl.DrawClear(c); } break; case Screen.SCREEN_CANVAS_REPAINT: gl.Reset(clear); break; case Screen.SCREEN_NOT_REPAINT: gl.Reset(clear); break; default: gl.Reset(clear); if (process.GetX() == 0 && process.GetY() == 0) { gl.DrawTexture( process.GetBackground(), repaintMode / 2 - LSystem.random.Next(repaintMode), repaintMode / 2 - LSystem.random.Next(repaintMode)); } else { gl.DrawTexture(process.GetBackground(), process.GetX() + repaintMode / 2 - LSystem.random.Next(repaintMode), process.GetY() + repaintMode / 2 - LSystem.random.Next(repaintMode)); } break; } process.Draw(); process.Drawable(elapsedTime); if (isFPS) { gl.Reset(false); framecount++; timeSinceLastUpdate += totalSeconds; if (timeSinceLastUpdate > updateInterval) { frameRate = Convert.ToInt16(framecount / timeSinceLastUpdate); framecount = 0; timeSinceLastUpdate -= updateInterval; } fps = string.Format(numformat, "FPS:{0}", frameRate); if (gl.UseFont) { gl.DrawString(fps, 5, 5, LColor.white); } else { if (XNAConfig.IsActive() && font == null) { font = XNAConfig.LoadFnt(LSystem.FRAMEWORK_IMG_NAME + "system"); } if (font != null) { font.DrawBatchString(5, 5, fps, LColor.white); } } } process.DrawEmulator(); gl.RestoreMatrix(); } }
/// <summary> /// Reload the font data. /// </summary> public static void Load(BMFont font, string name, byte[] bytes) { font.Clear(); if (bytes != null) { int offset = 0; char[] separator = new char[1] { ' ' }; while (offset < bytes.Length) { string line = ReadLine(bytes, ref offset); if (string.IsNullOrEmpty(line)) break; string[] split = line.Split(separator, System.StringSplitOptions.RemoveEmptyEntries); if (split[0] == "char") { // Expected data style: // char id=13 x=506 y=62 width=3 height=3 xoffset=-1 yoffset=50 xadvance=0 page=0 chnl=15 if (split.Length > 8) { int id = GetInt(split[1]); BMGlyph glyph = font.GetGlyph(id, true); if (glyph != null) { glyph.x = GetInt(split[2]); glyph.y = GetInt(split[3]); glyph.width = GetInt(split[4]); glyph.height = GetInt(split[5]); glyph.offsetX = GetInt(split[6]); glyph.offsetY = GetInt(split[7]); glyph.advance = GetInt(split[8]); } else Debug.Log("Char: " + split[1] + " (" + id + ") is NULL"); } else { Debug.LogError("Unexpected number of entries for the 'char' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "kerning") { // Expected data style: // kerning first=84 second=244 amount=-5 if (split.Length > 3) { int first = GetInt(split[1]); int second = GetInt(split[2]); int amount = GetInt(split[3]); BMGlyph glyph = font.GetGlyph(second, true); if (glyph != null) glyph.SetKerning(first, amount); } else { Debug.LogError("Unexpected number of entries for the 'kerning' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "common") { // Expected data style: // common lineHeight=64 base=51 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=1 redChnl=4 greenChnl=4 blueChnl=4 if (split.Length > 5) { font.charSize = GetInt(split[1]); font.baseOffset = GetInt(split[2]); font.texWidth = GetInt(split[3]); font.texHeight = GetInt(split[4]); int pages = GetInt(split[5]); if (pages != 1) { Debug.LogError("Font '" + name + "' must be created with only 1 texture, not " + pages); break; } } else { Debug.LogError("Unexpected number of entries for the 'common' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "page") { // Expected data style: // page id=0 file="textureName.png" if (split.Length > 2) { font.spriteName = GetString(split[2]).Replace("\"", ""); } } } } }
internal void AddGameObject(GameObject gameObject, string type, bool autoselect = true, bool addToSelectedParent = false, bool expand = false) { if (gameObject == null) { switch (type.ToLower()) { case "empty": gameObject = new GameObject(); gameObject.Name = "Empty Game Object"; break; case "sprite": gameObject = new Sprite(); gameObject.Name = "Sprite Game Object"; break; case "animatedsprite": gameObject = new AnimatedSprite(); gameObject.Name = "Animated Sprite Game Object"; break; case "audio": gameObject = new AudioObject(); gameObject.Name = "Audio Game Object"; break; case "tileset": gameObject = new Tileset(); gameObject.Name = "Tileset Game Object"; break; case "bmfont": gameObject = new BMFont(); gameObject.Name = "Bitmap Font Object"; break; case "particleemitter": gameObject = new ParticleEmitter(); gameObject.Name = "Particle Emitter Object"; break; } } else { gameObject.Initialize(); } if (SelectedItem == null) { SceneManager.ActiveScene.GameObjects.Add(gameObject); } else { if (addToSelectedParent) { GameObject _gameObject = (GameObject)(SelectedItem as DragDropTreeViewItem).Tag; if (_gameObject.Transform.Parent == null) { SceneManager.ActiveScene.GameObjects.Add(gameObject); } else { _gameObject.Transform.Parent.GameObject.Children.Add(gameObject); } } else { GameObject _gameObject = (GameObject)(SelectedItem as DragDropTreeViewItem).Tag; _gameObject.Children.Add(gameObject); } } if (gameObject != null) { DragDropTreeViewItem _parent = SelectedItem as DragDropTreeViewItem; if (addToSelectedParent) { var tmp = EditorUtils.FindVisualParent <DragDropTreeViewItem>(_parent); if (tmp != null) { _parent = tmp; } else { _parent = null; } } DragDropTreeViewItem node = AddNode(_parent, gameObject, GameObjectImageSource(gameObject)); if (_parent != null && expand) { //_parent.ExpandSubtree(); _parent.IsExpanded = true; } node.ContextMenu = contextMenu; // AddNodes(gameObject); //node.IsSelected = true; AttachChildren(node); //foreach (GameObject _obj in gameObject.Children) // AddGameObject(_obj, string.Empty); if (autoselect) { node.IsSelected = true; EditorHandler.SelectedGameObjects = new List <GameObject>(); EditorHandler.SelectedGameObjects.Add(gameObject); } } }
public unsafe override void Unity_NamedSerialize(int depth) { byte[] var_0_cp_0; int var_0_cp_1; if (depth <= 7) { ISerializedNamedStateWriter arg_23_0 = SerializedNamedStateWriter.Instance; UnityEngine.Object arg_23_1 = this.mMat; var_0_cp_0 = $FieldNamesStorage.$RuntimeNames; var_0_cp_1 = 0; arg_23_0.WriteUnityEngineObject(arg_23_1, &var_0_cp_0[var_0_cp_1] + 2796); } if (depth <= 7) { SerializedNamedStateWriter.Instance.BeginMetaGroup(&var_0_cp_0[var_0_cp_1] + 3517); this.mUVRect.Unity_NamedSerialize(depth + 1); SerializedNamedStateWriter.Instance.EndMetaGroup(); } SerializedNamedStateWriter.Instance.Align(); if (depth <= 7) { if (this.mFont == null) { this.mFont = new BMFont(); } BMFont arg_95_0 = this.mFont; SerializedNamedStateWriter.Instance.BeginMetaGroup(&var_0_cp_0[var_0_cp_1] + 3525); arg_95_0.Unity_NamedSerialize(depth + 1); SerializedNamedStateWriter.Instance.EndMetaGroup(); } if (depth <= 7) { SerializedNamedStateWriter.Instance.WriteUnityEngineObject(this.mAtlas, &var_0_cp_0[var_0_cp_1] + 3531); } if (depth <= 7) { SerializedNamedStateWriter.Instance.WriteUnityEngineObject(this.mReplacement, &var_0_cp_0[var_0_cp_1] + 3046); } if (depth <= 7) { if (this.mSymbols == null) { SerializedNamedStateWriter.Instance.BeginSequenceGroup(&var_0_cp_0[var_0_cp_1] + 3538, 0); SerializedNamedStateWriter.Instance.EndMetaGroup(); } else { SerializedNamedStateWriter.Instance.BeginSequenceGroup(&var_0_cp_0[var_0_cp_1] + 3538, this.mSymbols.Count); for (int i = 0; i < this.mSymbols.Count; i++) { BMSymbol arg_165_0 = (this.mSymbols[i] != null) ? this.mSymbols[i] : new BMSymbol(); SerializedNamedStateWriter.Instance.BeginMetaGroup((IntPtr)0); arg_165_0.Unity_NamedSerialize(depth + 1); SerializedNamedStateWriter.Instance.EndMetaGroup(); } SerializedNamedStateWriter.Instance.EndMetaGroup(); } } if (depth <= 7) { SerializedNamedStateWriter.Instance.WriteUnityEngineObject(this.mDynamicFont, &var_0_cp_0[var_0_cp_1] + 3547); } SerializedNamedStateWriter.Instance.WriteInt32(this.mDynamicFontSize, &var_0_cp_0[var_0_cp_1] + 3560); SerializedNamedStateWriter.Instance.WriteInt32((int)this.mDynamicFontStyle, &var_0_cp_0[var_0_cp_1] + 3577); }
/// <summary> /// Create a bitmap font from the specified dynamic font. /// </summary> static public bool CreateFont(Font ttf, int size, int faceIndex, bool kerning, string characters, int padding, out BMFont font, out Texture2D tex) { font = null; tex = null; if (ttf == null || !isPresent) { return(false); } IntPtr lib = IntPtr.Zero; IntPtr face = IntPtr.Zero; if (FT_Init_FreeType(out lib) != 0) { Debug.LogError("Failed to initialize FreeType"); return(false); } string fileName = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length) + UnityEditor.AssetDatabase.GetAssetPath(ttf); if (!File.Exists(fileName)) { Debug.LogError("Unable to use the chosen font."); } else if (FT_New_Face(lib, fileName, faceIndex, out face) != 0) { Debug.LogError("Unable to use the chosen font (FT_New_Face)."); } else { font = new BMFont(); font.charSize = size; Color32 white = Color.white; List <int> entries = new List <int>(); List <Texture2D> textures = new List <Texture2D>(); FT_FaceRec faceRec = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec)); FT_Set_Pixel_Sizes(face, 0, (uint)size); // Calculate the baseline value that would let the printed font be centered vertically //int ascender = (faceRec.met.ascender >> 6); //int descender = (faceRec.descender >> 6); //int baseline = ((ascender - descender) >> 1); //if ((baseline & 1) == 1) --baseline; //Debug.Log(ascender + " " + descender + " " + baseline); // Space character is not renderable FT_Load_Glyph(face, FT_Get_Char_Index(face, 32), FT_LOAD_DEFAULT); FT_GlyphSlotRec space = (FT_GlyphSlotRec)Marshal.PtrToStructure(faceRec.glyph, typeof(FT_GlyphSlotRec)); // Space is not visible and doesn't have a texture BMGlyph spaceGlyph = font.GetGlyph(32, true); spaceGlyph.offsetX = 0; spaceGlyph.offsetY = 0; spaceGlyph.advance = (space.metrics.horiAdvance >> 6); spaceGlyph.channel = 15; spaceGlyph.x = 0; spaceGlyph.y = 0; spaceGlyph.width = 0; spaceGlyph.height = 0; // Save kerning information if (kerning) { for (int b = 0; b < characters.Length; ++b) { uint ch2 = characters[b]; if (ch2 == 32) { continue; } FT_Vector vec; if (FT_Get_Kerning(face, ch2, 32, 0, out vec) != 0) { continue; } int offset = (vec.x >> 6); if (offset != 0) { spaceGlyph.SetKerning((int)ch2, offset); } } } // Run through all requested characters foreach (char ch in characters) { uint charIndex = FT_Get_Char_Index(face, (uint)ch); FT_Load_Glyph(face, charIndex, FT_LOAD_DEFAULT); FT_GlyphSlotRec glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(faceRec.glyph, typeof(FT_GlyphSlotRec)); FT_Render_Glyph(ref glyph, FT_Render_Mode.FT_RENDER_MODE_NORMAL); if (glyph.bitmap.width > 0 && glyph.bitmap.rows > 0) { byte[] buffer = new byte[glyph.bitmap.width * glyph.bitmap.rows]; Marshal.Copy(glyph.bitmap.buffer, buffer, 0, buffer.Length); Texture2D texture = new Texture2D(glyph.bitmap.width, glyph.bitmap.rows, UnityEngine.TextureFormat.ARGB32, false); Color32[] colors = new Color32[buffer.Length]; for (int i = 0, y = 0; y < glyph.bitmap.rows; ++y) { for (int x = 0; x < glyph.bitmap.width; ++x) { white.a = buffer[i++]; colors[x + glyph.bitmap.width * (glyph.bitmap.rows - y - 1)] = white; } } // Save the texture texture.SetPixels32(colors); texture.Apply(); textures.Add(texture); entries.Add(ch); // Record the metrics BMGlyph bmg = font.GetGlyph(ch, true); bmg.offsetX = (glyph.metrics.horiBearingX >> 6); bmg.offsetY = -(glyph.metrics.horiBearingY >> 6); bmg.advance = (glyph.metrics.horiAdvance >> 6); bmg.channel = 15; // Save kerning information if (kerning) { for (int b = 0; b < characters.Length; ++b) { uint ch2 = characters[b]; if (ch2 == ch) { continue; } FT_Vector vec; if (FT_Get_Kerning(face, ch2, ch, 0, out vec) != 0) { continue; } int offset = (vec.x >> 6); if (offset != 0) { bmg.SetKerning((int)ch2, offset); } } } } } // Create a packed texture with all the characters tex = new Texture2D(32, 32, TextureFormat.ARGB32, false); Rect[] rects = tex.PackTextures(textures.ToArray(), padding); // Make the RGB channel pure white Color32[] cols = tex.GetPixels32(); for (int i = 0, imax = cols.Length; i < imax; ++i) { Color32 c = cols[i]; c.r = 255; c.g = 255; c.b = 255; cols[i] = c; } tex.SetPixels32(cols); tex.Apply(); font.texWidth = tex.width; font.texHeight = tex.height; int min = int.MaxValue; int max = int.MinValue; // Other glyphs are visible and need to be added for (int i = 0, imax = entries.Count; i < imax; ++i) { // Destroy the texture now that it's a part of an atlas UnityEngine.Object.DestroyImmediate(textures[i]); textures[i] = null; Rect rect = rects[i]; // Set the texture coordinates BMGlyph glyph = font.GetGlyph(entries[i], true); glyph.x = Mathf.RoundToInt(rect.x * font.texWidth); glyph.y = Mathf.RoundToInt(rect.y * font.texHeight); glyph.width = Mathf.RoundToInt(rect.width * font.texWidth); glyph.height = Mathf.RoundToInt(rect.height * font.texHeight); // Flip the Y since the UV coordinate system is different glyph.y = font.texHeight - glyph.y - glyph.height; max = Mathf.Max(max, -glyph.offsetY); min = Mathf.Min(min, -glyph.offsetY - glyph.height); } int baseline = size + min; baseline += ((max - min - size) >> 1); // Offset all glyphs so that they are not using the baseline for (int i = 0, imax = entries.Count; i < imax; ++i) { BMGlyph glyph = font.GetGlyph(entries[i], true); glyph.offsetY += baseline; } } if (face != IntPtr.Zero) { FT_Done_Face(face); } #if !UNITY_3_5 if (lib != IntPtr.Zero) { FT_Done_FreeType(lib); } #endif return(tex != null); }
private void doMakeBMFont() { if (!_fnt) { EditorUtility.DisplayDialog("错误提示", "请选择fnt文件", "确定"); return; } EditorUtility.DisplayProgressBar("正在生成字体文件...", "请稍等,正在生成bundle文件...", 0.0f); string fntPath = AssetDatabase.GetAssetPath(_fnt); string rootPath = Path.GetDirectoryName(fntPath) + "/"; string fontName = Path.GetFileNameWithoutExtension(fntPath); string pathName = rootPath + fontName; Texture2D tex = (Texture2D)AssetDatabase.LoadAssetAtPath(pathName + ".png", typeof(Texture2D)); string matPath = pathName + ".mat"; Material mat = (Material)AssetDatabase.LoadAssetAtPath(matPath, typeof(Material)); if (mat == null) { //创建材质球 mat = new Material(Shader.Find("GUI/Text Shader")); mat.SetTexture("_MainTex", tex); AssetDatabase.CreateAsset(mat, matPath); } else { mat.shader = Shader.Find("GUI/Text Shader"); mat.SetTexture("_MainTex", tex); } Font font = (Font)AssetDatabase.LoadAssetAtPath(pathName + ".fontsettings", typeof(Font)); if (font == null) { font = new Font(fontName); AssetDatabase.CreateAsset(font, pathName + ".fontsettings"); } font.material = mat; BMFont mbFont = new BMFont(); BMFontReader.Load(mbFont, _fnt.name, _fnt.bytes); CharacterInfo[] characterInfo = new CharacterInfo[mbFont.glyphs.Count]; for (int i = 0; i < mbFont.glyphs.Count; i++) { BMGlyph bmInfo = mbFont.glyphs[i]; CharacterInfo info = new CharacterInfo(); info.index = bmInfo.index; float uvx = (float)bmInfo.x / (float)mbFont.texWidth; float uvy = 1 - (float)bmInfo.y / (float)mbFont.texHeight; float uvw = (float)bmInfo.width / (float)mbFont.texWidth; float uvh = -1f * (float)bmInfo.height / (float)mbFont.texHeight; info.uvBottomLeft = new Vector2(uvx, uvy); info.uvBottomRight = new Vector2(uvx + uvw, uvy); info.uvTopLeft = new Vector2(uvx, uvy + uvh); info.uvTopRight = new Vector2(uvx + uvw, uvy + uvh); info.minX = bmInfo.offsetX; info.minY = -bmInfo.offsetY; info.maxX = bmInfo.offsetX + bmInfo.width; info.maxY = -bmInfo.offsetY - bmInfo.height; info.advance = bmInfo.advance; characterInfo[i] = info; } font.characterInfo = characterInfo; EditorUtility.SetDirty(font); EditorUtility.ClearProgressBar(); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); EditorUtility.DisplayDialog("温馨提示", "字体文件生成成功!", "确定"); }
//public static void BatchCreateArtistFont() //{ // string dirName = ""; // string fntname = EditorUtils.SelectObjectPathInfo(ref dirName).Split('.')[0]; // Debug.Log(fntname); // Debug.Log(dirName); // string fntFileName = dirName + fntname + ".fnt"; // Font CustomFont = new Font(); // { // AssetDatabase.CreateAsset(CustomFont, dirName + fntname + ".fontsettings"); // AssetDatabase.SaveAssets(); // } // TextAsset BMFontText = null; // { // BMFontText = AssetDatabase.LoadAssetAtPath(fntFileName, typeof(TextAsset)) as TextAsset; // } // BMFont mbFont = new BMFont(); // BMFontReader.Load(mbFont, BMFontText.name, BMFontText.bytes); // 借用NGUI封装的读取类 // CharacterInfo[] characterInfo = new CharacterInfo[mbFont.glyphs.Count]; // for (int i = 0; i < mbFont.glyphs.Count; i++) // { // BMGlyph bmInfo = mbFont.glyphs[i]; // CharacterInfo info = new CharacterInfo(); // info.index = bmInfo.index; // float uvx = 1f * bmInfo.x / mbFont.texWidth; // float uvy = 1 - (1f * bmInfo.y / mbFont.texHeight); // float uvw = 1f * bmInfo.width / mbFont.texWidth; // float uvh = -1f * bmInfo.height / mbFont.texHeight; // info.uvBottomLeft = new Vector2(uvx, uvy); // info.uvBottomRight = new Vector2(uvx + uvw, uvy); // info.uvTopLeft = new Vector2(uvx, uvy + uvh); // info.uvTopRight = new Vector2(uvx + uvw, uvy + uvh); // info.minX = bmInfo.offsetX; // info.minY = bmInfo.offsetY + bmInfo.height / 2; // 这样调出来的效果是ok的,原理未知 // info.glyphWidth = bmInfo.width; // info.glyphHeight = -bmInfo.height; // 同上,不知道为什么要用负的,可能跟unity纹理uv有关 // info.advance = bmInfo.advance; // characterInfo[i] = info; // } // CustomFont.characterInfo = characterInfo; // string textureFilename = dirName + mbFont.spriteName + ".png"; // Material mat = null; // { // Shader shader = Shader.Find("Transparent/Diffuse"); // mat = new Material(shader); // Texture tex = AssetDatabase.LoadAssetAtPath(textureFilename, typeof(Texture)) as Texture; // mat.SetTexture("_MainTex", tex); // AssetDatabase.CreateAsset(mat, dirName + fntname + ".mat"); // AssetDatabase.SaveAssets(); // } // CustomFont.material = mat; // EditorUtility.SetDirty(CustomFont); // AssetDatabase.SaveAssets(); // EditorUtility.DisplayDialog("完成", $"字体文件{BMFontText.name}生成完成!", "OK"); //} internal static void BatchCreateArtistFont(string path) { string dirName = Path.GetDirectoryName(path); string fntname = Path.GetFileNameWithoutExtension(path); string fntFileName = path; Debug.Log(fntname); Debug.Log(dirName); Debug.Log(fntFileName); Font CustomFont = new Font(); { AssetDatabase.CreateAsset(CustomFont, Path.Combine(dirName, fntname + ".fontsettings")); AssetDatabase.SaveAssets(); } TextAsset BMFontText = null; { BMFontText = AssetDatabase.LoadAssetAtPath(fntFileName, typeof(TextAsset)) as TextAsset; } BMFont mbFont = new BMFont(); //BMFontReader.Load(mbFont, BMFontText.name, BMFontText.bytes); // 借用NGUI封装的读取类 BMFontReader.Load(mbFont, BMFontText.name, File.ReadAllText(Path.GetFullPath(fntFileName))); // 借用NGUI封装的读取类 CharacterInfo[] characterInfo = new CharacterInfo[mbFont.glyphs.Count]; for (int i = 0; i < mbFont.glyphs.Count; i++) { BMGlyph bmInfo = mbFont.glyphs[i]; CharacterInfo info = new CharacterInfo(); info.index = bmInfo.index; float uvx = 1f * bmInfo.x / mbFont.texWidth; float uvy = 1 - (1f * bmInfo.y / mbFont.texHeight); float uvw = 1f * bmInfo.width / mbFont.texWidth; float uvh = -1f * bmInfo.height / mbFont.texHeight; info.uvBottomLeft = new Vector2(uvx, uvy); info.uvBottomRight = new Vector2(uvx + uvw, uvy); info.uvTopLeft = new Vector2(uvx, uvy + uvh); info.uvTopRight = new Vector2(uvx + uvw, uvy + uvh); info.minX = bmInfo.offsetX; info.minY = bmInfo.offsetY + bmInfo.height / 2; // 这样调出来的效果是ok的,原理未知 info.glyphWidth = bmInfo.width; info.glyphHeight = -bmInfo.height; // 同上,不知道为什么要用负的,可能跟unity纹理uv有关 info.advance = bmInfo.advance; characterInfo[i] = info; } CustomFont.characterInfo = characterInfo; Debug.LogError(mbFont.spriteName); string textureFilename = Path.Combine(dirName, mbFont.spriteName + ".png"); Material mat = null; { Shader shader = Shader.Find("Transparent/Diffuse"); mat = new Material(shader); Texture tex = AssetDatabase.LoadAssetAtPath(textureFilename, typeof(Texture)) as Texture; mat.SetTexture("_MainTex", tex); AssetDatabase.CreateAsset(mat, Path.Combine(dirName, fntname + ".mat")); AssetDatabase.SaveAssets(); } CustomFont.material = mat; EditorUtility.SetDirty(CustomFont); AssetDatabase.SaveAssets(); EditorUtility.DisplayDialog("完成", $"字体文件{BMFontText.name}生成完成!", "OK"); }
public void Render(Renderer renderer, Size screenSize, Vector2 cameraPos, BMFont font) { var scale = 1f * Vector2.One; var hss = new Size((int)(screenSize.Width / 2f), (int)(screenSize.Height / 2f)); //var key = 0; foreach (var key in _layers.Keys.OrderByDescending(x => x)) { var items = _layers[key]; foreach (var layerItem in items) { var parallax = layerItem.Parallax; var pos = new Vector2( (hss.Width - cameraPos.X) * parallax.X - hss.Width, (hss.Height - cameraPos.Y) * parallax.Y - hss.Height); var p = new Vector2( hss.Width + pos.X + (hss.Width - hss.Width * parallax.X), hss.Height + pos.Y + (hss.Height - hss.Height * parallax.Y)); layerItem.Draw(renderer, p, scale); } //foreach (var layer in items) //{ // var parallax = layer.Parallax; // var pos = new Vector2( // (hss.Width - cameraPos.X) * parallax.X - hss.Width, // (hss.Height - cameraPos.Y) * parallax.Y - hss.Height); // var p = new Vector2( // hss.Width+pos.X + (hss.Width - hss.Width * parallax.X), // hss.Height+ pos.Y + (hss.Height - hss.Height * parallax.Y)); // layer.Sprite.Draw(renderer, p, scale); // //renderer.Draw(layer.Sprite.Texture, // // layer.Sprite.Offset, // // Vector2.Zero, 0, scale); //} } var textY = Size.Y * scale.Y + 40f; //foreach (var obj in _objects.OrderBy(x => x.ZSort)) //foreach (var obj in _objects.Skip(0).Take(1)) foreach (var obj in _objects.OrderByDescending(x => x.ZSort)) //foreach (var obj in _objects.Where(x=>x.Name== "chucksTombButton")) { if (obj.Sprite != null) { obj.Sprite.Draw(renderer, new Vector2(hss.Width - cameraPos.X + obj.Position.X * scale.X, hss.Height - cameraPos.Y + obj.Position.Y * scale.Y), scale); //var pos = new Vector2(obj.Position + obj.Sprite.Offset, pos.Y); ////var pos = new Vector2(obj.Position.X, Size.Y - obj.Position.Y); ////var pos = obj.Position + obj.Sprite.Offset; //renderer.Draw(obj.Sprite.Texture, // pos, // Vector2.Zero, 0, scale); } var x = obj.Position.X + obj.HotSpot.X; var y = obj.Position.Y + obj.HotSpot.Y; if (!obj.Prop && !obj.Spot && !obj.Trigger) { renderer.SetDrawColor(0xff, 0xff, 0xff, 0xff); renderer.DrawRect(x, y, obj.HotSpot.Width, obj.HotSpot.Height, scale); } if (!obj.Prop && !obj.Spot && !obj.Trigger && (Mouse.X >= x * scale.X && Mouse.X <= (x + obj.HotSpot.Width) * scale.X || Mouse.X >= (x + obj.HotSpot.Width) * scale.X && Mouse.X <= x * scale.X) && (Mouse.Y >= y * scale.Y && Mouse.Y <= (y + obj.HotSpot.Height) * scale.Y || Mouse.Y >= (y + obj.HotSpot.Height) * scale.Y) && Mouse.Y <= y * scale.Y) { renderer.SetDrawColor(0x00, 0xff, 0x00, 0xff); renderer.DrawRect(x, y, obj.HotSpot.Width, obj.HotSpot.Height, scale); renderer.SetDrawColor(0xff, 0xff, 0xff, 0xff); renderer.DrawRect(obj.Position.X - 1, obj.Position.Y - 1, 2, 2, scale); font.DrawText(renderer, obj.Name, 0, textY, 0xff, 0xff, 0xff); renderer.SetDrawColor(0x00, 0xff, 0x00, 0xff); var usePos = new Vector2(obj.Position.X + obj.UsePosition.X, obj.Position.Y - obj.UsePosition.Y); renderer.DrawRect(usePos.X - 1, usePos.Y - 1, 2, 2, scale); renderer.DrawLine(obj.Position, usePos, scale); textY += 20f; } } renderer.SetDrawColor(0x00, 0xff, 0x00, 0xff); foreach (var walkBox in _walkBoxes) { var pts = walkBox.Polygon.Points .Select(p => new Vector2(hss.Width - cameraPos.X + p.X * scale.X, hss.Height - cameraPos.Y + p.Y * scale.Y)) .ToList(); renderer.DrawLines(pts, Vector2.One); } font.DrawText(renderer, $"({Mouse.X}, {Mouse.Y})", 0, Size.Y * scale.Y + 20f, 0xff, 0xff, 0xff); renderer.SetDrawColor(0xff, 0x00, 0x00, 0xff); renderer.DrawRect(Size.X / 2 - 1, Size.Y / 2 - 1, 2, 2, scale); }
/// <summary> /// Apply an effect to the font. /// </summary> void ApplyEffect(Effect effect, Color foreground, Color background) { BMFont bf = mFont.bmFont; int offsetX = 0; int offsetY = 0; if (mFont.atlas != null) { UISpriteData sd = mFont.atlas.GetSprite(bf.spriteName); if (sd == null) { return; } offsetX = sd.x; offsetY = sd.y + mFont.texHeight - sd.paddingTop; } string path = AssetDatabase.GetAssetPath(mFont.texture); Texture2D bfTex = NGUIEditorTools.ImportTexture(path, true, true, false); Color32[] atlas = bfTex.GetPixels32(); // First we need to extract textures for all the glyphs, making them bigger in the process List <BMGlyph> glyphs = bf.glyphs; List <Texture2D> glyphTextures = new List <Texture2D>(glyphs.Count); for (int i = 0, imax = glyphs.Count; i < imax; ++i) { BMGlyph glyph = glyphs[i]; if (glyph.width < 1 || glyph.height < 1) { continue; } int width = glyph.width; int height = glyph.height; if (effect == Effect.Outline || effect == Effect.Shadow || effect == Effect.Border) { width += 2; height += 2; --glyph.offsetX; --glyph.offsetY; } else if (effect == Effect.Crop && width > 2 && height > 2) { width -= 2; height -= 2; ++glyph.offsetX; ++glyph.offsetY; } int size = width * height; Color32[] colors = new Color32[size]; Color32 clear = background; clear.a = 0; for (int b = 0; b < size; ++b) { colors[b] = clear; } if (effect == Effect.Crop) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { int fx = x + glyph.x + offsetX + 1; int fy = y + (mFont.texHeight - glyph.y - glyph.height) + 1; if (mFont.atlas != null) { fy += bfTex.height - offsetY; } colors[x + y * width] = atlas[fx + fy * bfTex.width]; } } } else { for (int y = 0; y < glyph.height; ++y) { for (int x = 0; x < glyph.width; ++x) { int fx = x + glyph.x + offsetX; int fy = y + (mFont.texHeight - glyph.y - glyph.height); if (mFont.atlas != null) { fy += bfTex.height - offsetY; } Color c = atlas[fx + fy * bfTex.width]; if (effect == Effect.Border) { colors[x + 1 + (y + 1) * width] = c; } else { if (effect == Effect.AlphaCurve) { c.a = Mathf.Clamp01(mCurve.Evaluate(c.a)); } Color bg = background; bg.a = (effect == Effect.BackgroundCurve) ? Mathf.Clamp01(mCurve.Evaluate(c.a)) : c.a; Color fg = foreground; fg.a = (effect == Effect.ForegroundCurve) ? Mathf.Clamp01(mCurve.Evaluate(c.a)) : c.a; if (effect == Effect.Outline || effect == Effect.Shadow) { colors[x + 1 + (y + 1) * width] = Color.Lerp(bg, c, c.a); } else { colors[x + y * width] = Color.Lerp(bg, fg, c.a); } } } } // Apply the appropriate affect if (effect == Effect.Shadow) { NGUIEditorTools.AddShadow(colors, width, height, NGUISettings.backgroundColor); } else if (effect == Effect.Outline) { NGUIEditorTools.AddDepth(colors, width, height, NGUISettings.backgroundColor); } } Texture2D tex = new Texture2D(width, height, TextureFormat.ARGB32, false); tex.SetPixels32(colors); tex.Apply(); glyphTextures.Add(tex); } // Pack all glyphs into a new texture Texture2D final = new Texture2D(bfTex.width, bfTex.height, TextureFormat.ARGB32, false); Rect[] rects = final.PackTextures(glyphTextures.ToArray(), 1); final.Apply(); // Make RGB channel use the background color (Unity makes it black by default) Color32[] fcs = final.GetPixels32(); Color32 bc = background; for (int i = 0, imax = fcs.Length; i < imax; ++i) { if (fcs[i].a == 0) { fcs[i].r = bc.r; fcs[i].g = bc.g; fcs[i].b = bc.b; } } final.SetPixels32(fcs); final.Apply(); // Update the glyph rectangles int index = 0; int tw = final.width; int th = final.height; for (int i = 0, imax = glyphs.Count; i < imax; ++i) { BMGlyph glyph = glyphs[i]; if (glyph.width < 1 || glyph.height < 1) { continue; } Rect rect = rects[index++]; glyph.x = Mathf.RoundToInt(rect.x * tw); glyph.y = Mathf.RoundToInt(rect.y * th); glyph.width = Mathf.RoundToInt(rect.width * tw); glyph.height = Mathf.RoundToInt(rect.height * th); glyph.y = th - glyph.y - glyph.height; } // Update the font's texture dimensions mFont.texWidth = final.width; mFont.texHeight = final.height; if (mFont.atlas == null) { // Save the final texture byte[] bytes = final.EncodeToPNG(); NGUITools.DestroyImmediate(final); System.IO.File.WriteAllBytes(path, bytes); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); } else { // Update the atlas final.name = mFont.spriteName; bool val = NGUISettings.atlasTrimming; NGUISettings.atlasTrimming = false; UIAtlasMaker.AddOrUpdate(mFont.atlas, final); NGUISettings.atlasTrimming = val; NGUITools.DestroyImmediate(final); } // Cleanup for (int i = 0; i < glyphTextures.Count; ++i) { NGUITools.DestroyImmediate(glyphTextures[i]); } // Refresh all labels mFont.MarkAsChanged(); }
private static void BMFontTools() { BMFont bmFont = new BMFont(); bmFont.Show(); }
/// <summary> /// Create a bitmap font from the specified dynamic font. /// </summary> static public bool CreateFont (Font ttf, int size, int faceIndex, bool kerning, string characters, int padding, out BMFont font, out Texture2D tex) { font = null; tex = null; if (ttf == null || !isPresent) return false; IntPtr lib = IntPtr.Zero; IntPtr face = IntPtr.Zero; if (FT_Init_FreeType(out lib) != 0) { Debug.LogError("Failed to initialize FreeType"); return false; } string fileName = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length) + UnityEditor.AssetDatabase.GetAssetPath(ttf); if (!File.Exists(fileName)) { Debug.LogError("Unable to use the chosen font."); } else if (FT_New_Face(lib, fileName, faceIndex, out face) != 0) { Debug.LogError("Unable to use the chosen font (FT_New_Face)."); } else { font = new BMFont(); font.charSize = size; Color32 white = Color.white; List<int> entries = new List<int>(); List<Texture2D> textures = new List<Texture2D>(); FT_FaceRec faceRec = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec)); FT_Set_Pixel_Sizes(face, 0, (uint)size); // Calculate the baseline value that would let the printed font be centered vertically //int ascender = (faceRec.met.ascender >> 6); //int descender = (faceRec.descender >> 6); //int baseline = ((ascender - descender) >> 1); //if ((baseline & 1) == 1) --baseline; //Debug.Log(ascender + " " + descender + " " + baseline); // Space character is not renderable FT_Load_Glyph(face, FT_Get_Char_Index(face, 32), FT_LOAD_DEFAULT); FT_GlyphSlotRec space = (FT_GlyphSlotRec)Marshal.PtrToStructure(faceRec.glyph, typeof(FT_GlyphSlotRec)); // Space is not visible and doesn't have a texture BMGlyph spaceGlyph = font.GetGlyph(32, true); spaceGlyph.offsetX = 0; spaceGlyph.offsetY = 0; spaceGlyph.advance = (space.metrics.horiAdvance >> 6); spaceGlyph.channel = 15; spaceGlyph.x = 0; spaceGlyph.y = 0; spaceGlyph.width = 0; spaceGlyph.height = 0; // Save kerning information if (kerning) { for (int b = 0; b < characters.Length; ++b) { uint ch2 = characters[b]; if (ch2 == 32) continue; FT_Vector vec; if (FT_Get_Kerning(face, ch2, 32, 0, out vec) != 0) continue; int offset = (vec.x >> 6); if (offset != 0) spaceGlyph.SetKerning((int)ch2, offset); } } // Run through all requested characters foreach (char ch in characters) { uint charIndex = FT_Get_Char_Index(face, (uint)ch); FT_Load_Glyph(face, charIndex, FT_LOAD_DEFAULT); FT_GlyphSlotRec glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(faceRec.glyph, typeof(FT_GlyphSlotRec)); FT_Render_Glyph(ref glyph, FT_Render_Mode.FT_RENDER_MODE_NORMAL); if (glyph.bitmap.width > 0 && glyph.bitmap.rows > 0) { byte[] buffer = new byte[glyph.bitmap.width * glyph.bitmap.rows]; Marshal.Copy(glyph.bitmap.buffer, buffer, 0, buffer.Length); Texture2D texture = new Texture2D(glyph.bitmap.width, glyph.bitmap.rows, UnityEngine.TextureFormat.ARGB32, false); Color32[] colors = new Color32[buffer.Length]; for (int i = 0, y = 0; y < glyph.bitmap.rows; ++y) { for (int x = 0; x < glyph.bitmap.width; ++x) { white.a = buffer[i++]; colors[x + glyph.bitmap.width * (glyph.bitmap.rows - y - 1)] = white; } } // Save the texture texture.SetPixels32(colors); texture.Apply(); textures.Add(texture); entries.Add(ch); // Record the metrics BMGlyph bmg = font.GetGlyph(ch, true); bmg.offsetX = (glyph.metrics.horiBearingX >> 6); bmg.offsetY = -(glyph.metrics.horiBearingY >> 6); bmg.advance = (glyph.metrics.horiAdvance >> 6); bmg.channel = 15; // Save kerning information if (kerning) { for (int b = 0; b < characters.Length; ++b) { uint ch2 = characters[b]; if (ch2 == ch) continue; FT_Vector vec; if (FT_Get_Kerning(face, ch2, ch, 0, out vec) != 0) continue; int offset = (vec.x >> 6); if (offset != 0) bmg.SetKerning((int)ch2, offset); } } } } // Create a packed texture with all the characters tex = new Texture2D(32, 32, TextureFormat.ARGB32, false); Rect[] rects = tex.PackTextures(textures.ToArray(), padding); // Make the RGB channel pure white Color32[] cols = tex.GetPixels32(); for (int i = 0, imax = cols.Length; i < imax; ++i) { Color32 c = cols[i]; c.r = 255; c.g = 255; c.b = 255; cols[i] = c; } tex.SetPixels32(cols); tex.Apply(); font.texWidth = tex.width; font.texHeight = tex.height; int min = int.MaxValue; int max = int.MinValue; // Other glyphs are visible and need to be added for (int i = 0, imax = entries.Count; i < imax; ++i) { // Destroy the texture now that it's a part of an atlas UnityEngine.Object.DestroyImmediate(textures[i]); textures[i] = null; Rect rect = rects[i]; // Set the texture coordinates BMGlyph glyph = font.GetGlyph(entries[i], true); glyph.x = Mathf.RoundToInt(rect.x * font.texWidth); glyph.y = Mathf.RoundToInt(rect.y * font.texHeight); glyph.width = Mathf.RoundToInt(rect.width * font.texWidth); glyph.height = Mathf.RoundToInt(rect.height * font.texHeight); // Flip the Y since the UV coordinate system is different glyph.y = font.texHeight - glyph.y - glyph.height; max = Mathf.Max(max, -glyph.offsetY); min = Mathf.Min(min, -glyph.offsetY - glyph.height); } int baseline = size + min; baseline += ((max - min - size) >> 1); // Offset all glyphs so that they are not using the baseline for (int i = 0, imax = entries.Count; i < imax; ++i) { BMGlyph glyph = font.GetGlyph(entries[i], true); glyph.offsetY += baseline; } } if (face != IntPtr.Zero) FT_Done_Face(face); #if !UNITY_3_5 if (lib != IntPtr.Zero) FT_Done_FreeType(lib); #endif return (tex != null); }
public void DrawStringClip(int width, BMFont bmFont, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) { if (bmFont == null) { throw new ArgumentNullException(nameof(bmFont)); } if (text == null) { throw new ArgumentNullException(nameof(text)); } Matrix temp; Matrix transform; Matrix.CreateScale(scale.X, scale.Y, 1, out temp); Matrix.CreateRotationZ(rotation, out transform); Matrix.Multiply(ref temp, ref transform, out transform); //character index int prevMaxX = -1; int index = 0; int rightMostCharacter = 0; bool isHighlighted = false; int selectionEdge = caretPosition + selectedPosition; int minSelection = Math.Min(caretPosition, selectedPosition); int maxSelection = Math.Max(caretPosition, selectedPosition); bmFont.ProcessChars(text, (actual, drawPos, data, previous) => { var sourceRectangle = new Rectangle(data.X, data.Y, data.Width, data.Height); Vector2.Transform(ref drawPos, ref transform, out drawPos); var destRectangle = new Rectangle((int)(position.X + drawPos.X), (int)(position.Y + drawPos.Y), (int)(data.Width * scale.X), (int)(data.Height * scale.Y)); //Check if the character is highlighted isHighlighted = text.Length > 0 && //text isnt empty selectedPosition != -1 && //we have highlighted something (maxSelection > index && minSelection <= index); //selection edge is greater than caret position //Check if it clips rightMostCharacter = destRectangle.Right; if (rightMostCharacter > width && destRectangle.X < width) //if the rectangle passes through width { //recalculate the rectangles //width * percentage of covered area = new width sourceRectangle.Width = (int)(sourceRectangle.Width * (float)(width - destRectangle.X) / destRectangle.Width); destRectangle.Width = width - destRectangle.X; } //Drawing if (isHighlighted) { if (prevMaxX == -1) { prevMaxX = destRectangle.X; } UiStateManager.DrawImage(new Rectangle(prevMaxX, location.Y + paddingY, destRectangle.Width + GameSettings.UIScale + (destRectangle.X - prevMaxX), size.Y - 2 * paddingY), new Rectangle(0, 0, 1, 1), TextureLoader.getWhitePixel(), HighlightColor); prevMaxX = prevMaxX + destRectangle.Width + GameSettings.UIScale + (destRectangle.X - prevMaxX); } UiStateManager.SpriteBatch.Draw(bmFont.Texture, destRectangle, sourceRectangle, color, rotation, origin, effects, layerDepth); index++; }, null); }