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 }