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