1 module d2d.font.bmtext; 2 3 import d2d; 4 5 import std.utf : byDchar; 6 7 /// Implementation containing text drawable functions using an AngelCode BMFont. Nice and fast for unscaled text, reduced memory usage, render time scales with text length, no re-render times, requires some additional shader uniforms. 8 class BMText : Transformable, IText 9 { 10 private: 11 float _scale = 1.0f; 12 string _text = ""; 13 BMFont _font; 14 bool _multiline = false; 15 RectangleShape unitRect; 16 float iWidth, iHeight; 17 18 public: 19 /// Creates an empty bmfont text 20 this(BMFont font) 21 { 22 _font = font; 23 iWidth = 1.0f / _font.handle.common.scaleW; 24 iHeight = 1.0f / _font.handle.common.scaleH; 25 unitRect = RectangleShape.create(vec2(0, 0), vec2(1, 1)); 26 } 27 28 /// Gets the scale in percent. 29 override @property float scale() 30 { 31 return _scale; 32 } 33 34 /// Sets the scale in percent. 35 override @property void scale(float value) 36 { 37 _scale = value; 38 } 39 40 /// Gets the text. 41 override @property string text() 42 { 43 return _text; 44 } 45 46 /// Modifies the text. 47 override @property void text(string value) 48 { 49 _text = value; 50 } 51 52 /// Returns if this text should be rendered multiline. 53 @property bool multiline() 54 { 55 return _multiline; 56 } 57 58 /// Sets if this text should be rendered multiline. 59 @property void multiline(bool value) 60 { 61 _multiline = value; 62 } 63 64 /// Dynamically draws the text onto a target. Requires the shader to have `texRect` vec4(uvX, uvY, uvW, uvH) and `sizeRect` vec4(posX, posY, width, height) uniforms. 65 override void draw(IRenderTarget target, ShaderProgram shader = null) 66 { 67 matrixStack.push(); 68 matrixStack.top *= mat4.scaling(_scale, _scale, 1); 69 matrixStack.top *= transform; 70 int x, y; 71 dchar last; 72 for (int i = 0; i < _font.textures.length; i++) 73 _font.textures[i].bind(i); 74 if (shader) 75 shader.bind(); 76 foreach (dc; _text.byDchar) 77 { 78 auto bmChar = _font.handle.getChar(dc); 79 if (bmChar.id == dchar.init) 80 { 81 if (_multiline && dc == '\n') 82 { 83 x = 0; 84 y += _font.handle.common.lineHeight; 85 } 86 continue; 87 } 88 89 shader.set("tex", cast(int) bmChar.page); 90 shader.set("texRect", vec4(bmChar.x * iWidth, bmChar.y * iHeight, 91 bmChar.width * iWidth, bmChar.height * iHeight)); 92 shader.set("sizeRect", vec4(x + bmChar.xoffset, y + bmChar.yoffset, 93 bmChar.width, bmChar.height)); 94 unitRect.draw(target, shader); 95 if (_multiline && dc == '\n') 96 { 97 x = 0; 98 y += _font.handle.common.lineHeight; 99 continue; 100 } 101 if (last != dchar.init) 102 x += _font.handle.getKerning(last, dc); 103 x += bmChar.xadvance; 104 last = dc; 105 } 106 matrixStack.pop(); 107 } 108 109 override @property bool valid() 110 { 111 return true; 112 } 113 114 override void dispose() 115 { 116 } 117 }