From cbafb9a68b7dde02b1ff5fb96281a34558ca4201 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 19 Nov 2023 17:44:14 +0300 Subject: [PATCH 01/13] Image related leaks fix --- src/assets/AssetsLoader.cpp | 12 +++++++----- src/coders/png.cpp | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 4b004d97..f74c3348 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -2,9 +2,12 @@ #include "Assets.h" #include +#include #include "../constants.h" +using std::unique_ptr; + AssetsLoader::AssetsLoader(Assets* assets) : assets(assets) { } @@ -62,18 +65,17 @@ bool _load_texture(Assets* assets, const std::string& filename, const std::strin } bool _load_atlas(Assets* assets, const std::string& filename, const std::string& name) { - ImageData* image = png::load_image(filename); + unique_ptr image (png::load_image(filename)); if (image == nullptr) { std::cerr << "failed to load image '" << name << "'" << std::endl; return false; } for (int i = 0; i < ATLAS_MARGIN_SIZE; i++) { - ImageData* newimage = add_atlas_margins(image, 16); - delete image; - image = newimage; + ImageData* newimage = add_atlas_margins(image.get(), 16); + image.reset(newimage); } - Texture* texture = Texture::from(image); + Texture* texture = Texture::from(image.get()); assets->store(texture, name); return true; } diff --git a/src/coders/png.cpp b/src/coders/png.cpp index e4d7090b..e15e0a98 100644 --- a/src/coders/png.cpp +++ b/src/coders/png.cpp @@ -326,12 +326,12 @@ ImageData* png::load_image(std::string filename) { } Texture* png::load_texture(std::string filename) { - ImageData* image = _png_load(filename.c_str()); + unique_ptr image (_png_load(filename.c_str())); if (image == nullptr){ std::cerr << "Could not load image " << filename << std::endl; return nullptr; } - return Texture::from(image); + return Texture::from(image.get()); } void png::write_image(std::string filename, const ImageData* image) { From 6d9070f3460084eb853c3633970e4f6a831a4fdb Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 19 Nov 2023 18:22:34 +0300 Subject: [PATCH 02/13] missing 'worlds' directory check fix --- src/frontend/screens.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/frontend/screens.cpp b/src/frontend/screens.cpp index 984ebc0e..0a45adfa 100644 --- a/src/frontend/screens.cpp +++ b/src/frontend/screens.cpp @@ -52,20 +52,23 @@ shared_ptr create_main_menu_panel(Engine* engine) { Panel* worldsPanel = new Panel(vec2(390, 200), vec4(5.0f)); worldsPanel->color(vec4(0.1f)); - for (auto const& entry : directory_iterator(enginefs::get_worlds_folder())) { - string name = entry.path().filename().string(); - Button* button = new Button(util::str2wstr_utf8(name), - vec4(10.0f, 8.0f, 10.0f, 8.0f)); - button->color(vec4(0.5f)); - button->listenAction([engine, panel, name](GUI*) { - EngineSettings& settings = engine->getSettings(); + path worldsFolder = enginefs::get_worlds_folder(); + if (std::filesystem::is_directory(worldsFolder)) { + for (auto const& entry : directory_iterator(worldsFolder)) { + string name = entry.path().filename().string(); + Button* button = new Button(util::str2wstr_utf8(name), + vec4(10.0f, 8.0f, 10.0f, 8.0f)); + button->color(vec4(0.5f)); + button->listenAction([engine, panel, name](GUI*) { + EngineSettings& settings = engine->getSettings(); - auto folder = enginefs::get_worlds_folder()/u8path(name); - World* world = new World(name, folder, 42, settings); - auto screen = new LevelScreen(engine, world->load(settings)); - engine->setScreen(shared_ptr(screen)); - }); - worldsPanel->add(button); + auto folder = enginefs::get_worlds_folder()/u8path(name); + World* world = new World(name, folder, 42, settings); + auto screen = new LevelScreen(engine, world->load(settings)); + engine->setScreen(shared_ptr(screen)); + }); + worldsPanel->add(button); + } } panel->add(worldsPanel); From 2ee9e33c6d677ce232449c0945a42dd2f7740c72 Mon Sep 17 00:00:00 2001 From: Che10vek Date: Mon, 20 Nov 2023 01:30:57 +1000 Subject: [PATCH 03/13] resources paths refact --- res/{ => fonts}/font.png | Bin res/{ => fonts}/font_0.png | Bin res/{ => fonts}/font_1.png | Bin res/{ => fonts}/font_2.png | Bin res/{ => fonts}/font_3.png | Bin res/{ => fonts}/font_4.png | Bin res/{ => shaders}/lines.glslf | 0 res/{ => shaders}/lines.glslv | 0 res/{ => shaders}/main.glslf | 0 res/{ => shaders}/main.glslv | 0 res/{ => shaders}/screen.glslf | 0 res/{ => shaders}/screen.glslv | 0 res/{ => shaders}/ui.glslf | 0 res/{ => shaders}/ui.glslv | 0 res/{ => textures}/block.png | Bin res/{ => textures}/menubg.png | Bin res/{ => textures}/slot.png | Bin src/assets/AssetsLoader.cpp | 16 ++++++++-------- src/constants.h | 6 ++++++ src/typedefs.h | 5 +++++ 20 files changed, 19 insertions(+), 8 deletions(-) rename res/{ => fonts}/font.png (100%) rename res/{ => fonts}/font_0.png (100%) rename res/{ => fonts}/font_1.png (100%) rename res/{ => fonts}/font_2.png (100%) rename res/{ => fonts}/font_3.png (100%) rename res/{ => fonts}/font_4.png (100%) rename res/{ => shaders}/lines.glslf (100%) rename res/{ => shaders}/lines.glslv (100%) rename res/{ => shaders}/main.glslf (100%) rename res/{ => shaders}/main.glslv (100%) rename res/{ => shaders}/screen.glslf (100%) rename res/{ => shaders}/screen.glslv (100%) rename res/{ => shaders}/ui.glslf (100%) rename res/{ => shaders}/ui.glslv (100%) rename res/{ => textures}/block.png (100%) rename res/{ => textures}/menubg.png (100%) rename res/{ => textures}/slot.png (100%) diff --git a/res/font.png b/res/fonts/font.png similarity index 100% rename from res/font.png rename to res/fonts/font.png diff --git a/res/font_0.png b/res/fonts/font_0.png similarity index 100% rename from res/font_0.png rename to res/fonts/font_0.png diff --git a/res/font_1.png b/res/fonts/font_1.png similarity index 100% rename from res/font_1.png rename to res/fonts/font_1.png diff --git a/res/font_2.png b/res/fonts/font_2.png similarity index 100% rename from res/font_2.png rename to res/fonts/font_2.png diff --git a/res/font_3.png b/res/fonts/font_3.png similarity index 100% rename from res/font_3.png rename to res/fonts/font_3.png diff --git a/res/font_4.png b/res/fonts/font_4.png similarity index 100% rename from res/font_4.png rename to res/fonts/font_4.png diff --git a/res/lines.glslf b/res/shaders/lines.glslf similarity index 100% rename from res/lines.glslf rename to res/shaders/lines.glslf diff --git a/res/lines.glslv b/res/shaders/lines.glslv similarity index 100% rename from res/lines.glslv rename to res/shaders/lines.glslv diff --git a/res/main.glslf b/res/shaders/main.glslf similarity index 100% rename from res/main.glslf rename to res/shaders/main.glslf diff --git a/res/main.glslv b/res/shaders/main.glslv similarity index 100% rename from res/main.glslv rename to res/shaders/main.glslv diff --git a/res/screen.glslf b/res/shaders/screen.glslf similarity index 100% rename from res/screen.glslf rename to res/shaders/screen.glslf diff --git a/res/screen.glslv b/res/shaders/screen.glslv similarity index 100% rename from res/screen.glslv rename to res/shaders/screen.glslv diff --git a/res/ui.glslf b/res/shaders/ui.glslf similarity index 100% rename from res/ui.glslf rename to res/shaders/ui.glslf diff --git a/res/ui.glslv b/res/shaders/ui.glslv similarity index 100% rename from res/ui.glslv rename to res/shaders/ui.glslv diff --git a/res/block.png b/res/textures/block.png similarity index 100% rename from res/block.png rename to res/textures/block.png diff --git a/res/menubg.png b/res/textures/menubg.png similarity index 100% rename from res/menubg.png rename to res/textures/menubg.png diff --git a/res/slot.png b/res/textures/slot.png similarity index 100% rename from res/slot.png rename to res/textures/slot.png diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index f74c3348..2e62556e 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -103,14 +103,14 @@ void AssetsLoader::createDefaults(AssetsLoader& loader) { } void AssetsLoader::addDefaults(AssetsLoader& loader) { - loader.add(ASSET_SHADER, "res/main", "main"); - loader.add(ASSET_SHADER, "res/lines", "lines"); - loader.add(ASSET_SHADER, "res/ui", "ui"); + loader.add(ASSET_SHADER, SHADERS_FOLDER"/main", "main"); + loader.add(ASSET_SHADER, SHADERS_FOLDER"/lines", "lines"); + loader.add(ASSET_SHADER, SHADERS_FOLDER"/ui", "ui"); - loader.add(ASSET_ATLAS, "res/block.png", "block"); - loader.add(ASSET_TEXTURE, "res/block.png", "block_tex"); - loader.add(ASSET_TEXTURE, "res/slot.png", "slot"); - loader.add(ASSET_TEXTURE, "res/menubg.png", "menubg"); + loader.add(ASSET_ATLAS, TEXTURES_FOLDER"/block.png", "block"); + loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/block.png", "block_tex"); + loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/slot.png", "slot"); + loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/menubg.png", "menubg"); - loader.add(ASSET_FONT, "res/font", "normal"); + loader.add(ASSET_FONT, FONTS_FOLDER"/font", "normal"); } diff --git a/src/constants.h b/src/constants.h index 06d0f67a..97a3f4e7 100644 --- a/src/constants.h +++ b/src/constants.h @@ -20,4 +20,10 @@ inline uint vox_index(int x, int y, int z, int w, int d) { #define ATLAS_MARGIN_SIZE 2 +#define RES_FLODER "res/" + +#define SHADERS_FOLDER "res/shaders" +#define TEXTURES_FOLDER "res/textures" +#define FONTS_FOLDER "res/fonts" + #endif // SRC_CONSTANTS_H_ diff --git a/src/typedefs.h b/src/typedefs.h index 8bc06297..920015c6 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -1,3 +1,6 @@ +#ifndef VOX_TYPEDEFS_H +#define VOX_TYPEDEFS_H + #include #include @@ -6,3 +9,5 @@ typedef unsigned char ubyte; typedef uint8_t blockid_t; typedef uint16_t light_t; + +#endif From ea729760d4353026cbb40cc07209e076bb34cae5 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 19 Nov 2023 19:46:14 +0300 Subject: [PATCH 04/13] stone block texture brightness increased --- res/textures/block.png | Bin 16151 -> 16371 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/res/textures/block.png b/res/textures/block.png index 3766eb6f3373d07531dcd49296ee41551c8e181e..8309b5457485627e3f5613dd68c01806e2ddab0c 100644 GIT binary patch delta 11871 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 Z{|o4`s_8U03?u*m002ovPDHLkV1lYrsyF}u delta 11831 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 From e3743b84639c625869fd127f677f122f5fd2d923 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 19 Nov 2023 20:18:44 +0300 Subject: [PATCH 05/13] GfxContext, render refactor --- src/frontend/hud.cpp | 75 ++++++++++--------- src/frontend/hud.h | 8 +- src/frontend/screens.cpp | 8 +- src/frontend/world_render.cpp | 130 ++++++++++++++++++--------------- src/frontend/world_render.h | 6 +- src/graphics/Batch2D.cpp | 4 + src/graphics/Batch2D.h | 2 + src/graphics/GfxContext.cpp | 59 +++++++++++++++ src/graphics/GfxContext.h | 27 +++++++ src/graphics/Viewport.cpp | 13 ++++ src/graphics/Viewport.h | 22 ++++++ src/objects/player_control.cpp | 19 ++++- 12 files changed, 270 insertions(+), 103 deletions(-) create mode 100644 src/graphics/GfxContext.cpp create mode 100644 src/graphics/GfxContext.h create mode 100644 src/graphics/Viewport.cpp create mode 100644 src/graphics/Viewport.h diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index e95bedf2..1e72d7fb 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -44,9 +44,9 @@ inline Label* create_label(gui::wstringsupplier supplier) { return label; } -HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(engine->getAssets()), guiController(engine->getGUI()) { +HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(engine->getAssets()), gui(engine->getGUI()) { batch = new Batch2D(1024); - uicamera = new Camera(vec3(), Window::height); + uicamera = new Camera(vec3(), 1); uicamera->perspective = false; uicamera->flipped = true; @@ -139,13 +139,13 @@ HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(en panel->add(shared_ptr(button)); } panel->visible(false); - guiController->add(this->debugPanel); - guiController->add(this->pauseMenu); + gui->add(this->debugPanel); + gui->add(this->pauseMenu); } HudRenderer::~HudRenderer() { - guiController->remove(debugPanel); - guiController->remove(pauseMenu); + gui->remove(debugPanel); + gui->remove(pauseMenu); delete batch; delete uicamera; } @@ -157,7 +157,11 @@ void HudRenderer::drawDebug(int fps, bool occlusion){ fpsMax = max(fps, fpsMax); } -void HudRenderer::drawInventory(Player* player) { +void HudRenderer::drawInventory(const GfxContext& ctx, Player* player) { + const Viewport& viewport = ctx.getViewport(); + const uint width = viewport.getWidth(); + const uint height = viewport.getHeight(); + Texture* blocks = assets->getTexture("block_tex"); uint size = 48; uint step = 64; @@ -165,15 +169,15 @@ void HudRenderer::drawInventory(Player* player) { uint inv_rows = 8; uint inv_w = step*inv_cols + size; uint inv_h = step*inv_rows + size; - int inv_x = (Window::width - (inv_w)) / 2; - int inv_y = (Window::height - (inv_h)) / 2; - int xs = (Window::width - inv_w + step)/2; - int ys = (Window::height - inv_h + step)/2; - if (Window::width > inv_w*3){ - inv_x = (Window::width + (inv_w)) / 2; - inv_y = (Window::height - (inv_h)) / 2; - xs = (Window::width + inv_w + step)/2; - ys = (Window::height - inv_h + step)/2; + int inv_x = (width - (inv_w)) / 2; + int inv_y = (height - (inv_h)) / 2; + int xs = (width - inv_w + step)/2; + int ys = (height - inv_h + step)/2; + if (width > inv_w*3){ + inv_x = (width + (inv_w)) / 2; + inv_y = (height - (inv_h)) / 2; + xs = (width + inv_w + step)/2; + ys = (height - inv_h + step)/2; } vec4 tint = vec4(1.0f); int mx = Events::x; @@ -234,17 +238,18 @@ void HudRenderer::drawInventory(Player* player) { } } -void HudRenderer::draw(){ +void HudRenderer::draw(const GfxContext& ctx){ + const Viewport& viewport = ctx.getViewport(); + const uint width = viewport.getWidth(); + const uint height = viewport.getHeight(); + debugPanel->visible(level->player->debug); - pauseMenu->setCoord((Window::size() - pauseMenu->size()) / 2.0f); + pauseMenu->setCoord((viewport.size() - pauseMenu->size()) / 2.0f); - auto settingsPanel = guiController->get("settings"); - settingsPanel->setCoord((Window::size() - settingsPanel->size()) / 2.0f); + auto settingsPanel = gui->get("settings"); + settingsPanel->setCoord((viewport.size() - settingsPanel->size()) / 2.0f); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - - uicamera->fov = Window::height; + uicamera->fov = height; Shader* uishader = assets->getShader("ui"); uishader->use(); @@ -256,9 +261,7 @@ void HudRenderer::draw(){ batch->texture(nullptr); batch->color = vec4(1.0f); if (Events::_cursor_locked && !level->player->debug) { - glLineWidth(2); - const uint width = Window::width; - const uint height = Window::height; + batch->lineWidth(2); batch->line(width/2, height/2-6, width/2, height/2+6, 0.2f, 0.2f, 0.2f, 1.0f); batch->line(width/2+6, height/2, width/2-6, height/2, 0.2f, 0.2f, 0.2f, 1.0f); batch->line(width/2-5, height/2-5, width/2+5, height/2+5, 0.9f, 0.9f, 0.9f, 1.0f); @@ -266,19 +269,19 @@ void HudRenderer::draw(){ } Player* player = level->player; - batch->rect(Window::width/2-128-4, Window::height-80-4, 256+8, 64+8, + batch->rect(width/2-128-4, height-80-4, 256+8, 64+8, 0.95f, 0.95f, 0.95f, 0.85f, 0.85f, 0.85f, 0.7f, 0.7f, 0.7f, 0.55f, 0.55f, 0.55f, 0.45f, 0.45f, 0.45f, 4); - batch->rect(Window::width/2-128, Window::height - 80, 256, 64, + batch->rect(width/2-128, height - 80, 256, 64, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 4); - batch->rect(Window::width/2-32+2, Window::height - 80+2, 60, 60, + batch->rect(width/2-32+2, height - 80+2, 60, 60, 0.45f, 0.45f, 0.45f, 0.55f, 0.55f, 0.55f, 0.7f, 0.7f, 0.7f, 0.85f, 0.85f, 0.85f, 0.95f, 0.95f, 0.95f, 2); - batch->rect(Window::width/2-32+4, Window::height - 80+4, 56, 56, + batch->rect(width/2-32+4, height - 80+4, 56, 56, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 2); @@ -288,13 +291,13 @@ void HudRenderer::draw(){ { Block* cblock = Block::blocks[player->choosenBlock]; if (cblock->model == BlockModel::block){ - batch->blockSprite(Window::width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces, vec4(1.0f)); + batch->blockSprite(width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces, vec4(1.0f)); } else if (cblock->model == BlockModel::xsprite){ - batch->sprite(Window::width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces[3], vec4(1.0f)); + batch->sprite(width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces[3], vec4(1.0f)); } } - if (Events::jpressed(keycode::ESCAPE) && !guiController->isFocusCaught()) { + if (Events::jpressed(keycode::ESCAPE) && !gui->isFocusCaught()) { if (pause) { pause = false; pauseMenu->visible(false); @@ -317,10 +320,10 @@ void HudRenderer::draw(){ if (pause || inventoryOpen) { batch->texture(nullptr); batch->color = vec4(0.0f, 0.0f, 0.0f, 0.5f); - batch->rect(0, 0, Window::width, Window::height); + batch->rect(0, 0, width, height); } if (inventoryOpen) { - drawInventory(player); + drawInventory(ctx, player); } batch->render(); } diff --git a/src/frontend/hud.h b/src/frontend/hud.h index a9b0ae4a..0dd0466d 100644 --- a/src/frontend/hud.h +++ b/src/frontend/hud.h @@ -4,6 +4,8 @@ #include #include +#include "../graphics/GfxContext.h" + class Batch2D; class Camera; class Level; @@ -33,12 +35,12 @@ class HudRenderer { std::shared_ptr debugPanel; std::shared_ptr pauseMenu; - gui::GUI* guiController; + gui::GUI* gui; public: HudRenderer(Engine* engine, Level* level); ~HudRenderer(); - void drawInventory(Player* player); - void draw(); + void drawInventory(const GfxContext& ctx, Player* player); + void draw(const GfxContext& context); void drawDebug(int fps, bool occlusion); bool isInventoryOpen() const; diff --git a/src/frontend/screens.cpp b/src/frontend/screens.cpp index 0a45adfa..e6d13241 100644 --- a/src/frontend/screens.cpp +++ b/src/frontend/screens.cpp @@ -13,6 +13,7 @@ #include "../window/input.h" #include "../graphics/Shader.h" #include "../graphics/Batch2D.h" +#include "../graphics/GfxContext.h" #include "../assets/Assets.h" #include "../world/Level.h" #include "../world/World.h" @@ -356,8 +357,11 @@ void LevelScreen::update(float delta) { void LevelScreen::draw(float delta) { Camera* camera = level->player->camera; - worldRenderer->draw(camera, occlusion); - hud->draw(); + Viewport viewport(Window::width, Window::height); + GfxContext ctx(nullptr, viewport, nullptr); + + worldRenderer->draw(ctx, camera, occlusion); + hud->draw(ctx); if (level->player->debug) { hud->drawDebug( 1 / delta, occlusion); } diff --git a/src/frontend/world_render.cpp b/src/frontend/world_render.cpp index c3227872..5e102287 100644 --- a/src/frontend/world_render.cpp +++ b/src/frontend/world_render.cpp @@ -60,51 +60,15 @@ bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool } mat4 model = glm::translate(mat4(1.0f), vec3(chunk->x*CHUNK_W, 0.0f, chunk->z*CHUNK_D+1)); shader->uniformMatrix("u_model", model); - mesh->draw(GL_TRIANGLES); + mesh->draw(); return true; } - -void WorldRenderer::draw(Camera* camera, bool occlusion){ - EngineSettings& settings = engine->getSettings(); - Assets* assets = engine->getAssets(); - Chunks* chunks = level->chunks; - - vec3 skyColor(0.7f, 0.81f, 1.0f); - - Window::setBgColor(skyColor); - Window::clear(); - Window::viewport(0, 0, Window::width, Window::height); - - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - - float fogFactor = 18.0f / (float)settings.chunks.loadDistance; - - Texture* texture = assets->getTexture("block"); - Shader* shader = assets->getShader("main"); - Shader* linesShader = assets->getShader("lines"); - shader->use(); - shader->uniformMatrix("u_proj", camera->getProjection()); - shader->uniformMatrix("u_view", camera->getView()); - shader->uniform1f("u_gamma", 1.6f); - shader->uniform3f("u_skyLightColor", 1.1f,1.1f,1.1f); - shader->uniform3f("u_fogColor", skyColor); - shader->uniform1f("u_fogFactor", fogFactor); - shader->uniform1f("u_fogCurve", settings.graphics.fogCurve); - shader->uniform3f("u_cameraPos", camera->position); - - Block* cblock = Block::blocks[level->player->choosenBlock]; - float multiplier = 0.5f; - shader->uniform3f("u_torchlightColor", - cblock->emission[0] / 15.0f * multiplier, - cblock->emission[1] / 15.0f * multiplier, - cblock->emission[2] / 15.0f * multiplier); - shader->uniform1f("u_torchlightDistance", 6.0f); - texture->bind(); - +void WorldRenderer::drawChunks(Chunks* chunks, + Camera* camera, + Shader* shader, + bool occlusion) { std::vector indices; - for (size_t i = 0; i < chunks->volume; i++){ shared_ptr chunk = chunks->chunks[i]; if (chunk == nullptr) @@ -126,34 +90,84 @@ void WorldRenderer::draw(Camera* camera, bool occlusion){ for (size_t i = 0; i < indices.size(); i++){ chunks->visible += drawChunk(indices[i], camera, shader, occlusion); } +} - shader->uniformMatrix("u_model", mat4(1.0f)); - if (level->playerController->selectedBlockId != -1){ - Block* selectedBlock = Block::blocks[level->playerController->selectedBlockId]; - vec3 pos = level->playerController->selectedBlockPosition; - linesShader->use(); - linesShader->uniformMatrix("u_projview", camera->getProjection()*camera->getView()); - glLineWidth(2.0f); - if (selectedBlock->model == BlockModel::block){ - lineBatch->box(pos.x+0.5f, pos.y+0.5f, pos.z+0.5f, 1.005f,1.005f,1.005f, 0,0,0,0.5f); - } else if (selectedBlock->model == BlockModel::xsprite){ - lineBatch->box(pos.x+0.5f, pos.y+0.35f, pos.z+0.5f, 0.805f,0.705f,0.805f, 0,0,0,0.5f); +void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion){ + Assets* assets = engine->getAssets(); + Texture* texture = assets->getTexture("block"); + Shader* shader = assets->getShader("main"); + Shader* linesShader = assets->getShader("lines"); + + const Viewport& viewport = pctx.getViewport(); + int displayWidth = viewport.getWidth(); + int displayHeight = viewport.getHeight(); + { + GfxContext ctx = pctx.sub(); + ctx.depthTest(true); + ctx.cullFace(true); + + EngineSettings& settings = engine->getSettings(); + + vec3 skyColor(0.7f, 0.81f, 1.0f); + + Window::setBgColor(skyColor); + Window::clear(); + Window::viewport(0, 0, displayWidth, displayHeight); + + float fogFactor = 18.0f / (float)settings.chunks.loadDistance; + + shader->use(); + shader->uniformMatrix("u_proj", camera->getProjection()); + shader->uniformMatrix("u_view", camera->getView()); + shader->uniform1f("u_gamma", 1.6f); + shader->uniform3f("u_skyLightColor", 1.1f,1.1f,1.1f); + shader->uniform3f("u_fogColor", skyColor); + shader->uniform1f("u_fogFactor", fogFactor); + shader->uniform1f("u_fogCurve", settings.graphics.fogCurve); + shader->uniform3f("u_cameraPos", camera->position); + + Block* cblock = Block::blocks[level->player->choosenBlock]; + float multiplier = 0.5f; + shader->uniform3f("u_torchlightColor", + cblock->emission[0] / 15.0f * multiplier, + cblock->emission[1] / 15.0f * multiplier, + cblock->emission[2] / 15.0f * multiplier); + shader->uniform1f("u_torchlightDistance", 6.0f); + texture->bind(); + + Chunks* chunks = level->chunks; + drawChunks(chunks, camera, shader, occlusion); + + shader->uniformMatrix("u_model", mat4(1.0f)); + + if (level->playerController->selectedBlockId != -1){ + Block* block = Block::blocks[level->playerController->selectedBlockId]; + vec3 pos = level->playerController->selectedBlockPosition; + linesShader->use(); + linesShader->uniformMatrix("u_projview", camera->getProjView()); + lineBatch->lineWidth(2.0f); + if (block->model == BlockModel::block){ + lineBatch->box(pos.x+0.5f, pos.y+0.5f, pos.z+0.5f, + 1.008f,1.008f,1.008f, 0,0,0,0.5f); + } else if (block->model == BlockModel::xsprite){ + lineBatch->box(pos.x+0.5f, pos.y+0.35f, pos.z+0.5f, + 0.805f,0.705f,0.805f, 0,0,0,0.5f); + } + lineBatch->render(); } - lineBatch->render(); } - glDisable(GL_DEPTH_TEST); - if (level->player->debug) { float length = 40.f; linesShader->use(); - vec3 tsl = vec3(Window::width/2, -((int)Window::height)/2, 0.f); + // top-right: vec3 tsl = vec3(displayWidth - length - 4, -length - 4, 0.f); + vec3 tsl = vec3(displayWidth/2, -((int)displayHeight)/2, 0.f); glm::mat4 model(glm::translate(glm::mat4(1.f), tsl)); linesShader->uniformMatrix("u_projview", glm::ortho( - 0.f, (float)Window::width, - -(float)Window::height, 0.f, + 0.f, (float)displayWidth, + -(float)displayHeight, 0.f, -length, length) * model * glm::inverse(camera->rotation)); lineBatch->lineWidth(4.0f); diff --git a/src/frontend/world_render.h b/src/frontend/world_render.h index 34e9df8b..3ff65c19 100644 --- a/src/frontend/world_render.h +++ b/src/frontend/world_render.h @@ -10,6 +10,8 @@ #include #include +#include "../graphics/GfxContext.h" + class Level; class Camera; class LineBatch; @@ -18,6 +20,7 @@ class Shader; class Texture; class Frustum; class Engine; +class Chunks; class WorldRenderer { Engine* engine; @@ -26,12 +29,13 @@ class WorldRenderer { LineBatch* lineBatch; ChunksRenderer* renderer; bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion); + void drawChunks(Chunks* chunks, Camera* camera, Shader* shader, bool occlusion); public: WorldRenderer(Engine* engine, Level* level); ~WorldRenderer(); - void draw(Camera* camera, bool occlusion); + void draw(const GfxContext& context, Camera* camera, bool occlusion); }; diff --git a/src/graphics/Batch2D.cpp b/src/graphics/Batch2D.cpp index e74a72a4..c27af864 100644 --- a/src/graphics/Batch2D.cpp +++ b/src/graphics/Batch2D.cpp @@ -361,3 +361,7 @@ void Batch2D::render(unsigned int gl_primitive) { void Batch2D::render() { render(GL_TRIANGLES); } + +void Batch2D::lineWidth(float width) { + glLineWidth(width); +} diff --git a/src/graphics/Batch2D.h b/src/graphics/Batch2D.h index 3f2933b9..6d66106f 100644 --- a/src/graphics/Batch2D.h +++ b/src/graphics/Batch2D.h @@ -62,6 +62,8 @@ public: float r4, float g4, float b4, int sh); void render(unsigned int gl_primitive); void render(); + + void lineWidth(float width); }; #endif /* SRC_GRAPHICS_BATCH2D_H_ */ diff --git a/src/graphics/GfxContext.cpp b/src/graphics/GfxContext.cpp new file mode 100644 index 00000000..e15dd5bf --- /dev/null +++ b/src/graphics/GfxContext.cpp @@ -0,0 +1,59 @@ +#include "GfxContext.h" + +#include + +#include "Batch2D.h" + +GfxContext::GfxContext(const GfxContext* parent, Viewport& viewport, Batch2D* g2d) + : parent(parent), viewport(viewport), g2d(g2d) { +} + +GfxContext::~GfxContext() { + if (parent == nullptr) + return; + if (depthTest_ != parent->depthTest_) { + if (depthTest_) glDisable(GL_DEPTH_TEST); + else glEnable(GL_DEPTH_TEST); + } + if (cullFace_ != parent->cullFace_) { + if (cullFace_) glDisable(GL_CULL_FACE); + else glEnable(GL_CULL_FACE); + } +} + +const Viewport& GfxContext::getViewport() const { + return viewport; +} + +Batch2D* GfxContext::getBatch2D() const { + return g2d; +} + +GfxContext GfxContext::sub() const { + auto ctx = GfxContext(this, viewport, g2d); + ctx.depthTest_ = depthTest_; + ctx.cullFace_ = cullFace_; + return ctx; +} + +void GfxContext::depthTest(bool flag) { + if (depthTest_ == flag) + return; + depthTest_ = flag; + if (depthTest_) { + glEnable(GL_DEPTH_TEST); + } else { + glDisable(GL_DEPTH_TEST); + } +} + +void GfxContext::cullFace(bool flag) { + if (cullFace_ == flag) + return; + cullFace_ = flag; + if (cullFace_) { + glEnable(GL_CULL_FACE); + } else { + glDisable(GL_CULL_FACE); + } +} \ No newline at end of file diff --git a/src/graphics/GfxContext.h b/src/graphics/GfxContext.h new file mode 100644 index 00000000..43e97b5c --- /dev/null +++ b/src/graphics/GfxContext.h @@ -0,0 +1,27 @@ +#ifndef GRAPHICS_GFX_CONTEXT_H_ +#define GRAPHICS_GFX_CONTEXT_H_ + +#include "../typedefs.h" +#include "Viewport.h" + +class Batch2D; + +class GfxContext { + const GfxContext* parent; + Viewport& viewport; + Batch2D* const g2d; + bool depthTest_ = false; + bool cullFace_ = false; +public: + GfxContext(const GfxContext* parent, Viewport& viewport, Batch2D* g2d); + ~GfxContext(); + + Batch2D* getBatch2D() const; + const Viewport& getViewport() const; + GfxContext sub() const; + + void depthTest(bool flag); + void cullFace(bool flag); +}; + +#endif // GRAPHICS_GFX_CONTEXT_H_ \ No newline at end of file diff --git a/src/graphics/Viewport.cpp b/src/graphics/Viewport.cpp new file mode 100644 index 00000000..166d28f8 --- /dev/null +++ b/src/graphics/Viewport.cpp @@ -0,0 +1,13 @@ +#include "Viewport.h" + +Viewport::Viewport(uint width, uint height) + : width(width), height(height) { +} + +uint Viewport::getWidth() const { + return width; +} + +uint Viewport::getHeight() const { + return height; +} \ No newline at end of file diff --git a/src/graphics/Viewport.h b/src/graphics/Viewport.h new file mode 100644 index 00000000..da027b8e --- /dev/null +++ b/src/graphics/Viewport.h @@ -0,0 +1,22 @@ +#ifndef GRAPHICS_VIEWPORT_H_ +#define GRAPHICS_VIEWPORT_H_ + +#include + +#include "../typedefs.h" + +class Viewport { + uint width; + uint height; +public: + Viewport(uint width, uint height); + + virtual uint getWidth() const; + virtual uint getHeight() const; + + glm::vec2 size() const { + return glm::vec2(width, height); + } +}; + +#endif // GRAPHICS_VIEWPORT_H_ \ No newline at end of file diff --git a/src/objects/player_control.cpp b/src/objects/player_control.cpp index 6c3b4fdc..73273ebf 100644 --- a/src/objects/player_control.cpp +++ b/src/objects/player_control.cpp @@ -215,8 +215,21 @@ void PlayerController::updateInteraction(){ Camera* camera = player->camera; vec3 end; vec3 norm; + + bool xkey = Events::pressed(keycode::X); + bool lclick = Events::jclicked(mousecode::BUTTON_1) || + (xkey && Events::clicked(mousecode::BUTTON_1)); + bool rclick = Events::jclicked(mousecode::BUTTON_2) || + (xkey && Events::clicked(mousecode::BUTTON_2)); + float maxDistance = 10.0f; + if (xkey) { + maxDistance *= 20.0f; + } vec3 iend; - voxel* vox = chunks->rayCast(camera->position, camera->front, 10.0f, end, norm, iend); + voxel* vox = chunks->rayCast(camera->position, + camera->front, + maxDistance, + end, norm, iend); if (vox != nullptr){ player->selectedVoxel = *vox; selectedBlockId = vox->id; @@ -238,11 +251,11 @@ void PlayerController::updateInteraction(){ } Block* block = Block::blocks[vox->id]; - if (Events::jclicked(mousecode::BUTTON_1) && block->breakable){ + if (lclick && block->breakable){ chunks->set(x,y,z, 0, 0); lighting->onBlockSet(x,y,z, 0); } - if (Events::jclicked(mousecode::BUTTON_2)){ + if (rclick){ if (block->model != BlockModel::xsprite){ x = (int)(iend.x)+(int)(norm.x); y = (int)(iend.y)+(int)(norm.y); From 9051db35262d63db84a3cbe7c916432b085c657c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 19 Nov 2023 22:37:15 +0300 Subject: [PATCH 06/13] bindings, controls.json file --- CMakeLists.txt | 1 + src/coders/json.cpp | 4 +++ src/coders/json.h | 1 + src/definitions.cpp | 16 +++++++++ src/definitions.h | 15 ++++++++- src/objects/player_control.cpp | 22 ++++++------- src/util/platform.cpp | 12 ++++--- src/util/platform.h | 4 ++- src/voxel_engine.cpp | 60 +++++++++++++++++++++++++++++++--- src/window/Events.cpp | 44 +++++++++++++++++++++++++ src/window/Events.h | 29 ++++++++++++++++ 11 files changed, 186 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bef1499..94762315 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ else() # additional warnings -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wundef + -Wswitch-enum -Wwrite-strings -Wno-unused-parameter) endif() diff --git a/src/coders/json.cpp b/src/coders/json.cpp index 648dc8d1..81741df3 100644 --- a/src/coders/json.cpp +++ b/src/coders/json.cpp @@ -258,6 +258,10 @@ JObject& JObject::put(string key, string value){ return *this; } +JObject& JObject::put(std::string key, const char* value) { + return put(key, string(value)); +} + JObject& JObject::put(string key, JObject* value){ auto found = map.find(key); if (found != map.end()) delete found->second; diff --git a/src/coders/json.h b/src/coders/json.h index 95fc4a23..f7b4c9cc 100644 --- a/src/coders/json.h +++ b/src/coders/json.h @@ -81,6 +81,7 @@ namespace json { JObject& put(std::string key, int value); JObject& put(std::string key, float value); JObject& put(std::string key, double value); + JObject& put(std::string key, const char* value); JObject& put(std::string key, std::string value); JObject& put(std::string key, JObject* value); JObject& put(std::string key, JArray* value); diff --git a/src/definitions.cpp b/src/definitions.cpp index 31d7be5f..68c40688 100644 --- a/src/definitions.cpp +++ b/src/definitions.cpp @@ -1,6 +1,8 @@ #include "definitions.h" #include "window/Window.h" +#include "window/Events.h" +#include "window/input.h" #include "voxels/Block.h" // All in-game definitions (blocks, items, etc..) @@ -91,3 +93,17 @@ void setup_definitions() { block = new Block(BLOCK_RUST, 19); Block::blocks[block->id] = block; } + +void setup_bindings() { + Events::bind(BIND_MOVE_FORWARD, inputtype::keyboard, keycode::W); + Events::bind(BIND_MOVE_BACK, inputtype::keyboard, keycode::S); + Events::bind(BIND_MOVE_RIGHT, inputtype::keyboard, keycode::D); + Events::bind(BIND_MOVE_LEFT, inputtype::keyboard, keycode::A); + Events::bind(BIND_MOVE_JUMP, inputtype::keyboard, keycode::SPACE); + Events::bind(BIND_MOVE_SPRINT, inputtype::keyboard, keycode::LEFT_CONTROL); + Events::bind(BIND_MOVE_CROUCH, inputtype::keyboard, keycode::LEFT_SHIFT); + Events::bind(BIND_MOVE_CHEAT, inputtype::keyboard, keycode::R); + Events::bind(BIND_CAM_ZOOM, inputtype::keyboard, keycode::C); + Events::bind(BIND_PLAYER_NOCLIP, inputtype::keyboard, keycode::N); + Events::bind(BIND_PLAYER_FLIGHT, inputtype::keyboard, keycode::F); +} \ No newline at end of file diff --git a/src/definitions.h b/src/definitions.h index 236ac204..3489d998 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -21,7 +21,20 @@ #define BLOCK_METAL 15 #define BLOCK_RUST 16 -void setup_definitions(); +#define BIND_MOVE_FORWARD "movement.forward" +#define BIND_MOVE_BACK "movement.back" +#define BIND_MOVE_LEFT "movement.left" +#define BIND_MOVE_RIGHT "movement.right" +#define BIND_MOVE_JUMP "movement.jump" +#define BIND_MOVE_SPRINT "movement.sprint" +#define BIND_MOVE_CROUCH "movement.crouch" +#define BIND_MOVE_CHEAT "movement.cheat" +#define BIND_CAM_ZOOM "camera.zoom" +#define BIND_PLAYER_NOCLIP "player.noclip" +#define BIND_PLAYER_FLIGHT "player.flight" + +extern void setup_bindings(); +extern void setup_definitions(); #endif // DECLARATIONS_H diff --git a/src/objects/player_control.cpp b/src/objects/player_control.cpp index 73273ebf..adc6df30 100644 --- a/src/objects/player_control.cpp +++ b/src/objects/player_control.cpp @@ -38,18 +38,18 @@ void PlayerController::refreshCamera() { } void PlayerController::updateKeyboard() { - input.zoom = Events::pressed(keycode::C); - input.moveForward = Events::pressed(keycode::W); - input.moveBack = Events::pressed(keycode::S); - input.moveLeft = Events::pressed(keycode::A); - input.moveRight = Events::pressed(keycode::D); - input.sprint = Events::pressed(keycode::LEFT_CONTROL); - input.shift = Events::pressed(keycode::LEFT_SHIFT); - input.cheat = Events::pressed(keycode::R); - input.jump = Events::pressed(keycode::SPACE); + input.moveForward = Events::active("movement.forward"); + input.moveBack = Events::active("movement.back"); + input.moveLeft = Events::active("movement.left"); + input.moveRight = Events::active("movement.right"); + input.sprint = Events::active("movement.sprint"); + input.shift = Events::active("movement.crouch"); + input.cheat = Events::active("movement.cheat"); + input.jump = Events::active("movement.jump"); + input.zoom = Events::active("camera.zoom"); - input.noclip = Events::jpressed(keycode::N); - input.flight = Events::jpressed(keycode::F); + input.noclip = Events::jactive("player.noclip"); + input.flight = Events::jactive("player.flight"); // block choice for (int i = 1; i < 10; i++){ diff --git a/src/util/platform.cpp b/src/util/platform.cpp index 8681d7fc..d4f338d9 100644 --- a/src/util/platform.cpp +++ b/src/util/platform.cpp @@ -1,19 +1,23 @@ #include "platform.h" #include -#include #include #include #include "../typedefs.h" #define SETTINGS_FILE "settings.toml" +#define CONTROLS_FILE "controls.json" -using std::string; +using std::filesystem::path; -string platform::get_settings_file() { - return SETTINGS_FILE; +path platform::get_settings_file() { + return path(SETTINGS_FILE); +} + +path platform::get_controls_file() { + return path(CONTROLS_FILE); } #ifdef WIN32 diff --git a/src/util/platform.h b/src/util/platform.h index a56e7d3a..65ed3ce8 100644 --- a/src/util/platform.h +++ b/src/util/platform.h @@ -2,10 +2,12 @@ #define UTIL_PLATFORM_H_ #include +#include namespace platform { extern void configure_encoding(); - extern std::string get_settings_file(); + extern std::filesystem::path get_settings_file(); + extern std::filesystem::path get_controls_file(); } #endif // UTIL_PLATFORM_H_ \ No newline at end of file diff --git a/src/voxel_engine.cpp b/src/voxel_engine.cpp index b0a57e77..7f0f882e 100644 --- a/src/voxel_engine.cpp +++ b/src/voxel_engine.cpp @@ -1,9 +1,9 @@ #include #include #include - #include #include +#include #include "definitions.h" @@ -11,8 +11,11 @@ #include "engine.h" #include "coders/toml.h" +#include "coders/json.h" #include "files/files.h" +#include "window/Events.h" + toml::Wrapper create_wrapper(EngineSettings& settings) { toml::Wrapper wrapper; toml::Section& display = wrapper.add("display"); @@ -38,6 +41,48 @@ toml::Wrapper create_wrapper(EngineSettings& settings) { return wrapper; } +std::string write_controls() { + json::JObject* obj = new json::JObject(); + for (auto& entry : Events::bindings) { + const auto& binding = entry.second; + + json::JObject* jentry = new json::JObject(); + switch (binding.type) { + case inputtype::keyboard: jentry->put("type", "keyboard"); break; + case inputtype::button: jentry->put("type", "button"); break; + default: throw std::runtime_error("unsupported control type"); + } + jentry->put("code", binding.code); + obj->put(entry.first, jentry); + } + return json::stringify(obj, true, " "); +} + +void load_controls(std::string filename, std::string source) { + json::JObject* obj = json::parse(filename, source); + for (auto& entry : Events::bindings) { + auto& binding = entry.second; + + json::JObject* jentry = obj->obj(entry.first); + if (jentry == nullptr) + continue; + inputtype type; + std::string typestr; + jentry->str("type", typestr); + + if (typestr == "keyboard") { + type = inputtype::keyboard; + } else if (typestr == "button") { + type = inputtype::button; + } else { + std::cerr << "unknown input type '" << typestr << "'" << std::endl; + continue; + } + binding.type = type; + jentry->num("code", binding.code); + } +} + int main() { platform::configure_encoding(); setup_definitions(); @@ -45,21 +90,26 @@ int main() { EngineSettings settings; toml::Wrapper wrapper = create_wrapper(settings); - std::string settings_file = platform::get_settings_file(); + std::filesystem::path settings_file = platform::get_settings_file(); + std::filesystem::path controls_file = platform::get_controls_file(); if (std::filesystem::is_regular_file(settings_file)) { std::cout << "-- loading settings" << std::endl; std::string content = files::read_string(settings_file); toml::Reader reader(&wrapper, settings_file, content); reader.read(); - } else { - std::cout << "-- creating settings file " << settings_file << std::endl; - files::write_string(settings_file, wrapper.write()); } Engine engine(settings); + setup_bindings(); + if (std::filesystem::is_regular_file(controls_file)) { + std::cout << "-- loading controls" << std::endl; + std::string content = files::read_string(controls_file); + load_controls(controls_file.string(), content); + } engine.mainloop(); std::cout << "-- saving settings" << std::endl; files::write_string(settings_file, wrapper.write()); + files::write_string(controls_file, write_controls()); } catch (const initialize_error& err) { std::cerr << "could not to initialize engine" << std::endl; diff --git a/src/window/Events.cpp b/src/window/Events.cpp index b89c5a4f..ec5fb3f9 100644 --- a/src/window/Events.cpp +++ b/src/window/Events.cpp @@ -14,6 +14,7 @@ bool Events::_cursor_locked = false; bool Events::_cursor_started = false; std::vector Events::codepoints; std::vector Events::pressedKeys; +std::unordered_map Events::bindings; int Events::initialize(){ _keys = new bool[1032]; @@ -64,4 +65,47 @@ void Events::pullEvents(){ codepoints.clear(); pressedKeys.clear(); glfwPollEvents(); + + for (auto& entry : bindings) { + auto& binding = entry.second; + binding.justChange = false; + + bool newstate = false; + switch (binding.type) { + case inputtype::keyboard: newstate = pressed(binding.code); break; + case inputtype::button: newstate = clicked(binding.code); break; + } + + if (newstate) { + if (!binding.state) { + binding.state = true; + binding.justChange = true; + } + } else { + if (binding.state) { + binding.state = false; + binding.justChange = true; + } + } + } +} + +void Events::bind(std::string name, inputtype type, int code) { + bindings[name] = {type, code, false, false}; +} + +bool Events::active(std::string name) { + const auto& found = bindings.find(name); + if (found == bindings.end()) { + return false; + } + return found->second.active(); +} + +bool Events::jactive(std::string name) { + const auto& found = bindings.find(name); + if (found == bindings.end()) { + return false; + } + return found->second.jactive(); } diff --git a/src/window/Events.h b/src/window/Events.h index 1627ffb1..2dd6885c 100644 --- a/src/window/Events.h +++ b/src/window/Events.h @@ -3,8 +3,32 @@ #include "Window.h" +#include +#include +#include + typedef unsigned int uint; +enum class inputtype { + keyboard, + button, +}; + +struct Binding { + inputtype type; + int code; + bool state = false; + bool justChange = false; + + bool active() const { + return state; + } + + bool jactive() const { + return state && justChange; + } +}; + class Events { public: static bool* _keys; @@ -18,6 +42,7 @@ public: static bool _cursor_started; static std::vector codepoints; static std::vector pressedKeys; + static std::unordered_map bindings; static int initialize(); static void finalize(); @@ -30,6 +55,10 @@ public: static bool jclicked(int button); static void toggleCursor(); + + static void bind(std::string name, inputtype type, int code); + static bool active(std::string name); + static bool jactive(std::string name); }; #define _MOUSE_BUTTONS 1024 From 7ab69ebc1e4735065e1e106a428989229711072d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 19 Nov 2023 23:11:35 +0300 Subject: [PATCH 07/13] added 'hud.inventory' binding --- src/definitions.cpp | 1 + src/definitions.h | 1 + src/frontend/hud.cpp | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/definitions.cpp b/src/definitions.cpp index 68c40688..d0112e48 100644 --- a/src/definitions.cpp +++ b/src/definitions.cpp @@ -106,4 +106,5 @@ void setup_bindings() { Events::bind(BIND_CAM_ZOOM, inputtype::keyboard, keycode::C); Events::bind(BIND_PLAYER_NOCLIP, inputtype::keyboard, keycode::N); Events::bind(BIND_PLAYER_FLIGHT, inputtype::keyboard, keycode::F); + Events::bind(BIND_HUD_INVENTORY, inputtype::keyboard, keycode::TAB); } \ No newline at end of file diff --git a/src/definitions.h b/src/definitions.h index 3489d998..ce70975d 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -32,6 +32,7 @@ #define BIND_CAM_ZOOM "camera.zoom" #define BIND_PLAYER_NOCLIP "player.noclip" #define BIND_PLAYER_FLIGHT "player.flight" +#define BIND_HUD_INVENTORY "hud.inventory" extern void setup_bindings(); extern void setup_definitions(); diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 1e72d7fb..51246ce1 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -309,7 +309,7 @@ void HudRenderer::draw(const GfxContext& ctx){ pauseMenu->visible(true); } } - if (Events::jpressed(keycode::TAB)) { + if (Events::jactive("hud.inventory")) { if (!pause) { inventoryOpen = !inventoryOpen; } From 41f9c51a2757cae471bf3e68ee062bffe055b017 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 19 Nov 2023 23:18:26 +0300 Subject: [PATCH 08/13] Minor refactor --- src/core_defs.h | 21 +++++++++++++++++++++ src/definitions.h | 15 +-------------- src/frontend/hud.cpp | 3 ++- src/objects/player_control.cpp | 24 +++++++++++++----------- 4 files changed, 37 insertions(+), 26 deletions(-) create mode 100644 src/core_defs.h diff --git a/src/core_defs.h b/src/core_defs.h new file mode 100644 index 00000000..c30135bf --- /dev/null +++ b/src/core_defs.h @@ -0,0 +1,21 @@ +#ifndef SRC_CORE_DEFS_H_ +#define SRC_CORE_DEFS_H_ + +/* blocks and bindings used in engine code */ + +#define BLOCK_AIR 0 + +#define BIND_MOVE_FORWARD "movement.forward" +#define BIND_MOVE_BACK "movement.back" +#define BIND_MOVE_LEFT "movement.left" +#define BIND_MOVE_RIGHT "movement.right" +#define BIND_MOVE_JUMP "movement.jump" +#define BIND_MOVE_SPRINT "movement.sprint" +#define BIND_MOVE_CROUCH "movement.crouch" +#define BIND_MOVE_CHEAT "movement.cheat" +#define BIND_CAM_ZOOM "camera.zoom" +#define BIND_PLAYER_NOCLIP "player.noclip" +#define BIND_PLAYER_FLIGHT "player.flight" +#define BIND_HUD_INVENTORY "hud.inventory" + +#endif // SRC_CORE_DEFS_H_ \ No newline at end of file diff --git a/src/definitions.h b/src/definitions.h index ce70975d..c4b5e0ba 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -2,8 +2,8 @@ #define DECLARATIONS_H #include +#include "core_defs.h" -#define BLOCK_AIR 0 #define BLOCK_DIRT 1 #define BLOCK_GRASS_BLOCK 2 #define BLOCK_LAMP 3 @@ -21,19 +21,6 @@ #define BLOCK_METAL 15 #define BLOCK_RUST 16 -#define BIND_MOVE_FORWARD "movement.forward" -#define BIND_MOVE_BACK "movement.back" -#define BIND_MOVE_LEFT "movement.left" -#define BIND_MOVE_RIGHT "movement.right" -#define BIND_MOVE_JUMP "movement.jump" -#define BIND_MOVE_SPRINT "movement.sprint" -#define BIND_MOVE_CROUCH "movement.crouch" -#define BIND_MOVE_CHEAT "movement.cheat" -#define BIND_CAM_ZOOM "camera.zoom" -#define BIND_PLAYER_NOCLIP "player.noclip" -#define BIND_PLAYER_FLIGHT "player.flight" -#define BIND_HUD_INVENTORY "hud.inventory" - extern void setup_bindings(); extern void setup_definitions(); diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 51246ce1..8fe79b8e 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -30,6 +30,7 @@ #include "gui/GUI.h" #include "screens.h" #include "../engine.h" +#include "../core_defs.h" using std::wstring; using std::shared_ptr; @@ -309,7 +310,7 @@ void HudRenderer::draw(const GfxContext& ctx){ pauseMenu->visible(true); } } - if (Events::jactive("hud.inventory")) { + if (Events::jactive(BIND_HUD_INVENTORY)) { if (!pause) { inventoryOpen = !inventoryOpen; } diff --git a/src/objects/player_control.cpp b/src/objects/player_control.cpp index adc6df30..0c426164 100644 --- a/src/objects/player_control.cpp +++ b/src/objects/player_control.cpp @@ -12,6 +12,8 @@ #include "../window/Events.h" #include "../window/input.h" +#include "../core_defs.h" + #define CROUCH_SPEED_MUL 0.25f #define CROUCH_SHIFT_Y -0.2f #define RUN_SPEED_MUL 1.5f @@ -38,18 +40,18 @@ void PlayerController::refreshCamera() { } void PlayerController::updateKeyboard() { - input.moveForward = Events::active("movement.forward"); - input.moveBack = Events::active("movement.back"); - input.moveLeft = Events::active("movement.left"); - input.moveRight = Events::active("movement.right"); - input.sprint = Events::active("movement.sprint"); - input.shift = Events::active("movement.crouch"); - input.cheat = Events::active("movement.cheat"); - input.jump = Events::active("movement.jump"); - input.zoom = Events::active("camera.zoom"); + input.moveForward = Events::active(BIND_MOVE_FORWARD); + input.moveBack = Events::active(BIND_MOVE_BACK); + input.moveLeft = Events::active(BIND_MOVE_LEFT); + input.moveRight = Events::active(BIND_MOVE_RIGHT); + input.sprint = Events::active(BIND_MOVE_SPRINT); + input.shift = Events::active(BIND_MOVE_CROUCH); + input.cheat = Events::active(BIND_MOVE_CHEAT); + input.jump = Events::active(BIND_MOVE_JUMP); + input.zoom = Events::active(BIND_CAM_ZOOM); - input.noclip = Events::jactive("player.noclip"); - input.flight = Events::jactive("player.flight"); + input.noclip = Events::jactive(BIND_PLAYER_NOCLIP); + input.flight = Events::jactive(BIND_PLAYER_FLIGHT); // block choice for (int i = 1; i < 10; i++){ From 4ea7bda2494d9f10ab6bb7a5f82c635fca095860 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 20 Nov 2023 03:31:18 +0300 Subject: [PATCH 09/13] PagesControl, refactor --- src/engine.cpp | 4 +- src/frontend/gui/GUI.cpp | 19 ++++-- src/frontend/gui/UINode.cpp | 3 +- src/frontend/gui/UINode.h | 2 + src/frontend/gui/controls.cpp | 47 +++++++++++++- src/frontend/gui/controls.h | 18 ++++++ src/frontend/gui/panels.cpp | 62 +++++++++++++++++-- src/frontend/gui/panels.h | 24 ++++++++ src/frontend/hud.cpp | 74 +++++++++++----------- src/frontend/hud.h | 3 +- src/frontend/screens.cpp | 113 +++++++++++++++++++++------------- src/frontend/screens.h | 3 +- src/window/Events.h | 21 +------ src/window/input.cpp | 30 +++++++++ src/window/input.h | 33 ++++++++++ 15 files changed, 339 insertions(+), 117 deletions(-) diff --git a/src/engine.cpp b/src/engine.cpp index f9be1b35..572db177 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -59,8 +59,6 @@ Engine::Engine(EngineSettings& settings) : settings(settings) { Audio::initialize(); gui = new GUI(); std::cout << "-- initializing finished" << std::endl; - - setScreen(shared_ptr(new MenuScreen(this))); } void Engine::updateTimers() { @@ -81,6 +79,8 @@ void Engine::updateHotkeys() { } void Engine::mainloop() { + setScreen(shared_ptr(new MenuScreen(this))); + std::cout << "-- preparing systems" << std::endl; Batch2D batch(1024); diff --git a/src/frontend/gui/GUI.cpp b/src/frontend/gui/GUI.cpp index 2ccf4895..f28ad67d 100644 --- a/src/frontend/gui/GUI.cpp +++ b/src/frontend/gui/GUI.cpp @@ -45,6 +45,7 @@ void GUI::act(float delta) { } this->hover = hover; + auto prevfocus = focus; if (Events::jclicked(0)) { if (pressed == nullptr && this->hover) { pressed = hover; @@ -52,7 +53,10 @@ void GUI::act(float delta) { if (focus && focus != pressed) { focus->defocus(); } - focus = pressed; + if (focus != pressed) { + focus = pressed; + focus->focus(this); + } } if (this->hover == nullptr && focus) { focus->defocus(); @@ -63,9 +67,7 @@ void GUI::act(float delta) { pressed = nullptr; } if (focus) { - if (!focus->isfocused()){ - focus = nullptr; - } else if (Events::jpressed(keycode::ESCAPE)) { + if (Events::jpressed(keycode::ESCAPE)) { focus->defocus(); focus = nullptr; } else { @@ -78,8 +80,17 @@ void GUI::act(float delta) { if (Events::clicked(mousecode::BUTTON_1)) { focus->mouseMove(this, mx, my); } + if (prevfocus == focus) + for (int i = mousecode::BUTTON_1; i < mousecode::BUTTON_1+12; i++) { + if (Events::jclicked(i)) { + focus->clicked(this, i); + } + } } } + if (focus && !focus->isfocused()) { + focus = nullptr; + } } void GUI::draw(Batch2D* batch, Assets* assets) { diff --git a/src/frontend/gui/UINode.cpp b/src/frontend/gui/UINode.cpp index cd4c9477..751c341a 100644 --- a/src/frontend/gui/UINode.cpp +++ b/src/frontend/gui/UINode.cpp @@ -52,7 +52,6 @@ UINode* UINode::getParent() const { void UINode::click(GUI*, int x, int y) { pressed_ = true; - focused_ = true; } void UINode::mouseRelease(GUI*, int x, int y) { @@ -103,7 +102,7 @@ void UINode::size(vec2 size) { this->size_ = size; if (parent) { sizelock = true; - parent->refresh(); + //parent->refresh(); sizelock = false; } } diff --git a/src/frontend/gui/UINode.h b/src/frontend/gui/UINode.h index e9699118..1620fc5a 100644 --- a/src/frontend/gui/UINode.h +++ b/src/frontend/gui/UINode.h @@ -56,7 +56,9 @@ namespace gui { virtual void margin(glm::vec4 margin); glm::vec4 margin() const; + virtual void focus(GUI*) {focused_ = true;} virtual void click(GUI*, int x, int y); + virtual void clicked(GUI*, int button) {} virtual void mouseMove(GUI*, int x, int y) {}; virtual void mouseRelease(GUI*, int x, int y); diff --git a/src/frontend/gui/controls.cpp b/src/frontend/gui/controls.cpp index c0293703..295073e5 100644 --- a/src/frontend/gui/controls.cpp +++ b/src/frontend/gui/controls.cpp @@ -5,6 +5,7 @@ #include "../../assets/Assets.h" #include "../../graphics/Batch2D.h" #include "../../graphics/Font.h" +#include "../../util/stringutil.h" using std::string; using std::wstring; @@ -36,7 +37,7 @@ void Label::draw(Batch2D* batch, Assets* assets) { } batch->color = color_; Font* font = assets->getFont(fontName_); - vec2 size = this->size(); + vec2 size = UINode::size(); vec2 newsize = vec2(font->calcWidth(text_), font->lineHeight()); if (newsize.x > size.x) { this->size(newsize); @@ -51,6 +52,11 @@ Label* Label::textSupplier(wstringsupplier supplier) { return this; } +void Label::size(vec2 sizenew) { + UINode::size(vec2(UINode::size().x, sizenew.y)); +} + +// ================================= Button =================================== Button::Button(shared_ptr content, glm::vec4 padding) : Panel(vec2(32,32), padding, 0) { add(content); } @@ -86,12 +92,12 @@ Button* Button::listenAction(onaction action) { return this; } +// ================================ TextBox =================================== TextBox::TextBox(wstring placeholder, vec4 padding) : Panel(vec2(200,32), padding, 0, false), input(L""), placeholder(placeholder) { label = new Label(L""); - label->align(Align::center); add(shared_ptr(label)); } @@ -151,6 +157,42 @@ wstring TextBox::text() const { return input; } +// ============================== InputBindBox ================================ +InputBindBox::InputBindBox(Binding& binding, vec4 padding) + : Panel(vec2(100,32), padding, 0, false), + binding(binding) { + label = new Label(L""); + //label->align(Align::center); + add(shared_ptr(label)); +} + +shared_ptr InputBindBox::getAt(vec2 pos, shared_ptr self) { + return UINode::getAt(pos, self); +} + +void InputBindBox::drawBackground(Batch2D* batch, Assets* assets) { + vec2 coord = calcCoord(); + batch->texture(nullptr); + batch->color = (isfocused() ? focusedColor : (hover_ ? hoverColor : color_)); + batch->rect(coord.x, coord.y, size_.x, size_.y); + label->text(util::str2wstr_utf8(binding.text())); +} + +void InputBindBox::clicked(GUI*, int button) { + binding.type = inputtype::button; + binding.code = button; + defocus(); +} + +void InputBindBox::keyPressed(int key) { + if (key != keycode::ESCAPE) { + binding.type = inputtype::keyboard; + binding.code = key; + } + defocus(); +} + +// ================================ TrackBar ================================== TrackBar::TrackBar(double min, double max, double value, double step, int trackWidth) : UINode(vec2(), vec2(32)), min(min), max(max), value(value), step(step), trackWidth(trackWidth) { color(vec4(0.f, 0.f, 0.f, 0.4f)); @@ -194,6 +236,7 @@ void TrackBar::mouseMove(GUI*, int x, int y) { } } +// ================================ CheckBox ================================== CheckBox::CheckBox(bool checked) : UINode(vec2(), vec2(32.0f)), checked_(checked) { color(vec4(0.0f, 0.0f, 0.0f, 0.5f)); } diff --git a/src/frontend/gui/controls.h b/src/frontend/gui/controls.h index 8bbe6f1e..0ef15269 100644 --- a/src/frontend/gui/controls.h +++ b/src/frontend/gui/controls.h @@ -8,6 +8,7 @@ #include #include "UINode.h" #include "panels.h" +#include "../../window/input.h" class Batch2D; class Assets; @@ -36,6 +37,7 @@ namespace gui { virtual void draw(Batch2D* batch, Assets* assets) override; virtual Label* textSupplier(wstringsupplier supplier); + virtual void size(glm::vec2 size) override; }; class Button : public Panel { @@ -79,6 +81,22 @@ namespace gui { virtual std::wstring text() const; }; + class InputBindBox : public Panel { + protected: + glm::vec4 hoverColor {0.05f, 0.1f, 0.2f, 0.75f}; + glm::vec4 focusedColor {0.0f, 0.0f, 0.0f, 1.0f}; + Label* label; + Binding& binding; + public: + InputBindBox(Binding& binding, glm::vec4 padding=glm::vec4(6.0f)); + virtual void drawBackground(Batch2D* batch, Assets* assets) override; + virtual std::shared_ptr getAt(glm::vec2 pos, std::shared_ptr self) override; + + virtual void clicked(GUI*, int button) override; + virtual void keyPressed(int key) override; + virtual bool isfocuskeeper() const override {return true;} + }; + class TrackBar : public UINode { protected: glm::vec4 hoverColor {0.01f, 0.02f, 0.03f, 0.5f}; diff --git a/src/frontend/gui/panels.cpp b/src/frontend/gui/panels.cpp index 85bedbbb..871bc0d4 100644 --- a/src/frontend/gui/panels.cpp +++ b/src/frontend/gui/panels.cpp @@ -1,15 +1,14 @@ #include "panels.h" +#include + #include "../../window/Window.h" #include "../../assets/Assets.h" #include "../../graphics/Batch2D.h" using std::shared_ptr; -using gui::UINode; -using gui::Container; -using gui::Panel; -using gui::Orientation; +using namespace gui; using glm::vec2; using glm::vec4; @@ -138,7 +137,8 @@ void Panel::refresh() { y += nodesize.y + margin.w + interval; float width = size.x - padding.x - padding.z - margin.x - margin.z; - node->size(vec2(width, nodesize.y)); + node->size(vec2(width, nodesize.y));; + node->refresh(); maxw = fmax(maxw, ex+node->size().x+margin.z+padding.z); } if (resizing_) @@ -154,6 +154,7 @@ void Panel::refresh() { float height = size.y - padding.y - padding.w - margin.y - margin.w; node->size(vec2(nodesize.x, height)); + node->refresh(); maxh = fmax(maxh, y+margin.y+node->size().y+margin.w+padding.w); } bool increased = maxh > size.y; @@ -177,4 +178,55 @@ void Panel::lock(){ node->lock(); } resizing_ = false; +} + +PagesControl::PagesControl() : Container(vec2(), vec2(1)){ +} + +void PagesControl::add(std::string name, std::shared_ptr panel) { + panel->visible(false); + pages[name] = Page{panel}; + Container::add(panel); +} + +void PagesControl::set(std::string name, bool history) { + auto found = pages.find(name); + if (found == pages.end()) { + throw std::runtime_error("no page found"); + } + if (current_.panel) { + current_.panel->visible(false); + } + if (history) { + pageStack.push(curname_); + } + curname_ = name; + current_ = found->second; + current_.panel->visible(true); + size(current_.panel->size()); +} + +void PagesControl::back() { + if (pageStack.empty()) + return; + std::string name = pageStack.top(); + pageStack.pop(); + set(name, false); +} + +Page PagesControl::current() { + return current_; +} + +void PagesControl::clearHistory() { + pageStack = std::stack(); +} + +void PagesControl::reset() { + clearHistory(); + if (current_.panel) { + curname_ = ""; + current_.panel->visible(false); + current_ = Page{nullptr}; + } } \ No newline at end of file diff --git a/src/frontend/gui/panels.h b/src/frontend/gui/panels.h index 7441f211..174180c7 100644 --- a/src/frontend/gui/panels.h +++ b/src/frontend/gui/panels.h @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include "UINode.h" @@ -56,5 +58,27 @@ namespace gui { virtual void refresh() override; virtual void lock() override; }; + + struct Page { + std::shared_ptr panel = nullptr; + }; + + class PagesControl : public Container { + protected: + std::unordered_map pages; + std::stack pageStack; + Page current_; + std::string curname_ = ""; + public: + PagesControl(); + + void set(std::string name, bool history=true); + void add(std::string name, std::shared_ptr panel); + void back(); + void clearHistory(); + void reset(); + + Page current(); + }; } #endif // FRONTEND_GUI_PANELS_H_ \ No newline at end of file diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 8fe79b8e..0d0b04cb 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -51,6 +51,9 @@ HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(en uicamera->perspective = false; uicamera->flipped = true; + auto pagesptr = gui->get("pages"); + PagesControl* pages = (PagesControl*)(pagesptr.get()); + Panel* panel = new Panel(vec2(250, 200), vec4(5.0f), 1.0f); debugPanel = shared_ptr(panel); panel->listenInterval(1.0f, [this]() { @@ -116,37 +119,35 @@ HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(en panel->refresh(); panel = new Panel(vec2(350, 200)); - pauseMenu = shared_ptr(panel); + auto pauseMenu = shared_ptr(panel); panel->color(vec4(0.0f)); { Button* button = new Button(L"Continue", vec4(10.0f)); - button->listenAction([this](GUI*){ - this->pause = false; - pauseMenu->visible(false); + button->listenAction([=](GUI*){ + pages->reset(); + pause = false; }); panel->add(shared_ptr(button)); } panel->add((new Button(L"Settings", vec4(10.f)))->listenAction([=](GUI* gui) { - pauseMenu->visible(false); - gui->store("back", pauseMenu); - gui->get("settings")->visible(true); + pages->set("settings"); })); { Button* button = new Button(L"Save and Quit to Menu", vec4(10.f)); button->listenAction([this, engine](GUI*){ - this->pauseMenu->visible(false); engine->setScreen(shared_ptr(new MenuScreen(engine))); }); panel->add(shared_ptr(button)); } - panel->visible(false); + + pages->reset(); + pages->add("pause", pauseMenu); gui->add(this->debugPanel); - gui->add(this->pauseMenu); } HudRenderer::~HudRenderer() { gui->remove(debugPanel); - gui->remove(pauseMenu); + //gui->remove(gui->get("pages")); delete batch; delete uicamera; } @@ -226,8 +227,7 @@ void HudRenderer::drawInventory(const GfxContext& ctx, Player* player) { if (Events::jclicked(GLFW_MOUSE_BUTTON_LEFT)) { player->choosenBlock = i+1; } - } else - { + } else { tint = vec4(1.0f); } @@ -239,16 +239,36 @@ void HudRenderer::drawInventory(const GfxContext& ctx, Player* player) { } } +void HudRenderer::update() { + PagesControl* pages = (PagesControl*)(gui->get("pages").get()); + if (Events::jpressed(keycode::ESCAPE) && !gui->isFocusCaught()) { + if (pause) { + pause = false; + pages->reset(); + } else if (inventoryOpen) { + inventoryOpen = false; + } else { + pause = true; + pages->set("pause"); + } + } + if (Events::jactive(BIND_HUD_INVENTORY)) { + if (!pause) { + inventoryOpen = !inventoryOpen; + } + } + if ((pause || inventoryOpen) == Events::_cursor_locked) + Events::toggleCursor(); +} + void HudRenderer::draw(const GfxContext& ctx){ const Viewport& viewport = ctx.getViewport(); const uint width = viewport.getWidth(); const uint height = viewport.getHeight(); + auto pages = gui->get("pages"); debugPanel->visible(level->player->debug); - pauseMenu->setCoord((viewport.size() - pauseMenu->size()) / 2.0f); - - auto settingsPanel = gui->get("settings"); - settingsPanel->setCoord((viewport.size() - settingsPanel->size()) / 2.0f); + pages->setCoord((viewport.size() - pages->size()) / 2.0f); uicamera->fov = height; @@ -298,26 +318,6 @@ void HudRenderer::draw(const GfxContext& ctx){ } } - if (Events::jpressed(keycode::ESCAPE) && !gui->isFocusCaught()) { - if (pause) { - pause = false; - pauseMenu->visible(false); - settingsPanel->visible(false); - } else if (inventoryOpen) { - inventoryOpen = false; - } else { - pause = true; - pauseMenu->visible(true); - } - } - if (Events::jactive(BIND_HUD_INVENTORY)) { - if (!pause) { - inventoryOpen = !inventoryOpen; - } - } - if ((pause || inventoryOpen) == Events::_cursor_locked) - Events::toggleCursor(); - if (pause || inventoryOpen) { batch->texture(nullptr); batch->color = vec4(0.0f, 0.0f, 0.0f, 0.5f); diff --git a/src/frontend/hud.h b/src/frontend/hud.h index 0dd0466d..2da61830 100644 --- a/src/frontend/hud.h +++ b/src/frontend/hud.h @@ -34,11 +34,12 @@ class HudRenderer { bool pause = false; std::shared_ptr debugPanel; - std::shared_ptr pauseMenu; gui::GUI* gui; public: HudRenderer(Engine* engine, Level* level); ~HudRenderer(); + + void update(); void drawInventory(const GfxContext& ctx, Player* player); void draw(const GfxContext& context); void drawDebug(int fps, bool occlusion); diff --git a/src/frontend/screens.cpp b/src/frontend/screens.cpp index e6d13241..09a00844 100644 --- a/src/frontend/screens.cpp +++ b/src/frontend/screens.cpp @@ -29,6 +29,7 @@ #include "../engine.h" #include "../files/engine_files.h" #include "../util/stringutil.h" +#include "../core_defs.h" using std::string; using std::wstring; @@ -40,15 +41,13 @@ using std::filesystem::u8path; using std::filesystem::directory_iterator; using namespace gui; -shared_ptr create_main_menu_panel(Engine* engine) { +shared_ptr create_main_menu_panel(Engine* engine, PagesControl* pages) { Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 1.0f); shared_ptr panelptr(panel); panel->color(vec4(0.0f)); - panel->setCoord(vec2(10, 10)); panel->add((new Button(L"New World", vec4(10.f)))->listenAction([=](GUI* gui) { - panel->visible(false); - gui->get("new-world")->visible(true); + pages->set("new-world"); })); Panel* worldsPanel = new Panel(vec2(390, 200), vec4(5.0f)); @@ -74,22 +73,20 @@ shared_ptr create_main_menu_panel(Engine* engine) { panel->add(worldsPanel); panel->add((new Button(L"Settings", vec4(10.f)))->listenAction([=](GUI* gui) { - panel->visible(false); - gui->store("back", panelptr); - gui->get("settings")->visible(true); + pages->set("settings"); })); panel->add((new Button(L"Quit", vec4(10.f)))->listenAction([](GUI*) { Window::setShouldClose(true); })); + panel->refresh(); return panelptr; } -shared_ptr create_new_world_panel(Engine* engine) { +shared_ptr create_new_world_panel(Engine* engine, PagesControl* pages) { Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 1.0f); shared_ptr panelptr(panel); panel->color(vec4(0.0f)); - panel->setCoord(vec2(10, 10)); TextBox* worldNameInput; { @@ -167,17 +164,44 @@ shared_ptr create_new_world_panel(Engine* engine) { } panel->add((new Button(L"Back", vec4(10.f)))->listenAction([=](GUI* gui) { - panel->visible(false); - gui->get("main-menu")->visible(true); + pages->back(); })); - + panel->refresh(); return panelptr; } -Panel* create_settings_panel(Engine* engine) { +Panel* create_controls_panel(Engine* engine, PagesControl* pages) { Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 1.0f); panel->color(vec4(0.0f)); - panel->setCoord(vec2(10, 10)); + + for (auto& entry : Events::bindings){ + string bindname = entry.first; + std::cout << bindname << std::endl; + + Panel* subpanel = new Panel(vec2(400, 45), vec4(5.0f), 1.0f); + subpanel->color(vec4(0.0f)); + subpanel->orientation(Orientation::horizontal); + + InputBindBox* bindbox = new InputBindBox(entry.second); + subpanel->add(bindbox); + Label* label = new Label(util::str2wstr_utf8(bindname)); + label->margin(vec4(6.0f)); + subpanel->add(label); + panel->add(subpanel); + } + + panel->add((new Button(L"Back", vec4(10.f)))->listenAction([=](GUI* gui) { + pages->back(); + })); + panel->refresh(); + return panel; +} + +shared_ptr create_settings_panel(Engine* engine, PagesControl* pages) { + Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 1.0f); + panel->color(vec4(0.0f)); + + shared_ptr panelptr(panel); /* Load Distance setting track bar */{ panel->add((new Label(L""))->textSupplier([=]() { @@ -232,30 +256,44 @@ Panel* create_settings_panel(Engine* engine) { panel->add(checkpanel); } - panel->add((new Button(L"Back", vec4(10.f)))->listenAction([=](GUI* gui) { - panel->visible(false); - gui->get("back")->visible(true); + panel->add((new Button(L"Controls", vec4(10.f)))->listenAction([=](GUI* gui) { + pages->set("controls"); })); - return panel; + + panel->add((new Button(L"Back", vec4(10.f)))->listenAction([=](GUI* gui) { + pages->back(); + })); + panel->refresh(); + return panelptr; } MenuScreen::MenuScreen(Engine* engine_) : Screen(engine_) { GUI* gui = engine->getGUI(); - panel = create_main_menu_panel(engine); - newWorldPanel = create_new_world_panel(engine); - newWorldPanel->visible(false); - auto settingsPanel = shared_ptr(create_settings_panel(engine)); - settingsPanel->visible(false); + auto pagesptr = gui->get("pages"); + PagesControl* pages; + if (pagesptr == nullptr) { + pages = new PagesControl(); + auto newWorldPanel = create_new_world_panel(engine, pages); - gui->store("main-menu", panel); - gui->store("new-world", newWorldPanel); - if (gui->get("settings") == nullptr) { - gui->store("settings", settingsPanel); + auto settingsPanel = shared_ptr(create_settings_panel(engine, pages)); + auto controlsPanel = shared_ptr(create_controls_panel(engine, pages)); + + pages->add("new-world", newWorldPanel); + pages->add("settings", settingsPanel); + pages->add("controls", controlsPanel); + + this->pages = shared_ptr(pages); + gui->add(this->pages); + gui->store("pages", this->pages); + } else { + this->pages = pagesptr; + pages = (PagesControl*)(pagesptr.get()); + pages->reset(); } - gui->add(panel); - gui->add(newWorldPanel); - gui->add(settingsPanel); + auto mainMenuPanel = create_main_menu_panel(engine, pages); + pages->add("main", mainMenuPanel); + pages->set("main"); batch = new Batch2D(1024); uicamera = new Camera(vec3(), Window::height); @@ -264,13 +302,6 @@ MenuScreen::MenuScreen(Engine* engine_) : Screen(engine_) { } MenuScreen::~MenuScreen() { - GUI* gui = engine->getGUI(); - - gui->remove("main-menu"); - gui->remove("new-world"); - - gui->remove(newWorldPanel); - gui->remove(panel); delete batch; delete uicamera; } @@ -279,11 +310,7 @@ void MenuScreen::update(float delta) { } void MenuScreen::draw(float delta) { - panel->setCoord((Window::size() - panel->size()) / 2.0f); - newWorldPanel->setCoord((Window::size() - newWorldPanel->size()) / 2.0f); - - auto settingsPanel = engine->getGUI()->get("settings"); - settingsPanel->setCoord((Window::size() - settingsPanel->size()) / 2.0f); + pages->setCoord((Window::size() - pages->size()) / 2.0f); Window::clear(); Window::setBgColor(vec3(0.2f, 0.2f, 0.2f)); @@ -352,6 +379,8 @@ void LevelScreen::update(float delta) { level->update(); level->chunksController->update(settings.chunks.loadSpeed); + + hud->update(); } void LevelScreen::draw(float delta) { diff --git a/src/frontend/screens.h b/src/frontend/screens.h index 37c72b7f..c29299c8 100644 --- a/src/frontend/screens.h +++ b/src/frontend/screens.h @@ -28,8 +28,7 @@ public: }; class MenuScreen : public Screen { - std::shared_ptr panel; - std::shared_ptr newWorldPanel; + std::shared_ptr pages; Batch2D* batch; Camera* uicamera; public: diff --git a/src/window/Events.h b/src/window/Events.h index 2dd6885c..c4d4813f 100644 --- a/src/window/Events.h +++ b/src/window/Events.h @@ -2,6 +2,7 @@ #define WINDOW_EVENTS_H_ #include "Window.h" +#include "input.h" #include #include @@ -9,26 +10,6 @@ typedef unsigned int uint; -enum class inputtype { - keyboard, - button, -}; - -struct Binding { - inputtype type; - int code; - bool state = false; - bool justChange = false; - - bool active() const { - return state; - } - - bool jactive() const { - return state && justChange; - } -}; - class Events { public: static bool* _keys; diff --git a/src/window/input.cpp b/src/window/input.cpp index 1f5e50ec..93cb08b2 100644 --- a/src/window/input.cpp +++ b/src/window/input.cpp @@ -66,6 +66,36 @@ int keycode::NUM_7 = GLFW_KEY_7; int keycode::NUM_8 = GLFW_KEY_8; int keycode::NUM_9 = GLFW_KEY_9; +const char* keycode::name(int code) { + const char* name = glfwGetKeyName(code, glfwGetKeyScancode(code)); + if (name == nullptr) { + switch (code) { + case GLFW_KEY_TAB: return "Tab"; + case GLFW_KEY_LEFT_CONTROL: return "Left Ctrl"; + case GLFW_KEY_RIGHT_CONTROL: return "Right Ctrl"; + case GLFW_KEY_LEFT_ALT: return "Left Alt"; + case GLFW_KEY_RIGHT_ALT: return "Right Alt"; + case GLFW_KEY_LEFT_SHIFT: return "Left Shift"; + case GLFW_KEY_RIGHT_SHIFT: return "Right Shift"; + case GLFW_KEY_CAPS_LOCK: return "Caps-Lock"; + case GLFW_KEY_SPACE: return "Space"; + case GLFW_KEY_ESCAPE: return "Esc"; + default: + return "Unknown"; + } + } + return name; +} + int mousecode::BUTTON_1 = GLFW_MOUSE_BUTTON_1; int mousecode::BUTTON_2 = GLFW_MOUSE_BUTTON_2; int mousecode::BUTTON_3 = GLFW_MOUSE_BUTTON_3; + +const char* mousecode::name(int code) { + switch (code) { + case GLFW_MOUSE_BUTTON_1: return "LMB"; + case GLFW_MOUSE_BUTTON_2: return "RMB"; + case GLFW_MOUSE_BUTTON_3: return "MMB"; + } + return "unknown button"; +} diff --git a/src/window/input.h b/src/window/input.h index 9cb9ce3b..33469fdc 100644 --- a/src/window/input.h +++ b/src/window/input.h @@ -66,12 +66,45 @@ namespace keycode { extern int NUM_7; extern int NUM_8; extern int NUM_9; + + extern const char* name(int code); } namespace mousecode { extern int BUTTON_1; extern int BUTTON_2; extern int BUTTON_3; + + extern const char* name(int code); } +enum class inputtype { + keyboard, + button, +}; + +struct Binding { + inputtype type; + int code; + bool state = false; + bool justChange = false; + + bool active() const { + return state; + } + + bool jactive() const { + return state && justChange; + } + + const char* text() const { + switch (type) { + case inputtype::keyboard: return keycode::name(code); + case inputtype::button: return mousecode::name(code); + } + return ""; + } +}; + + #endif // WINDOW_INPUT_H_ \ No newline at end of file From 3b5c039db14fefc99de26a87bc9e9fb16e4fc09f Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 20 Nov 2023 03:59:59 +0300 Subject: [PATCH 10/13] PagesControl leak fix --- src/frontend/gui/panels.cpp | 8 +++----- src/frontend/screens.cpp | 3 +-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/frontend/gui/panels.cpp b/src/frontend/gui/panels.cpp index 871bc0d4..6488b6be 100644 --- a/src/frontend/gui/panels.cpp +++ b/src/frontend/gui/panels.cpp @@ -184,9 +184,7 @@ PagesControl::PagesControl() : Container(vec2(), vec2(1)){ } void PagesControl::add(std::string name, std::shared_ptr panel) { - panel->visible(false); pages[name] = Page{panel}; - Container::add(panel); } void PagesControl::set(std::string name, bool history) { @@ -195,14 +193,14 @@ void PagesControl::set(std::string name, bool history) { throw std::runtime_error("no page found"); } if (current_.panel) { - current_.panel->visible(false); + Container::remove(current_.panel); } if (history) { pageStack.push(curname_); } curname_ = name; current_ = found->second; - current_.panel->visible(true); + Container::add(current_.panel); size(current_.panel->size()); } @@ -226,7 +224,7 @@ void PagesControl::reset() { clearHistory(); if (current_.panel) { curname_ = ""; - current_.panel->visible(false); + Container::remove(current_.panel); current_ = Page{nullptr}; } } \ No newline at end of file diff --git a/src/frontend/screens.cpp b/src/frontend/screens.cpp index 09a00844..22cb092f 100644 --- a/src/frontend/screens.cpp +++ b/src/frontend/screens.cpp @@ -176,8 +176,7 @@ Panel* create_controls_panel(Engine* engine, PagesControl* pages) { for (auto& entry : Events::bindings){ string bindname = entry.first; - std::cout << bindname << std::endl; - + Panel* subpanel = new Panel(vec2(400, 45), vec4(5.0f), 1.0f); subpanel->color(vec4(0.0f)); subpanel->orientation(Orientation::horizontal); From 3eb6e82631cc1fd2e962f8c20e9774e9332c7ab3 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 20 Nov 2023 06:35:23 +0300 Subject: [PATCH 11/13] Added missing key names --- CMakeLists.txt | 1 - src/window/input.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 94762315..1bef1499 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,6 @@ else() # additional warnings -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wundef - -Wswitch-enum -Wwrite-strings -Wno-unused-parameter) endif() diff --git a/src/window/input.cpp b/src/window/input.cpp index 93cb08b2..10c1a415 100644 --- a/src/window/input.cpp +++ b/src/window/input.cpp @@ -80,6 +80,36 @@ const char* keycode::name(int code) { case GLFW_KEY_CAPS_LOCK: return "Caps-Lock"; case GLFW_KEY_SPACE: return "Space"; case GLFW_KEY_ESCAPE: return "Esc"; + case GLFW_KEY_ENTER: return "Enter"; + case GLFW_KEY_UP: return "Up"; + case GLFW_KEY_DOWN: return "Down"; + case GLFW_KEY_LEFT: return "Left"; + case GLFW_KEY_RIGHT: return "Right"; + case GLFW_KEY_BACKSPACE: return "Backspace"; + case GLFW_KEY_F1: return "F1"; + case GLFW_KEY_F2: return "F2"; + case GLFW_KEY_F3: return "F3"; + case GLFW_KEY_F4: return "F4"; + case GLFW_KEY_F5: return "F5"; + case GLFW_KEY_F6: return "F6"; + case GLFW_KEY_F7: return "F7"; + case GLFW_KEY_F8: return "F8"; + case GLFW_KEY_F9: return "F9"; + case GLFW_KEY_F10: return "F10"; + case GLFW_KEY_F11: return "F11"; + case GLFW_KEY_F12: return "F12"; + case GLFW_KEY_DELETE: return "Delete"; + case GLFW_KEY_HOME: return "Home"; + case GLFW_KEY_END: return "End"; + case GLFW_KEY_LEFT_SUPER: return "Left Super"; + case GLFW_KEY_RIGHT_SUPER: return "Right Super"; + case GLFW_KEY_PAGE_UP: return "Page Up"; + case GLFW_KEY_PAGE_DOWN: return "Page Down"; + case GLFW_KEY_INSERT: return "Insert"; + case GLFW_KEY_PRINT_SCREEN: return "Print Screen"; + case GLFW_KEY_NUM_LOCK: return "Num Lock"; + case GLFW_KEY_MENU: return "Menu"; + case GLFW_KEY_PAUSE: return "Pause"; default: return "Unknown"; } From e04abe79d88ff634dbc8675146096865fecc0373 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 20 Nov 2023 06:39:42 +0300 Subject: [PATCH 12/13] inputtype::button renamed to inputtype::mouse --- src/frontend/gui/controls.cpp | 2 +- src/voxel_engine.cpp | 6 +++--- src/window/Events.cpp | 2 +- src/window/input.h | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/frontend/gui/controls.cpp b/src/frontend/gui/controls.cpp index 295073e5..8b4935cb 100644 --- a/src/frontend/gui/controls.cpp +++ b/src/frontend/gui/controls.cpp @@ -179,7 +179,7 @@ void InputBindBox::drawBackground(Batch2D* batch, Assets* assets) { } void InputBindBox::clicked(GUI*, int button) { - binding.type = inputtype::button; + binding.type = inputtype::mouse; binding.code = button; defocus(); } diff --git a/src/voxel_engine.cpp b/src/voxel_engine.cpp index 7f0f882e..00203474 100644 --- a/src/voxel_engine.cpp +++ b/src/voxel_engine.cpp @@ -49,7 +49,7 @@ std::string write_controls() { json::JObject* jentry = new json::JObject(); switch (binding.type) { case inputtype::keyboard: jentry->put("type", "keyboard"); break; - case inputtype::button: jentry->put("type", "button"); break; + case inputtype::mouse: jentry->put("type", "mouse"); break; default: throw std::runtime_error("unsupported control type"); } jentry->put("code", binding.code); @@ -72,8 +72,8 @@ void load_controls(std::string filename, std::string source) { if (typestr == "keyboard") { type = inputtype::keyboard; - } else if (typestr == "button") { - type = inputtype::button; + } else if (typestr == "mouse") { + type = inputtype::mouse; } else { std::cerr << "unknown input type '" << typestr << "'" << std::endl; continue; diff --git a/src/window/Events.cpp b/src/window/Events.cpp index ec5fb3f9..6bbc7f63 100644 --- a/src/window/Events.cpp +++ b/src/window/Events.cpp @@ -73,7 +73,7 @@ void Events::pullEvents(){ bool newstate = false; switch (binding.type) { case inputtype::keyboard: newstate = pressed(binding.code); break; - case inputtype::button: newstate = clicked(binding.code); break; + case inputtype::mouse: newstate = clicked(binding.code); break; } if (newstate) { diff --git a/src/window/input.h b/src/window/input.h index 33469fdc..ef5840ba 100644 --- a/src/window/input.h +++ b/src/window/input.h @@ -80,7 +80,7 @@ namespace mousecode { enum class inputtype { keyboard, - button, + mouse, }; struct Binding { @@ -100,7 +100,7 @@ struct Binding { const char* text() const { switch (type) { case inputtype::keyboard: return keycode::name(code); - case inputtype::button: return mousecode::name(code); + case inputtype::mouse: return mousecode::name(code); } return ""; } From c712c2239f7e2e76630cbe01fbe91559af7a2498 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 20 Nov 2023 06:48:30 +0300 Subject: [PATCH 13/13] Added missing keycodes --- src/window/input.cpp | 14 ++++++++++++++ src/window/input.h | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/window/input.cpp b/src/window/input.cpp index 10c1a415..cd39a996 100644 --- a/src/window/input.cpp +++ b/src/window/input.cpp @@ -65,6 +65,20 @@ int keycode::NUM_6 = GLFW_KEY_6; int keycode::NUM_7 = GLFW_KEY_7; int keycode::NUM_8 = GLFW_KEY_8; int keycode::NUM_9 = GLFW_KEY_9; +int keycode::MENU = GLFW_KEY_MENU; +int keycode::PAUSE = GLFW_KEY_PAUSE; +int keycode::INSERT = GLFW_KEY_INSERT; +int keycode::LEFT_SUPER = GLFW_KEY_LEFT_SUPER; +int keycode::RIGHT_SUPER = GLFW_KEY_RIGHT_SUPER; +int keycode::DELETE = GLFW_KEY_DELETE; +int keycode::PAGE_UP = GLFW_KEY_PAGE_UP; +int keycode::PAGE_DOWN = GLFW_KEY_PAGE_DOWN; +int keycode::HOME = GLFW_KEY_HOME; +int keycode::END = GLFW_KEY_END; +int keycode::PRINT_SCREEN = GLFW_KEY_PRINT_SCREEN; +int keycode::NUM_LOCK = GLFW_KEY_NUM_LOCK; +int keycode::LEFT_BRACKET = GLFW_KEY_LEFT_BRACKET; +int keycode::RIGHT_BRACKET = GLFW_KEY_RIGHT_BRACKET; const char* keycode::name(int code) { const char* name = glfwGetKeyName(code, glfwGetKeyScancode(code)); diff --git a/src/window/input.h b/src/window/input.h index ef5840ba..afc27935 100644 --- a/src/window/input.h +++ b/src/window/input.h @@ -66,6 +66,20 @@ namespace keycode { extern int NUM_7; extern int NUM_8; extern int NUM_9; + extern int MENU; + extern int PAUSE; + extern int INSERT; + extern int LEFT_SUPER; + extern int RIGHT_SUPER; + extern int DELETE; + extern int PAGE_UP; + extern int PAGE_DOWN; + extern int HOME; + extern int END; + extern int PRINT_SCREEN; + extern int NUM_LOCK; + extern int LEFT_BRACKET; + extern int RIGHT_BRACKET; extern const char* name(int code); }