1 module Engine.UI.Label; 2 3 import Engine.Component; 4 import Engine.Batch; 5 import Engine.Material; 6 import gl3n.linalg; 7 import Engine.Font; 8 import Engine.Core; 9 10 class Label : Batchable { 11 mixin ComponentBase; 12 // This will identify our vertex buffer 13 string text; 14 Font font; 15 package vec4 _color = vec4(1,1,1,1); 16 17 18 Material _material; 19 20 @property Material material() { 21 return _material; 22 }; 23 24 25 @property ref vec4 color() { 26 if (batchData !is null) { 27 batchData.MarkCheck(BatchData.Type.Color); 28 } 29 return _color; 30 } 31 32 package int actualSize; 33 package BatchData* batchData; 34 35 this(Font f,string text) { 36 this.text = text; 37 font = f; 38 _material = font.Atlas.GetMaterial(); 39 SetText(text); 40 } 41 42 void OnBatchSetup(BatchData* data) { 43 batchData = data; 44 } 45 46 47 @property int vertecies() { 48 return actualSize*4; 49 }; 50 @property int indecies() { 51 return actualSize*6; 52 }; 53 54 vec2 GetPixelSize(string text ) { 55 auto index = 0; 56 vec2 size = vec2(0,0); 57 foreach (chr; text) { 58 auto spaceMult = 1; 59 60 auto letterInfoPTR = chr in font.Map; 61 if (letterInfoPTR is null) { 62 size.x += 1; 63 continue; 64 } 65 auto letterInfo = *letterInfoPTR; 66 67 size.x += letterInfo.XAdvance * spaceMult; 68 /* 69 yratio := letterInfo.PlaneHeight 70 ygrid := letterInfo.YGrid 71 if yratio < 0 { 72 yratio = -yratio 73 } 74 if ygrid < 0 { 75 ygrid = -ygrid 76 } 77 78 if yratio+ygrid > height { 79 height = yratio + ygrid 80 } 81 */ 82 size.y = 1; 83 } 84 return size; 85 } 86 87 88 void SetText(string text) { 89 this.text = text; 90 auto oldSize = actualSize; 91 actualSize = 0; 92 foreach(chr; text) { 93 auto letterInfo = chr in font.Map; 94 if (letterInfo !is null) { 95 actualSize++; 96 } 97 } 98 if (batchData !is null) { 99 batchData.MarkCheck(BatchData.Type.UV, BatchData.Type.Vertex); 100 if ( oldSize != actualSize) { 101 batchData.MarkCheck(BatchData.Type.Size); 102 } 103 } 104 } 105 106 void UpdateBatch(vec3[] vertexData, vec2[] uvData, vec4[] colorData, uint[] indexData, uint indexPosition) { 107 108 if (vertexData is null && uvData is null && indexData is null) { 109 if (colorData !is null) { 110 colorData[] = _color; 111 } 112 return; 113 } 114 float space = 0; 115 float spaceMult = 1; 116 int index = 0; 117 118 auto size = GetPixelSize(text); 119 foreach(chr; text) { 120 auto letterInfo = chr in font.Map; 121 if (letterInfo is null) { 122 space += 0.5; 123 continue; 124 } 125 auto yratio = letterInfo.RelativeHeight; 126 auto xratio = letterInfo.RelativeWidth; 127 auto ygrid = -(size.y / 2) + (letterInfo.YOffset); 128 auto xgrid = -(size.x / 2) + (letterInfo.XOffset) + space; 129 130 space += letterInfo.XAdvance * spaceMult; 131 auto uv = font.Atlas.RectUV(letterInfo.AtlasRect); 132 133 if (vertexData !is null) { 134 vertexData[index*4+0] = vec3(xgrid,ygrid,1); 135 vertexData[index*4+1] = vec3((xratio) + xgrid,ygrid,1); 136 vertexData[index*4+2] = vec3((xratio) + xgrid, (yratio) + ygrid,1); 137 vertexData[index*4+3] = vec3(xgrid,(yratio) + ygrid,1); 138 } 139 140 if (colorData !is null) { 141 colorData[index*4+0] = _color; 142 colorData[index*4+1] = _color; 143 colorData[index*4+2] = _color; 144 colorData[index*4+3] = _color; 145 } 146 147 if (uvData !is null) { 148 uvData[index*4+0] = vec2(uv.U1,uv.V1); 149 uvData[index*4+1] = vec2(uv.U2,uv.V1); 150 uvData[index*4+2] = vec2(uv.U2,uv.V2); 151 uvData[index*4+3] = vec2(uv.U1,uv.V2); 152 } 153 154 if (indexData !is null) { 155 indexData[index*6+0] = indexPosition+(index*4); 156 indexData[index*6+1] = indexPosition+(index*4)+1; 157 indexData[index*6+2] = indexPosition+(index*4)+2; 158 indexData[index*6+3] = indexPosition+(index*4); 159 indexData[index*6+4] = indexPosition+(index*4)+2; 160 indexData[index*6+5] = indexPosition+(index*4)+3; 161 } 162 163 index++; 164 } 165 } 166 }