sol::constructors<Physics(void), Physics()>(),
"standing", &Physics::standing);
-
- auto gamespace = lua["game"].get_or_create<sol::table>();
- gamespace.set_function("spawn", entitySpawn);
- gamespace.set_function("worldRegister", worldRegister);
+ lua.new_usertype<World>("World",
+ sol::constructors<World(sol::object), World(void)>(),
+ "Generate", &World::generate,
+ "Seed", sol::property(&World::setSeed, &World::getSeed),
+ "setData", &World::setData,
+ "registerMaterial", &World::registerMaterial,
+ "setSize", &World::setSize,
+ "getSize", &World::getSize);
+
- game.set_function("spawn", [this](sol::table t) { return spawn(t); });
+ game = lua["game"].get_or_create<sol::table>();
++ game.set_function("spawn", entitySpawn);
++ game.set_function("worldRegister", worldRegister);
}
sol::table ScriptSystem::spawn(sol::object param)
--- /dev/null
- //FT_Library freetype;
- //std::map<std::string, FT_Face> fonts;
- //std::map<std::string, std::vector<FT_Info>> fontData;
-
+#include "text.hpp"
+
+#include <iostream>
+
- fontData.try_emplace(name, 95);
-
- char c = 32;
- for (auto& d : fontData[name]) {
- FT_Load_Char(face, c++, FT_LOAD_RENDER);
-
- glGenTextures(1, &d.tex);
- glBindTexture(GL_TEXTURE_2D, d.tex);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_LINEAR);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- // convert red-on-black to RGBA
- auto& g = face->glyph;
- std::vector<uint32_t> buf (g->bitmap.width * g->bitmap.rows, 0xFFFFFF);
- for (auto j = buf.size(); j--;)
- buf[j] |= g->bitmap.buffer[j] << 24;
-
- d.wh = { g->bitmap.width, g->bitmap.rows };
- d.bl = { g->bitmap_left, g->bitmap_top };
- d.ad = { g->advance.x >> 6, g->advance.y >> 6 };
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g->bitmap.width, g->bitmap.rows,
- 0, GL_RGBA, GL_UNSIGNED_BYTE, buf.data());
+void TextSystem::configure([[maybe_unused]] entityx::EntityManager& entities,
+ [[maybe_unused]] entityx::EventManager& events)
+{
+ if (FT_Init_FreeType(&freetype) != 0) {
+ // TODO handle error
+ }
+}
+
+/**
+ * Draws the text for all entities.
+ */
+void TextSystem::update([[maybe_unused]] entityx::EntityManager& entites,
+ [[maybe_unused]] entityx::EventManager& events,
+ [[maybe_unused]] entityx::TimeDelta dt)
+{
+ // TODO render each Text component's text
+}
+
+void TextSystem::loadFont(const std::string& name,
+ const std::string& file,
+ int size)
+{
++ // Find or load font at given size
++ //
+
+ if (fonts.find(file) == fonts.end()) {
+ FT_Face face;
+ if (FT_New_Face(freetype, file.c_str(), 0, &face)) {
+ // TODO handle this error
+ }
+ fonts.emplace(file, face);
+ }
+
+ auto& face = fonts[file];
+ FT_Set_Pixel_Sizes(face, 0, size);
- std::cout << "Loaded font: " << file << " (size: " << size << ')'
- << std::endl;
++ fontData.try_emplace(name);
++
++ // Calculate dimensions of final texture
++ //
++
++ float width = 0, height = 0;
++ for (int c = 32; c < 128; c++) {
++ FT_Load_Char(face, c, FT_LOAD_RENDER);
++ width += face->glyph->bitmap.width + 1;
++ height = std::max(height, static_cast<float>(face->glyph->bitmap.rows));
+ }
+
++ // Generate texture to hold entire font
++ //
++
++ auto& font = fontData[name];
++ glGenTextures(1, &font.tex);
++ glGenBuffers(1, &font.vbo);
++ glBindTexture(GL_TEXTURE_2D, font.tex);
++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height,
++ 0, GL_RED, GL_UNSIGNED_BYTE, 0);
++ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++
++ // // convert red-on-black to RGBA
++ // auto& g = face->glyph;
++ // std::vector<uint32_t> buf (g->bitmap.width * g->bitmap.rows, 0xFFFFFF);
++ // for (auto j = buf.size(); j--;)
++ // buf[j] |= g->bitmap.buffer[j] << 24;
++
++ // Load each character and add it to the texture
++ //
++
++ float offsetX = 0, offsetY = 0;
++ for (int c = 32; c < 128; c++) {
++ FT_Load_Char(face, c, FT_LOAD_RENDER);
++
++ auto* g = face->glyph;
++ glTexSubImage2D(GL_TEXTURE_2D, 0, offsetX, offsetY,
++ g->bitmap.width, g->bitmap.rows,
++ GL_RED, GL_UNSIGNED_BYTE,
++ g->bitmap.buffer);
++
++ auto& d = font.data[c - 32];
++ d.dim = { g->bitmap.width, g->bitmap.rows };
++ d.bitmap = { g->bitmap_left, g->bitmap_top };
++ d.advance = { g->advance.x >> 6, g->advance.y >> 6 };
++
++ d.offset = { offsetX / width, offsetY / height };
++ offsetX += g->bitmap.width;
++ // Keep offsetY at zero?
++ }
++
++ std::cout << "Loaded font: " << file << " (size: " << size << ", tex: "
++ << font.tex << ")" << std::endl;
++}
++
++void TextSystem::updateVBOs(void)
++{
++ for (auto& data : fontData) {
++ auto& d = data.second;
++ d.buffer.clear();
++ for (auto& text : d.text) {
++ for (char c : text.text) {
++ if (c < 32)
++ continue;
++
++ d.buffer += {
++ text.x, text.y, text.z,
++ d.data[c].offset.first, d.data[c].offset.second,
++ 1.0f
++ };
++ }
++ }
++
++ glBindBuffer(GL_ARRAY_BUFFER, d.vbo);
++ glBufferData(GL_ARRAY_BUFFER,
++ d.text.size() * sizeof(TextMeshData), d.text.data(),
++ GL_STREAM_DRAW);
++ }
+}
+
--- /dev/null
-
+/**
+ * @file text.hpp
+ * Manages entity text.
+ *
+ * Copyright (C) 2019 Clyne Sullivan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SYSTEM_TEXT_HPP_
+#define SYSTEM_TEXT_HPP_
+
+#include <entityx/entityx.h>
+#include <ft2build.h>
+#include <freetype/freetype.h>
++#include <GL/glew.h>
+#include <SDL2/SDL_opengl.h>
+
- std::pair<float, float> wh;
- std::pair<float, float> bl;
- std::pair<float, float> ad;
- GLuint tex;
+#include <map>
+#include <string>
+#include <tuple>
+#include <vector>
+
++struct TextMeshData
++{
++ float posX, posY, posZ;
++ float texX, texY;
++ float transparency;
++} __attribute__ ((packed));
++
+struct FT_Info {
- FT_Info(void)
- : tex(0) {}
++ std::pair<float, float> offset;
++ std::pair<float, float> dim;
++ std::pair<float, float> bitmap;
++ std::pair<float, float> advance;
++};
+
- /**
- * @class PhysicsSystem
- * Handles the position and velocity updating of all entities
- */
++struct Text {
++ std::string text;
++ float x;
++ float y;
++ float z;
++};
++
++// Stores texture and placement data for a font at a size.
++struct Font {
++ GLuint tex;
++ GLuint vbo;
++
++ std::array<FT_Info, 96> data;
++ // Stores currently shown text at given index into VBO?
++ std::vector<Text> text;
++ std::basic_string<TextMeshData> buffer;
+};
+
- std::map<std::string, std::vector<FT_Info>> fontData;
+class TextSystem : public entityx::System<TextSystem>
+{
+public:
+ /**
+ * Prepares the system for running.
+ */
+ void configure(entityx::EntityManager& entities,
+ entityx::EventManager& events) final;
+
+ /**
+ * Draws the text for all entities.
+ */
+ void update(entityx::EntityManager& entites,
+ entityx::EventManager& events,
+ entityx::TimeDelta dt) final;
+
+ void loadFont(const std::string& name, const std::string& file, int size);
+
+private:
+ FT_Library freetype;
+ std::map<std::string, FT_Face> fonts;
++ std::map<std::string, Font> fontData;
++
++ void updateVBOs(void);
+};
+
+#endif // SYSTEM_TEXT_HPP_
+