// Copyright (c) 2023 Dominic Masters // // This software is released under the MIT License. // https://opensource.org/licenses/MIT #include "UICanvas.hpp" #include "display/pass/RenderPass.hpp" #include "display/mesh/QuadMesh.hpp" #include "ui/UIElement.hpp" using namespace Dawn; void UICanvas::onInit() { mesh = std::make_shared(); mesh->createBuffers( QUAD_VERTICE_COUNT * UI_SHADER_QUAD_COUNT, QUAD_INDICE_COUNT * UI_SHADER_QUAD_COUNT ); for(int32_t i = 0; i < UI_SHADER_QUAD_COUNT; i++) { QuadMesh::bufferWithIndex( mesh, glm::vec4(0, 0, 1, 1), glm::vec4(0, 0, 1, 1), i * QUAD_VERTICE_COUNT, i * QUAD_INDICE_COUNT, i * QUAD_VERTICE_COUNT ); } } void UICanvas::onDispose() { mesh = nullptr; } std::vector> UICanvas::getPasses( struct RenderPassContext &ctx ) { if(this->elements.empty()) return {}; glm::mat4 projection; glm::mat4 view; // Setup the projection and views data.projection = glm::ortho( 0.0f, ctx.renderTarget->getWidth(), ctx.renderTarget->getHeight(), 0.0f, 0.0f, 1.0f ); data.view = glm::mat4(1.0f); data.model = glm::mat4(1.0f); // Reset the passes this->passes.clear(); this->textureBindings.clear(); this->textures.clear(); quadCount = 0; nextBinding = 0; // Alignment root const glm::vec2 rootPosition = { 0, 0 }; const glm::vec2 rootSize = { ctx.renderTarget->getWidth(), ctx.renderTarget->getHeight() }; const float_t rootScale = 1.0f; // Get the quads for each component auto itComponents = elements.begin(); auto self = std::ref(*this); while(itComponents != elements.end()) { auto component = *itComponents; component->updateAlignment(rootPosition, rootSize, rootScale); component->getQuads(self); ++itComponents; } // Flush the remaining quads flushPass(); return passes; } void UICanvas::addQuad( const glm::vec4 quad, const glm::vec4 uvs, const struct Color color, const enum UIShaderQuadStyle style, const std::shared_ptr text ) { glm::vec4 styleData; styleData[0] = (float_t)style; if(text == nullptr) { styleData[1] = -1; } else { shadertexturebinding_t texture; auto bindingIt = textureBindings.find(text); if(bindingIt == textureBindings.end()) { if(nextBinding >= UI_SHADER_TEXTURE_COUNT) { flushPass(); } textureBindings[text] = nextBinding; textures[nextBinding] = text; data.textures[nextBinding] = nextBinding; texture = nextBinding++; } else { texture = bindingIt->second; } styleData[1] = (float_t)texture; } data.quads[quadCount] = { quad, uvs, color, styleData }; quadCount++; if(quadCount == UI_SHADER_QUAD_COUNT) flushPass(); } void UICanvas::flushPass() { if(quadCount == 0) return; auto pass = createRenderPass( std::ref(*this), data, textures, mesh, MeshDrawMode::TRIANGLES, 0, quadCount * QUAD_INDICE_COUNT ); passes.push_back(pass); quadCount = 0; nextBinding = 0; textures.clear(); textureBindings.clear(); } void UICanvas::addElement(const std::shared_ptr element) { elements.push_back(element); }