Added clickable buttons; Custom button textures can be specified; Added default cubemap

This commit is contained in:
Grayson Riffe (Laptop) 2021-09-11 15:31:38 -05:00
parent cd41123beb
commit 805a1cef1f
41 changed files with 409 additions and 104 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

View File

@ -9,7 +9,7 @@ out vec4 color;
void main() {
vec3 tc;
tc = vec3(-texCoord.x, texCoord.y, texCoord.z);
if (texCoord.y > 0.99 || texCoord.y < -0.99) {
if (texCoord.y > 0.999999 || texCoord.y < -0.999999) {
tc = vec3(texCoord.x, texCoord.y, texCoord.z);
}
color = texture(cm, tc);

View File

@ -91,7 +91,7 @@ int main(int argc, char* argv[]) {
}
std::set<std::string> extensions;
extensions.insert({ "obj", "png", "shader", "ttf" });
extensions.insert({ "obj", "png", "jpg", "shader", "ttf" });
unsigned int dirCount = 0;
const std::filesystem::path workingDir = std::filesystem::current_path();

View File

@ -200,6 +200,7 @@
<ClCompile Include="src\Gamestate.cpp" />
<ClCompile Include="src\IntroGamestate.cpp" />
<ClCompile Include="src\Renderer\Camera.cpp" />
<ClCompile Include="src\Renderer\Drawable\Button.cpp" />
<ClCompile Include="src\Renderer\Drawable\Cubemap.cpp" />
<ClCompile Include="src\Renderer\Drawable\Drawable.cpp" />
<ClCompile Include="src\Renderer\Drawable\Entity.cpp" />
@ -218,6 +219,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\include\Assets.h" />
<ClInclude Include="src\include\Button.h" />
<ClInclude Include="src\include\Camera.h" />
<ClInclude Include="src\include\Cubemap.h" />
<ClInclude Include="src\include\Entity.h" />

View File

@ -75,6 +75,9 @@
<ClCompile Include="src\Renderer\Drawable\Cubemap.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Renderer\Drawable\Button.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\include\Config.h">
@ -149,6 +152,9 @@
<ClInclude Include="src\include\NFObject.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\include\Button.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Natvis Include="NatvisFile.natvis" />

View File

@ -138,22 +138,27 @@ namespace nf {
}
bool Application::isKeyHeld(unsigned int code) {
if (code < 164) {
return m_keys[code].first;
}
if (code > 7 && code < 164)
return GetKeyState(code) & 0x8000;
return false;
}
bool Application::isKeyPressed(unsigned int code) {
if (code < 164) {
if (m_keys[code].second) {
m_keys[code].second = false;
if (code > 7 && code < 164) {
if (m_keysPressed[code]) {
m_keysPressed[code] = false;
return true;
}
}
return false;
}
bool Application::isMouse(unsigned int code) {
if (code < 7)
return GetKeyState(code) & 0x8000;
return false;
}
void Application::trackMouse(bool track) {
m_trackingMouse = track;
if (m_trackingMouse == true)
@ -167,6 +172,10 @@ namespace nf {
m_mouseDiffY = 0;
}
Vec2 Application::getMousePos() {
return Vec2(m_mouseX, m_mouseY);
}
Application* Application::getApp() {
return currentApp;
}
@ -284,10 +293,12 @@ namespace nf {
m_fpsDuration = m_fpsClock2 - m_fpsClock1;
if (m_fpsDuration.count() >= 0.2) {
m_FPS = (int)std::round(1.0 / m_deltaTime);
#ifdef _DEBUG
static int i = 0;
i++;
if (i % 5 == 0)
Log("FPS: " + std::to_string(m_FPS));
#endif
m_fpsClock1 = std::chrono::steady_clock::now();
}
}
@ -347,14 +358,12 @@ namespace nf {
}
case WM_KEYDOWN: {
if (wParam < 164 && !(lParam & (1 << 30)))
app->m_keys[wParam].first = app->m_keys[wParam].second = true;
app->m_keysPressed[wParam] = true;
return 0;
}
case WM_KEYUP: {
if (wParam < 164)
app->m_keys[wParam].first = app->m_keys[wParam].second = false;
app->m_keysPressed[wParam] = false;
return 0;
}
case WM_SETCURSOR: {

View File

@ -28,11 +28,15 @@ namespace nf {
delete[] rightData;
}
AShader::~AShader() {
AFont::~AFont() {
}
AFont::~AFont() {
AButton::~AButton() {
}
AShader::~AShader() {
}
@ -45,7 +49,9 @@ namespace nf {
std::string packContents = readFile(path);
std::string packContentsOBJ = packContents;
std::unordered_map<std::string, ACubemap*> cubemaps;
std::unordered_map<std::string, AButton*> buttons;
unsigned int cubemapCount = 0;
unsigned int buttonCount = 0;
while (packContents.size()) {
unsigned int startingPos = packContents.find_first_of("#NFASSET ") + 9;
packContents = packContents.substr(9);
@ -68,13 +74,12 @@ namespace nf {
if (extension == "obj")
continue;
if (extension == "png") {
if (extension == "png" || extension == "jpg") {
if (assetName.find("_cmfront") != std::string::npos || assetName.find("_cmback") != std::string::npos || assetName.find("_cmtop") != std::string::npos || assetName.find("_cmbottom") != std::string::npos || assetName.find("_cmleft") != std::string::npos || assetName.find("_cmright") != std::string::npos) {
std::string cmName = assetName.substr(0, assetName.find('_'));
ACubemap* curr;
if (cubemaps.find(cmName) == cubemaps.end()) {
cubemaps[cmName] = new ACubemap;
cubemaps[cmName]->numImages = 0;
}
curr = cubemaps[cmName];
if (curr->numImages == 6)
@ -111,13 +116,45 @@ namespace nf {
}
curr->numImages++;
if (curr->numImages == 6) {
if (curr->numImages == 6)
m_assets[cmName + (std::string)".cm"] = curr;
}
cubemapCount++;
continue;
}
else if (assetName.find("_buttonidle") != std::string::npos || assetName.find("_buttonhover") != std::string::npos || assetName.find("_buttonpressed") != std::string::npos) {
std::string buttonName = assetName.substr(0, assetName.find('_'));
AButton* curr;
if (buttons.find(buttonName) == buttons.end()) {
buttons[buttonName] = new AButton;
buttons[buttonName]->numImages = 0;
}
curr = buttons[buttonName];
if (curr->numImages == 3)
Error("Duplicate button images in pack \"" + (std::string)packName + (std::string)"\"!");
if (assetName.find("_buttonidle") != std::string::npos) {
curr->idleTex.data = new char[assetSize];
std::memcpy(curr->idleTex.data, &assetContents[0], assetSize);
curr->idleTex.size = assetSize;
}
if (assetName.find("_buttonhover") != std::string::npos) {
curr->hoverTex.data = new char[assetSize];
std::memcpy(curr->hoverTex.data, &assetContents[0], assetSize);
curr->hoverTex.size = assetSize;
}
if (assetName.find("_buttonpressed") != std::string::npos) {
curr->pressedTex.data = new char[assetSize];
std::memcpy(curr->pressedTex.data, &assetContents[0], assetSize);
curr->pressedTex.size = assetSize;
}
curr->numImages++;
if (curr->numImages == 3)
m_assets[buttonName + (std::string)".button"] = curr;
buttonCount++;
continue;
}
ATexture* texture = new ATexture;
texture->data = new char[assetSize];
std::memcpy(texture->data, &assetContents[0], assetSize);
@ -149,6 +186,8 @@ namespace nf {
}
if (cubemapCount % 6 != 0)
Error("Could not find full cubemap in pack \"" + (std::string)packName + (std::string)"\"!");
if (buttonCount % 3 != 0)
Error("Could not find full button set in pack \"" + (std::string)packName + (std::string)"\"!");
while (packContentsOBJ.size()) {
unsigned int startingPos = packContentsOBJ.find_first_of("#NFASSET ") + 9;
@ -229,5 +268,9 @@ namespace nf {
ATexture* BaseAssets::logo;
AFont* BaseAssets::defaultFont;
ACubemap* BaseAssets::cubemap;
AFont* BaseAssets::font;
AButton* BaseAssets::button;
}

View File

@ -76,7 +76,7 @@ namespace nf {
switch (m_type) {
case Type::UI: {
view = glm::mat4(1.0);
break;
}
case Type::FIRST_PERSON: {
@ -91,15 +91,6 @@ namespace nf {
m_pitch = 89.0f;
if (m_pitch < -89.0f)
m_pitch = -89.0f;
glm::vec3 rotation;
rotation.x = std::cos(glm::radians(m_yaw)) * std::cos(glm::radians(m_pitch));
rotation.y = std::sin(glm::radians(m_pitch));
rotation.z = std::sin(glm::radians(m_yaw)) * std::cos(glm::radians(m_pitch));
rotation = glm::normalize(rotation);
m_front = { rotation.x, rotation.y, rotation.z };
glm::vec3 position(m_position.x, m_position.y, m_position.z);
glm::vec3 up(0.0, 1.0, 0.0);
view = glm::lookAt(position, position + rotation, up);
break;
}
case Type::ORBIT: {
@ -113,6 +104,16 @@ namespace nf {
}
glm::vec3 pos(m_position.x, m_position.y, m_position.z);
entityShader->setUniform("camera.pos", pos);
glm::vec3 rotation;
rotation.x = std::cos(glm::radians(m_yaw)) * std::cos(glm::radians(m_pitch));
rotation.y = std::sin(glm::radians(m_pitch));
rotation.z = std::sin(glm::radians(m_yaw)) * std::cos(glm::radians(m_pitch));
rotation = glm::normalize(rotation);
m_front = { rotation.x, rotation.y, rotation.z };
glm::vec3 position(m_position.x, m_position.y, m_position.z);
glm::vec3 up(0.0, 1.0, 0.0);
view = glm::lookAt(position, position + rotation, up);
entityShader->setUniform("view", view);
glm::mat4 cubemapView = glm::mat4(glm::mat3(view));

View File

@ -0,0 +1,136 @@
#include "Button.h"
#include "GL/glew.h"
#include "Application.h"
#include "Input.h"
#include "Texture.h"
#include "Shader.h"
namespace nf {
Button::Button() :
m_idleTexture(nullptr),
m_hoverTexture(nullptr),
m_pressedTexture(nullptr),
m_currentTexture(nullptr),
m_scale(1.0f),
m_opacity(1.0f),
m_clicked(false),
m_triggered(false)
{
}
void Button::create(const Vec2& position, std::string string, Asset* buttonAsset, double scale, double opacity) {
m_constructed = true;
m_position = position;
m_string = string;
if (m_string.size()) {
m_text.create(m_string, Vec2(0.0, 0.0));
m_text.centered(true);
}
m_scale = (float)scale * 0.3f;
m_opacity = (float)opacity;
m_text.setOpacity(m_opacity);
AButton* button;
if ((button = dynamic_cast<AButton*>(buttonAsset)) == nullptr)
Error("Non-button asset passed to Button::create!");
m_idleTexture = new Texture(&button->idleTex);
m_hoverTexture = new Texture(&button->hoverTex);
m_pressedTexture = new Texture(&button->pressedTex);
if (!((m_idleTexture->getDimensions() == m_hoverTexture->getDimensions()) && (m_idleTexture->getDimensions() == m_pressedTexture->getDimensions()))) {
Error("Button images are not the same size!");
}
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_vao = new VertexArray;
m_vao->addBuffer(nullptr, 0);
m_vao->push<float>(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(tc, sizeof(tc));
m_vao->push<float>(2);
m_vao->finishBufferLayout();
Application::getApp()->getCurrentState()->m_nfObjects.push_back(this);
}
const char* Button::identity() {
return "button";
}
void Button::render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight, Application* app, Shader* textShader) {
float posX = (float)m_position.x * windowWidth, posY = (float)m_position.y * windowHeight;
float scale = windowWidth / 5.0f;
Vec2 texDim = m_idleTexture->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;
m_currentTexture = m_idleTexture;
Vec2 mousePos = app->getMousePos();
m_triggered = false;
if (mousePos.x >= posX && mousePos.x <= posX + width && mousePos.y <= windowHeight - posY && mousePos.y >= (windowHeight - posY) - height) {
m_currentTexture = m_hoverTexture;
if (app->isMouse(NFI_LEFTMOUSE))
m_clicked = true;
else if (m_clicked) {
m_triggered = true;
m_clicked = false;
}
}
else m_clicked = false;
if (m_clicked)
m_currentTexture = m_pressedTexture;
float vb[] = {
posX, posY + height,
posX, posY,
posX + width, posY,
posX, posY + height,
posX + width, posY,
posX + width, posY + height
};
m_currentTexture->bind();
m_vao->setBufferData(0, vb, sizeof(vb));
shader->setUniform("opacity", m_opacity);
glDrawArrays(GL_TRIANGLES, 0, 6);
if (m_string.size()) {
Vec2 pos = Vec2(posX, posY);
m_text.render(textShader, windowWidth, windowHeight, true, width, height, pos);
}
}
bool Button::isClicked() {
return m_triggered;
}
void Button::destroy() {
m_constructed = false;
m_clicked = false;
m_position = Vec2(0.0);
m_centeredX = m_centeredY = false;
if (!m_idleTexture->isBaseAsset())
delete m_idleTexture;
if (!m_hoverTexture->isBaseAsset())
delete m_hoverTexture;
if (!m_pressedTexture->isBaseAsset())
delete m_pressedTexture;
delete m_vao;
}
Button::~Button() {
}
}

View File

@ -5,6 +5,7 @@
#include "stb_image.h"
#include "Application.h"
#include "Shader.h"
#include "Assets.h"
namespace nf {
@ -19,6 +20,7 @@ namespace nf {
m_constructed = true;
ACubemap& cm = *(ACubemap*)cubemapAsset;
glGenTextures(1, &m_id);
glActiveTexture(GL_TEXTURE12);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_id);
struct CMFace {
CMFace(unsigned char* d, unsigned int w, unsigned int h, unsigned int nc) :
@ -61,6 +63,8 @@ namespace nf {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glActiveTexture(GL_TEXTURE0);
float vb[] = {
-1.0f, 1.0f, -1.0f,
@ -117,8 +121,10 @@ namespace nf {
return m_constructed;
}
void Cubemap::render() {
void Cubemap::render(Shader* shader) {
m_vao->bind();
glActiveTexture(GL_TEXTURE12);
shader->setUniform("cm", 12);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_id);
glDepthFunc(GL_LEQUAL);
glDrawArrays(GL_TRIANGLES, 0, 36);

View File

@ -19,16 +19,18 @@ namespace nf {
void Entity::create(Asset* modelAsset) {
m_constructed = true;
AModel& model = *(AModel*)modelAsset;
if (model.alreadyLoaded) {
m_model = model.loadedModel;
AModel* model;
if ((model = dynamic_cast<AModel*>(modelAsset)) == nullptr)
Error("Non-model asset passed to Entity::create!");
if (model->alreadyLoaded) {
m_model = model->loadedModel;
}
else {
m_model = new Model(&model);
model.alreadyLoaded = true;
model.loadedModel = m_model;
m_model = new Model(model);
model->alreadyLoaded = true;
model->loadedModel = m_model;
}
m_model->setBaseAsset(model.isBaseAsset);
Application::getApp()->getCurrentState()->m_nfObjects.push_back(this);
}

View File

@ -24,12 +24,18 @@ namespace nf {
m_ib = new IndexBuffer(ib, ibCount);
if (diffTex) {
m_hasDiffuse = true;
m_diffuseTexture = new Texture(diffTex);
if (diffTex->alreadyLoaded)
m_diffuseTexture = diffTex->loadedTexture;
else
m_diffuseTexture = new Texture(diffTex);
}
m_diffColor = diffColor;
if (specTex) {
m_hasSpecular = true;
m_specularTexture = new Texture(specTex);
if (specTex->alreadyLoaded)
m_specularTexture = specTex->loadedTexture;
else
m_specularTexture = new Texture(specTex);
}
m_shininess = shininess;
}
@ -63,7 +69,7 @@ namespace nf {
}
Model::Model(AModel* model) :
m_base(false)
m_base(model->isBaseAsset)
{
std::string obj = model->data;
unsigned int startMtlPos = obj.find("newmtl");
@ -281,10 +287,6 @@ namespace nf {
}
}
void Model::setBaseAsset(bool isBase) {
m_base = isBase;
}
bool Model::isBaseAsset() {
return m_base;
}

View File

@ -92,11 +92,12 @@ namespace nf {
return "text";
}
void Text::render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight) {
void Text::render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight, bool onButton, float buttonWidth, float buttonHeight, const Vec2& buttonPos) {
float scale = windowWidth / 4000.0f;
m_vao->bind();
std::string::const_iterator si;
if (onButton)
scale *= buttonHeight / 100.0f;
float currX = (float)m_position.x * windowWidth, currY = (float)m_position.y * windowHeight;
std::string::const_iterator si;
if (m_centeredX || m_centeredY) {
float textWidth = 0.0f;
float textHeight = 0.0f;
@ -110,7 +111,23 @@ namespace nf {
currX = ((float)windowWidth - textWidth) / 2;
if (m_centeredY)
currY = ((float)windowHeight - textHeight) / 2;
if (onButton) {
while (textWidth > buttonWidth - 20) {
scale -= 0.01f;
textHeight = textWidth = 0.0f;
for (si = m_string.begin(); si != m_string.end(); si++) {
Character& c = m_font->m_characters[*si];
textWidth += (c.advance >> 6) * scale * m_scale;
if (c.size.y >= textHeight)
textHeight = (float)c.size.y * scale * m_scale;
}
}
currX = (((float)buttonWidth - textWidth) / 2) + (float)buttonPos.x;
currY = (((float)buttonHeight - textHeight) / 2) + (float)buttonPos.y;
}
}
glm::vec3 color = { m_color.x, m_color.y, m_color.z };
shader->setUniform("textColor", color);
shader->setUniform("opacity", m_opacity);
@ -120,7 +137,7 @@ namespace nf {
float y = currY - float(c.size.y - c.bearing.y) * scale * m_scale;
float w = (float)c.size.x * scale * m_scale;
float h = (float)c.size.y * scale * m_scale;
float vb[3][4] = {
float vb[] = {
x, y + h,
x, y,
x + w, y,
@ -128,7 +145,7 @@ namespace nf {
x + w, y,
x + w, y + h
};
float tc[3][4] = {
float tc[] = {
0.0, 0.0,
0.0, 1.0,
1.0, 1.0,
@ -138,6 +155,7 @@ namespace nf {
};
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D, c.texID);
m_vao->bind();
m_vao->setBufferData(0, vb, sizeof(vb));
m_vao->setBufferData(1, tc, sizeof(tc));
shader->setUniform("text", 10);

View File

@ -13,7 +13,7 @@ namespace nf {
return "none";
}
void UIElement::setPosition(float x, float y) {
void UIElement::setPosition(double x, double y) {
m_position = Vec2(x, y);
}
void UIElement::setPosition(const Vec2& position) {

View File

@ -2,6 +2,7 @@
#include "GL/glew.h"
#include "Application.h"
#include "Assets.h"
#include "Texture.h"
#include "Shader.h"
@ -17,7 +18,9 @@ namespace nf {
void UITexture::create(Asset* textureAsset, const Vec2& position, double scale, double opacity) {
m_constructed = true;
ATexture* tex = (ATexture*)textureAsset;
ATexture* tex;
if ((tex = dynamic_cast<ATexture*>(textureAsset)) == nullptr)
Error("Non-texture asset passed to UITexture::create!");
m_position = position;
m_scale = (float)scale;
m_opacity = (float)opacity;
@ -28,13 +31,23 @@ namespace nf {
m_texture = new Texture(tex);
}
float tc[] = {
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_vao = new VertexArray;
m_vao->addBuffer(nullptr, 0);
m_vao->push<float>(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(nullptr, 0);
m_vao->addBuffer(tc, sizeof(tc));
m_vao->push<float>(2);
m_vao->finishBufferLayout();
Application::getApp()->getCurrentState()->m_nfObjects.push_back(this);
}
const char* UITexture::identity() {
@ -68,17 +81,9 @@ namespace nf {
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));
shader->setUniform("opacity", m_opacity);
glDrawArrays(GL_TRIANGLES, 0, 6);
}

View File

@ -8,9 +8,9 @@
#include "Shader.h"
#include "Light.h"
#include "Entity.h"
#include "Model.h"
#include "Cubemap.h"
#include "UIElement.h"
#include "Button.h"
#include "Camera.h"
#include "Utility.h"
@ -67,31 +67,7 @@ namespace nf {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
m_baseAP.load("base.nfpack");
const char* entityVertex = m_baseAP["entityVertex.shader"]->data;
const char* entityFragment = m_baseAP["entityFragment.shader"]->data;
m_entityShader = new Shader(entityVertex, entityFragment);
const char* textVertex = m_baseAP["textVertex.shader"]->data;
const char* textFragment = m_baseAP["textFragment.shader"]->data;
m_textShader = new Shader(textVertex, textFragment);
const char* uiTextureVertex = m_baseAP["uiTextureVertex.shader"]->data;
const char* uiTextureFragment = m_baseAP["uiTextureFragment.shader"]->data;
m_uiTextureShader = new Shader(uiTextureVertex, uiTextureFragment);
const char* cubemapVertex = m_baseAP["cubemapVertex.shader"]->data;
const char* cubemapFragment = m_baseAP["cubemapFragment.shader"]->data;
m_cubemapShader = new Shader(cubemapVertex, cubemapFragment);
const char* fadeVertex = m_baseAP["fadeVertex.shader"]->data;
const char* fadeFragment = m_baseAP["fadeFragment.shader"]->data;
m_fadeShader = new Shader(fadeVertex, fadeFragment);
BaseAssets::cube = (AModel*)m_baseAP["cube.obj"];
BaseAssets::plane = (AModel*)m_baseAP["plane.obj"];
BaseAssets::sphere = (AModel*)m_baseAP["sphere.obj"];
BaseAssets::cone = (AModel*)m_baseAP["cone.obj"];
BaseAssets::cylinder = (AModel*)m_baseAP["cylinder.obj"];
BaseAssets::torus = (AModel*)m_baseAP["torus.obj"];
BaseAssets::logo = (ATexture*)m_baseAP["logo.png"];
BaseAssets::defaultFont = (AFont*)m_baseAP["default.ttf"];
loadBaseAssets();
float fadeVB[] = {
-1.0, -1.0,
@ -168,7 +144,7 @@ namespace nf {
//Draw cubemap where there isn't anything else
if (m_cubemap != nullptr) {
m_cubemapShader->setUniform("proj", proj);
m_cubemap->render();
m_cubemap->render(m_cubemapShader);
}
m_cubemap = nullptr;
@ -179,13 +155,19 @@ namespace nf {
UIElement& curr = *draw;
if (curr.identity() == "text") {
m_textShader->setUniform("proj", proj);
curr.render(m_textShader, m_app->getConfig().width, m_app->getConfig().height);
Text& text = *(Text*)draw;
text.render(m_textShader, m_app->getConfig().width, m_app->getConfig().height);
continue;
}
if (curr.identity() == "texture") {
else if (curr.identity() == "texture") {
m_uiTextureShader->setUniform("proj", proj);
curr.render(m_uiTextureShader, m_app->getConfig().width, m_app->getConfig().height);
}
else if (curr.identity() == "button") {
m_uiTextureShader->setUniform("proj", proj);
Button& button = *(Button*)draw;
button.render(m_uiTextureShader, m_app->getConfig().width, m_app->getConfig().height, m_app, m_textShader);
}
}
m_lUI.clear();
@ -236,6 +218,36 @@ namespace nf {
Error("OpenGL error " + std::to_string(err));
}
void Renderer::loadBaseAssets() {
m_baseAP.load("base.nfpack");
const char* entityVertex = m_baseAP["entityVertex.shader"]->data;
const char* entityFragment = m_baseAP["entityFragment.shader"]->data;
m_entityShader = new Shader(entityVertex, entityFragment);
const char* textVertex = m_baseAP["textVertex.shader"]->data;
const char* textFragment = m_baseAP["textFragment.shader"]->data;
m_textShader = new Shader(textVertex, textFragment);
const char* uiTextureVertex = m_baseAP["uiTextureVertex.shader"]->data;
const char* uiTextureFragment = m_baseAP["uiTextureFragment.shader"]->data;
m_uiTextureShader = new Shader(uiTextureVertex, uiTextureFragment);
const char* cubemapVertex = m_baseAP["cubemapVertex.shader"]->data;
const char* cubemapFragment = m_baseAP["cubemapFragment.shader"]->data;
m_cubemapShader = new Shader(cubemapVertex, cubemapFragment);
const char* fadeVertex = m_baseAP["fadeVertex.shader"]->data;
const char* fadeFragment = m_baseAP["fadeFragment.shader"]->data;
m_fadeShader = new Shader(fadeVertex, fadeFragment);
BaseAssets::cube = (AModel*)m_baseAP["cube.obj"];
BaseAssets::plane = (AModel*)m_baseAP["plane.obj"];
BaseAssets::sphere = (AModel*)m_baseAP["sphere.obj"];
BaseAssets::cone = (AModel*)m_baseAP["cone.obj"];
BaseAssets::cylinder = (AModel*)m_baseAP["cylinder.obj"];
BaseAssets::torus = (AModel*)m_baseAP["torus.obj"];
BaseAssets::logo = (ATexture*)m_baseAP["logo.png"];
BaseAssets::cubemap = (ACubemap*)m_baseAP["default.cm"];
BaseAssets::font = (AFont*)m_baseAP["default.ttf"];
BaseAssets::button = (AButton*)m_baseAP["default.button"];
}
Renderer::~Renderer() {
delete m_entityShader;
delete m_textShader;

View File

@ -32,8 +32,10 @@ namespace nf {
int getFPS() const;
bool isKeyHeld(unsigned int code);
bool isKeyPressed(unsigned int code);
bool isMouse(unsigned int code);
void trackMouse(bool track);
void getMouseDiff(int& x, int& y);
Vec2 getMousePos();
static Application* getApp();
void quit();
@ -79,7 +81,7 @@ namespace nf {
std::string m_nextState;
//Array of booleans that represent keyboard and mouse input minus the scrollwheel
std::array<std::pair<bool, bool>, 164> m_keys;
std::array<bool, 164> m_keysPressed;
unsigned int m_mouseX, m_mouseY;
bool m_trackingMouse;
bool m_mouseTrackFirst;

View File

@ -49,10 +49,6 @@ namespace nf {
~ACubemap();
};
struct AShader : Asset {
~AShader() override;
};
struct AFont : Asset {
size_t size = 0;
Font* loadedFont = nullptr;
@ -60,6 +56,20 @@ namespace nf {
~AFont() override;
};
struct AButton : Asset {
ATexture idleTex;
ATexture hoverTex;
ATexture pressedTex;
unsigned int numImages = 0;
~AButton() override;
};
struct AShader : Asset {
~AShader() override;
};
class AssetPack : public NFObject {
public:
AssetPack();
@ -85,7 +95,10 @@ namespace nf {
static ATexture* logo;
static AFont* defaultFont;
static ACubemap* cubemap;
static AFont* font;
static AButton* button;
};
}

View File

@ -0,0 +1,36 @@
#pragma once
#include <string>
#include "UIElement.h"
#include "NFObject.h"
#include "Text.h"
namespace nf {
class Application;
class Texture;
struct Asset;
class Button : public UIElement, public NFObject {
public:
Button();
void create(const Vec2& position, std::string string = "", Asset* buttonAsset = nf::BaseAssets::button, double scale = 1.0, double opacity = 1.0);
const char* identity() override;
void render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight, Application* app, Shader* textShader);
bool isClicked();
void destroy() override;
~Button();
private:
Texture* m_idleTexture;
Texture* m_hoverTexture;
Texture* m_pressedTexture;
Texture* m_currentTexture;
std::string m_string;
Text m_text;
float m_scale;
float m_opacity;
bool m_clicked;
bool m_triggered;
};
}

View File

@ -4,6 +4,7 @@
namespace nf {
struct Asset;
class Shader;
class Cubemap : public Drawable, public NFObject {
public:
@ -11,7 +12,7 @@ namespace nf {
void create(Asset* cubemapAsset);
bool isConstructed();
void render();
void render(Shader* shader);
void destroy() override;
~Cubemap();

View File

@ -30,7 +30,6 @@ namespace nf {
void render(Shader* shader);
void setBaseAsset(bool isBase);
bool isBaseAsset();
~Model();

View File

@ -15,6 +15,7 @@
#include "Cubemap.h"
#include "Text.h"
#include "UITexture.h"
#include "Button.h"
#include "Input.h"
namespace nf {
@ -85,8 +86,10 @@ namespace nf {
int getFPS() const;
bool isKeyHeld(unsigned int code);
bool isKeyPressed(unsigned int code);
bool isMouse(unsigned int code);
void trackMouse(bool track);
void getMouseDiff(int& x, int& y);
Vec2 getMousePos();
static Application* getApp();
void quit();
@ -132,7 +135,7 @@ namespace nf {
std::string m_nextState;
//Array of booleans that represent keyboard and mouse input minus the scrollwheel
std::array<std::pair<bool, bool>, 164> m_keys;
std::array<bool, 164> m_keysPressed;
unsigned int m_mouseX, m_mouseY;
bool m_trackingMouse;
bool m_mouseTrackFirst;

View File

@ -32,6 +32,8 @@ namespace nf {
~Renderer();
private:
void loadBaseAssets();
Application* m_app;
HDC m_hdc;

View File

@ -23,13 +23,13 @@ namespace nf {
public:
Text();
void create(const std::string& string, const Vec2& position, const Vec3& color = {1.0, 1.0, 1.0}, double opacity = 1.0, double scale = 1.0, Asset* font = BaseAssets::defaultFont);
void create(const std::string& string, const Vec2& position, const Vec3& color = {1.0, 1.0, 1.0}, double opacity = 1.0, double scale = 1.0, Asset* font = BaseAssets::font);
const char* identity() override;
void setText(const std::string& string);
void setColor(const Vec3& color);
void setScale(double scale);
void setOpacity(double opacity);
void render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight) override;
void render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight, bool onButton = false, float buttonWidth = 0.0f, float buttonHeight = 0.0f, const Vec2& buttonPos = Vec2());
void destroy() override;
~Text();

View File

@ -11,7 +11,7 @@ namespace nf {
UIElement();
virtual const char* identity();
void setPosition(float x, float y);
void setPosition(double x, double y);
void setPosition(const Vec2& position);
void centered(bool x, bool y = false);
bool isConstructed();

View File

@ -11,7 +11,7 @@ namespace nf {
public:
UITexture();
void create(Asset* textureAsset, const Vec2& position, double scale = 1.0, double opacity = 1.0 );
void create(Asset* textureAsset, const Vec2& position, double scale = 1.0, double opacity = 1.0);
const char* identity() override;
void setScale(double scale);
void setOpacity(double opacity);

View File

@ -15,7 +15,7 @@ namespace nf {
#define SleepMS(x) std::this_thread::sleep_for(std::chrono::milliseconds(x))
//Prints a nicely-formatted message complete with a timestamp
#define Log(x) nf::Debug::LogImp(x)
//Prints error message and breaks the debugger
//Prints error message and breaks the debugger in debug mode
#define Error(x) {nf::Debug::ErrorImp(x,__FILENAME__, __LINE__);\
__debugbreak();}
@ -34,6 +34,7 @@ __debugbreak();}
#else
#define DEBUGINIT
#define Log(x)
//Shows error dialog with specified message then exits
#define Error(x) {MessageBox(FindWindow(L"NFClass", NULL), toWide(x), L"NF Engine Error", MB_OK | MB_ICONERROR);\
std::exit(-1);}
#endif
@ -54,6 +55,9 @@ std::exit(-1);}
this->y -= rhs.y;
return *this;
}
bool operator==(const Vec2& rhs) {
return this->x == rhs.x && this->y == rhs.y;
}
double x, y;
};
struct Vec3 {
@ -75,6 +79,9 @@ std::exit(-1);}
this->z -= rhs.z;
return *this;
}
bool operator==(const Vec3& rhs) {
return this->x == rhs.x && this->y == rhs.y && this->z == rhs.z ;
}
double x, y, z;
};