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 }