1 module rpui.render.components_factory; 2 3 import std.traits; 4 import std.string; 5 import std.container.array; 6 7 import rpdl; 8 9 import gapi.texture; 10 import gapi.geometry; 11 import gapi.geometry_quad; 12 import gapi.shader; 13 import gapi.text; 14 import gapi.vec; 15 16 import rpui.render.components; 17 import rpui.gapi_rpdl_exts; 18 import rpui.theme; 19 import rpui.primitives; 20 21 StatefulChain createStatefulChainFromRdpl( 22 Theme theme, 23 in Orientation orientation, 24 in string style, 25 immutable State[] states = [EnumMembers!State] 26 ) { 27 StatefulChain chain; 28 29 immutable chainParts = orientation == Orientation.horizontal 30 ? horizontalChainParts 31 : verticalChainParts; 32 33 foreach (immutable part; chainParts) { 34 chain.parts[part] = createUiSkinTextureQuad(theme); 35 36 foreach (immutable state; states) { 37 const texCoords = createOriginalWithNormilizedTextureCoordsFromRdpl( 38 theme, 39 style ~ "." ~ getStateRdplName(state) ~ "." ~ getChainPartRdplName(part) 40 ); 41 chain.texCoords[state][part] = texCoords.normilizedTexCoords; 42 chain.widths[part] = orientation == Orientation.horizontal 43 ? texCoords.originalTexCoords.size.x 44 : texCoords.originalTexCoords.size.y; 45 } 46 } 47 48 return chain; 49 } 50 51 Chain createChainFromRdpl(Theme theme, in Orientation orientation, in string style) { 52 Chain chain; 53 54 immutable chainParts = orientation == Orientation.horizontal 55 ? horizontalChainParts 56 : verticalChainParts; 57 58 foreach (immutable part; chainParts) { 59 chain.parts[part] = createUiSkinTextureQuad(theme); 60 61 const texCoords = createOriginalWithNormilizedTextureCoordsFromRdpl( 62 theme, 63 style ~ "." ~ getChainPartRdplName(part) 64 ); 65 66 chain.texCoords[part] = texCoords.normilizedTexCoords; 67 chain.widths[part] = texCoords.originalTexCoords.size.x; 68 chain.height = texCoords.originalTexCoords.size.y; 69 } 70 71 return chain; 72 } 73 74 Block createBlockFromRdpl(Theme theme, in string style) { 75 Block block; 76 77 block.topChain = createChainFromRdpl(theme, Orientation.horizontal, style ~ ".Top"); 78 block.middleChain = createChainFromRdpl(theme, Orientation.horizontal, style ~ ".Middle"); 79 block.bottomChain = createChainFromRdpl(theme, Orientation.horizontal, style ~ ".Bottom"); 80 81 block.widths[BlockRow.top] = block.topChain.widths; 82 block.widths[BlockRow.middle] = block.middleChain.widths; 83 block.widths[BlockRow.bottom] = block.bottomChain.widths; 84 85 block.heights[BlockRow.top] = block.topChain.height; 86 block.heights[BlockRow.middle] = block.middleChain.height; 87 block.heights[BlockRow.bottom] = block.bottomChain.height; 88 89 return block; 90 } 91 92 TextureQuad createUiSkinTextureQuad(in Theme theme) { 93 TextureQuad quad; 94 quad.geometry = createGeometry(); 95 quad.texture = theme.skin; 96 97 return quad; 98 } 99 100 StatefulTexAtlasTextureQuad createStatefulTexAtlasTextureQuadFromRdpl( 101 Theme theme, 102 in string style, 103 in string name, 104 immutable State[] states = [EnumMembers!State] 105 ) { 106 StatefulTexAtlasTextureQuad quad; 107 108 quad.geometry = createGeometry(); 109 quad.texture = theme.skin; 110 111 foreach (immutable state; states) { 112 const texCoords = createOriginalWithNormilizedTextureCoordsFromRdpl( 113 theme, 114 style ~ "." ~ getStateRdplName(state) ~ "." ~ name 115 ); 116 quad.texCoords[state] = texCoords; 117 } 118 119 return quad; 120 } 121 122 TexAtlasTextureQuad createTexAtlasTextureQuadFromRdpl( 123 Theme theme, 124 in string style, 125 in string name 126 ) { 127 TexAtlasTextureQuad quad; 128 129 quad.geometry = createGeometry(); 130 quad.texture = theme.skin; 131 quad.texCoords = createOriginalWithNormilizedTextureCoordsFromRdpl( 132 theme, 133 style ~ "." ~ name 134 ); 135 136 return quad; 137 } 138 139 TexAtlasTextureQuad createTexAtlasTextureQuad( 140 Texture2D texture, 141 Texture2DCoords texCoords 142 ) { 143 return TexAtlasTextureQuad( 144 createGeometry(), 145 texture, 146 OriginalWithNormilizedTextureCoords(texCoords, texCoords) 147 ); 148 } 149 150 OriginalWithNormilizedTextureCoords createOriginalWithNormilizedTextureCoordsFromRdpl( 151 Theme theme, 152 in string style, 153 ) { 154 const textCoord = theme.tree.data.getTexCoord(style); 155 const normilized = normilizeTexture2DCoords(textCoord, theme.skin); 156 157 return OriginalWithNormilizedTextureCoords(textCoord, normilized); 158 } 159 160 Texture2DCoords createNormilizedTextureCoordsFromRdpl( 161 Theme theme, 162 in string style, 163 ) { 164 const textCoord = theme.tree.data.getTexCoord(style); 165 return normilizeTexture2DCoords(textCoord, theme.skin); 166 } 167 168 UiText createUiTextFromRdpl( 169 Theme theme, 170 in string style, 171 in string name 172 ) { 173 UiText text; 174 175 text.render = createUiTextRenderObject(); 176 text.attrs = createTextAttributesFromRdpl(theme, style ~ "." ~ name); 177 178 return text; 179 } 180 181 StatefulUiText createStatefulUiTextFromRdpl( 182 Theme theme, 183 in string style, 184 in string name, 185 immutable State[] states = [EnumMembers!State] 186 ) { 187 StatefulUiText text; 188 text.render = createUiTextRenderObject(); 189 190 foreach (immutable state; states) { 191 text.attrs[state] = createTextAttributesFromRdpl( 192 theme, 193 style ~ "." ~ getStateRdplName(state) ~ "." ~ name 194 ); 195 } 196 197 return text; 198 } 199 200 UiTextAttributes createTextAttributesFromRdpl(Theme theme, in string style) { 201 UiTextAttributes attrs; 202 203 attrs.color = theme.tree.data.getNormColor(style ~ ".color"); 204 attrs.offset = theme.tree.data.optVec2f(style ~ ".offset", vec2(0, 0)); 205 attrs.fontSize = theme.tree.data.optInteger(style ~ ".fontSize.0", theme.regularFontSize); 206 attrs.textAlign = theme.tree.data.optEnum(style ~ ".textAlign.0", Align.center); 207 attrs.textVerticalAlign = theme.tree.data.optEnum(style ~ ".textVerticalAlign.0", VerticalAlign.middle); 208 // TODO: read from rdpl 209 attrs.font = theme.regularFont; 210 211 return attrs; 212 } 213 214 UiTextRender createUiTextRenderObject() { 215 return UiTextRender(createGeometry(), createText()); 216 } 217 218 Geometry createGeometry() { 219 Geometry geometry; 220 221 geometry.indicesBuffer = createIndicesBuffer(quadIndices); 222 geometry.verticesBuffer = createVector2fBuffer(quadVertices); 223 geometry.texCoordsBuffer = createVector2fBuffer(quadTexCoords); 224 225 geometry.vao = createVAO(); 226 bindVAO(geometry.vao); 227 228 createVector2fVAO(geometry.verticesBuffer, inAttrPosition); 229 createVector2fVAO(geometry.texCoordsBuffer, inAttrTextCoords); 230 231 return geometry; 232 } 233 234 LinesGeometry createDynamicLinesGeometry(ref Array!vec2 vertices, ref Array!uint indices) { 235 LinesGeometry geometry; 236 237 geometry.indicesBuffer = createIndicesBuffer(indices, false); 238 geometry.verticesBuffer = createVector2fBuffer(vertices, false); 239 240 geometry.vao = createVAO(); 241 bindVAO(geometry.vao); 242 243 createVector2fVAO(geometry.verticesBuffer, inAttrPosition); 244 245 return geometry; 246 } 247 248 void updateLinesGeometryData(ref LinesGeometry geometry, ref Array!vec2 vertices, ref Array!uint indices) { 249 updateIndicesBufferData(geometry.indicesBuffer, indices); 250 updateVector2fBufferData(geometry.verticesBuffer, vertices); 251 geometry.pointsCount = cast(uint) indices.length; 252 }