diff --git a/config/client.example.lua b/config/client.example.lua deleted file mode 100644 index 9b3d2b53..00000000 --- a/config/client.example.lua +++ /dev/null @@ -1,34 +0,0 @@ --- You can copy this file as 'config/client.lua' to load automatically those settings at client startup --- Here the default values are set, you can remove options or change them accordingly --- See source/client/core/Config.cpp for more details - --- Gameplay -isFlyModeEnabled = false -isNoClipEnabled = false - --- Interface -isBlockInfoWidgetEnabled = true -isFpsCounterEnabled = true -isHotbarVisible = true -isCrosshairVisible = true - --- Graphics -renderDistance = 8 -isSmoothLightingEnabled = true -isAmbientOcclusionEnabled = false -isWireframeModeEnabled = false -isFullscreenModeEnabled = false -isVerticalSyncEnabled = true -cameraFOV = 70.0 -screenWidth = 1600 -screenHeight = 1050 -guiScale = 3 -mipmapLevels = 0 -aoStrength = 1 - --- Input -mouseSensitivity = 8 - --- Other -username = "" - diff --git a/config/server.example.lua b/config/server.example.lua deleted file mode 100644 index af9da775..00000000 --- a/config/server.example.lua +++ /dev/null @@ -1,6 +0,0 @@ --- You can copy this file as 'config/server.lua' to load automatically those settings at server startup --- Here the default values are set, you can remove options or change them accordingly --- See source/server/core/ServerConfig.cpp for more details - -maxPlayers = 5 - diff --git a/source/client/core/Config.cpp b/source/client/core/Config.cpp index 3e1ab2f1..8c231a9d 100644 --- a/source/client/core/Config.cpp +++ b/source/client/core/Config.cpp @@ -59,7 +59,6 @@ u16 Config::screenWidth = 1600; u16 Config::screenHeight = 1050; u8 Config::guiScale = 3; u8 Config::mipmapLevels = 3; -float Config::aoStrength = 1.0f; // Input u8 Config::mouseSensitivity = 8; @@ -99,7 +98,6 @@ void Config::loadConfigFromFile(const char *filename) { screenHeight = lua["screenHeight"].get_or(screenHeight); guiScale = lua["guiScale"].get_or(guiScale); mipmapLevels = lua["mipmapLevels"].get_or(mipmapLevels); - aoStrength = lua["aoStrength"].get_or(aoStrength); mouseSensitivity = lua["mouseSensitivity"].get_or(mouseSensitivity); @@ -135,7 +133,6 @@ void Config::saveConfigToFile(const char *filename) { file << "screenHeight = " << screenHeight << std::endl; file << "guiScale = " << (u16)guiScale << std::endl; file << "mipmapLevels = " << (u16)mipmapLevels << std::endl; - file << "aoStrength = " << aoStrength << std::endl; file << std::endl; file << "mouseSensitivity = " << (u16)mouseSensitivity << std::endl; file << std::endl; diff --git a/source/client/core/Config.hpp b/source/client/core/Config.hpp index 4d660c27..fecb59d6 100644 --- a/source/client/core/Config.hpp +++ b/source/client/core/Config.hpp @@ -54,7 +54,6 @@ namespace Config { extern u16 screenHeight; extern u8 guiScale; extern u8 mipmapLevels; - extern float aoStrength; // Input extern u8 mouseSensitivity; diff --git a/source/client/gui/MenuWidget.cpp b/source/client/gui/MenuWidget.cpp index bf54f480..ea6fc979 100644 --- a/source/client/gui/MenuWidget.cpp +++ b/source/client/gui/MenuWidget.cpp @@ -37,21 +37,26 @@ void MenuWidget::reset(u16 width, u16 height) { m_height = height; m_buttons.clear(); - m_buttons.reserve(m_width * m_height); + m_sliders.clear(); Widget::m_width = 0; Widget::m_height = 0; } void MenuWidget::onEvent(const SDL_Event &event) { - for (std::size_t i = 0 ; i < m_buttons.size() ; ++i) { - m_buttons.at(i).onEvent(event); + for (auto &it : m_buttons) { + it.first.onEvent(event); if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { - int x = i % m_width; - int y = i / m_width; + updateWidgetPosition(it.first, it.second.x, it.second.y); + } + } - updateButtonPosition(m_buttons.at(i), x, y); + for (auto &it : m_sliders) { + it.first.onEvent(event); + + if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { + updateWidgetPosition(it.first, it.second.x, it.second.y); } } } @@ -59,54 +64,78 @@ void MenuWidget::onEvent(const SDL_Event &event) { void MenuWidget::onGuiScaleChanged(const GuiScaleChangedEvent &event) { setScale(event.guiScale, event.guiScale, 1); - for (std::size_t i = 0 ; i < m_buttons.size() ; ++i) { - int x = i % m_width; - int y = i / m_width; + for (auto &it : m_buttons) { + updateWidgetPosition(it.first, it.second.x, it.second.y); + } - updateButtonPosition(m_buttons.at(i), x, y); + for (auto &it : m_sliders) { + updateWidgetPosition(it.first, it.second.x, it.second.y); } } TextButton &MenuWidget::addButton(const std::string &text, const TextButton::CppCallback &callback, u16 width) { - int x = m_buttons.size() % m_width; - int y = m_buttons.size() / m_width; + int x = (m_buttons.size() + m_sliders.size()) % m_width; + int y = (m_buttons.size() + m_sliders.size()) / m_width; - m_buttons.emplace_back(width, this); + m_buttons.emplace_back(std::piecewise_construct, + std::forward_as_tuple(width, this), std::forward_as_tuple(x, y)); - TextButton &button = m_buttons.back(); + TextButton &button = m_buttons.back().first; button.setText(text); button.setCallback(callback); - updateButtonPosition(button, x, y); + updateWidgetPosition(button, x, y); return button; } void MenuWidget::setButtonEnabled(const std::string &text, bool isEnabled) { for (auto &it : m_buttons) { - if (it.text() == text) - it.setEnabled(isEnabled); + if (it.first.text() == text) + it.first.setEnabled(isEnabled); } } -void MenuWidget::updateButtonPosition(TextButton &button, int x, int y) { - button.setPosition(x * (button.width() + m_horizontalSpacing), - y * (button.height() + m_verticalSpacing)); +SliderWidget &MenuWidget::addSlider(const std::string &text, const SliderWidget::CppCallback &callback, int min, int max, int initialValue) { + int x = (m_buttons.size() + m_sliders.size()) % m_width; + int y = (m_buttons.size() + m_sliders.size()) / m_width; - if (button.getPosition().x + button.width() > Widget::m_width) { - Widget::m_width = button.getPosition().x + button.width(); + m_sliders.emplace_back(std::piecewise_construct, + std::forward_as_tuple(this), std::forward_as_tuple(x, y)); + + SliderWidget &slider = m_sliders.back().first; + slider.setText(text); + slider.setCallback(callback); + slider.setMinMaxValues(min, max); + slider.setCurrentValue(initialValue); + + updateWidgetPosition(slider, x, y); + + return slider; +} + +void MenuWidget::updateWidgetPosition(Widget &widget, int x, int y) { + widget.setPosition(x * (widget.width() + m_horizontalSpacing), + y * (widget.height() + m_verticalSpacing)); + + if (widget.getPosition().x + widget.width() > Widget::m_width) { + Widget::m_width = widget.getPosition().x + widget.width(); } - if (button.getPosition().y + button.height() > Widget::m_height) { - Widget::m_height = button.getPosition().y + button.height(); + if (widget.getPosition().y + widget.height() > Widget::m_height) { + Widget::m_height = widget.getPosition().y + widget.height(); } } void MenuWidget::draw(gk::RenderTarget &target, gk::RenderStates states) const { states.transform *= getTransform(); - for (const TextButton &button : m_buttons) { - if (!button.text().empty()) - target.draw(button, states); + for (auto &it : m_buttons) { + if (!it.first.text().empty()) + target.draw(it.first, states); + } + + for (auto &it : m_sliders) { + target.draw(it.first, states); } } diff --git a/source/client/gui/MenuWidget.hpp b/source/client/gui/MenuWidget.hpp index 9f9c9500..f3fc333c 100644 --- a/source/client/gui/MenuWidget.hpp +++ b/source/client/gui/MenuWidget.hpp @@ -27,6 +27,7 @@ #ifndef MENUWIDGET_HPP_ #define MENUWIDGET_HPP_ +#include "SliderWidget.hpp" #include "TextButton.hpp" struct GuiScaleChangedEvent; @@ -45,11 +46,13 @@ class MenuWidget : public Widget { TextButton &addButton(const std::string &text, const TextButton::CppCallback &callback, u16 width = 200); void setButtonEnabled(const std::string &text, bool isEnabled); + SliderWidget &addSlider(const std::string &text, const SliderWidget::CppCallback &callback, int min, int max, int initialValue); + void setVerticalSpacing(u16 verticalSpacing) { m_verticalSpacing = verticalSpacing; } void setHorizontalSpacing(u16 horizontalSpacing) { m_horizontalSpacing = horizontalSpacing; } private: - void updateButtonPosition(TextButton &button, int x, int y); + void updateWidgetPosition(Widget &widget, int x, int y); void draw(gk::RenderTarget &target, gk::RenderStates states) const override; @@ -59,7 +62,8 @@ class MenuWidget : public Widget { u16 m_width = 1; u16 m_height = 1; - std::vector m_buttons; + std::vector> m_buttons; + std::vector> m_sliders; }; #endif // MENUWIDGET_HPP_ diff --git a/source/client/gui/SliderWidget.cpp b/source/client/gui/SliderWidget.cpp new file mode 100644 index 00000000..b648b06d --- /dev/null +++ b/source/client/gui/SliderWidget.cpp @@ -0,0 +1,111 @@ +/* + * ===================================================================================== + * + * OpenMiner + * + * Copyright (C) 2018-2020 Unarelith, Quentin Bazin + * Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md) + * + * This file is part of OpenMiner. + * + * OpenMiner is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * OpenMiner is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenMiner; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * ===================================================================================== + */ +#include "Config.hpp" +#include "SliderWidget.hpp" + +SliderWidget::SliderWidget(Widget *parent) : SliderWidget(200, parent) { +} + +SliderWidget::SliderWidget(u16 width, Widget *parent) : Widget(width, 20, parent) { + m_text.setColor(m_defaultTextColor); + m_text.setShadowColor({56, 56, 56}); + + m_slider.setClipRect(0, 66, 8, 20); + m_background.setClipRect(0, 46, width, 20); + + m_sliderBorder.setClipRect(200 - 2, 66, 2, 20); + m_backgroundBorder.setClipRect(200 - 2, 46, 2, 20); + + m_sliderBorder.setPosition(8 - 2, 0); + m_backgroundBorder.setPosition(width - 2, 0); +} + +void SliderWidget::onEvent(const SDL_Event &event) { + if (event.type == SDL_MOUSEMOTION) { + if (m_isDragging || isPointInWidget(event.motion.x, event.motion.y)) { + m_text.setColor(m_hoverColor); + + updatePercentage(event.motion.x); + } + else + m_text.setColor(m_defaultTextColor); + + if (m_isDragging) + m_callback(*this, event.type); + } + else if (event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT) { + m_isDragging = isPointInWidget(event.button.x, event.button.y); + updatePercentage(event.button.x); + if (m_isDragging) + m_callback(*this, event.type); + } + else if (event.type == SDL_MOUSEBUTTONUP && event.button.button == SDL_BUTTON_LEFT) { + if (m_isDragging) + m_callback(*this, event.type); + m_isDragging = false; + } +} + +void SliderWidget::setCurrentValue(int currentValue) { + m_percentage = (currentValue - m_min) / float(m_max - m_min); + + updateSliderPosition(); +} + +void SliderWidget::setText(const std::string &text) { + m_text.setString(text); + m_text.updateVertexBuffer(); + m_text.setPosition(m_width / 2 - m_text.getSize().x / 2, + m_height / 2 - m_text.getSize().y / 2, 0); +} + +void SliderWidget::updatePercentage(s32 mouseX) { + if (m_isDragging) { + m_percentage = (mouseX - getGlobalBounds().x) / Config::guiScale / m_width; + m_percentage = std::clamp(m_percentage, 0.f, 1.f); + + updateSliderPosition(); + } +} + +void SliderWidget::updateSliderPosition() { + m_slider.setPosition(m_percentage * (m_width - 8), 0); + m_sliderBorder.setPosition(m_percentage * (m_width - 8) + 6, 0); +} + +void SliderWidget::draw(gk::RenderTarget &target, gk::RenderStates states) const { + states.transform *= getTransform(); + + target.draw(m_background, states); + target.draw(m_backgroundBorder, states); + + target.draw(m_slider, states); + target.draw(m_sliderBorder, states); + + target.draw(m_text, states); +} + diff --git a/source/client/gui/SliderWidget.hpp b/source/client/gui/SliderWidget.hpp new file mode 100644 index 00000000..56fd23fe --- /dev/null +++ b/source/client/gui/SliderWidget.hpp @@ -0,0 +1,82 @@ +/* + * ===================================================================================== + * + * OpenMiner + * + * Copyright (C) 2018-2020 Unarelith, Quentin Bazin + * Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md) + * + * This file is part of OpenMiner. + * + * OpenMiner is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * OpenMiner is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenMiner; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * ===================================================================================== + */ +#ifndef SLIDERWIDGET_HPP_ +#define SLIDERWIDGET_HPP_ + +#include + +#include + +#include "Text.hpp" +#include "Widget.hpp" + +class SliderWidget : public Widget { + public: + using CppCallback = std::function; + + SliderWidget(Widget *parent = nullptr); + SliderWidget(u16 width, Widget *parent = nullptr); + + void onEvent(const SDL_Event &event) override; + + int getCurrentValue() const { return m_min + (m_max - m_min) * m_percentage; } + void setMinMaxValues(int min, int max) { m_min = min; m_max = max; } + void setCurrentValue(int currentValue); + + const std::string &text() const { return m_text.string(); } + void setText(const std::string &text); + + void setCallback(const CppCallback &callback) { m_callback = callback; } + + private: + void updatePercentage(s32 mouseX); + void updateSliderPosition(); + + void draw(gk::RenderTarget &target, gk::RenderStates states) const override; + + const gk::Color m_defaultTextColor{224, 224, 224}; + const gk::Color m_hoverColor{255, 255, 160}; + + gk::Image m_slider{"texture-widgets"}; + gk::Image m_background{"texture-widgets"}; + + gk::Image m_sliderBorder{"texture-widgets"}; + gk::Image m_backgroundBorder{"texture-widgets"}; + + Text m_text; + + int m_min = 0; + int m_max = 100; + + float m_percentage = 0.f; + + bool m_isDragging = false; + + CppCallback m_callback; +}; + +#endif // SLIDERWIDGET_HPP_ diff --git a/source/client/states/GameState.cpp b/source/client/states/GameState.cpp index d5a8dd82..c3de4746 100644 --- a/source/client/states/GameState.cpp +++ b/source/client/states/GameState.cpp @@ -153,7 +153,7 @@ void GameState::onEvent(const SDL_Event &event) { void GameState::update() { m_world.checkPlayerChunk(m_player.x(), m_player.y(), m_player.z()); - m_world.update(); + m_world.update(!m_stateStack->empty() && &m_stateStack->top() == this); if (m_camera.getFieldOfView() != Config::cameraFOV) m_camera.setFieldOfView(Config::cameraFOV); diff --git a/source/client/states/SettingsMenuState.cpp b/source/client/states/SettingsMenuState.cpp index f0dc1ad4..c798258b 100644 --- a/source/client/states/SettingsMenuState.cpp +++ b/source/client/states/SettingsMenuState.cpp @@ -193,11 +193,11 @@ void SettingsMenuState::addInterfaceButtons() { void SettingsMenuState::addGraphicsButtons() { m_menuWidget.reset(2, 8); - m_menuWidget.addButton("Render Distance: " + std::to_string(Config::renderDistance), [] (TextButton &button) { - Config::renderDistance = std::max(4, (Config::renderDistance + 2) % 16); - button.setText("Render Distance: " + std::to_string(Config::renderDistance)); + m_menuWidget.addSlider("Render Distance: " + std::to_string(Config::renderDistance), [] (SliderWidget &slider, u32) { + Config::renderDistance = slider.getCurrentValue(); + slider.setText("Render Distance: " + std::to_string(Config::renderDistance)); World::isReloadRequested = true; - }); + }, 4, 16, Config::renderDistance); addToggleButton("Wireframe Mode", Config::isWireframeModeEnabled, false); @@ -213,12 +213,13 @@ void SettingsMenuState::addGraphicsButtons() { m_aoButton = &addToggleButton("Ambient Occlusion", Config::isAmbientOcclusionEnabled, true); m_aoButton->setEnabled(!Config::isSmoothLightingEnabled); - m_menuWidget.addButton("GUI Scale: " + std::to_string(Config::guiScale), [this] (TextButton &button) { - Config::guiScale = 1 + (Config::guiScale + 1) % 3; - button.setText("GUI Scale: " + std::to_string(Config::guiScale)); - - m_eventHandler->emplaceEvent(Config::guiScale); - }); + m_menuWidget.addSlider("GUI Scale: " + std::to_string(Config::guiScale), [this] (SliderWidget &slider, u32 eventType) { + slider.setText("GUI Scale: " + std::to_string(slider.getCurrentValue())); + if (eventType == SDL_MOUSEBUTTONUP) { + Config::guiScale = slider.getCurrentValue(); + m_eventHandler->emplaceEvent(Config::guiScale); + } + }, 1, 3, Config::guiScale); addToggleButton("Fullscreen", Config::isFullscreenModeEnabled, false); m_menuWidget.addButton("Resolution: " + std::to_string(Config::screenWidth) + "x" + std::to_string(Config::screenHeight), [] (TextButton &button) { @@ -243,20 +244,10 @@ void SettingsMenuState::addGraphicsButtons() { addToggleButton("Use VSync", Config::isVerticalSyncEnabled, false); - m_menuWidget.addButton("Mipmap Levels: " + std::to_string(Config::mipmapLevels), [] (TextButton &button) { - Config::mipmapLevels = (Config::mipmapLevels + 1) % 5; - button.setText("Mipmap Levels: " + std::to_string(Config::mipmapLevels)); - }); - - m_menuWidget.addButton("AO Strength: " + gk::toString(Config::aoStrength, 2), [] (TextButton &button) { - Config::aoStrength += 0.25f; - if (Config::aoStrength > 1.5f) - Config::aoStrength = 0.f; - - button.setText("AO Strength: " + gk::toString(Config::aoStrength, 2)); - - World::isReloadRequested = true; - }); + m_menuWidget.addSlider("Mipmap Levels: " + std::to_string(Config::mipmapLevels), [] (SliderWidget &slider, u32) { + Config::mipmapLevels = slider.getCurrentValue(); + slider.setText("Mipmap Levels: " + std::to_string(Config::mipmapLevels)); + }, 0, 4, Config::mipmapLevels); updateWidgetPosition(); } @@ -274,10 +265,10 @@ void SettingsMenuState::addInputButtons() { }); } - m_menuWidget.addButton("Mouse sensitivity: " + std::to_string(Config::mouseSensitivity), [] (TextButton &button) { - Config::mouseSensitivity = std::max(2, (Config::mouseSensitivity + 2) % 22); - button.setText("Mouse sensitivity: " + std::to_string(Config::mouseSensitivity)); - }); + m_menuWidget.addSlider("Mouse Sensitivity: " + std::to_string(Config::mouseSensitivity), [] (SliderWidget &slider, u32) { + Config::mouseSensitivity = slider.getCurrentValue(); + slider.setText("Mouse Sensitivity: " + std::to_string(Config::mouseSensitivity)); + }, 4, 32, Config::mouseSensitivity); updateWidgetPosition(); } diff --git a/source/client/world/ChunkBuilder.cpp b/source/client/world/ChunkBuilder.cpp index ac0b2a56..319c1e83 100644 --- a/source/client/world/ChunkBuilder.cpp +++ b/source/client/world/ChunkBuilder.cpp @@ -406,9 +406,11 @@ inline u8 ChunkBuilder::getLightForVertex(Light light, s8f x, s8f y, s8f z, cons // If the chunk is initialized, add the light value to the total if (lightValues[i] != -1) { - float strength = ((surroundingBlocks[i] - normal == gk::Vector3i{x, y, z}) ? 1 : Config::aoStrength); - total += lightValues[i] * strength; - count += strength; + // float strength = ((surroundingBlocks[i] - normal == gk::Vector3i{x, y, z}) ? 1 : Config::aoStrength); + // total += lightValues[i] * strength; + // count += strength; + total += lightValues[i]; + ++count; } } diff --git a/source/client/world/ClientWorld.cpp b/source/client/world/ClientWorld.cpp index 769791be..398303e0 100644 --- a/source/client/world/ClientWorld.cpp +++ b/source/client/world/ClientWorld.cpp @@ -43,7 +43,7 @@ ClientWorld::ClientWorld() : m_textureAtlas(gk::ResourceHandler::getInstance().g { } -void ClientWorld::update() { +void ClientWorld::update(bool allowWorldReload) { // Update loaded chunks for (auto it = m_chunks.begin() ; it != m_chunks.end() ;) { // If chunk is too far, remove it @@ -52,7 +52,7 @@ void ClientWorld::update() { } // Otherwise, update the chunk else { - if (World::isReloadRequested) + if (World::isReloadRequested && allowWorldReload) it->second->setChanged(true); if (it->second->areAllNeighboursInitialized()) @@ -62,7 +62,8 @@ void ClientWorld::update() { } } - World::isReloadRequested = false; + if (allowWorldReload) + World::isReloadRequested = false; sendChunkRequests(); diff --git a/source/client/world/ClientWorld.hpp b/source/client/world/ClientWorld.hpp index f1a23484..d9aecc13 100644 --- a/source/client/world/ClientWorld.hpp +++ b/source/client/world/ClientWorld.hpp @@ -47,7 +47,7 @@ class ClientWorld : public World, public gk::Drawable { public: ClientWorld(); - void update(); + void update(bool allowWorldReload); void sendChunkRequests(); void checkPlayerChunk(double playerX, double playerY, double playerZ);