Dawn/archive/component/ui/UICanvas.cpp

144 lines
3.2 KiB
C++

// 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>();
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<std::shared_ptr<IRenderPass>> 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<Texture> 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<UIShader, UIShaderData>(
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<UIElement> element) {
elements.push_back(element);
}