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