From dff0d86558bb2f4d5f618487bdd9e60f60a14a42 Mon Sep 17 00:00:00 2001 From: "Grayson Riffe (Desktop)" Date: Thu, 2 Sep 2021 02:21:27 -0500 Subject: [PATCH] Added UITexture and font caching --- DevScreenshots/5. UI Texture.png | Bin 0 -> 33550 bytes Game/src/MainState.cpp | 2 +- .../base/shaders/entityFragment.shader | 4 +- .../base/shaders/textFragment.shader | 4 +- .../AssetBuild/base/shaders/textVertex.shader | 1 - .../base/shaders/uiTextureFragment.shader | 11 +++ .../base/shaders/uiTextureVertex.shader | 13 +++ NothinFancy/NothinFancy.vcxproj | 2 + NothinFancy/NothinFancy.vcxproj.filters | 6 ++ NothinFancy/src/Application.cpp | 2 +- NothinFancy/src/Assets.cpp | 6 +- NothinFancy/src/Renderer/Drawable/Entity.cpp | 4 +- NothinFancy/src/Renderer/Drawable/Model.cpp | 17 ++-- NothinFancy/src/Renderer/Drawable/Text.cpp | 62 +++++++------- .../src/Renderer/Drawable/UIElement.cpp | 17 +++- .../src/Renderer/Drawable/UITexture.cpp | 76 ++++++++++++++++++ NothinFancy/src/Renderer/Renderer.cpp | 15 +++- NothinFancy/src/Renderer/Texture.cpp | 10 ++- NothinFancy/src/include/Assets.h | 6 +- NothinFancy/src/include/Model.h | 4 +- NothinFancy/src/include/NothinFancy.h | 1 + NothinFancy/src/include/Renderer.h | 1 + NothinFancy/src/include/Text.h | 11 +-- NothinFancy/src/include/Texture.h | 4 + NothinFancy/src/include/UIElement.h | 11 ++- NothinFancy/src/include/UITexture.h | 22 +++++ 26 files changed, 252 insertions(+), 60 deletions(-) create mode 100644 DevScreenshots/5. UI Texture.png create mode 100644 NFPackCreator/AssetBuild/base/shaders/uiTextureFragment.shader create mode 100644 NFPackCreator/AssetBuild/base/shaders/uiTextureVertex.shader create mode 100644 NothinFancy/src/Renderer/Drawable/UITexture.cpp create mode 100644 NothinFancy/src/include/UITexture.h diff --git a/DevScreenshots/5. UI Texture.png b/DevScreenshots/5. UI Texture.png new file mode 100644 index 0000000000000000000000000000000000000000..9248578febbca0aa0227b966deb5bef326482d55 GIT binary patch literal 33550 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 + @@ -231,6 +232,7 @@ + diff --git a/NothinFancy/NothinFancy.vcxproj.filters b/NothinFancy/NothinFancy.vcxproj.filters index 993779f..16a3c57 100644 --- a/NothinFancy/NothinFancy.vcxproj.filters +++ b/NothinFancy/NothinFancy.vcxproj.filters @@ -66,6 +66,9 @@ Source Files + + Source Files + @@ -128,6 +131,9 @@ Header Files + + Header Files + diff --git a/NothinFancy/src/Application.cpp b/NothinFancy/src/Application.cpp index 3bf6eec..3f79555 100644 --- a/NothinFancy/src/Application.cpp +++ b/NothinFancy/src/Application.cpp @@ -121,7 +121,7 @@ namespace nf { const Config& Application::getConfig() const { return m_currentConfig; } - //TODO: Test this + int Application::getFPS() const { return m_FPS; } diff --git a/NothinFancy/src/Assets.cpp b/NothinFancy/src/Assets.cpp index f007411..3a77c9e 100644 --- a/NothinFancy/src/Assets.cpp +++ b/NothinFancy/src/Assets.cpp @@ -5,15 +5,15 @@ namespace nf { Asset::~Asset() { - + delete[] data; } AModel::~AModel() { - delete[] data; + } ATexture::~ATexture() { - delete[] data; + } AShader::~AShader() { diff --git a/NothinFancy/src/Renderer/Drawable/Entity.cpp b/NothinFancy/src/Renderer/Drawable/Entity.cpp index 11d859c..5ae09e6 100644 --- a/NothinFancy/src/Renderer/Drawable/Entity.cpp +++ b/NothinFancy/src/Renderer/Drawable/Entity.cpp @@ -30,7 +30,7 @@ namespace nf { size_t ibCount = 0; std::vector tc; parseOBJ(obj, vb, ib, ibCount, tc); - m_model->create(&vb[0], vb.size() * sizeof(float), &ib[0], ibCount, &tc[0], tc.size() * sizeof(float), texture.data, texture.size); + m_model->create(&vb[0], vb.size() * sizeof(float), &ib[0], ibCount, &tc[0], tc.size() * sizeof(float), &texture); model.alreadyLoaded = true; model.loadedModel = m_model; } @@ -52,7 +52,7 @@ namespace nf { } void Entity::setScale(double x) { - m_rotation = { x, x, x }; + m_scale = { x, x, x }; } void Entity::setScale(double x, double y, double z) { diff --git a/NothinFancy/src/Renderer/Drawable/Model.cpp b/NothinFancy/src/Renderer/Drawable/Model.cpp index 86cfff4..9049b8b 100644 --- a/NothinFancy/src/Renderer/Drawable/Model.cpp +++ b/NothinFancy/src/Renderer/Drawable/Model.cpp @@ -13,17 +13,22 @@ namespace nf { } - void Model::create(const void* vertexBufferData, const size_t vertexBufferSize, const void* indexBufferData, size_t indexBufferCount, const void* textureCoordinatesBufferData, size_t textureCoordinatesBufferSize, const char* textureData, size_t textureSize) { + void Model::create(const void* vertexBufferData, const size_t vertexBufferSize, const void* indexBufferData, size_t indexBufferCount, const void* textureCoordinatesBufferData, size_t textureCoordinatesBufferSize, ATexture* texture) { m_vao = new VertexArray; m_vao->addBuffer(vertexBufferData, vertexBufferSize); m_vao->push(3); m_vao->finishBufferLayout(); - if (textureCoordinatesBufferData && textureCoordinatesBufferSize && textureData) { - m_vao->addBuffer(textureCoordinatesBufferData, textureCoordinatesBufferSize); - m_vao->push(2); - m_vao->finishBufferLayout(); + m_vao->addBuffer(textureCoordinatesBufferData, textureCoordinatesBufferSize); + m_vao->push(2); + m_vao->finishBufferLayout(); + if (texture->alreadyLoaded) { + m_texture = texture->loadedTexture; + } + else { m_texture = new Texture; - m_texture->create(textureData, textureSize); + m_texture->create(texture->data, texture->size); + texture->alreadyLoaded = true; + texture->loadedTexture = m_texture; } m_ib = new IndexBuffer(indexBufferData, indexBufferCount); } diff --git a/NothinFancy/src/Renderer/Drawable/Text.cpp b/NothinFancy/src/Renderer/Drawable/Text.cpp index 82305f8..70be3db 100644 --- a/NothinFancy/src/Renderer/Drawable/Text.cpp +++ b/NothinFancy/src/Renderer/Drawable/Text.cpp @@ -8,9 +8,7 @@ #include "Shader.h" namespace nf { - Text::Text() : - m_centered(false) - { + Text::Text() { } @@ -23,24 +21,32 @@ namespace nf { Error("Could not initialize FreeType!"); FT_Face face; AFont& newFont = *(AFont*)font; - if (FT_New_Memory_Face(ft, (const unsigned char*)newFont.data, newFont.size, 0, &face)) - Error("Could not load font!"); - FT_Set_Pixel_Sizes(face, 0, size); - for (unsigned char c = 0; c < 128; c++) { - FT_Load_Char(face, c, FT_LOAD_RENDER); - unsigned int tex; - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, face->glyph->bitmap.width, face->glyph->bitmap.rows, 0, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - Character ch = { tex, Vec2((float)face->glyph->bitmap.width, (float)face->glyph->bitmap.rows), Vec2(face->glyph->bitmap_left, face->glyph->bitmap_top), (unsigned int)face->glyph->advance.x }; - m_font[c] = ch; + if (newFont.alreadyLoaded) { + m_font = newFont.loadedFont; + } + else { + m_font = new Font; + if (FT_New_Memory_Face(ft, (const unsigned char*)newFont.data, newFont.size, 0, &face)) + Error("Could not load font!"); + FT_Set_Pixel_Sizes(face, 0, size); + for (unsigned char c = 0; c < 128; c++) { + FT_Load_Char(face, c, FT_LOAD_RENDER); + unsigned int tex; + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, face->glyph->bitmap.width, face->glyph->bitmap.rows, 0, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + Character ch = { tex, Vec2((float)face->glyph->bitmap.width, (float)face->glyph->bitmap.rows), Vec2(face->glyph->bitmap_left, face->glyph->bitmap_top), (unsigned int)face->glyph->advance.x }; + m_font->m_characters[c] = ch; + } + FT_Done_Face(face); + FT_Done_FreeType(ft); + newFont.alreadyLoaded = true; + newFont.loadedFont = m_font; } - FT_Done_Face(face); - FT_Done_FreeType(ft); m_vao = new VertexArray; m_vao->addBuffer(nullptr, 0); m_vao->push(2); @@ -50,8 +56,8 @@ namespace nf { m_vao->finishBufferLayout(); } - void Text::centered(bool centered) { - m_centered = centered; + void Text::setText(const std::string& string) { + m_string = string; } const char* Text::identity() { @@ -63,22 +69,24 @@ namespace nf { m_vao->bind(); std::string::const_iterator si; float currX = (float)m_position.x * windowWidth, currY = (float)m_position.y * windowHeight; - if (m_centered) { + if (m_centeredX || m_centeredY) { float textWidth = 0.0f; float textHeight = 0.0f; for (si = m_string.begin(); si != m_string.end(); si++) { - Character& c = m_font[*si]; + Character& c = m_font->m_characters[*si]; textWidth += (c.advance >> 6) * scale; if (c.size.y >= textHeight) textHeight = (float)c.size.y * scale; } - currX = ((float)windowWidth - textWidth) / 2; - currY = ((float)windowHeight - textHeight) / 2; + if (m_centeredX) + currX = ((float)windowWidth - textWidth) / 2; + if (m_centeredY) + currY = ((float)windowHeight - textHeight) / 2; } glm::vec3 color = { m_color.x, m_color.y, m_color.z }; shader->setUniform("textColor", color); for (si = m_string.begin(); si != m_string.end(); si++) { - Character& c = m_font[*si]; + Character& c = m_font->m_characters[*si]; float x = currX + (float)c.bearing.x * scale; float y = currY - float(c.size.y - c.bearing.y) * scale; float w = (float)c.size.x * scale; diff --git a/NothinFancy/src/Renderer/Drawable/UIElement.cpp b/NothinFancy/src/Renderer/Drawable/UIElement.cpp index ba5be01..6d7dbd5 100644 --- a/NothinFancy/src/Renderer/Drawable/UIElement.cpp +++ b/NothinFancy/src/Renderer/Drawable/UIElement.cpp @@ -1,7 +1,10 @@ #include "UIElement.h" namespace nf { - UIElement::UIElement() { + UIElement::UIElement() : + m_centeredX(false), + m_centeredY(false) + { } @@ -9,6 +12,18 @@ namespace nf { return "none"; } + void UIElement::setPosition(float x, float y) { + m_position = Vec2(x, y); + } + void UIElement::setPosition(const Vec2& position) { + m_position = position; + } + + void UIElement::centered(bool x, bool y) { + m_centeredX = x; + m_centeredY = y; + } + void UIElement::render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight) { } diff --git a/NothinFancy/src/Renderer/Drawable/UITexture.cpp b/NothinFancy/src/Renderer/Drawable/UITexture.cpp new file mode 100644 index 0000000..f0b0112 --- /dev/null +++ b/NothinFancy/src/Renderer/Drawable/UITexture.cpp @@ -0,0 +1,76 @@ +#include "UITexture.h" + +#include "GL/glew.h" + +#include "Assets.h" +#include "Texture.h" + +namespace nf { + UITexture::UITexture() : + m_texture(0) + { + + } + + void UITexture::create(Asset* texture, const Vec2& position, double scale) { + ATexture* tex = (ATexture*)texture; + m_position = position; + m_scale = (float)scale; + if (tex->alreadyLoaded) { + m_texture = tex->loadedTexture; + } + else { + m_texture = new Texture; + m_texture->create(tex->data, tex->size); + } + + m_vao = new VertexArray; + m_vao->addBuffer(nullptr, 0); + m_vao->push(2); + m_vao->finishBufferLayout(); + m_vao->addBuffer(nullptr, 0); + m_vao->push(2); + m_vao->finishBufferLayout(); + } + + const char* UITexture::identity() { + return "texture"; + } + + void UITexture::render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight) { + float posX = (float)m_position.x * windowWidth, posY = (float)m_position.y * windowHeight; + float scale = windowWidth / 5.0f; + + Vec2 texDim = m_texture->getDimensions(); + float height = scale * m_scale; + float width = ((float)texDim.x / (float)texDim.y) * scale * m_scale; + if (m_centeredX) + posX = ((float)windowWidth - width) / 2; + if (m_centeredY) + posY = ((float)windowHeight - height) / 2; + float vb[3][4] = { + posX, posY + height, + posX, posY, + posX + width, posY, + posX, posY + height, + posX + width, posY, + posX + width, posY + height + }; + float tc[3][4] = { + 0.0, 1.0, + 0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0, + 1.0, 0.0, + 1.0, 1.0 + }; + m_texture->bind(); + m_vao->setBufferData(0, vb, sizeof(vb)); + m_vao->setBufferData(1, tc, sizeof(tc)); + glDrawArrays(GL_TRIANGLES, 0, 6); + } + + UITexture::~UITexture() { + + } +} \ No newline at end of file diff --git a/NothinFancy/src/Renderer/Renderer.cpp b/NothinFancy/src/Renderer/Renderer.cpp index d947636..94ccb19 100644 --- a/NothinFancy/src/Renderer/Renderer.cpp +++ b/NothinFancy/src/Renderer/Renderer.cpp @@ -49,7 +49,6 @@ namespace nf { wglMakeCurrent(m_hdc, m_hglrc); wglSwapIntervalEXT(0); Log("OpenGL version: " + std::string((char*)glGetString(GL_VERSION))); - glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -64,6 +63,9 @@ namespace nf { const char* textVertex = baseAP["textVertex.shader"]->data; const char* textFragment = baseAP["textFragment.shader"]->data; m_textShader = new Shader(textVertex, textFragment); + const char* uiTextureVertex = baseAP["uiTextureVertex.shader"]->data; + const char* uiTextureFragment = baseAP["uiTextureFragment.shader"]->data; + m_uiTextureShader = new Shader(uiTextureVertex, uiTextureFragment); BaseAssets::cube = (AModel*)baseAP["cube.obj"]; BaseAssets::plane = (AModel*)baseAP["plane.obj"]; @@ -91,6 +93,7 @@ namespace nf { glViewport(0, 0, m_app->getConfig().width, m_app->getConfig().height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)m_app->getConfig().width / (float)m_app->getConfig().height, 0.1f, 100000.0f); for (Entity* draw : m_lGame) { Entity& curr = *draw; @@ -102,6 +105,7 @@ namespace nf { } m_lGame.clear(); + glDisable(GL_DEPTH_TEST); proj = glm::ortho(0.0f, (float)m_app->getConfig().width, 0.0f, (float)m_app->getConfig().height); for (UIElement* draw : m_lUI) { UIElement& curr = *draw; @@ -111,7 +115,11 @@ namespace nf { curr.render(m_textShader, m_app->getConfig().width, m_app->getConfig().height); continue; } - //TODO: Add else if for UI texture + if (curr.identity() == "texture") { + m_uiTextureShader->bind(); + m_uiTextureShader->setUniform("proj", proj); + curr.render(m_uiTextureShader, m_app->getConfig().width, m_app->getConfig().height); + } } m_lUI.clear(); @@ -123,6 +131,9 @@ namespace nf { } Renderer::~Renderer() { + delete m_entityShader; + delete m_textShader; + delete m_uiTextureShader; ReleaseDC(m_app->getWindow(), m_hdc); wglMakeCurrent(NULL, NULL); wglDeleteContext(m_hglrc); diff --git a/NothinFancy/src/Renderer/Texture.cpp b/NothinFancy/src/Renderer/Texture.cpp index d0a03ae..118511b 100644 --- a/NothinFancy/src/Renderer/Texture.cpp +++ b/NothinFancy/src/Renderer/Texture.cpp @@ -12,15 +12,15 @@ namespace nf { } void Texture::create(const char* textureData, size_t textureSize) { - int width, height, nChannels; + int nChannels; stbi_set_flip_vertically_on_load(true); - unsigned char* texture = stbi_load_from_memory((unsigned char*)textureData, textureSize, &width, &height, &nChannels, 0); + unsigned char* texture = stbi_load_from_memory((unsigned char*)textureData, textureSize, &m_x, &m_y, &nChannels, 0); if (!texture) Error("Texture failed to load from memory!"); glBindTexture(GL_TEXTURE_2D, m_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_x, m_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); glGenerateMipmap(GL_TEXTURE_2D); stbi_image_free(texture); } @@ -29,6 +29,10 @@ namespace nf { glBindTexture(GL_TEXTURE_2D, m_id); } + Vec2 Texture::getDimensions() { + return { (float)m_x, (float)m_y }; + } + Texture::~Texture() { glDeleteTextures(1, &m_id); } diff --git a/NothinFancy/src/include/Assets.h b/NothinFancy/src/include/Assets.h index c6689cf..507693f 100644 --- a/NothinFancy/src/include/Assets.h +++ b/NothinFancy/src/include/Assets.h @@ -3,15 +3,17 @@ namespace nf { class Model; + class Texture; + struct Font; struct Asset { char* data; + bool alreadyLoaded = false; virtual ~Asset(); }; struct AModel : Asset { - bool alreadyLoaded; Model* loadedModel; ~AModel() override; @@ -19,6 +21,7 @@ namespace nf { struct ATexture : Asset { size_t size; + Texture* loadedTexture; ~ATexture() override; }; @@ -29,6 +32,7 @@ namespace nf { struct AFont : Asset { size_t size; + Font* loadedFont; ~AFont() override; }; diff --git a/NothinFancy/src/include/Model.h b/NothinFancy/src/include/Model.h index 14e4d44..1f4a6d8 100644 --- a/NothinFancy/src/include/Model.h +++ b/NothinFancy/src/include/Model.h @@ -1,14 +1,16 @@ #pragma once #include "Drawable.h" +#include "Assets.h" namespace nf { class Drawable; class Texture; + class Model : public Drawable { public: Model(); - void create(const void* vertexBufferData, const size_t vertexBufferSize, const void* indexBufferData, size_t indexBufferCount, const void* textureCoordinates, size_t textureCoordinatesBufferSize, const char* textureData, size_t textureSize); + void create(const void* vertexBufferData, const size_t vertexBufferSize, const void* indexBufferData, size_t indexBufferCount, const void* textureCoordinates, size_t textureCoordinatesBufferSize, ATexture* texture); void bind() override; ~Model(); diff --git a/NothinFancy/src/include/NothinFancy.h b/NothinFancy/src/include/NothinFancy.h index 212bb43..55684a4 100644 --- a/NothinFancy/src/include/NothinFancy.h +++ b/NothinFancy/src/include/NothinFancy.h @@ -10,6 +10,7 @@ #include "IntroGamestate.h" #include "Assets.h" #include "Text.h" +#include "UITexture.h" #include "Input.h" namespace nf { diff --git a/NothinFancy/src/include/Renderer.h b/NothinFancy/src/include/Renderer.h index cb7a40b..67d6c06 100644 --- a/NothinFancy/src/include/Renderer.h +++ b/NothinFancy/src/include/Renderer.h @@ -32,5 +32,6 @@ namespace nf { std::vector m_lUI; Shader* m_entityShader; Shader* m_textShader; + Shader* m_uiTextureShader; }; } \ No newline at end of file diff --git a/NothinFancy/src/include/Text.h b/NothinFancy/src/include/Text.h index f1eec91..264f532 100644 --- a/NothinFancy/src/include/Text.h +++ b/NothinFancy/src/include/Text.h @@ -13,22 +13,23 @@ namespace nf { unsigned int advance; }; + struct Font { + std::map m_characters; + }; + class Text : public UIElement { public: Text(); void create(const std::string& string, const Vec2& position, const Vec3& color = {1.0, 1.0, 1.0}, unsigned int size = 160, Asset* font = BaseAssets::defaultFont); - void centered(bool centered); - + void setText(const std::string& string); const char* identity() override; void render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight) override; ~Text(); private: std::string m_string; - Vec2 m_position; + Font* m_font; Vec3 m_color; - bool m_centered; - std::map m_font; }; } \ No newline at end of file diff --git a/NothinFancy/src/include/Texture.h b/NothinFancy/src/include/Texture.h index 3b31cb5..c917fc7 100644 --- a/NothinFancy/src/include/Texture.h +++ b/NothinFancy/src/include/Texture.h @@ -1,4 +1,5 @@ #pragma once +#include "Utility.h" namespace nf { class Texture { @@ -7,9 +8,12 @@ namespace nf { void create(const char* textureData, size_t textureSize); void bind(); + Vec2 getDimensions(); ~Texture(); private: unsigned int m_id; + int m_x; + int m_y; }; } \ No newline at end of file diff --git a/NothinFancy/src/include/UIElement.h b/NothinFancy/src/include/UIElement.h index 84664a2..a862b52 100644 --- a/NothinFancy/src/include/UIElement.h +++ b/NothinFancy/src/include/UIElement.h @@ -1,6 +1,8 @@ #pragma once #include "Drawable.h" +#include "Utility.h" + namespace nf { class Shader; @@ -9,10 +11,15 @@ namespace nf { UIElement(); virtual const char* identity(); + void setPosition(float x, float y); + void setPosition(const Vec2& position); + void centered(bool x, bool y = false); virtual void render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight); ~UIElement(); - private: - + protected: + Vec2 m_position; + bool m_centeredX; + bool m_centeredY; }; } \ No newline at end of file diff --git a/NothinFancy/src/include/UITexture.h b/NothinFancy/src/include/UITexture.h new file mode 100644 index 0000000..2e34ac1 --- /dev/null +++ b/NothinFancy/src/include/UITexture.h @@ -0,0 +1,22 @@ +#pragma once +#include "UIElement.h" +#include "Utility.h" + +namespace nf { + class Texture; + struct Asset; + + class UITexture : public UIElement { + public: + UITexture(); + + void create(Asset* texture, const Vec2& position, double scale = 1.0); + const char* identity() override; + void render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight) override; + + ~UITexture(); + private: + Texture* m_texture; + float m_scale; + }; +} \ No newline at end of file