summaryrefslogtreecommitdiff
path: root/ui/text.cpp
blob: bdaaba5d6e3d081fb56d7d08688354dd6685944e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "text.h"
#include "font.h"
#include "gfx/gl/uiShader.h"
#include "gfx/gl/vertexArrayObject.h"
#include "uiComponent.h"
#include <array>
#include <collections.h>
#include <glArrays.h>
#include <glm/gtc/type_ptr.hpp>
#include <maths.h>
#include <numeric>
#include <utility>

Text::Text(std::string_view s, const Font & font, Position pos, glm::vec3 c) :
	UIComponent {pos}, colour {c}, font {font}
{
	VertexArrayObject {vao}.addAttribs<Font::Quad::value_type>(quads.bufferName(), 0);
	operator=(s);
}

Text &
Text::operator=(const std::string_view s)
{
	auto tquads = font.render(s);
	models.resize(tquads.size());
	const auto glyphCount = std::accumulate(tquads.begin(), tquads.end(), size_t {}, [](auto && init, const auto & q) {
		return init += q.second.size();
	});
	quads.resize(glyphCount);
	GLushort current = 0;
	auto model = models.begin();
	auto quad = quads.begin();
	for (const auto & [texture, fquads] : tquads) {
		model->textureId = texture;
		model->range.resize(fquads.size() * 6);
		for (auto out = model->range.begin(); const auto & q [[maybe_unused]] : fquads) {
			static constexpr std::array<GLushort, 6> quadIndices {0, 1, 2, 2, 3, 0};
			std::transform(quadIndices.begin(), quadIndices.end(), out, [current](auto x) {
				return current + x;
			});
			current += 4;
			out += 6;
		}
		model++;
		quad = std::transform(fquads.begin(), fquads.end(), quad, [this](const Font::Quad & q) {
			return q * [this](const glm::vec4 & corner) {
				return corner + glm::vec4 {this->position.origin, 0, 0};
			};
		});
	}
	quads.unmap();
	return *this;
}

void
Text::render(const UIShader & shader, const Position &) const
{
	shader.text.use(colour);
	glActiveTexture(GL_TEXTURE0);
	glBindVertexArray(vao);
	for (const auto & m : models) {
		glBindTexture(GL_TEXTURE_2D, m.textureId);
		glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m.range.size()), GL_UNSIGNED_SHORT, m.range.data());
	}
	glBindVertexArray(0);
	glBindTexture(GL_TEXTURE_2D, 0);
}

bool
Text::handleInput(const SDL_Event &, const Position &)
{
	return false;
}