Browse Source

Merge branch 'master' of https://gitgud.io/odilitime/netrunner

pull/2/head
Nubben 5 years ago
parent
commit
d43f6ddf9d
  1. 2
      .gitignore
  2. 1
      README.md
  3. 77
      src/URL.cpp
  4. 10
      src/URL.h
  5. 24
      src/graphics/components/AnimeComponent.cpp
  6. 1
      src/graphics/components/AnimeComponent.h
  7. 169
      src/graphics/components/BoxComponent.cpp
  8. 19
      src/graphics/components/BoxComponent.h
  9. 75
      src/graphics/components/Component.cpp
  10. 22
      src/graphics/components/Component.h
  11. 32
      src/graphics/components/ComponentBuilder.cpp
  12. 1
      src/graphics/components/ComponentBuilder.h
  13. 255
      src/graphics/components/InputComponent.cpp
  14. 24
      src/graphics/components/InputComponent.h
  15. 101
      src/graphics/components/TextComponent.cpp
  16. 20
      src/graphics/components/TextComponent.h
  17. 24
      src/graphics/elements/INPUTElement.cpp
  18. 15
      src/graphics/elements/INPUTElement.h
  19. 320
      src/graphics/opengl/Window.cpp
  20. 8
      src/graphics/opengl/Window.h
  21. 316
      src/graphics/text/TextRasterizer.cpp
  22. 48
      src/graphics/text/TextRasterizer.h
  23. 4
      src/main.cpp
  24. 233
      visualc/NetRunner/NetRunner.vcxproj
  25. 264
      visualc/NetRunner/NetRunner.vcxproj.filters
  26. 13
      visualc/NetRunner/NetRunner.vcxproj.user

2
.gitignore vendored

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
d
gen
src/graphics/opengl/shaders/gen
netrunner
/netrunner
*.iml
tags
src/networking/URI

1
README.md

@ -77,6 +77,7 @@ I don't think one on here could ever say they know what their doing without bein @@ -77,6 +77,7 @@ I don't think one on here could ever say they know what their doing without bein
- Tomleb
- contributed keyboard code
- repo: https://github.com/tomleb/netrunner
- RetroTech - Web / Sys Admin
- Created original website

77
src/URL.cpp

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
*
*/
enum uri_parse_state {
enum URIParseState {
SCHEME,
FIRST_SLASH,
SECOND_SLASH_OR_ELSE,
@ -27,17 +27,27 @@ enum uri_parse_state { @@ -27,17 +27,27 @@ enum uri_parse_state {
FRAGMENT,
};
std::unique_ptr<URL> parseUri(std::string raw) {
// TODO
bool isValidCharacter(char c);
bool isValidCharacter(char c) {
return true;
}
// put inside URL(std::string) constructor?
std::tuple<std::unique_ptr<URL>,enum URIParseError> parseUri(std::string raw) {
std::unique_ptr<URL> uri = std::make_unique<URL>();
uri->path = "/";
unsigned int cursor = 0;
unsigned int last = 0;
unsigned int last_semicolon = 0;
enum uri_parse_state state = SCHEME;
unsigned int lastSemicolon = 0;
bool isPercentEncoded = true;
enum URIParseState state = SCHEME;
// TODO Validate at the end that every field were defined (ie: http:// is valid, but it's clearly not)
// Remember file:// doesn't need a port (for end validation)
// First character of scheme MUST be alphabetic
if (!isalpha(raw[cursor])) {
std::cout << "parse scheme error" << std::endl;
return NULL;
std::cerr << "invalid scheme: '" << raw.substr(last, cursor - last+1) << "'" << std::endl;
return std::make_tuple(std::move(uri), URI_PARSE_ERROR_SCHEME);
}
for (cursor = 1; cursor < raw.length(); cursor++) {
/* TODO
@ -54,27 +64,35 @@ std::unique_ptr<URL> parseUri(std::string raw) { @@ -54,27 +64,35 @@ std::unique_ptr<URL> parseUri(std::string raw) {
state = FIRST_SLASH;
} else if (!isalpha(raw[cursor]) && !isdigit(raw[cursor]) && raw[cursor] != '+' &&
raw[cursor] != '-' && raw[cursor] != '.') {
std::cout << "parse scheme error" << std::endl;
return NULL;
/* URI MUST have a scheme */
std::cerr << "invalid scheme: '" << raw.substr(last, cursor - last+1) << "'" << std::endl;
return std::make_tuple(std::move(uri), URI_PARSE_ERROR_SCHEME);
}
} else if (state == FIRST_SLASH) {
if (raw[cursor] == '/') {
state = SECOND_SLASH_OR_ELSE;
} else {
std::cout << "parse error" << std::endl;
std::cerr << "missing '/' after scheme" << std::endl;
return std::make_tuple(std::move(uri), URI_PARSE_ERROR_SCHEME);
}
} else if (state == SECOND_SLASH_OR_ELSE) {
if (raw[cursor] == '/') {
last = cursor + 1;
state = AUTHORITY;
if (uri->scheme == "file") {
std::cout << "file scheme, current path[" << uri->path << "]" << std::endl;
state = PATH;
}
} else {
// TODO Handle this, URI may have only one slash
std::cerr << "URI with only one '/' not currently supported" << std::endl;
return std::make_tuple(std::move(uri), URI_PARSE_ERROR_SCHEME);
}
} else if (state == AUTHORITY) {
/* At this point, this could either be the semi colon for
* the password or for the port*/
if (raw[cursor] == ':') {
last_semicolon = cursor;
lastSemicolon = cursor;
} else if (raw[cursor] == '@') {
uri->userinfo = raw.substr(last, cursor - last);
last = cursor + 1;
@ -83,12 +101,12 @@ std::unique_ptr<URL> parseUri(std::string raw) { @@ -83,12 +101,12 @@ std::unique_ptr<URL> parseUri(std::string raw) {
// TODO terminated by the next slash ("/"), question mark ("?"), or number sign ("#") character, or by the end of the URI.
// What to do when ? and # ?
} else if (raw[cursor] == '/') {
if (last_semicolon > 0) {
if (lastSemicolon > 0) {
// TODO Validate port
if (cursor - last_semicolon - 1 > 0) {
uri->port = std::stoi(raw.substr(last_semicolon+1, cursor - last_semicolon+1));
if (cursor - lastSemicolon - 1 > 0) {
uri->port = std::stoi(raw.substr(lastSemicolon+1, cursor - lastSemicolon+1));
}
uri->host = raw.substr(last, last_semicolon - last);
uri->host = raw.substr(last, lastSemicolon - last);
} else {
uri->host = raw.substr(last, cursor - last);
}
@ -104,10 +122,17 @@ std::unique_ptr<URL> parseUri(std::string raw) { @@ -104,10 +122,17 @@ std::unique_ptr<URL> parseUri(std::string raw) {
state = FRAGMENT;
}
} else if (cursor + 1 == raw.length()) {
uri->host = raw.substr(last, last_semicolon - last);
uri->host = raw.substr(last, lastSemicolon - last);
uri->path = "/";
break;
} else {
if (isPercentEncoded && !isValidCharacter(raw[cursor])) {
isPercentEncoded = false;
}
}
// TODO Accept Ipv weirdness (ipversion and literal)
/* We are accepting pretty much anything here.. However not everything
* is valid. Should we try to validate at this point ? */
} else if (state == AUTHORITY_HOST) {
if (raw[cursor] == ':') {
uri->host = raw.substr(last, cursor - last);
@ -118,17 +143,24 @@ std::unique_ptr<URL> parseUri(std::string raw) { @@ -118,17 +143,24 @@ std::unique_ptr<URL> parseUri(std::string raw) {
last = cursor;
cursor--;
state = PATH;
} else {
if (isPercentEncoded && !isValidCharacter(raw[cursor])) {
isPercentEncoded = false;
}
}
} else if (state == AUTHORITY_PORT) {
if (raw[cursor] == '/') {
if (cursor - last > 0) {
/* RFC doesn't specify the max port number, so at this point
* just accept it. */
uri->port = std::stoi(raw.substr(last, cursor - last));
}
last = cursor;
cursor--;
state = PATH;
} else if (!isdigit(raw[cursor])) {
std::cerr << "invalid port: '" << raw.substr(last, cursor - last + 1) << "'" << std::endl;
return std::make_tuple(std::move(uri), URI_PARSE_ERROR_PORT);
}
} else if (state == PATH) {
if (raw[cursor] == '?' || raw[cursor] == '#') {
@ -159,7 +191,7 @@ std::unique_ptr<URL> parseUri(std::string raw) { @@ -159,7 +191,7 @@ std::unique_ptr<URL> parseUri(std::string raw) {
}
}
}
return uri;
return std::make_tuple(std::move(uri), URI_PARSE_ERROR_NONE);
}
@ -178,6 +210,7 @@ URL::URL(std::string const& url) { @@ -178,6 +210,7 @@ URL::URL(std::string const& url) {
}
std::string URL::toString() const {
std::cout << "scheme[" << scheme << "] host[" << host << "] path [" << path << "]" << std::endl;
if (isRelative()) {
return path;
}
@ -224,7 +257,13 @@ URL URL::merge(URL const& url) const { @@ -224,7 +257,13 @@ URL URL::merge(URL const& url) const {
}
void URL::construct(std::string const& url) {
std::unique_ptr<URL> uri=parseUri(url);
auto result = parseUri(url);
if (std::get<1>(result) != URI_PARSE_ERROR_NONE) {
// TODO We probably wanna handle this better..
std::cerr << "error parsing uri" << std::endl;
return;
}
std::unique_ptr<URL> uri = std::move(std::get<0>(result));
scheme = uri->scheme;
userinfo = uri->userinfo;
host = uri->host;
@ -246,7 +285,7 @@ void URL::construct(std::string const& url) { @@ -246,7 +285,7 @@ void URL::construct(std::string const& url) {
if (path.size() == 0) {
path = "/";
}
*/
*/
}
URL URL::copy() const {

10
src/URL.h

@ -5,10 +5,10 @@ @@ -5,10 +5,10 @@
#include <memory>
#include <iostream>
struct Authority {
std::string userinfo;
std::string host;
int port;
enum URIParseError {
URI_PARSE_ERROR_SCHEME,
URI_PARSE_ERROR_PORT,
URI_PARSE_ERROR_NONE,
};
struct URL {
@ -34,7 +34,7 @@ private: @@ -34,7 +34,7 @@ private:
URL copy() const;
};
std::unique_ptr<URL> parseUri(std::string raw);
std::tuple<std::unique_ptr<URL>,enum URIParseError> parseUri(std::string raw);
std::ostream& operator<<(std::ostream& out, URL const& url);
#endif

24
src/graphics/components/AnimeComponent.cpp

@ -3,31 +3,37 @@ @@ -3,31 +3,37 @@
#include "../../../anime.h"
#endif
#include <cmath>
#include <iostream>
AnimeComponent::AnimeComponent(const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int passedWindowWidth, const int passedWindowHeight) : BoxComponent(rawX, rawY, rawWidth, rawHeight, passedWindowWidth, passedWindowHeight){
//std::cout << "AnimeComponent::AnimeComponent" << std::endl;
windowWidth = passedWindowWidth;
windowHeight = passedWindowHeight;
x = rawX;
y = rawY;
width = rawWidth;
height = rawHeight;
for (int py = 0; py < 1024; py++) {
for (int px = 0; px < 1024; px++) {
#ifndef _MSC_VER
if (width == 512) {
for (int py = 0; py < 1024; py++) {
for (int px = 0; px < 1024; px++) {
for (int i = 0; i < 4; i++) {
data[1023 - py][px][i] = anime.pixel_data[((px * 4) + (py * 4 * 1024)) + i];
}
for (int i = 0; i < 4; i++) {
data[1023 - py][px][i] = anime.pixel_data[((px * 4) + (py * 4 * 1024)) + i];
}
#else
data[1023 - py][px][3] = 0x00; // just make it all transparent for now
#endif
}
}
#endif
float vx = rawX;
float vy = rawY;
float vWidth = rawWidth;
float vHeight = rawHeight;
pointToViewport(vx, vy, windowWidth, windowHeight);
distanceToViewport(vWidth, vHeight, windowWidth, windowHeight);
pointToViewport(vx, vy);
distanceToViewport(vWidth, vHeight);
vertices[(0 * 5) + 0] = vx;
vertices[(0 * 5) + 1] = vy + vHeight;

1
src/graphics/components/AnimeComponent.h

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
class AnimeComponent : public BoxComponent {
public:
AnimeComponent(const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int passedWindowWidth, const int passedWindowHeight);
unsigned char data[1024][1024][4];
};
#endif

169
src/graphics/components/BoxComponent.cpp

@ -2,26 +2,43 @@ @@ -2,26 +2,43 @@
#include <cmath>
#include <iostream>
BoxComponent::BoxComponent() {
//std::cout << "BoxComponent::BoxComponent - empty" << std::endl;
}
BoxComponent::BoxComponent(const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int passedWindowWidth, const int passedWindowHeight) {
x = rawX;
y = rawY;
//std::cout << "BoxComponent::BoxComponent - data" << std::endl;
//std::cout << "BoxComponent::BoxComponent - window: " << windowWidth << "x" << windowHeight << " passed " << passedWindowWidth << "x" << passedWindowHeight << std::endl;
boundToPage = false;
// set up state
windowWidth = passedWindowWidth;
windowHeight = passedWindowHeight;
width = rawWidth;
height = rawHeight;
for (int py = 0; py < 1024; py++) {
for (int px = 0; px < 1024; px++) {
for (int i = 0; i < 3; i++) {
data[1023 - py][px][i] = 0x88;
}
data[1023 - py][px][3] = 0xff;
}
x = rawX;
y = rawY;
// copy initial state
initialX = x;
initialY = y;
initialWidth = width;
initialHeight = height;
initialWindowWidth = windowWidth;
initialWindowHeight = windowHeight;
for (int i = 0; i < 3; i++) {
data[0][0][i] = 0x88; // set RGB color
}
data[0][0][3] = 0xff; // set alpha
float vx = rawX;
float vy = rawY;
//std::cout << "placing box at " << (int)vx << "x" << (int)vy << " size: " << (int)rawWidth << "x" << (int)rawHeight << std::endl;
float vWidth = rawWidth;
float vHeight = rawHeight;
pointToViewport(vx, vy, windowWidth, windowHeight);
pointToViewport(vx, vy);
/*
// if has rawWidth > 1
@ -40,8 +57,10 @@ BoxComponent::BoxComponent(const float rawX, const float rawY, const float rawWi @@ -40,8 +57,10 @@ BoxComponent::BoxComponent(const float rawX, const float rawY, const float rawWi
*/
// converts 512 to 1 and 1 to 2
//std::cout << "vWidth before: " << (int)vWidth << std::endl;
distanceToViewport(vWidth, vHeight, windowWidth, windowHeight);
distanceToViewport(vWidth, vHeight);
//std::cout << "vWidth after: " << (int)vWidth << std::endl;
//std::cout << "placing box at GL " << (int)vx << "x" << (int)vy << " size: " << (int)(vWidth*10000) << "x" << (int)(vHeight*10000) << std::endl;
vertices[(0 * 5) + 0] = vx;
vertices[(0 * 5) + 1] = vy + vHeight;
@ -73,8 +92,10 @@ BoxComponent::BoxComponent(const float rawX, const float rawY, const float rawWi @@ -73,8 +92,10 @@ BoxComponent::BoxComponent(const float rawX, const float rawY, const float rawWi
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindVertexArray(0); // protect what we created against any further modification
}
BoxComponent::~BoxComponent() {
@ -85,60 +106,94 @@ BoxComponent::~BoxComponent() { @@ -85,60 +106,94 @@ BoxComponent::~BoxComponent() {
}
void BoxComponent::render() {
//std::cout << "BoxComponent::render" << std::endl;
GLenum glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "BoxComponent::render - start not ok: " << glErr << std::endl;
}
if (verticesDirty) {
//std::cout << "BoxComponent::render - update dirty vertex" << std::endl;
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "BoxComponent::render - glBindBuffer not ok: " << glErr << std::endl;
}
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "BoxComponent::render - glBufferData not ok: " << glErr << std::endl;
}
verticesDirty = false;
}
glBindVertexArray(vertexArrayObject);
glBindTexture(GL_TEXTURE_2D, texture);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
}
void BoxComponent::resize() {
float vx = x;
float vy = y;
float vWidth = width;
float vHeight = height;
pointToViewport(vx, vy, windowWidth, windowHeight);
distanceToViewport(vWidth, vHeight, windowWidth, windowHeight);
vertices[(0 * 5) + 0] = vx;
vertices[(0 * 5) + 1] = vy + vHeight;
vertices[(1 * 5) + 0] = vx + vWidth;
vertices[(1 * 5) + 1] = vy + vHeight;
vertices[(2 * 5) + 0] = vx + vWidth;
vertices[(2 * 5) + 1] = vy;
vertices[(3 * 5) + 0] = vx;
vertices[(3 * 5) + 1] = vy;
verticesDirty = true;
}
void BoxComponent::pointToViewport(float &rawX, float &rawY, const int passedWindowWidth, const int passedWindowHeight) const {
if (rawX < 0) {
rawX += windowWidth;
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "BoxComponent::render - glBindVertexArray not ok: " << glErr << std::endl;
}
if (rawY < 0) {
rawY += windowHeight;
}
if (rawX > 1) {
rawX /= windowWidth;
glBindTexture(GL_TEXTURE_2D, texture);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "BoxComponent::render - glBindTexture not ok: " << glErr << std::endl;
}
if (rawY > 1) {
rawY /= windowHeight;
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "BoxComponent::render - glDrawElements not ok: " << glErr << std::endl;
}
rawX = (rawX * 2) - 1;
rawY = (rawY * 2) - 1;
glBindVertexArray(0);
// can actuall delete vertices here
}
void BoxComponent::distanceToViewport(float &rawX, float &rawY, const int passedWindowWidth, const int passedWindowHeight) const {
if (std::abs(rawX) > 1) {
rawX /= windowWidth;
}
if (std::abs(rawY) > 1) {
rawY /= windowHeight;
/*
void BoxComponent::resize(const int passedWindowWidth, const int passedWindowHeight) {
std::cout << "BoxComponent::resize" << std::endl;
windowWidth = passedWindowWidth;
windowHeight = passedWindowHeight;
if (boundToPage) {
std::cout << "BoxComponent::resize - boundToPage doing nothing" << std::endl;
} else {
// figure out our percentages
// 0 / WW = 0
// 768 / 1024 = 75%
float xPer = initialX / (float)initialWindowWidth;
float yPer = initialY / (float)initialWindowHeight;
// adjust width
float wPer = initialWidth / (float)initialWindowWidth;
//float hPer = initialHeight / (float)initialWindowHeight;
float vx = xPer * windowWidth;
float vy = yPer * windowHeight;
// nah I don't think we want things to stretch
//float vWidth = wPer * windowWidth;
//float vHeight = hPer * windowHeight;
// ugh these just need to be relaid out
//float vWidth = width;
float vWidth = wPer * windowWidth;
float vHeight = height;
//std::cout << "initial: " << initialX << "x" << initialY << " size: " << initialWidth << "x" << initialHeight << " window size: " << initialWindowWidth << "x" << initialWindowHeight << std::endl;
//std::cout << "scaled to: " << (int)vx << "x" << (int)vy << " size: " << (int)vWidth << "x" << (int)vHeight << " window size: " << windowWidth << "x" << windowHeight << std::endl;
pointToViewport(vx, vy);
distanceToViewport(vWidth, vHeight);
vertices[(0 * 5) + 0] = vx;
vertices[(0 * 5) + 1] = vy + vHeight;
vertices[(1 * 5) + 0] = vx + vWidth;
vertices[(1 * 5) + 1] = vy + vHeight;
vertices[(2 * 5) + 0] = vx + vWidth;
vertices[(2 * 5) + 1] = vy;
vertices[(3 * 5) + 0] = vx;
vertices[(3 * 5) + 1] = vy;
verticesDirty = true;
}
rawX *= 2;
rawY *= 2;
}
*/

19
src/graphics/components/BoxComponent.h

@ -12,22 +12,23 @@ protected: @@ -12,22 +12,23 @@ protected:
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f
};
const unsigned int indices[6] = {
0, 1, 2,
0, 2, 3
};
unsigned char data[1024][1024][4];
unsigned char data[1][1][4];
GLuint vertexArrayObject = 0;
GLuint vertexBufferObject = 0;
GLuint elementBufferObject = 0;
GLuint texture = 0;
int initialX;
int initialY;
int initialWidth;
int initialHeight;
int initialWindowWidth;
int initialWindowHeight;
public:
BoxComponent();
BoxComponent(const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int passedWindowWidth, const int passedWindowHeight);
~BoxComponent();
void render();
void resize();
void pointToViewport(float &rawX, float &rawY, const int passedWindowWidth, const int passedWindowHeight) const ;
void distanceToViewport(float &rawX, float &rawY, const int passedWindowWidth, const int passedWindowHeight) const ;
virtual void render();
//void resize(const int passedWindowWidth, const int passedWindowHeight);
};
#endif

75
src/graphics/components/Component.cpp

@ -1,12 +1,43 @@ @@ -1,12 +1,43 @@
#include "Component.h"
#include <iostream>
#include <algorithm>
#include <cmath>
#include "TextComponent.h"
Component::~Component() {
}
void Component::resize() {
void Component::resize(const int passedWindowWidth, const int passedWindowHeight) {
//std::cout << "Component::resize" << std::endl;
windowWidth = passedWindowWidth;
windowHeight = passedWindowHeight;
/*
if (boundToPage) {
} else {
*/
// no vertices in component
/*
float vx = x;
float vy = y;
float vWidth = width;
float vHeight = height;
pointToViewport(vx, vy);
distanceToViewport(vWidth, vHeight);
vertices[(0 * 5) + 0] = vx;
vertices[(0 * 5) + 1] = vy + vHeight;
vertices[(1 * 5) + 0] = vx + vWidth;
vertices[(1 * 5) + 1] = vy + vHeight;
vertices[(2 * 5) + 0] = vx + vWidth;
vertices[(2 * 5) + 1] = vy;
vertices[(3 * 5) + 0] = vx;
vertices[(3 * 5) + 1] = vy;
verticesDirty = true;
*/
//}
}
void Component::setParent(std::shared_ptr<Component> passedParent) {
@ -133,7 +164,7 @@ void Component::layout() { @@ -133,7 +164,7 @@ void Component::layout() {
void Component::wrap() {
float lW = width;
float lH = height;
resize(); // this may change our w/h
resize(windowWidth, windowHeight); // this may change our w/h
textureSetup = true;
if (lW != width || lH != height) {
//std::cout << "Component::wrap - component was " << (int)lW << "x" << (int)lH << " now " << (int)width << "x" << (int)height << std::endl;
@ -210,3 +241,43 @@ void Component::updateParentSize() { @@ -210,3 +241,43 @@ void Component::updateParentSize() {
parent->updateParentSize(); // our parent size can only be recalculated by looking at it's children
}
}
// converts 0-1 to screen
// but centered
void Component::pointToViewport(float &rawX, float &rawY) const {
if (boundToPage) {
//std::cout << "BoundToPage using " << screenWidth << "x" << screenHeight << std::endl;
rawX = ((rawX / windowWidth) * 2) - 1;
rawY = ((rawY / windowHeight) * 2) - 1;
} else {
//std::cout << "notBoundToPage using " << screenWidth << "x" << screenHeight << std::endl;
if (rawX < 0) {
rawX += windowWidth;
}
if (rawY < 0) {
rawY += windowHeight;
}
if (rawX > 1) {
rawX /= windowWidth;
}
if (rawY > 1) {
rawY /= windowHeight;
}
rawX = (rawX * 2) - 1;
rawY = (rawY * 2) - 1;
}
}
// keeps 0-1 (and *2 to convert to screen)
// but also takes pixels (and converts to screen)
// anchors to upperleft
void Component::distanceToViewport(float &rawX, float &rawY) const {
if (std::abs(rawX) > 1) {
rawX /= windowWidth;
}
if (std::abs(rawY) > 1) {
rawY /= windowHeight;
}
rawX *= 2;
rawY *= 2;
}

22
src/graphics/components/Component.h

@ -12,6 +12,9 @@ struct rgba { @@ -12,6 +12,9 @@ struct rgba {
unsigned int a;
};
// should have 2 classes after this
// non-rendererable component (wtf are these?)
// and renderable component
class Component {
public:
virtual ~Component();
@ -30,8 +33,12 @@ public: @@ -30,8 +33,12 @@ public:
// since we update the window size before resize, why just not pass it
// well no need to pass it if it's just a window* and then we'd already have it
// but we may hang onto the variables to know what the state is set up for
virtual void resize();
// why pass it here? on resize we call layout no this...
virtual void resize(const int passedWindowWidth, const int passedWindowHeight);
void pointToViewport(float &rawX, float &rawY) const ;
void distanceToViewport(float &rawX, float &rawY) const ;
// HELP I'M LOOKING FOR YOUR OPINION
// a ptr to window would be less memory
// but it would increase Component's depenedencies
@ -46,7 +53,11 @@ public: @@ -46,7 +53,11 @@ public:
*/
int windowWidth;
int windowHeight;
bool boundToPage = true;
const unsigned int indices[6] = {
0, 1, 2,
0, 2, 3
};
bool verticesDirty = false;
std::shared_ptr<Component> parent = nullptr;
std::shared_ptr<Component> previous = nullptr;
@ -69,7 +80,7 @@ public: @@ -69,7 +80,7 @@ public:
float reqHeight = 0.0f;
float reqWidth = 0.0f;
unsigned int reqMinHeight = 0;
unsigned int reqMinWidth = 0.;
unsigned int reqMinWidth = 0;
unsigned int reqMaxHeight = 0;
unsigned int reqMaxWidth = 0;
// margin
@ -93,7 +104,12 @@ public: @@ -93,7 +104,12 @@ public:
bool isVisibile = true;
bool isInline = false; // text-only thing but there maybe other non-text inline
bool textureSetup = false;
// probably shoudl be vector (or maybe use the event emitter)
std::function<void(int x, int y)> onMousedown = nullptr;
std::function<void(int x, int y)> onMouseup = nullptr;
std::function<void()> onClick = nullptr;
std::function<void()> onFocus = nullptr;
std::function<void()> onBlur = nullptr;
};
#endif

32
src/graphics/components/ComponentBuilder.cpp

@ -14,6 +14,7 @@ const std::unordered_map<std::string, std::shared_ptr<Element>> ComponentBuilder @@ -14,6 +14,7 @@ const std::unordered_map<std::string, std::shared_ptr<Element>> ComponentBuilder
{"div", std::make_shared<DIVElement>()},
{"br", std::make_shared<DIVElement>()},
{"strong", std::make_shared<STRONGElement>()},
{"input", std::make_shared<INPUTElement>()},
{"b", std::make_shared<STRONGElement>()}
};
@ -26,8 +27,7 @@ std::shared_ptr<Component> ComponentBuilder::build(const std::shared_ptr<Node> n @@ -26,8 +27,7 @@ std::shared_ptr<Component> ComponentBuilder::build(const std::shared_ptr<Node> n
if (tagNode) {
tag = tagNode->tag;
}
}
else if (node->nodeType == NodeType::TEXT) {
} else if (node->nodeType == NodeType::TEXT) {
TagNode *tagNode = dynamic_cast<TagNode*>(node->parent.get());
if (tagNode) {
tag = tagNode->tag;
@ -35,7 +35,7 @@ std::shared_ptr<Component> ComponentBuilder::build(const std::shared_ptr<Node> n @@ -35,7 +35,7 @@ std::shared_ptr<Component> ComponentBuilder::build(const std::shared_ptr<Node> n
}
bool isInline = false;
std::unordered_map<std::string, std::shared_ptr<Element>>::const_iterator elementPair = elementMap.find(tag);
if (elementPair != elementMap.end()) {
std::shared_ptr<Element> element = elementPair->second;
@ -53,14 +53,28 @@ std::shared_ptr<Component> ComponentBuilder::build(const std::shared_ptr<Node> n @@ -53,14 +53,28 @@ std::shared_ptr<Component> ComponentBuilder::build(const std::shared_ptr<Node> n
}
if (!component) {
//std::cout << "tag [" << tag << "] didn't yeild any component" << std::endl;
component = std::make_unique<Component>();
}
/*
TextComponent *textComponent = dynamic_cast<TextComponent*>(component.get());
if (textComponent) {
std::cout << "compositing [" << textComponent->text << "]" << std::endl;
//std::cout << "compositing [" << textComponent->text << "]" << std::endl;
component->onMousedown = [component](int x, int y) {
std::cout << "TextSelection starting at " << x << "," << y << std::endl;
// 0 to -640 (windowHeight)
// so if y=640 , f(y)=-640
int ny = -y;
std::cout << "TextSelection adjusted " << x << "," << ny << std::endl;
std::cout << "Component at " << static_cast<int>(component->x) << "," << static_cast<int>(component->y) << std::endl;
};
component->onMouseup = [component](int x, int y) {
std::cout << "TextSelection ending at " << x << "," << y << std::endl;
};
}
InputComponent *inputComponent = dynamic_cast<InputComponent*>(component.get());
if (inputComponent) {
// any input set up we need to do?
}
*/
//std::cout << "composting component, initial: " << (int)component->width << "x" << (int)component->height << std::endl;
// set our available dimensions
@ -80,6 +94,12 @@ std::shared_ptr<Component> ComponentBuilder::build(const std::shared_ptr<Node> n @@ -80,6 +94,12 @@ std::shared_ptr<Component> ComponentBuilder::build(const std::shared_ptr<Node> n
// figure out our position, size, texture
component->layout();
/*
InputComponent *inputComponent = dynamic_cast<InputComponent*>(component.get());
if (inputComponent) {
std::cout << "ComponentBuilder::build - Just laid out input component" << std::endl;
}
*/
//std::cout << "post layout placed: " << (int)component->x << "x" << (int)component->y << " w/h: " << (int)component->width << "x" << (int)component->height << std::endl;
return component;

1
src/graphics/components/ComponentBuilder.h

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
#include "../elements/SPANElement.h"
#include "../elements/DIVElement.h"
#include "../elements/STRONGElement.h"
#include "../elements/INPUTElement.h"
#include "../../html/TagNode.h"
#include "../../html/TextNode.h"
#include "../../html/Node.h"

255
src/graphics/components/InputComponent.cpp

@ -0,0 +1,255 @@ @@ -0,0 +1,255 @@
#include "InputComponent.h"
#include <iostream>
#include "../opengl/Window.h"
#include "../text/TextRasterizerCache.h"
extern TextRasterizerCache *rasterizerCache;
// : BoxComponent(rawX, rawY, rawWidth, rawHeight, passedWindowWidth, passedWindowHeight)
InputComponent::InputComponent(const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int passedWindowWidth, const int passedWindowHeight) {
//std::cout << "InputComponent::InputComponent - data" << std::endl;
//std::cout << "InputComponent::InputComponent - window: " << windowWidth << "x" << windowHeight << " passed " << passedWindowWidth << "x" << passedWindowHeight << std::endl;
boundToPage = true;
// set up state
windowWidth = passedWindowWidth;
windowHeight = passedWindowHeight;
width = rawWidth;
height = rawHeight;
x = rawX;
y = rawY;
// copy initial state
initialX = x;
initialY = y;
initialWidth = width;
initialHeight = height;
initialWindowWidth = windowWidth;
initialWindowHeight = windowHeight;
for (int i = 0; i < 3; i++) {
data[0][0][i] = 0xf0; // set RGB color
}
data[0][0][3] = 0xff; // set alpha
float vx = rawX;
float vy = rawY;
//std::cout << "placing box at " << (int)vx << "x" << (int)vy << " size: " << (int)rawWidth << "x" << (int)rawHeight << std::endl;
float vWidth = rawWidth;
float vHeight = rawHeight;
pointToViewport(vx, vy);
// converts 512 to 1 and 1 to 2
//std::cout << "vWidth before: " << (int)vWidth << std::endl;
distanceToViewport(vWidth, vHeight);
//std::cout << "vWidth after: " << (int)vWidth << std::endl;
//std::cout << "placing box at GL " << (int)vx << "x" << (int)vy << " size: " << (int)(vWidth*10000) << "x" << (int)(vHeight*10000) << std::endl;
vertices[(0 * 5) + 0] = vx;
vertices[(0 * 5) + 1] = vy + vHeight;
vertices[(1 * 5) + 0] = vx + vWidth;
vertices[(1 * 5) + 1] = vy + vHeight;
vertices[(2 * 5) + 0] = vx + vWidth;
vertices[(2 * 5) + 1] = vy;
vertices[(3 * 5) + 0] = vx;
vertices[(3 * 5) + 1] = vy;
glGenVertexArrays(1, &vertexArrayObject);
glGenBuffers(1, &vertexBufferObject);
glGenBuffers(1, &elementBufferObject);
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObject);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), reinterpret_cast<void*>(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindVertexArray(0); // protect what we created against any further modification
}
void InputComponent::render() {
//std::cout << "InputComponent::render" << std::endl;
GLenum glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "InputComponent::render - start not ok: " << glErr << std::endl;
}
if (verticesDirty) {
//std::cout << "BoxComponent::render - update dirty vertex" << std::endl;
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "InputComponent::render - glBindBuffer not ok: " << glErr << std::endl;
}
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "InputComponent::render - glBufferData not ok: " << glErr << std::endl;
}
verticesDirty = false;
}
glBindVertexArray(vertexArrayObject);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "InputComponent::render - glBindVertexArray not ok: " << glErr << std::endl;
}
glBindTexture(GL_TEXTURE_2D, texture);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "InputComponent::render - glBindTexture not ok: " << glErr << std::endl;
}
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glErr=glGetError();
if(glErr != GL_NO_ERROR) {
std::cout << "InputComponent::render - glDrawElements not ok: " << glErr << std::endl;
}
glBindVertexArray(0);
// can actuall delete vertices here
if (userInputText) {
glUseProgram(window->fontProgram);
//std::cout << "rendering some text" << std::endl;
userInputText->render();
glUseProgram(window->textureProgram);
}
}
void InputComponent::resize(const int passedWindowWidth, const int passedWindowHeight) {
//std::cout << "InputComponent::resize" << std::endl;
//std::cout << "InputComponent::resize - rasterizing at " << (int)x << "x" << (int)y << " size: " << (int)width << "x" << (int)height << std::endl;
// maybe already done at component::resize
// set up state
windowWidth = passedWindowWidth;
windowHeight = passedWindowHeight;
// turning this off breaks coordinates
boundToPage = false;
for (int i = 0; i < 3; i++) {
data[0][0][i] = 0xf0; // set RGB color
}
data[0][0][3] = 0xff; // set alpha
float vx = x;
float vy = y;
float vx1 = x + width;
float vy1 = y - height;
/*
std::cout << "placing box at " << (int)vx << "," << (int)vy << " size: " << (int)width << "x" << (int)height << " v1: " << (int)vx1 << "," << (int)vy1 << std::endl;
//float vWidth = width;
//float vHeight = height;
boundToPage = true;
pointToViewport(vx, vy);
pointToViewport(vx1, vy1);
std::cout << "TRUE placing box at GL v: " << vx << "," << vy << " v1: " << vx1 << "," << vy1 << std::endl;
vx = x;
vy = y;
vx1 = x + width;
vy1 = y - height;
boundToPage = false;
*/
pointToViewport(vx, vy);
pointToViewport(vx1, vy1);
//std::cout << "FALSE placing box at GL v: " << vx << "," << vy << " v1: " << vx1 << "," << vy1 << std::endl;
// converts 512 to 1 and 1 to 2
//std::cout << "vWidth before: " << (int)vWidth << std::endl;
//distanceToViewport(vWidth, vHeight);
//std::cout << "vWidth after: " << (int)vWidth << std::endl;
vertices[(0 * 5) + 0] = vx;
vertices[(0 * 5) + 1] = vy1;
vertices[(1 * 5) + 0] = vx1;
vertices[(1 * 5) + 1] = vy1;
vertices[(2 * 5) + 0] = vx1;
vertices[(2 * 5) + 1] = vy;
vertices[(3 * 5) + 0] = vx;
vertices[(3 * 5) + 1] = vy;
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObject);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindVertexArray(0); // protect what we created against any further modification
}
void InputComponent::addChar(char c) {
value+=c;
//std::cout << "input value is now: " << value << std::endl;
if (userInputText) {
delete userInputText;
}
//std::cout << "InputComponent::addChar - at " << (int)x << "," << (int)y << std::endl;
updateText();
}
void InputComponent::backSpace() {
value=value.substr(0, value.length() - 1);
if (userInputText) {
delete userInputText;
}
//std::cout << "InputComponent::addChar - at " << (int)x << "," << (int)y << std::endl;
updateText();
}
void InputComponent::updateText() {
userInputText=new TextComponent(value, 0, 0, 12, false, 0x000000FF, windowWidth, windowHeight);
userInputText->x = x;
userInputText->y = y;
// 125 pixels width
// but first we need to know how wide the text is
const std::shared_ptr<TextRasterizer> textRasterizer=rasterizerCache->loadFont(12, false); // fontSize, bold
rasterizationRequest request;
request.text = value;
request.startX = x;
request.availableWidth = windowWidth;
request.sourceStartX = 0;
request.sourceStartY = 0;
request.noWrap = true;
std::unique_ptr<std::pair<int, int>> textInfo=textRasterizer->size(request);
if (textInfo.get() == nullptr) {
std::cout << "InputComponent::updateText couldn't estimate value[" << value << "] size" << std::endl;
return;
}
int estWidth = std::get<0>(*textInfo.get());
//int estHeight = std::get<1>(*textInfo.get());
userInputText->rasterStartX = 0;
userInputText->rasterStartY = 0;
//std::cout << "estWidth: " << estWidth << " width: " << static_cast<int>(width) << std::endl;
if (estWidth > width) {
//std::cout << "scrolling text" << std::endl;
userInputText->rasterStartX = estWidth - width;
}
userInputText->noWrap = true;
// FIXME: not really 125, if we're x>windowWidth-125
// why does changing the width mess shit up?
//std::cout << "our width: " << static_cast<int>(width) << " windowWidth: " << windowWidth << std::endl;
userInputText->resize(windowWidth, windowHeight, 125); // need to make sure there's a texture
window->renderDirty = true;
}

24
src/graphics/components/InputComponent.h

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
#ifndef INPUTCOMPONENT_H
#define INPUTCOMPONENT_H
#include <GL/glew.h>
#include <string>
#include "BoxComponent.h"
#include "TextComponent.h"
class InputComponent : public BoxComponent {
public:
//: BoxComponent(rawX, rawY, rawWidth, rawHeight, passedWindowWidth, passedWindowHeight) { }
InputComponent(const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int passedWindowWidth, const int passedWindowHeight);
// or
//using BoxComponent::BoxComponent;
void resize(const int passedWindowWidth, const int passedWindowHeight);
void render();
void addChar(char c);
void backSpace();
void updateText();
std::string value="";
TextComponent *userInputText = nullptr;
};
#endif

101
src/graphics/components/TextComponent.cpp

@ -7,6 +7,10 @@ @@ -7,6 +7,10 @@
extern TextRasterizerCache *rasterizerCache;
TextComponent::TextComponent(const std::string &rawText, const int rawX, const int rawY, const unsigned int size, const bool bolded, const unsigned int hexColor, const int passedWindowWidth, const int passedWindowHeight) {
windowWidth = passedWindowWidth;
windowHeight = passedWindowHeight;
//const std::clock_t begin = clock();
text = rawText;
//x = rawX;
@ -92,44 +96,61 @@ inline void setVerticesColor(std::unique_ptr<float[]> &vertices, int p, unsigned @@ -92,44 +96,61 @@ inline void setVerticesColor(std::unique_ptr<float[]> &vertices, int p, unsigned
vertices[static_cast<size_t>(posMac(p) + 6)] = (static_cast<float>((color >> 0) & 0xFF)) / 255;
}
void TextComponent::rasterize(const int rawX, const int rawY, const int passedWindowWidth, const int passedWindowHeight) {
void TextComponent::rasterize(const int rawX, const int rawY) {
//const std::clock_t begin = clock();
const std::shared_ptr<TextRasterizer> textRasterizer=rasterizerCache->loadFont(fontSize, bold);
unsigned int glyphCount;
//unsigned int glyphCount;
// we need to know how much width we have between x and windowWidth
// and preferrable where the inline starts
// my inline start is parent->children adding width from start to me
// actually the run of all inline before me, starting at parent x as a minimum
//std::cout << "TextComponent::rasterize pre-height: " << (int)height << std::endl;
int wrapToX = 0; // windowWidth - rawX;
bool wrapped;
glyphs = textRasterizer->rasterize(text, rawX, windowWidth, wrapToX, width, height, glyphCount, endingX, endingY, wrapped);
//std::cout << "TextComponent::rasterize done [" << text << "] - start x: " << rawX << " width: " << (int)width << " wrapWidth: " << windowWidth << " wrapTo: " << wrapToX << std::endl;
//std::cout << "TextComponent::rasterize post-height: " << (int)height << std::endl;
if (glyphs == nullptr) {
//bool wrapped;
//glyphs = textRasterizer->rasterize(text, rawX, windowWidth, wrapToX, width, height, glyphCount, endingX, endingY, wrapped);
rasterizationRequest request;
request.text = text;
request.startX = rawX;
request.availableWidth = availableWidth;
request.sourceStartX = rasterStartX;
request.sourceStartY = rasterStartY;
request.noWrap = noWrap;
std::shared_ptr<rasterizationResponse> response = textRasterizer->rasterize(request);
if (response.get() == nullptr) {
std::cout << "TextComponent::rasterize - got nullptr from rasterizer" << std::endl;
return;
}
width = response->width;
height = response->height;
endingX = response->endingX;
endingY = response->endingY;
//std::cout << "TextComponent::rasterize done [" << text << "] - start x: " << rawX << " width: " << (int)width << " wrapWidth: " << windowWidth << " wrapTo: " << wrapToX << std::endl;
//std::cout << "TextComponent::rasterize post-height: " << (int)height << std::endl;
//if (glyphs == nullptr) {
// return;
//}
// did we wrap
int startX = rawX;
// if we didn't we have a nice little texture starting at rawX potentially up to windowWidth
// if we did wrap, then we start at wrapToX (0) and we're a big square texture
if (wrapped) {
if (response->wrapped) {
//std::cout << "it's wrapped starting at " << wrapToX << std::endl;
startX = wrapToX;
}
//std::cout << "startX: " << startX << std::endl;
glyphVertices.clear();
for (unsigned int i = 0; i < glyphCount; i++) {
//for (unsigned int i = 0; i < glyphCount; i++) {
//for(std::vector<Glyph>::iterator it=glyphs->begin(); it!=glyphs->end(); ++it) {
const Glyph &glyph = glyphs[i];
//const Glyph &glyph = glyphs[i];
//Glyph &glyph=*it;
float vx0 = startX;
float vy0 = glyph.y0 + rawY;
float vy0 = response->y0 + rawY;
//std::cout << "glyph x from: " << (int)glyph.x0 << " to " << (int)glyph.x1 << std::endl;
float vx1 = startX + (glyph.x1 - glyph.x0);
float vy1 = glyph.y1 + rawY;
float vx1 = startX + (response->x1 - response->x0);
float vy1 = response->y1 + rawY;
//std::cout << "textcomponent at " << (int)vx0 << "," << (int)vy0 << " to " << (int)vx1 << "," << (int)vy1 << std::endl;
// convert our local x,y,w,h into actual ogl coords
@ -138,37 +159,43 @@ void TextComponent::rasterize(const int rawX, const int rawY, const int passedWi @@ -138,37 +159,43 @@ void TextComponent::rasterize(const int rawX, const int rawY, const int passedWi
//vx0 = ((vx0 / windowWidth) * 2) - 1;
//vy0 = ((vy0 / windowHeight) * 2) - 1;
pointToViewport(vx0, vy0, windowWidth, windowHeight);
pointToViewport(vx1, vy1, windowWidth, windowHeight);
pointToViewport(vx0, vy0);
pointToViewport(vx1, vy1);
//std::cout << "textcomponent at GL" << (int)vx0 << "," << (int)vy0 << " to GL" << (int)vx1 << "," << (int)vy1 << std::endl;
std::unique_ptr<float[]> vertices = std::make_unique<float[]>(36);
vertices[posMac(0) + 0] = vx0;
vertices[posMac(0) + 1] = vy0;
setVerticesColor(vertices, 0, color);
vertices[posMac(0) + 7] = glyph.s0;
vertices[posMac(0) + 8] = glyph.t0;
vertices[posMac(0) + 7] = response->s0;
vertices[posMac(0) + 8] = response->t0;
vertices[posMac(1) + 0] = vx0;
vertices[posMac(1) + 1] = vy1;
setVerticesColor(vertices, 1, color);
vertices[posMac(1) + 7] = glyph.s0;
vertices[posMac(1) + 8] = glyph.t1;
vertices[posMac(1) + 7] = response->s0;
vertices[posMac(1) + 8] = response->t1;
vertices[posMac(2) + 0] = vx1;
vertices[posMac(2) + 1] = vy1;
setVerticesColor(vertices, 2, color);
vertices[posMac(2) + 7] = glyph.s1;
vertices[posMac(2) + 8] = glyph.t1;
vertices[posMac(2) + 7] = response->s1;
vertices[posMac(2) + 8] = response->t1;
vertices[posMac(3) + 0] = vx1;
vertices[posMac(3) + 1] = vy0;
setVerticesColor(vertices, 3, color);
vertices[posMac(3) + 7] = glyph.s1;
vertices[posMac(3) + 8] = glyph.t0;
vertices[posMac(3) + 7] = response->s1;
vertices[posMac(3) + 8] = response->t0;
glyphVertices.push_back(std::move(vertices));
}
//std::cout << "TextComponent::rasterize - glyphVertices count: " << glyphVertices.size() << std::endl;
textureWidth = static_cast<GLsizei>(response->textureWidth);
textureHeight = static_cast<GLsizei>(response->textureHeight);
textureData = std::move(response->textureData);
//}
//const std::clock_t end = clock();
//std::cout << "rasterize text [" << text << "] in: " << std::fixed << ((static_cast<double>(end - begin)) / CLOCKS_PER_SEC) << std::scientific << " seconds" << std::endl;
}
@ -199,10 +226,19 @@ void TextComponent::render() { @@ -199,10 +226,19 @@ void TextComponent::render() {
}
}
void TextComponent::resize() {
// compatible adapter
void TextComponent::resize(const int passedWindowWidth, const int passedWindowHeight) {
resize(passedWindowWidth, passedWindowHeight, passedWindowWidth);
}
// more detailed control
void TextComponent::resize(const int passedWindowWidth, const int passedWindowHeight, const int passedAvailableWidth) {
windowWidth = passedWindowWidth;
windowHeight = passedWindowHeight;
availableWidth = passedAvailableWidth;
//std::cout << "TextComponent::resize" << std::endl;
//std::cout << "TextComponent::resize - rasterizing at " << (int)x << "x" << (int)y << std::endl;
rasterize(x, y, windowWidth, windowHeight);
rasterize(x, y);
//std::cout << "TextComponent::resize - rasterizing at " << (int)x << "x" << (int)y << " size: " << (int)width << "x" << (int)height << std::endl;
// make sure we have glyphs
if (!glyphVertices.size()) {
@ -211,27 +247,24 @@ void TextComponent::resize() { @@ -211,27 +247,24 @@ void TextComponent::resize() {
}
// reupload NEW texture to video card
/*
const Glyph &glyph = glyphs[0];
if (!glyphs) {
std::cout << "TextComponent::resize - glyph points no where" << std::endl;
return;
}
*/
if (!textures.size()) {
textures.push_back(0);
glGenTextures(1, &textures.back());
}
glBindTexture(GL_TEXTURE_2D, textures.back()); // select texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glyph.textureWidth, glyph.textureHeight, 0, GL_RED, GL_UNSIGNED_BYTE, glyph.textureData.get()); // update texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RED, GL_UNSIGNED_BYTE, textureData.get()); // update texture
glGenerateMipmap(GL_TEXTURE_2D);
verticesDirty = true;
}
void TextComponent::pointToViewport(float &rawX, float &rawY, const int passedWindowWidth, const int passedWindowHeight) const {
rawX = ((rawX / windowWidth) * 2) - 1;
rawY = ((rawY / windowHeight) * 2) - 1;
}
void TextComponent::sanitize(std::string &str) {
size_t found = 0; // position
while ((found = str.find("&", found)) != std::string::npos) {

20
src/graphics/components/TextComponent.h

@ -14,10 +14,6 @@ private: @@ -14,10 +14,6 @@ private:
unsigned int fontSize;
bool bold;
unsigned int color;
const unsigned int indices[6] = {
0, 1, 2,
0, 2, 3
};
std::unique_ptr<Glyph[]> glyphs;
std::vector<std::unique_ptr<float[]>> glyphVertices;
std::vector<GLuint> vertexArrayObjects;
@ -29,11 +25,21 @@ public: @@ -29,11 +25,21 @@ public:
std::string text;
TextComponent(const std::string &rawText, const int rawX, const int rawY, const unsigned int size, const bool bolded, const unsigned int hexColor, const int passedWindowWidth, const int passedWindowHeight);
~TextComponent();
void rasterize(const int rawX, const int rawY, const int passedWindowWidth, const int passedWindowHeight);
void rasterize(const int rawX, const int rawY);
void render();
void resize();
void pointToViewport(float &rawX, float &rawY, const int passedWindowWidth, const int passedWindowHeight) const;
void resize(const int passedWindowWidth, const int passedWindowHeight); // compatible adapter
void resize(const int passedWindowWidth, const int passedWindowHeight, const int passedAvailableWidth); // more detailed control
void sanitize(std::string &str);
// input needed stuff
int rasterStartX = 0; // start reading text source at and place at destination 0
int rasterStartY = 0;
bool noWrap = false; // different than overflow but related
int availableWidth = 0;
GLsizei textureWidth;
GLsizei textureHeight;
std::unique_ptr<unsigned char[]> textureData;
// backgroundColor
rgba backgroundColor;

24
src/graphics/elements/INPUTElement.cpp