Covellite++  Version: 2.3.0 Revision: ??? Platform: x64 Build: 23:13 04.01.2025
Кроссплатформенный фреймворк для разработки приложений на С++
Загрузка...
Поиск...
Не найдено
Renderer.cpp
1
2#include "stdafx.h"
3#include <Covellite/Gui/Renderer.hpp>
4#include <alicorn/std/vector.hpp>
5#include <alicorn/boost/filesystem.hpp>
6#include <alicorn/patterns/factory.hpp>
7#include <alicorn/image.hpp>
8#include <Covellite/App/Vfs.hpp>
9#include <Covellite/Api/Component.inl>
10#include <Covellite/Api/Renders.hpp>
11#include <Covellite/Api/Vertex.hpp>
12
13namespace covellite
14{
15
16namespace gui
17{
18
19Renderer::Renderer(const RendersPtr_t & _pRenders) :
20 m_pRenders(_pRenders),
21 m_DefaultRenders(
22 {
23 m_pRenders->Obtain(Component_t::Make(
24 {
25 { uT("id"), uT("Covellite.Gui.Camera.Gui") },
26 { uT("type"), uT("Camera") },
27 { uT("kind"), uT("Orthographic") },
28 })),
29 m_pRenders->Obtain(Component_t::Make(
30 {
31 { uT("id"), uT("Covellite.Gui.State.Blend") },
32 { uT("type"), uT("State") },
33 { uT("kind"), uT("Blend") },
34 })),
35 m_pRenders->Obtain(Component_t::Make(
36 {
37 { uT("id"), uT("Covellite.Gui.State.Sampler") },
38 { uT("type"), uT("State") },
39 { uT("kind"), uT("Sampler") },
40 })),
41 m_pRenders->Obtain(Component_t::Make(
42 {
43 { uT("id"), uT("Covellite.Gui.Shader.Vertex") },
44 { uT("type"), uT("Shader") },
45 { uT("entry"), uT("vsFlat") },
46 })),
47 }),
48 m_pScissorRect(Component_t::Make(
49 {
50 { uT("type"), uT("Data") },
51 { uT("kind"), uT("Rect") },
52 }))
53{
54}
55
56//Renderer::~Renderer(void)
57//{
58 // Рендеры общих компонентов не удаляются, т.к. они будут удалены вместе с
59 // уникальным (для объектв класса Renderer) объектом m_pRenders.
60 // m_pRenders->Remove(...);
61//}
62
63void Renderer::RenderGeometry(
64 CovelliteGui::Vertex * _pVertex, int _VertexCount,
65 int * _pIndex, int _IndexCount,
66 CovelliteGui::TextureHandle _hTexture,
67 const CovelliteGui::Vector2f & _Position) /*override*/
68{
69 const auto hGeometry = CompileGeometry(
70 _pVertex, _VertexCount,
71 _pIndex, _IndexCount,
72 _hTexture);
73 RenderCompiledGeometry(hGeometry, _Position);
74 ReleaseCompiledGeometry(hGeometry);
75}
76
77CovelliteGui::CompiledGeometryHandle Renderer::CompileGeometry(
78 CovelliteGui::Vertex * _pVertex, int _VertexCount,
79 int * _pIndex, int _IndexCount,
80 CovelliteGui::TextureHandle _hTexture) /*override*/
81{
82 static size_t ObjectId = 0;
83
84 const auto strObjectId = String_t{ uT("%ID%") }
85 .Replace(uT("%ID%"), (size_t)++ObjectId);
86
87 Renders_t & Object = m_Objects[ObjectId].Renders;
88 m_Objects[ObjectId].pPosition = Component_t::Make(
89 {
90 { uT("type"), uT("Data") },
91 { uT("kind"), uT("Position") },
92 { uT("x"), 0.0f },
93 { uT("y"), 0.0f },
94 });
95
96 using namespace ::alicorn::extension::std;
97
98 if (_hTexture == 0)
99 {
100 Object.push_back(m_pRenders->Obtain(Component_t::Make(
101 {
102 { uT("id"), uT("Covellite.Gui.Shader.Pixel.Colored") },
103 { uT("type"), uT("Shader") },
104 { uT("entry"), uT("psColored") },
105 })));
106 }
107 else
108 {
109 const auto strTextureId = uT("Covellite.Gui.Texture.%ID%")
110 .Replace(uT("%ID%"), (size_t)_hTexture);
111
112 Object += Renders_t
113 {
114 m_pRenders->Obtain(Component_t::Make(
115 {
116 { uT("id"), uT("Covellite.Gui.Shader.Pixel.Textured") },
117 { uT("type"), uT("Shader") },
118 { uT("entry"), uT("psTextured") },
119 })),
120 m_pRenders->Obtain(Component_t::Make(
121 {
122 { uT("id"), strTextureId },
123 { uT("type"), uT("Texture") },
124 }))
125 };
126 }
127
128 const auto Convert =
129 [](CovelliteGui::Vertex * _pVertex, const ::std::size_t _VertexCount)
130 {
131 ::std::vector<::covellite::api::Vertex> Result{ _VertexCount };
132
133 for (::std::size_t i = 0; i < _VertexCount; i++)
134 {
135 auto & Vertex = Result[i];
136
137 Vertex.px = _pVertex[i].position.x;
138 Vertex.py = _pVertex[i].position.y;
139 Vertex.pz = 0.0f;
140 Vertex.pw = 1.0f;
141
142 Vertex.tu = _pVertex[i].tex_coord.x;
143 Vertex.tv = _pVertex[i].tex_coord.y;
144
145 Vertex.ex = _pVertex[i].colour.red / 255.0f;
146 Vertex.ey = _pVertex[i].colour.green / 255.0f;
147 Vertex.ez = _pVertex[i].colour.blue / 255.0f;
148 Vertex.ew = _pVertex[i].colour.alpha / 255.0f;
149 }
150
151 return Result;
152 };
153
154 Object += Renders_t
155 {
156 m_pRenders->Obtain(Component_t::Make(
157 {
158 { uT("id"), uT("Covellite.Gui.Buffer.Vertex.") + strObjectId },
159 { uT("type"), uT("Buffer") },
160 { uT("content"), Convert(_pVertex, static_cast<::std::size_t>(_VertexCount)) },
161 { uT("dimension"), 2 },
162 })),
163 m_pRenders->Obtain(Component_t::Make(
164 {
165 { uT("id"), uT("Covellite.Gui.Transform.") + strObjectId },
166 { uT("type"), uT("Transform") },
167 { uT("service"), Object_t{ m_Objects[ObjectId].pPosition } },
168 })),
169 m_pRenders->Obtain(Component_t::Make(
170 {
171 { uT("id"), uT("Covellite.Gui.Present.") + strObjectId },
172 { uT("type"), uT("Present") },
173 { uT("content"), ::std::vector<int>{ _pIndex, _pIndex + _IndexCount } },
174 }))
175 };
176
177 return (CovelliteGui::CompiledGeometryHandle)ObjectId;
178}
179
180void Renderer::RenderCompiledGeometry(
181 CovelliteGui::CompiledGeometryHandle _hGeometry,
182 const CovelliteGui::Vector2f & _Position) /*override*/
183{
184 const auto itObject = m_Objects.find((size_t)_hGeometry);
185 if (itObject == m_Objects.end()) return;
186
187 auto & Position = *itObject->second.pPosition;
188
189 Position[uT("x")] = _Position.x;
190 Position[uT("y")] = _Position.y;
191
192 using namespace ::alicorn::extension::std;
193
194 m_RenderQueue += itObject->second.Renders;
195}
196
197void Renderer::ReleaseCompiledGeometry(
198 CovelliteGui::CompiledGeometryHandle _hGeometry) /*override*/
199{
200 const auto strObjectId = String_t{ uT("%ID%") }
201 .Replace(uT("%ID%"), (size_t)_hGeometry);
202
203 m_pRenders->Remove(Component_t::Make(
204 {
205 { uT("id"), uT("Covellite.Gui.Buffer.Vertex.") + strObjectId }
206 }));
207 m_pRenders->Remove(Component_t::Make(
208 {
209 { uT("id"), uT("Covellite.Gui.Present.") + strObjectId }
210 }));
211
212 m_Objects.erase((size_t)_hGeometry);
213}
214
215void Renderer::EnableScissorRegion(bool _IsEnable) /*override*/
216{
217 if (_IsEnable) return;
218
219 using namespace ::alicorn::extension::std;
220
221 m_RenderQueue.push_back(m_pRenders->Obtain(Component_t::Make(
222 {
223 { uT("id"), uT("Covellite.Gui.State.Scissor.Disabled") },
224 { uT("type"), uT("State") },
225 { uT("kind"), uT("Scissor") },
226 { uT("enabled"), uT("false") }
227 })));
228}
229
230void Renderer::SetScissorRegion(int _X, int _Y, int _Width, int _Height) /*override*/
231{
232 m_RenderQueue.push_back([&, _X, _Y, _Width, _Height]()
233 {
234 auto & ScissorRect = *m_pScissorRect;
235
236 ScissorRect[uT("left")] = _X;
237 ScissorRect[uT("right")] = _X + _Width;
238 ScissorRect[uT("top")] = _Y;
239 ScissorRect[uT("bottom")] = _Y + _Height;
240 });
241
242 using namespace ::alicorn::extension::std;
243
244 m_RenderQueue.push_back(m_pRenders->Obtain(Component_t::Make(
245 {
246 { uT("id"), uT("Covellite.Gui.State.Scissor.Enabled") },
247 { uT("type"), uT("State") },
248 { uT("kind"), uT("Scissor") },
249 { uT("enabled"), uT("true") },
250 { uT("service"), Object_t{ m_pScissorRect } }
251 })));
252}
253
254bool Renderer::LoadTexture(
255 CovelliteGui::TextureHandle & _hTexture,
256 CovelliteGui::Vector2i & _TextureDimensions,
257 const CovelliteGui::String & _PathToFile) /*override*/
258{
259 // В Android'e файлы грузятся из 'папки' assets, кроме того, возможно
260 // использование виртуальной файловой системы, поэтому exists использовать
261 // НЕЛЬЗЯ!!!
262 //if (!::boost::filesystem::exists(_PathToFile.CString())) return false;
263
264 // Один файл грузится один раз, оптимизировать загрузку не нужно.
265
266 using namespace ::alicorn::source;
267
268 try
269 {
270 const image::Universal_t<image::pixel::RGBA> Image
271 {
272 app::Vfs_t::GetInstance().GetData(CovelliteGuiStringToUtf8(_PathToFile))
273 };
274
275 _TextureDimensions.x = static_cast<int>(Image.GetData().Width);
276 _TextureDimensions.y = static_cast<int>(Image.GetData().Height);
277
278 // 13 Июнь 2020 22:06 (unicornum.verum@gmail.com)
279 TODO("Лишнее копирование данных текстуры.");
280
281 return GenerateTexture(_hTexture,
282 Image.GetData().Buffer.data(), _TextureDimensions);
283 }
284 catch (const ::std::exception &)
285 {
286 // Сюда попадаем, если нет файла текстуры или он имеет невалидый формат
287 // (записывать в лог ничего не нужно, это используемая библиотека GUI
288 // сделает сама).
289 }
290
291 return false;
292}
293
294bool Renderer::GenerateTexture(
295 CovelliteGui::TextureHandle & _hTexture,
296 const CovelliteGui::byte * _pSource,
297 const CovelliteGui::Vector2i & _SourceDimensions) /*override*/
298{
299 static CovelliteGui::TextureHandle TextureId = 0;
300
301 const auto strTextureId = String_t{ uT("Covellite.Gui.Texture.%ID%") }
302 .Replace(uT("%ID%"), (size_t)++TextureId);
303
304 const auto Count = 4 * _SourceDimensions.x * _SourceDimensions.y;
305
306 m_pRenders->Obtain(Component_t::Make(
307 {
308 { uT("id"), strTextureId },
309 { uT("type"), uT("Texture") },
310 { uT("content"), ::std::vector<uint8_t>{ _pSource, _pSource + Count } },
311 { uT("width"), _SourceDimensions.x },
312 { uT("height"), _SourceDimensions.y },
313 }));
314
315 _hTexture = TextureId;
316
317 return true;
318}
319
320void Renderer::ReleaseTexture(CovelliteGui::TextureHandle _hTexture) /*override*/
321{
322 const auto strTextureId = String_t{ uT("Covellite.Gui.Texture.%ID%") }
323 .Replace(uT("%ID%"), (size_t)_hTexture);
324
325 m_pRenders->Remove(Component_t::Make(
326 {
327 { uT("id"), strTextureId },
328 { uT("type"), uT("Texture") },
329 }));
330}
331
332void Renderer::RenderScene(void)
333{
334 for (const auto & Render : m_DefaultRenders) Render();
335 for (const auto & Render : m_RenderQueue) Render();
336
337 m_RenderQueue.clear();
338}
339
340} // namespace gui
341
342} // namespace covellite