Added pause menu, new F3 debug panel, fogCurve setting
This commit is contained in:
parent
b9ed7a2b28
commit
e48e41c99a
@ -8,6 +8,7 @@ out vec4 f_color;
|
||||
uniform sampler2D u_texture0;
|
||||
uniform vec3 u_fogColor;
|
||||
uniform float u_fogFactor;
|
||||
uniform float u_fogCurve;
|
||||
|
||||
void main(){
|
||||
vec4 tex_color = texture(u_texture0, a_texCoord);
|
||||
@ -16,6 +17,6 @@ void main(){
|
||||
// anyway it's any alpha-test alternative required
|
||||
if (alpha < 0.1f)
|
||||
discard;
|
||||
f_color = mix(a_color * tex_color, vec4(u_fogColor,1.0), min(1.0, depth*u_fogFactor));
|
||||
f_color = mix(a_color * tex_color, vec4(u_fogColor,1.0), min(1.0, pow(depth*u_fogFactor, u_fogCurve)));
|
||||
f_color.a = alpha;
|
||||
}
|
||||
|
||||
@ -72,6 +72,7 @@ void setup_definitions() {
|
||||
block->lightPassing = true;
|
||||
block->obstacle = false;
|
||||
block->model = 2;
|
||||
block->hitboxScale = 0.5f;
|
||||
Block::blocks[block->id] = block;
|
||||
|
||||
block = new Block(BLOCK_FLOWER, 16);
|
||||
|
||||
160
src/engine.cpp
Normal file
160
src/engine.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
#include "engine.h"
|
||||
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "audio/Audio.h"
|
||||
#include "assets/Assets.h"
|
||||
#include "assets/AssetsLoader.h"
|
||||
#include "window/Window.h"
|
||||
#include "window/Events.h"
|
||||
#include "window/Camera.h"
|
||||
#include "window/input.h"
|
||||
#include "graphics/Batch2D.h"
|
||||
#include "world/World.h"
|
||||
#include "world/Level.h"
|
||||
#include "voxels/Chunk.h"
|
||||
#include "voxels/Chunks.h"
|
||||
#include "voxels/ChunksController.h"
|
||||
#include "voxels/ChunksStorage.h"
|
||||
#include "objects/Player.h"
|
||||
#include "frontend/world_render.h"
|
||||
#include "frontend/hud.h"
|
||||
#include "frontend/gui/GUI.h"
|
||||
|
||||
#include "coders/json.h"
|
||||
#include "files/files.h"
|
||||
|
||||
using std::shared_ptr;
|
||||
using glm::vec3;
|
||||
using gui::GUI;
|
||||
|
||||
void load_settings(EngineSettings& settings, std::string filename) {
|
||||
std::string source = files::read_string(filename);
|
||||
std::unique_ptr<json::JObject> obj(json::parse(filename, source));
|
||||
obj->num("display-width", settings.displayWidth);
|
||||
obj->num("display-height", settings.displayHeight);
|
||||
obj->num("display-samples", settings.displaySamples);
|
||||
obj->num("display-swap-interval", settings.displaySwapInterval);
|
||||
obj->num("chunks-load-distance", settings.chunksLoadDistance);
|
||||
obj->num("chunks-load-speed", settings.chunksLoadSpeed);
|
||||
obj->num("chunks-padding", settings.chunksPadding);
|
||||
obj->num("fog-curve", settings.fogCurve);
|
||||
}
|
||||
|
||||
void save_settings(EngineSettings& settings, std::string filename) {
|
||||
json::JObject obj;
|
||||
obj.put("display-width", settings.displayWidth);
|
||||
obj.put("display-height", settings.displayHeight);
|
||||
obj.put("display-samples", settings.displaySamples);
|
||||
obj.put("display-swap-interval", settings.displaySwapInterval);
|
||||
obj.put("chunks-load-distance", settings.chunksLoadDistance);
|
||||
obj.put("chunks-load-speed", settings.chunksLoadSpeed);
|
||||
obj.put("chunks-padding", settings.chunksPadding);
|
||||
obj.put("fog-curve", settings.fogCurve);
|
||||
files::write_string(filename, json::stringify(&obj, true, " "));
|
||||
}
|
||||
|
||||
Engine::Engine(const EngineSettings& settings) {
|
||||
this->settings = settings;
|
||||
|
||||
Window::initialize(settings.displayWidth,
|
||||
settings.displayHeight,
|
||||
settings.displayTitle,
|
||||
settings.displaySamples);
|
||||
Window::swapInterval(settings.displaySwapInterval);
|
||||
|
||||
assets = new Assets();
|
||||
std::cout << "-- loading assets" << std::endl;
|
||||
AssetsLoader loader(assets);
|
||||
AssetsLoader::createDefaults(loader);
|
||||
AssetsLoader::addDefaults(loader);
|
||||
while (loader.hasNext()) {
|
||||
if (!loader.loadNext()) {
|
||||
delete assets;
|
||||
Window::terminate();
|
||||
throw initialize_error("could not to initialize assets");
|
||||
}
|
||||
}
|
||||
std::cout << "-- loading world" << std::endl;
|
||||
vec3 playerPosition = vec3(0, 64, 0);
|
||||
Camera* camera = new Camera(playerPosition, radians(90.0f));
|
||||
World* world = new World("world-1", "world/", 42);
|
||||
Player* player = new Player(playerPosition, 4.0f, camera);
|
||||
level = world->loadLevel(player, settings.chunksLoadDistance, settings.chunksPadding);
|
||||
|
||||
std::cout << "-- initializing finished" << std::endl;
|
||||
|
||||
Audio::initialize();
|
||||
|
||||
gui = new GUI();
|
||||
}
|
||||
|
||||
void Engine::updateTimers() {
|
||||
frame++;
|
||||
double currentTime = Window::time();
|
||||
delta = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
}
|
||||
|
||||
void Engine::updateHotkeys() {
|
||||
if (Events::jpressed(keycode::O)) {
|
||||
occlusion = !occlusion;
|
||||
}
|
||||
if (Events::jpressed(keycode::F3)) {
|
||||
level->player->debug = !level->player->debug;
|
||||
}
|
||||
if (Events::jpressed(keycode::F5)) {
|
||||
for (uint i = 0; i < level->chunks->volume; i++) {
|
||||
shared_ptr<Chunk> chunk = level->chunks->chunks[i];
|
||||
if (chunk != nullptr && chunk->isReady()) {
|
||||
chunk->setModified(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::mainloop() {
|
||||
Camera* camera = level->player->camera;
|
||||
std::cout << "-- preparing systems" << std::endl;
|
||||
WorldRenderer worldRenderer(level, assets);
|
||||
HudRenderer hud(gui, level, assets);
|
||||
Batch2D batch(1024);
|
||||
lastTime = Window::time();
|
||||
|
||||
while (!Window::isShouldClose()){
|
||||
updateTimers();
|
||||
updateHotkeys();
|
||||
|
||||
level->update(delta, Events::_cursor_locked, Events::_cursor_locked);
|
||||
level->chunksController->update(settings.chunksLoadSpeed);
|
||||
|
||||
worldRenderer.draw(camera, occlusion, 1.6f / (float)settings.chunksLoadDistance, settings.fogCurve);
|
||||
hud.draw();
|
||||
if (level->player->debug) {
|
||||
hud.drawDebug( 1 / delta, occlusion);
|
||||
}
|
||||
gui->act();
|
||||
gui->draw(&batch, assets);
|
||||
|
||||
Window::swapBuffers();
|
||||
Events::pullEvents();
|
||||
}
|
||||
}
|
||||
|
||||
Engine::~Engine() {
|
||||
Audio::finalize();
|
||||
|
||||
World* world = level->world;
|
||||
|
||||
std::cout << "-- saving world" << std::endl;
|
||||
world->write(level);
|
||||
|
||||
delete level;
|
||||
delete world;
|
||||
|
||||
std::cout << "-- shutting down" << std::endl;
|
||||
delete assets;
|
||||
Window::terminate();
|
||||
}
|
||||
67
src/engine.h
Normal file
67
src/engine.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef SRC_ENGINE_H_
|
||||
#define SRC_ENGINE_H_
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include "typedefs.h"
|
||||
|
||||
class Assets;
|
||||
class Level;
|
||||
|
||||
namespace gui {
|
||||
class GUI;
|
||||
}
|
||||
|
||||
struct EngineSettings {
|
||||
/* Window width (pixels) */
|
||||
int displayWidth;
|
||||
/* Window height (pixels) */
|
||||
int displayHeight;
|
||||
/* Anti-aliasing samples */
|
||||
int displaySamples;
|
||||
/* GLFW swap interval value, 0 - unlimited fps, 1 - vsync*/
|
||||
int displaySwapInterval;
|
||||
/* Window title */
|
||||
const char* displayTitle;
|
||||
/* Max milliseconds that engine uses for chunks loading only */
|
||||
uint chunksLoadSpeed;
|
||||
/* Radius of chunks loading zone (chunk is unit) */
|
||||
uint chunksLoadDistance;
|
||||
/* Buffer zone where chunks are not unloading (chunk is unit)*/
|
||||
uint chunksPadding;
|
||||
/* Fog opacity is calculated as `pow(depth*k, fogCurve)` where k depends on chunksLoadDistance.
|
||||
Use values in range [1.0 - 2.0] where 1.0 is linear, 2.0 is quadratic
|
||||
*/
|
||||
float fogCurve;
|
||||
};
|
||||
|
||||
void load_settings(EngineSettings& settings, std::string filename);
|
||||
void save_settings(EngineSettings& settings, std::string filename);
|
||||
|
||||
class initialize_error : public std::runtime_error {
|
||||
public:
|
||||
initialize_error(const std::string& message) : std::runtime_error(message) {}
|
||||
};
|
||||
|
||||
class Engine {
|
||||
Assets* assets;
|
||||
Level* level;
|
||||
EngineSettings settings;
|
||||
|
||||
uint64_t frame = 0;
|
||||
double lastTime = 0.0;
|
||||
double delta = 0.0;
|
||||
bool occlusion = true;
|
||||
|
||||
gui::GUI* gui;
|
||||
public:
|
||||
Engine(const EngineSettings& settings);
|
||||
~Engine();
|
||||
|
||||
void updateTimers();
|
||||
void updateHotkeys();
|
||||
void mainloop();
|
||||
};
|
||||
|
||||
#endif // SRC_ENGINE_H_
|
||||
85
src/frontend/gui/GUI.cpp
Normal file
85
src/frontend/gui/GUI.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include "GUI.h"
|
||||
#include "UINode.h"
|
||||
#include "panels.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../../assets/Assets.h"
|
||||
#include "../../graphics/Batch2D.h"
|
||||
#include "../../window/Events.h"
|
||||
#include "../../window/input.h"
|
||||
|
||||
using std::shared_ptr;
|
||||
using namespace gui;
|
||||
|
||||
GUI::GUI() {
|
||||
container = new Container(vec2(0, 0), vec2(Window::width, Window::height));
|
||||
}
|
||||
|
||||
GUI::~GUI() {
|
||||
delete container;
|
||||
}
|
||||
|
||||
void GUI::act() {
|
||||
container->size(vec2(Window::width, Window::height));
|
||||
int mx = Events::x;
|
||||
int my = Events::y;
|
||||
|
||||
auto hover = container->getAt(vec2(mx, my), nullptr);
|
||||
if (this->hover && this->hover != hover) {
|
||||
this->hover->hover(false);
|
||||
}
|
||||
if (hover) {
|
||||
hover->hover(true);
|
||||
}
|
||||
this->hover = hover;
|
||||
|
||||
if (Events::clicked(0)) {
|
||||
if (pressed == nullptr && this->hover) {
|
||||
pressed = hover;
|
||||
pressed->click(this, mx, my);
|
||||
if (focus) {
|
||||
focus->defocus();
|
||||
}
|
||||
focus = pressed;
|
||||
}
|
||||
if (this->hover == nullptr && focus) {
|
||||
focus->defocus();
|
||||
focus = nullptr;
|
||||
}
|
||||
} else if (pressed) {
|
||||
pressed->mouseRelease(this, mx, my);
|
||||
pressed = nullptr;
|
||||
}
|
||||
if (focus) {
|
||||
if (!focus->isfocused()){
|
||||
focus = nullptr;
|
||||
} else if (Events::jpressed(keycode::ESCAPE)) {
|
||||
focus->defocus();
|
||||
focus = nullptr;
|
||||
} else {
|
||||
for (auto codepoint : Events::codepoints) {
|
||||
focus->typed(codepoint);
|
||||
}
|
||||
for (auto key : Events::pressedKeys) {
|
||||
focus->keyPressed(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::draw(Batch2D* batch, Assets* assets) {
|
||||
container->draw(batch, assets);
|
||||
}
|
||||
|
||||
shared_ptr<UINode> GUI::getFocused() const {
|
||||
return focus;
|
||||
}
|
||||
|
||||
bool GUI::isFocusCaught() const {
|
||||
return focus && focus->isfocuskeeper();
|
||||
}
|
||||
|
||||
void GUI::add(shared_ptr<UINode> panel) {
|
||||
container->add(panel);
|
||||
}
|
||||
64
src/frontend/gui/GUI.h
Normal file
64
src/frontend/gui/GUI.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef FRONTEND_GUI_GUI_H_
|
||||
#define FRONTEND_GUI_GUI_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class Batch2D;
|
||||
class Assets;
|
||||
|
||||
/*
|
||||
Some info about padding and margin.
|
||||
Padding is element inner space, margin is outer
|
||||
glm::vec4 usage:
|
||||
x - left
|
||||
y - top
|
||||
z - right
|
||||
w - bottom
|
||||
|
||||
Outer element
|
||||
+======================================================================+
|
||||
| . . . . |
|
||||
| .padding.y . . . |
|
||||
| padding.x . . . . padding.z |
|
||||
|- - - - - - + - - - - - + - - - - - - - - - -+- - - - - + - - - - - - |
|
||||
| . . . . |
|
||||
| . .margin.y . . |
|
||||
| .margin.x . . margin.z. |
|
||||
|- - - - - - + - - - - - +====================+- - - - - + - - - - - - |
|
||||
| . | Inner element | . |
|
||||
|- - - - - - + - - - - - +====================+- - - - - + - - - - - - |
|
||||
| . . . . |
|
||||
| . .margin.w . . |
|
||||
| . . . . |
|
||||
|- - - - - - + - - - - - + - - - - - - - - - -+- - - - - + - - - - - - |
|
||||
| . . . . |
|
||||
| .padding.w . . . |
|
||||
| . . . . |
|
||||
+======================================================================+
|
||||
*/
|
||||
|
||||
namespace gui {
|
||||
class UINode;
|
||||
class Container;
|
||||
|
||||
class GUI {
|
||||
Container* container;
|
||||
std::shared_ptr<UINode> hover = nullptr;
|
||||
std::shared_ptr<UINode> pressed = nullptr;
|
||||
std::shared_ptr<UINode> focus = nullptr;
|
||||
public:
|
||||
GUI();
|
||||
~GUI();
|
||||
|
||||
std::shared_ptr<UINode> getFocused() const;
|
||||
bool isFocusCaught() const;
|
||||
|
||||
void act();
|
||||
void draw(Batch2D* batch, Assets* assets);
|
||||
void add(std::shared_ptr<UINode> panel);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // FRONTEND_GUI_GUI_H_
|
||||
24
src/frontend/gui/Panel.cpp
Normal file
24
src/frontend/gui/Panel.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "Panel.h"
|
||||
|
||||
#include "../../graphics/Batch2D.h"
|
||||
|
||||
using gui::Panel;
|
||||
|
||||
Panel::Panel(glm::vec2 coord, glm::vec2 size, glm::vec4 color)
|
||||
: coord(coord), size(size), color(color) {
|
||||
|
||||
}
|
||||
|
||||
void Panel::draw(Batch2D* batch) {
|
||||
batch->texture(nullptr);
|
||||
batch->color = color;
|
||||
batch->rect(coord.x, coord.y, size.x, size.y);
|
||||
}
|
||||
|
||||
bool Panel::isVisible() const {
|
||||
return visible;
|
||||
}
|
||||
|
||||
void Panel::setVisible(bool flag) {
|
||||
visible = flag;
|
||||
}
|
||||
24
src/frontend/gui/Panel.h
Normal file
24
src/frontend/gui/Panel.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef FRONTEND_GUI_PANEL_H_
|
||||
#define FRONTEND_GUI_PANEL_H_
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class Batch2D;
|
||||
|
||||
namespace gui {
|
||||
class Panel {
|
||||
glm::vec2 coord;
|
||||
glm::vec2 size;
|
||||
glm::vec4 color;
|
||||
bool visible = true;
|
||||
public:
|
||||
Panel(glm::vec2 coord, glm::vec2 size, glm::vec4 color);
|
||||
|
||||
void draw(Batch2D* batch);
|
||||
|
||||
void setVisible(bool flag);
|
||||
bool isVisible() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // FRONTEND_GUI_PANEL_H_
|
||||
134
src/frontend/gui/UINode.cpp
Normal file
134
src/frontend/gui/UINode.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
#include "UINode.h"
|
||||
|
||||
#include "../../graphics/Batch2D.h"
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
using gui::UINode;
|
||||
using gui::Align;
|
||||
|
||||
using glm::vec2;
|
||||
using glm::vec4;
|
||||
|
||||
#include <iostream>
|
||||
|
||||
UINode::UINode(vec2 coord, vec2 size) : coord(coord), size_(size) {
|
||||
}
|
||||
|
||||
UINode::~UINode() {
|
||||
}
|
||||
|
||||
bool UINode::visible() const {
|
||||
return isvisible;
|
||||
}
|
||||
|
||||
void UINode::visible(bool flag) {
|
||||
isvisible = flag;
|
||||
}
|
||||
|
||||
Align UINode::align() const {
|
||||
return align_;
|
||||
}
|
||||
|
||||
void UINode::align(Align align) {
|
||||
align_ = align;
|
||||
}
|
||||
|
||||
void UINode::hover(bool flag) {
|
||||
hover_ = flag;
|
||||
}
|
||||
|
||||
bool UINode::hover() const {
|
||||
return hover_;
|
||||
}
|
||||
|
||||
void UINode::setParent(UINode* node) {
|
||||
parent = node;
|
||||
}
|
||||
|
||||
UINode* UINode::getParent() const {
|
||||
return parent;
|
||||
}
|
||||
|
||||
void UINode::click(GUI*, int x, int y) {
|
||||
pressed_ = true;
|
||||
focused_ = true;
|
||||
}
|
||||
|
||||
void UINode::mouseRelease(GUI*, int x, int y) {
|
||||
pressed_ = false;
|
||||
}
|
||||
|
||||
bool UINode::ispressed() const {
|
||||
return pressed_;
|
||||
}
|
||||
|
||||
void UINode::defocus() {
|
||||
focused_ = false;
|
||||
}
|
||||
|
||||
bool UINode::isfocused() const {
|
||||
return focused_;
|
||||
}
|
||||
|
||||
bool UINode::isInside(glm::vec2 pos) {
|
||||
vec2 coord = calcCoord();
|
||||
vec2 size = this->size();
|
||||
return (pos.x >= coord.x && pos.y >= coord.y &&
|
||||
pos.x < coord.x + size.x && pos.y < coord.y + size.y);
|
||||
}
|
||||
|
||||
shared_ptr<UINode> UINode::getAt(vec2 pos, shared_ptr<UINode> self) {
|
||||
return isInside(pos) ? self : nullptr;
|
||||
}
|
||||
|
||||
vec2 UINode::calcCoord() const {
|
||||
if (parent) {
|
||||
return coord + parent->calcCoord();
|
||||
}
|
||||
return coord;
|
||||
}
|
||||
|
||||
void UINode::setCoord(vec2 coord) {
|
||||
this->coord = coord;
|
||||
}
|
||||
|
||||
vec2 UINode::size() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
void UINode::size(vec2 size) {
|
||||
if (sizelock)
|
||||
return;
|
||||
this->size_ = size;
|
||||
if (parent) {
|
||||
sizelock = true;
|
||||
parent->refresh();
|
||||
sizelock = false;
|
||||
}
|
||||
}
|
||||
|
||||
void UINode::_size(vec2 size) {
|
||||
if (sizelock)
|
||||
return;
|
||||
this->size_ = size;
|
||||
}
|
||||
|
||||
void UINode::color(vec4 color) {
|
||||
this->color_ = color;
|
||||
}
|
||||
|
||||
vec4 UINode::color() const {
|
||||
return color_;
|
||||
}
|
||||
|
||||
void UINode::margin(vec4 margin) {
|
||||
this->margin_ = margin;
|
||||
}
|
||||
|
||||
vec4 UINode::margin() const {
|
||||
return margin_;
|
||||
}
|
||||
|
||||
void UINode::lock() {
|
||||
}
|
||||
82
src/frontend/gui/UINode.h
Normal file
82
src/frontend/gui/UINode.h
Normal file
@ -0,0 +1,82 @@
|
||||
#ifndef FRONTEND_GUI_UINODE_H_
|
||||
#define FRONTEND_GUI_UINODE_H_
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
class Batch2D;
|
||||
class Assets;
|
||||
|
||||
namespace gui {
|
||||
class UINode;
|
||||
class GUI;
|
||||
|
||||
typedef std::function<void(GUI*)> onaction;
|
||||
typedef std::function<void(GUI*, double)> onnumberchange;
|
||||
|
||||
enum class Align {
|
||||
left, center, right
|
||||
};
|
||||
class UINode {
|
||||
protected:
|
||||
glm::vec2 coord;
|
||||
glm::vec2 size_;
|
||||
glm::vec4 color_ {1.0f};
|
||||
glm::vec4 margin_ {1.0f};
|
||||
bool isvisible = true;
|
||||
bool sizelock = false;
|
||||
bool hover_ = false;
|
||||
bool pressed_ = false;
|
||||
bool focused_ = false;
|
||||
Align align_ = Align::left;
|
||||
UINode* parent = nullptr;
|
||||
UINode(glm::vec2 coord, glm::vec2 size);
|
||||
public:
|
||||
virtual ~UINode();
|
||||
virtual void draw(Batch2D* batch, Assets* assets) = 0;
|
||||
|
||||
virtual void visible(bool flag);
|
||||
bool visible() const;
|
||||
|
||||
virtual void align(Align align);
|
||||
Align align() const;
|
||||
|
||||
virtual void hover(bool flag);
|
||||
bool hover() const;
|
||||
|
||||
virtual void setParent(UINode* node);
|
||||
UINode* getParent() const;
|
||||
|
||||
virtual void color(glm::vec4 newColor);
|
||||
glm::vec4 color() const;
|
||||
|
||||
virtual void margin(glm::vec4 margin);
|
||||
glm::vec4 margin() const;
|
||||
|
||||
virtual void click(GUI*, int x, int y);
|
||||
virtual void mouseRelease(GUI*, int x, int y);
|
||||
|
||||
bool ispressed() const;
|
||||
void defocus();
|
||||
bool isfocused() const;
|
||||
virtual bool isfocuskeeper() const {return false;}
|
||||
|
||||
virtual void typed(unsigned int codepoint) {};
|
||||
virtual void keyPressed(int key) {};
|
||||
|
||||
virtual bool isInside(glm::vec2 pos);
|
||||
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self);
|
||||
|
||||
glm::vec2 calcCoord() const;
|
||||
void setCoord(glm::vec2 coord);
|
||||
glm::vec2 size() const;
|
||||
virtual void size(glm::vec2 size);
|
||||
void _size(glm::vec2 size);
|
||||
virtual void refresh() {};
|
||||
virtual void lock();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // FRONTEND_GUI_UINODE_H_
|
||||
133
src/frontend/gui/controls.cpp
Normal file
133
src/frontend/gui/controls.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
#include "controls.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../../assets/Assets.h"
|
||||
#include "../../graphics/Batch2D.h"
|
||||
#include "../../graphics/Font.h"
|
||||
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using std::shared_ptr;
|
||||
using glm::vec2;
|
||||
|
||||
#define KEY_ESCAPE 256
|
||||
#define KEY_ENTER 257
|
||||
#define KEY_BACKSPACE 259
|
||||
|
||||
using namespace gui;
|
||||
|
||||
Label::Label(wstring text, string fontName)
|
||||
: UINode(vec2(), vec2(text.length() * 8, 15)), text_(text), fontName_(fontName) {
|
||||
}
|
||||
|
||||
Label& Label::text(wstring text) {
|
||||
this->text_ = text;
|
||||
return *this;
|
||||
}
|
||||
|
||||
wstring Label::text() const {
|
||||
return text_;
|
||||
}
|
||||
|
||||
void Label::draw(Batch2D* batch, Assets* assets) {
|
||||
if (supplier) {
|
||||
text(supplier());
|
||||
}
|
||||
batch->color = color_;
|
||||
Font* font = assets->getFont(fontName_);
|
||||
vec2 size = this->size();
|
||||
vec2 newsize = vec2(font->calcWidth(text_), font->lineHeight());
|
||||
if (newsize.x > size.x) {
|
||||
this->size(newsize);
|
||||
size = newsize;
|
||||
}
|
||||
vec2 coord = calcCoord();
|
||||
font->draw(batch, text_, coord.x, coord.y);
|
||||
}
|
||||
|
||||
void Label::textSupplier(wstringsupplier supplier) {
|
||||
this->supplier = supplier;
|
||||
}
|
||||
|
||||
Button::Button(shared_ptr<UINode> content, glm::vec4 padding) : Panel(vec2(32,32), padding, 0) {
|
||||
add(content);
|
||||
}
|
||||
|
||||
Button::Button(wstring text, glm::vec4 padding) : Panel(vec2(32,32), padding, 0) {
|
||||
Label* label = new Label(text);
|
||||
label->align(Align::center);
|
||||
add(shared_ptr<UINode>(label));
|
||||
}
|
||||
|
||||
void Button::drawBackground(Batch2D* batch, Assets* assets) {
|
||||
vec2 coord = calcCoord();
|
||||
batch->texture(nullptr);
|
||||
batch->color = (ispressed() ? pressedColor : (hover_ ? hoverColor : color_));
|
||||
batch->rect(coord.x, coord.y, size_.x, size_.y);
|
||||
}
|
||||
|
||||
shared_ptr<UINode> Button::getAt(vec2 pos, shared_ptr<UINode> self) {
|
||||
return UINode::getAt(pos, self);
|
||||
}
|
||||
|
||||
void Button::mouseRelease(GUI* gui, int x, int y) {
|
||||
UINode::mouseRelease(gui, x, y);
|
||||
if (isInside(vec2(x, y))) {
|
||||
for (auto callback : actions) {
|
||||
callback(gui);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Button::listenAction(onaction action) {
|
||||
actions.push_back(action);
|
||||
}
|
||||
|
||||
TextBox::TextBox(wstring text, vec4 padding) : Panel(vec2(200,32), padding, 0, false) {
|
||||
label = new Label(text);
|
||||
label->align(Align::center);
|
||||
add(shared_ptr<UINode>(label));
|
||||
}
|
||||
|
||||
void TextBox::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);
|
||||
if (!focused_ && supplier) {
|
||||
label->text(supplier());
|
||||
}
|
||||
}
|
||||
|
||||
void TextBox::typed(unsigned int codepoint) {
|
||||
label->text(label->text() + wstring({(wchar_t)codepoint}));
|
||||
}
|
||||
|
||||
void TextBox::keyPressed(int key) {
|
||||
wstring src = label->text();
|
||||
switch (key) {
|
||||
case KEY_BACKSPACE:
|
||||
if (src.length())
|
||||
label->text(src.substr(0, src.length()-1));
|
||||
break;
|
||||
case KEY_ENTER:
|
||||
if (consumer) {
|
||||
consumer(label->text());
|
||||
}
|
||||
defocus();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<UINode> TextBox::getAt(vec2 pos, shared_ptr<UINode> self) {
|
||||
return UINode::getAt(pos, self);
|
||||
}
|
||||
|
||||
void TextBox::textSupplier(wstringsupplier supplier) {
|
||||
this->supplier = supplier;
|
||||
}
|
||||
|
||||
void TextBox::textConsumer(wstringconsumer consumer) {
|
||||
this->consumer = consumer;
|
||||
}
|
||||
72
src/frontend/gui/controls.h
Normal file
72
src/frontend/gui/controls.h
Normal file
@ -0,0 +1,72 @@
|
||||
#ifndef FRONTEND_GUI_CONTROLS_H_
|
||||
#define FRONTEND_GUI_CONTROLS_H_
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <glm/glm.hpp>
|
||||
#include "UINode.h"
|
||||
#include "panels.h"
|
||||
|
||||
class Batch2D;
|
||||
class Assets;
|
||||
|
||||
namespace gui {
|
||||
typedef std::function<std::wstring()> wstringsupplier;
|
||||
typedef std::function<void(std::wstring)> wstringconsumer;
|
||||
|
||||
class Label : public UINode {
|
||||
protected:
|
||||
std::wstring text_;
|
||||
std::string fontName_;
|
||||
wstringsupplier supplier = nullptr;
|
||||
public:
|
||||
Label(std::wstring text, std::string fontName="normal");
|
||||
|
||||
virtual Label& text(std::wstring text);
|
||||
std::wstring text() const;
|
||||
|
||||
virtual void draw(Batch2D* batch, Assets* assets);
|
||||
|
||||
virtual void textSupplier(wstringsupplier supplier);
|
||||
};
|
||||
class Button : public Panel {
|
||||
protected:
|
||||
glm::vec4 hoverColor {0.05f, 0.1f, 0.2f, 0.75f};
|
||||
glm::vec4 pressedColor {0.0f, 0.0f, 0.0f, 0.95f};
|
||||
std::vector<onaction> actions;
|
||||
public:
|
||||
Button(std::shared_ptr<UINode> content, glm::vec4 padding=glm::vec4(2.0f));
|
||||
Button(std::wstring text, glm::vec4 padding=glm::vec4(2.0f));
|
||||
|
||||
virtual void drawBackground(Batch2D* batch, Assets* assets);
|
||||
|
||||
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self) override;
|
||||
|
||||
virtual void mouseRelease(GUI*, int x, int y) override;
|
||||
virtual void listenAction(onaction action);
|
||||
};
|
||||
|
||||
class TextBox : 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;
|
||||
wstringsupplier supplier = nullptr;
|
||||
wstringconsumer consumer = nullptr;
|
||||
public:
|
||||
TextBox(std::wstring text, glm::vec4 padding=glm::vec4(2.0f));
|
||||
|
||||
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self) override;
|
||||
|
||||
virtual void drawBackground(Batch2D* batch, Assets* assets) override;
|
||||
virtual void typed(unsigned int codepoint) override;
|
||||
virtual void keyPressed(int key) override;
|
||||
virtual void textSupplier(wstringsupplier supplier);
|
||||
virtual void textConsumer(wstringconsumer consumer);
|
||||
virtual bool isfocuskeeper() const override {return true;}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // FRONTEND_GUI_CONTROLS_H_
|
||||
130
src/frontend/gui/panels.cpp
Normal file
130
src/frontend/gui/panels.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
#include "panels.h"
|
||||
|
||||
#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 glm::vec2;
|
||||
using glm::vec4;
|
||||
|
||||
Container::Container(vec2 coord, vec2 size) : UINode(coord, size) {
|
||||
}
|
||||
|
||||
shared_ptr<UINode> Container::getAt(vec2 pos, shared_ptr<UINode> self) {
|
||||
for (auto node : nodes) {
|
||||
if (!node->visible())
|
||||
continue;
|
||||
auto hover = node->getAt(pos, node);
|
||||
if (hover != nullptr) {
|
||||
return hover;
|
||||
}
|
||||
}
|
||||
return UINode::getAt(pos, self);
|
||||
}
|
||||
|
||||
void Container::draw(Batch2D* batch, Assets* assets) {
|
||||
vec2 coord = calcCoord();
|
||||
vec2 size = this->size();
|
||||
drawBackground(batch, assets);
|
||||
batch->texture(nullptr);
|
||||
batch->render();
|
||||
Window::pushScissor(vec4(coord.x, coord.y, size.x, size.y));
|
||||
for (auto node : nodes) {
|
||||
if (node->visible())
|
||||
node->draw(batch, assets);
|
||||
}
|
||||
batch->render();
|
||||
Window::popScissor();
|
||||
}
|
||||
|
||||
void Container::add(shared_ptr<UINode> node) {
|
||||
nodes.push_back(node);
|
||||
node->setParent(this);
|
||||
refresh();
|
||||
}
|
||||
|
||||
Panel::Panel(vec2 size, glm::vec4 padding, float interval, bool resizing)
|
||||
: Container(vec2(), size), padding(padding), interval(interval), resizing_(resizing) {
|
||||
color_ = vec4(0.0f, 0.0f, 0.0f, 0.75f);
|
||||
}
|
||||
|
||||
Panel::~Panel() {
|
||||
}
|
||||
|
||||
void Panel::drawBackground(Batch2D* batch, Assets* assets) {
|
||||
vec2 coord = calcCoord();
|
||||
batch->texture(nullptr);
|
||||
batch->color = color_;
|
||||
batch->rect(coord.x, coord.y, size_.x, size_.y);
|
||||
}
|
||||
|
||||
void Panel::refresh() {
|
||||
float x = padding.x;
|
||||
float y = padding.y;
|
||||
vec2 size = this->size();
|
||||
if (orientation_ == Orientation::vertical) {
|
||||
float maxw = size.x;
|
||||
for (auto node : nodes) {
|
||||
vec2 nodesize = node->size();
|
||||
const vec4 margin = node->margin();
|
||||
y += margin.y;
|
||||
|
||||
float ex;
|
||||
|
||||
switch (node->align()) {
|
||||
case Align::center:
|
||||
ex = x + fmax(0.0f, (size.x - margin.z - padding.z) - node->size().x) / 2.0f;
|
||||
break;
|
||||
case Align::right:
|
||||
ex = x + size.x - margin.z - padding.z - node->size().x;
|
||||
break;
|
||||
default:
|
||||
ex = x + margin.x;
|
||||
}
|
||||
node->setCoord(vec2(ex, y));
|
||||
y += nodesize.y + margin.w + interval;
|
||||
node->size(vec2(size.x - padding.x - padding.z - margin.x - margin.z, nodesize.y));
|
||||
maxw = fmax(maxw, ex+node->size().x+margin.z+padding.z);
|
||||
}
|
||||
if (resizing_)
|
||||
this->size(vec2(maxw, y+padding.w));
|
||||
} else {
|
||||
float maxh = size.y;
|
||||
for (auto node : nodes) {
|
||||
vec2 nodesize = node->size();
|
||||
const vec4 margin = node->margin();
|
||||
x += margin.x;
|
||||
node->setCoord(vec2(x, y+margin.y));
|
||||
x += nodesize.x + margin.z + interval;
|
||||
node->size(vec2(nodesize.x, size.y - padding.y - padding.w - margin.y - margin.w));
|
||||
maxh = fmax(maxh, y+margin.y+node->size().y+margin.w+padding.w);
|
||||
}
|
||||
bool increased = maxh > size.y;
|
||||
if (resizing_)
|
||||
this->size(vec2(x+padding.z, maxh));
|
||||
if (increased)
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::orientation(Orientation orientation) {
|
||||
this->orientation_ = orientation;
|
||||
}
|
||||
|
||||
Orientation Panel::orientation() const {
|
||||
return orientation_;
|
||||
}
|
||||
|
||||
void Panel::lock(){
|
||||
for (auto node : nodes) {
|
||||
node->lock();
|
||||
}
|
||||
resizing_ = false;
|
||||
}
|
||||
46
src/frontend/gui/panels.h
Normal file
46
src/frontend/gui/panels.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef FRONTEND_GUI_PANELS_H_
|
||||
#define FRONTEND_GUI_PANELS_H_
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "UINode.h"
|
||||
|
||||
class Batch2D;
|
||||
class Assets;
|
||||
|
||||
namespace gui {
|
||||
enum class Orientation { vertical, horizontal };
|
||||
|
||||
class Container : public UINode {
|
||||
protected:
|
||||
std::vector<std::shared_ptr<UINode>> nodes;
|
||||
public:
|
||||
Container(glm::vec2 coord, glm::vec2 size);
|
||||
|
||||
virtual void drawBackground(Batch2D* batch, Assets* assets) {};
|
||||
virtual void draw(Batch2D* batch, Assets* assets);
|
||||
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self) override;
|
||||
virtual void add(std::shared_ptr<UINode> node);
|
||||
};
|
||||
|
||||
class Panel : public Container {
|
||||
protected:
|
||||
Orientation orientation_ = Orientation::vertical;
|
||||
glm::vec4 padding {2.0f};
|
||||
float interval = 2.0f;
|
||||
bool resizing_;
|
||||
public:
|
||||
Panel(glm::vec2 size, glm::vec4 padding=glm::vec4(2.0f), float interval=2.0f, bool resizing=true);
|
||||
virtual ~Panel();
|
||||
|
||||
virtual void drawBackground(Batch2D* batch, Assets* assets) override;
|
||||
|
||||
virtual void orientation(Orientation orientation);
|
||||
Orientation orientation() const;
|
||||
|
||||
virtual void refresh() override;
|
||||
virtual void lock() override;
|
||||
};
|
||||
}
|
||||
#endif // FRONTEND_GUI_PANELS_H_
|
||||
@ -1,10 +1,14 @@
|
||||
#include "hud_render.h"
|
||||
#include "hud.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "../util/stringutil.h"
|
||||
#include "../assets/Assets.h"
|
||||
#include "../graphics/Shader.h"
|
||||
#include "../graphics/Batch2D.h"
|
||||
@ -13,59 +17,132 @@
|
||||
#include "../window/Camera.h"
|
||||
#include "../window/Window.h"
|
||||
#include "../window/Events.h"
|
||||
#include "../window/input.h"
|
||||
#include "../voxels/Chunks.h"
|
||||
#include "../voxels/Block.h"
|
||||
#include "../world/World.h"
|
||||
#include "../world/Level.h"
|
||||
#include "../objects/Player.h"
|
||||
#include "../physics/Hitbox.h"
|
||||
#include "gui/controls.h"
|
||||
#include "gui/panels.h"
|
||||
#include "gui/UINode.h"
|
||||
#include "gui/GUI.h"
|
||||
|
||||
using std::wstring;
|
||||
using std::shared_ptr;
|
||||
using glm::vec2;
|
||||
using glm::vec3;
|
||||
using glm::vec4;
|
||||
using gui::GUI;
|
||||
using gui::UINode;
|
||||
using gui::Panel;
|
||||
using gui::Label;
|
||||
using gui::Button;
|
||||
using gui::TextBox;
|
||||
|
||||
HudRenderer::HudRenderer(Assets* assets) : assets(assets) {
|
||||
inline Label* create_label(gui::wstringsupplier supplier) {
|
||||
Label* label = new Label(L"-");
|
||||
label->textSupplier(supplier);
|
||||
return label;
|
||||
}
|
||||
|
||||
HudRenderer::HudRenderer(GUI* gui, Level* level, Assets* assets) : level(level), assets(assets), guiController(gui) {
|
||||
batch = new Batch2D(1024);
|
||||
uicamera = new Camera(glm::vec3(), Window::height);
|
||||
uicamera->perspective = false;
|
||||
uicamera->flipped = true;
|
||||
|
||||
Panel* panel = new Panel(vec2(200, 200), vec4(5.0f), 1.0f);
|
||||
panel->setCoord(vec2(10, 10));
|
||||
panel->add(shared_ptr<Label>(create_label([this](){
|
||||
return L"chunks: "+std::to_wstring(this->level->chunks->chunksCount);
|
||||
})));
|
||||
panel->add(shared_ptr<Label>(create_label([this](){
|
||||
return L"fps: "+this->fpsString;
|
||||
})));
|
||||
panel->add(shared_ptr<Label>(create_label([this](){
|
||||
return L"occlusion: "+wstring(this->occlusion ? L"on" : L"off");
|
||||
})));
|
||||
panel->add(shared_ptr<Label>(create_label([this](){
|
||||
std::wstringstream stream;
|
||||
stream << std::hex << this->level->player->selectedVoxel.states;
|
||||
return L"block-selected: "+std::to_wstring(this->level->player->selectedVoxel.id)+L" "+stream.str();
|
||||
})));
|
||||
panel->add(shared_ptr<Label>(create_label([this](){
|
||||
return L"meshes: " + std::to_wstring(Mesh::meshesCount);
|
||||
})));
|
||||
for (int ax = 0; ax < 3; ax++){
|
||||
Panel* sub = new Panel(vec2(10, 27), vec4(0.0f));
|
||||
sub->orientation(gui::Orientation::horizontal);
|
||||
Label* label = new Label(wstring({L'x'+ax})+L": ");
|
||||
label->margin(vec4(2, 3, 2, 3));
|
||||
sub->add(shared_ptr<UINode>(label));
|
||||
sub->color(vec4(0.0f));
|
||||
TextBox* box = new TextBox(L"");
|
||||
box->textSupplier([this, ax]() {
|
||||
Hitbox* hitbox = this->level->player->hitbox;
|
||||
return std::to_wstring((int)hitbox->position[ax]);
|
||||
});
|
||||
box->textConsumer([this, ax](wstring text) {
|
||||
try {
|
||||
this->level->player->hitbox->position[ax] = std::stoi(text);
|
||||
} catch (std::invalid_argument& _){
|
||||
}
|
||||
});
|
||||
|
||||
sub->add(shared_ptr<UINode>(box));
|
||||
panel->add(shared_ptr<UINode>(sub));
|
||||
}
|
||||
panel->refresh();
|
||||
debugPanel = panel;
|
||||
|
||||
pauseMenu = new Panel(vec2(350, 200));
|
||||
pauseMenu->color(vec4(0.0f));
|
||||
{
|
||||
Button* button = new Button(L"Continue", vec4(12.0f, 10.0f, 12.0f, 12.0f));
|
||||
button->listenAction([this](GUI*){
|
||||
this->pause = false;
|
||||
});
|
||||
pauseMenu->add(shared_ptr<UINode>(button));
|
||||
}
|
||||
{
|
||||
Button* button = new Button(L"Save and Quit", vec4(12.0f, 10.0f, 12.0f, 12.0f));
|
||||
button->listenAction([this](GUI*){
|
||||
Window::setShouldClose(true);
|
||||
});
|
||||
pauseMenu->add(shared_ptr<UINode>(button));
|
||||
}
|
||||
guiController->add(shared_ptr<UINode>(debugPanel));
|
||||
guiController->add(shared_ptr<UINode>(pauseMenu));
|
||||
}
|
||||
|
||||
HudRenderer::~HudRenderer() {
|
||||
delete batch;
|
||||
delete uicamera;
|
||||
delete guiController;
|
||||
}
|
||||
|
||||
void HudRenderer::drawDebug(Level* level, int fps, bool occlusion){
|
||||
Chunks* chunks = level->chunks;
|
||||
Player* player = level->player;
|
||||
|
||||
Font* font = assets->getFont("normal");
|
||||
|
||||
Shader* uishader = assets->getShader("ui");
|
||||
uishader->use();
|
||||
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
|
||||
batch->color = vec4(1.0f);
|
||||
batch->begin();
|
||||
font->draw(batch, L"chunks: "+std::to_wstring(chunks->chunksCount), 16, 16, STYLE_OUTLINE);
|
||||
font->draw(batch, std::to_wstring((int)player->camera->position.x), 10, 30, STYLE_OUTLINE);
|
||||
font->draw(batch, std::to_wstring((int)player->camera->position.y), 90, 30, STYLE_OUTLINE);
|
||||
font->draw(batch, std::to_wstring((int)player->camera->position.z), 170, 30, STYLE_OUTLINE);
|
||||
font->draw(batch, L"fps:", 16, 42, STYLE_OUTLINE);
|
||||
font->draw(batch, std::to_wstring(fps), 44, 42, STYLE_OUTLINE);
|
||||
font->draw(batch, L"occlusion: "+std::to_wstring(occlusion), 16, 54, STYLE_OUTLINE);
|
||||
|
||||
std::wstringstream stream;
|
||||
stream << std::hex << player->selectedVoxel.states;
|
||||
font->draw(batch, L"block-selected: "+std::to_wstring(player->selectedVoxel.id)+L" "+stream.str(), 16, 78, STYLE_OUTLINE);
|
||||
font->draw(batch, L"meshes: " + std::to_wstring(Mesh::meshesCount), 16, 102, STYLE_OUTLINE);
|
||||
batch->render();
|
||||
void HudRenderer::drawDebug(int fps, bool occlusion){
|
||||
this->occlusion = occlusion;
|
||||
if (fpsFrame % 60 == 0) {
|
||||
fpsString = std::to_wstring(fpsMax)+L" / "+std::to_wstring(fpsMin);
|
||||
fpsMin = fps;
|
||||
fpsMax = fps;
|
||||
}
|
||||
fpsFrame++;
|
||||
fpsMin = min(fps, fpsMin);
|
||||
fpsMax = max(fps, fpsMax);
|
||||
}
|
||||
|
||||
void HudRenderer::drawInventory(Player* player) {
|
||||
Texture* blocks = assets->getTexture("block");
|
||||
uint size = 48;
|
||||
uint step = 64;
|
||||
uint inv_wm = step*10;
|
||||
uint inv_hm = step*8;
|
||||
uint inv_w = inv_wm - (step - size);
|
||||
uint inv_h = inv_hm - (step - size);
|
||||
uint inv_cols = 10;
|
||||
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;
|
||||
@ -76,17 +153,14 @@ void HudRenderer::drawInventory(Player* player) {
|
||||
xs = (Window::width + inv_w + step)/2;
|
||||
ys = (Window::height - inv_h + step)/2;
|
||||
}
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
vec4 tint = vec4(1.0f);
|
||||
int mx = Events::x;
|
||||
int my = Events::y;
|
||||
uint count = (inv_w / step) * (inv_h / step) + 1;
|
||||
uint count = inv_cols * inv_rows;
|
||||
|
||||
//back
|
||||
// back
|
||||
batch->texture(nullptr);
|
||||
batch->color = vec4(0.0f, 0.0f, 0.0f, 0.3f);
|
||||
batch->rect(0, 0, Window::width, Window::height);
|
||||
batch->rect(inv_x - 4, inv_y - 4, inv_w+8, inv_h+8,
|
||||
0.95f, 0.95f, 0.95f, 0.85f, 0.85f, 0.85f,
|
||||
0.7f, 0.7f, 0.7f,
|
||||
@ -97,9 +171,9 @@ void HudRenderer::drawInventory(Player* player) {
|
||||
0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 4);
|
||||
|
||||
batch->color = vec4(0.35f, 0.35f, 0.35f, 1.0f);
|
||||
for (uint i = 1; i < count; i++) {
|
||||
x = xs + step * ((i-1) % (inv_w / step));
|
||||
y = ys + step * ((i-1) / (inv_w / step));
|
||||
for (uint i = 0; i < count; i++) {
|
||||
int x = xs + step * (i % (inv_cols));
|
||||
int y = ys + step * (i / (inv_cols));
|
||||
batch->rect(x-2, y-2, size+4, size+4,
|
||||
0.45f, 0.45f, 0.45f, 0.55f, 0.55f, 0.55f,
|
||||
0.7f, 0.7f, 0.7f,
|
||||
@ -110,20 +184,20 @@ void HudRenderer::drawInventory(Player* player) {
|
||||
0.65f, 0.65f, 0.65f, 0.65f, 0.65f, 0.65f, 2);
|
||||
}
|
||||
|
||||
//front
|
||||
// front
|
||||
batch->texture(blocks);
|
||||
for (uint i = 1; i < count; i++) {
|
||||
Block* cblock = Block::blocks[i];
|
||||
for (uint i = 0; i < count; i++) {
|
||||
Block* cblock = Block::blocks[i+1];
|
||||
if (cblock == nullptr)
|
||||
break;
|
||||
x = xs + step * ((i-1) % (inv_w / step));
|
||||
y = ys + step * ((i-1) / (inv_w / step));
|
||||
int x = xs + step * (i % inv_cols);
|
||||
int y = ys + step * (i / inv_cols);
|
||||
if (mx > x && mx < x + (int)size && my > y && my < y + (int)size) {
|
||||
tint.r *= 1.2f;
|
||||
tint.g *= 1.2f;
|
||||
tint.b *= 1.2f;
|
||||
if (Events::jclicked(GLFW_MOUSE_BUTTON_LEFT)) {
|
||||
player->choosenBlock = i;
|
||||
player->choosenBlock = i+1;
|
||||
}
|
||||
} else
|
||||
{
|
||||
@ -138,13 +212,16 @@ void HudRenderer::drawInventory(Player* player) {
|
||||
}
|
||||
}
|
||||
|
||||
void HudRenderer::draw(Level* level){
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
uicamera->fov = Window::height;
|
||||
void HudRenderer::draw(){
|
||||
debugPanel->visible(level->player->debug);
|
||||
pauseMenu->visible(pause);
|
||||
pauseMenu->setCoord(vec2(Window::width/2.0f, Window::height/2.0f) - pauseMenu->size() / 2.0f);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
uicamera->fov = Window::height;
|
||||
|
||||
Shader* uishader = assets->getShader("ui");
|
||||
uishader->use();
|
||||
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
|
||||
@ -181,7 +258,6 @@ void HudRenderer::draw(Level* level){
|
||||
0.75f, 0.75f, 0.75f,
|
||||
0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 2);
|
||||
|
||||
|
||||
batch->texture(blocks);
|
||||
Player* player = level->player;
|
||||
{
|
||||
@ -193,9 +269,30 @@ void HudRenderer::draw(Level* level){
|
||||
}
|
||||
}
|
||||
|
||||
if (!Events::_cursor_locked) {
|
||||
if (Events::jpressed(keycode::ESCAPE) && !guiController->isFocusCaught()) {
|
||||
if (pause) {
|
||||
pause = false;
|
||||
} else if (inventoryOpen) {
|
||||
inventoryOpen = false;
|
||||
} else {
|
||||
pause = true;
|
||||
}
|
||||
}
|
||||
if (Events::jpressed(keycode::TAB)) {
|
||||
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);
|
||||
batch->rect(0, 0, Window::width, Window::height);
|
||||
}
|
||||
if (inventoryOpen) {
|
||||
drawInventory(player);
|
||||
}
|
||||
batch->render();
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
}
|
||||
43
src/frontend/hud.h
Normal file
43
src/frontend/hud.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef SRC_HUD_H_
|
||||
#define SRC_HUD_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
class Batch2D;
|
||||
class Camera;
|
||||
class Level;
|
||||
class Assets;
|
||||
class Player;
|
||||
class Level;
|
||||
|
||||
namespace gui {
|
||||
class GUI;
|
||||
class Panel;
|
||||
}
|
||||
|
||||
class HudRenderer {
|
||||
Level* level;
|
||||
Assets* assets;
|
||||
Batch2D* batch;
|
||||
Camera* uicamera;
|
||||
|
||||
int fpsMin = 60;
|
||||
int fpsMax = 60;
|
||||
int fpsFrame = 0;
|
||||
std::wstring fpsString;
|
||||
bool occlusion;
|
||||
bool inventoryOpen = false;
|
||||
bool pause = true;
|
||||
|
||||
gui::Panel* debugPanel;
|
||||
gui::Panel* pauseMenu;
|
||||
gui::GUI* guiController;
|
||||
public:
|
||||
HudRenderer(gui::GUI* gui, Level* level, Assets* assets);
|
||||
~HudRenderer();
|
||||
void drawInventory(Player* player);
|
||||
void draw();
|
||||
void drawDebug(int fps, bool occlusion);
|
||||
};
|
||||
|
||||
#endif /* SRC_HUD_H_ */
|
||||
@ -1,22 +0,0 @@
|
||||
#ifndef SRC_HUD_RENDER_H_
|
||||
#define SRC_HUD_RENDER_H_
|
||||
|
||||
class Batch2D;
|
||||
class Camera;
|
||||
class Level;
|
||||
class Assets;
|
||||
class Player;
|
||||
|
||||
class HudRenderer {
|
||||
Assets* assets;
|
||||
Batch2D* batch;
|
||||
Camera* uicamera;
|
||||
public:
|
||||
HudRenderer(Assets* assets);
|
||||
~HudRenderer();
|
||||
void drawInventory(Player* player);
|
||||
void draw(Level* level);
|
||||
void drawDebug(Level* level, int fps, bool occlusion);
|
||||
};
|
||||
|
||||
#endif /* SRC_HUD_RENDER_H_ */
|
||||
@ -24,9 +24,6 @@
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
float _camera_cx;
|
||||
float _camera_cz;
|
||||
|
||||
WorldRenderer::WorldRenderer(Level* level, Assets* assets) : assets(assets), level(level) {
|
||||
lineBatch = new LineBatch(4096);
|
||||
batch3d = new Batch3D(1024);
|
||||
@ -42,15 +39,6 @@ WorldRenderer::~WorldRenderer() {
|
||||
delete renderer;
|
||||
}
|
||||
|
||||
Chunks* _chunks = nullptr;
|
||||
|
||||
bool chunks_distance_compare(size_t i, size_t j) {
|
||||
shared_ptr<Chunk> a = _chunks->chunks[i];
|
||||
shared_ptr<Chunk> b = _chunks->chunks[j];
|
||||
return ((a->x + 0.5f - _camera_cx)*(a->x + 0.5f - _camera_cx) + (a->z + 0.5f - _camera_cz)*(a->z + 0.5f - _camera_cz) >
|
||||
(b->x + 0.5f - _camera_cx)*(b->x + 0.5f - _camera_cx) + (b->z + 0.5f - _camera_cz)*(b->z + 0.5f - _camera_cz));
|
||||
}
|
||||
|
||||
bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion){
|
||||
shared_ptr<Chunk> chunk = level->chunks->chunks[index];
|
||||
if (!chunk->isLighted())
|
||||
@ -75,14 +63,12 @@ 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);
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
mesh->draw(GL_TRIANGLES);
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void WorldRenderer::draw(Camera* camera, bool occlusion){
|
||||
void WorldRenderer::draw(Camera* camera, bool occlusion, float fogFactor, float fogCurve){
|
||||
Chunks* chunks = level->chunks;
|
||||
|
||||
vec4 skyColor(0.7f, 0.81f, 1.0f, 1.0f);
|
||||
@ -103,7 +89,8 @@ void WorldRenderer::draw(Camera* camera, bool occlusion){
|
||||
shader->uniform1f("u_gamma", 1.6f);
|
||||
shader->uniform3f("u_skyLightColor", 1.1f,1.1f,1.1f);
|
||||
shader->uniform3f("u_fogColor", skyColor.r,skyColor.g,skyColor.b);
|
||||
shader->uniform1f("u_fogFactor", 0.025f);
|
||||
shader->uniform1f("u_fogFactor", fogFactor);
|
||||
shader->uniform1f("u_fogCurve", fogCurve);
|
||||
shader->uniform3f("u_cameraPos", camera->position.x,camera->position.y,camera->position.z);
|
||||
|
||||
Block* cblock = Block::blocks[level->player->choosenBlock];
|
||||
@ -112,7 +99,6 @@ void WorldRenderer::draw(Camera* camera, bool occlusion){
|
||||
cblock->emission[1] / 15.0f,
|
||||
cblock->emission[2] / 15.0f);
|
||||
shader->uniform1f("u_torchlightDistance", 6.0f);
|
||||
shader->uniform1f("u_fogFactor", 0.025f);
|
||||
texture->bind();
|
||||
|
||||
std::vector<size_t> indices;
|
||||
@ -126,11 +112,12 @@ void WorldRenderer::draw(Camera* camera, bool occlusion){
|
||||
|
||||
float px = camera->position.x / (float)CHUNK_W;
|
||||
float pz = camera->position.z / (float)CHUNK_D;
|
||||
|
||||
_camera_cx = px;
|
||||
_camera_cz = pz;
|
||||
_chunks = chunks;
|
||||
std::sort(indices.begin(), indices.end(), chunks_distance_compare);
|
||||
std::sort(indices.begin(), indices.end(), [this, chunks, px, pz](size_t i, size_t j) {
|
||||
shared_ptr<Chunk> a = chunks->chunks[i];
|
||||
shared_ptr<Chunk> b = chunks->chunks[j];
|
||||
return ((a->x + 0.5f - px)*(a->x + 0.5f - px) + (a->z + 0.5f - pz)*(a->z + 0.5f - pz) >
|
||||
(b->x + 0.5f - px)*(b->x + 0.5f - px) + (b->z + 0.5f - pz)*(b->z + 0.5f - pz));
|
||||
});
|
||||
|
||||
|
||||
int occludedChunks = 0;
|
||||
@ -161,9 +148,9 @@ void WorldRenderer::draw(Camera* camera, bool occlusion){
|
||||
linesShader->use();
|
||||
linesShader->uniformMatrix("u_projview", camera->getProjection()*camera->getView());
|
||||
|
||||
vec3 point = vec3(camera->position.x+camera->front.x/1,
|
||||
camera->position.y+camera->front.y/1,
|
||||
camera->position.z+camera->front.z/1);
|
||||
vec3 point = vec3(camera->position.x+camera->front.x,
|
||||
camera->position.y+camera->front.y,
|
||||
camera->position.z+camera->front.z);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ class Framebuffer;
|
||||
|
||||
|
||||
class WorldRenderer {
|
||||
Batch3D *batch3d;
|
||||
Batch3D* batch3d;
|
||||
Assets* assets;
|
||||
Level* level;
|
||||
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion);
|
||||
@ -34,7 +34,7 @@ public:
|
||||
WorldRenderer(Level* level, Assets* assets);
|
||||
~WorldRenderer();
|
||||
|
||||
void draw(Camera* camera, bool occlusion);
|
||||
void draw(Camera* camera, bool occlusion, float fogFactor, float fogCurve);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
PlayerController::PlayerController(Level* level) : level(level) {
|
||||
}
|
||||
|
||||
void PlayerController::update_controls(float delta){
|
||||
void PlayerController::update_controls(float delta, bool movement){
|
||||
Player* player = level->player;
|
||||
|
||||
/*block choose*/{
|
||||
@ -45,10 +45,10 @@ void PlayerController::update_controls(float delta){
|
||||
|
||||
Camera* camera = player->camera;
|
||||
Hitbox* hitbox = player->hitbox;
|
||||
bool sprint = Events::pressed(keycode::LEFT_CONTROL);
|
||||
bool shift = Events::pressed(keycode::LEFT_SHIFT) && hitbox->grounded && !sprint;
|
||||
bool zoom = Events::pressed(keycode::C);
|
||||
bool cheat = Events::pressed(keycode::R);
|
||||
bool sprint = Events::pressed(keycode::LEFT_CONTROL) && movement;
|
||||
bool shift = Events::pressed(keycode::LEFT_SHIFT) && hitbox->grounded && !sprint && movement;
|
||||
bool zoom = Events::pressed(keycode::C) && movement;
|
||||
bool cheat = Events::pressed(keycode::R) && movement;
|
||||
|
||||
float speed = player->speed;
|
||||
if (player->flight){
|
||||
@ -59,7 +59,8 @@ void PlayerController::update_controls(float delta){
|
||||
}
|
||||
int substeps = (int)(delta * 1000);
|
||||
substeps = (substeps <= 0 ? 1 : (substeps > 100 ? 100 : substeps));
|
||||
level->physics->step(level->chunks, hitbox, delta, substeps, shift, player->flight ? 0.0f : 1.0f, !player->noclip);
|
||||
if (movement)
|
||||
level->physics->step(level->chunks, hitbox, delta, substeps, shift, player->flight ? 0.0f : 1.0f, !player->noclip);
|
||||
camera->position.x = hitbox->position.x;
|
||||
camera->position.y = hitbox->position.y + 0.7f;
|
||||
camera->position.z = hitbox->position.z;
|
||||
@ -81,14 +82,14 @@ void PlayerController::update_controls(float delta){
|
||||
camera->position -= min(player->interpVel * 0.05f, 1.0f);
|
||||
}//end
|
||||
|
||||
if ((Events::jpressed(keycode::F) && !player->noclip) ||
|
||||
(Events::jpressed(keycode::N) && player->flight == player->noclip)){
|
||||
if ((Events::jpressed(keycode::F) && movement && !player->noclip) ||
|
||||
(Events::jpressed(keycode::N) && movement && player->flight == player->noclip)){
|
||||
player->flight = !player->flight;
|
||||
if (player->flight){
|
||||
hitbox->grounded = false;
|
||||
}
|
||||
}
|
||||
if (Events::jpressed(keycode::N)) {
|
||||
if (Events::jpressed(keycode::N) && movement) {
|
||||
player->noclip = !player->noclip;
|
||||
}
|
||||
|
||||
@ -108,23 +109,23 @@ void PlayerController::update_controls(float delta){
|
||||
camera->zoom = zoomValue * dt + camera->zoom * (1.0f - dt);
|
||||
}//end
|
||||
|
||||
if (Events::pressed(keycode::SPACE) && hitbox->grounded){
|
||||
if (Events::pressed(keycode::SPACE) && movement && hitbox->grounded){
|
||||
hitbox->velocity.y = JUMP_FORCE;
|
||||
}
|
||||
vec3 dir(0,0,0);
|
||||
if (Events::pressed(keycode::W)){
|
||||
if (Events::pressed(keycode::W) && movement){
|
||||
dir.x += camera->dir.x;
|
||||
dir.z += camera->dir.z;
|
||||
}
|
||||
if (Events::pressed(keycode::S)){
|
||||
if (Events::pressed(keycode::S) && movement){
|
||||
dir.x -= camera->dir.x;
|
||||
dir.z -= camera->dir.z;
|
||||
}
|
||||
if (Events::pressed(keycode::D)){
|
||||
if (Events::pressed(keycode::D) && movement){
|
||||
dir.x += camera->right.x;
|
||||
dir.z += camera->right.z;
|
||||
}
|
||||
if (Events::pressed(keycode::A)){
|
||||
if (Events::pressed(keycode::A) && movement){
|
||||
dir.x -= camera->right.x;
|
||||
dir.z -= camera->right.z;
|
||||
}
|
||||
@ -133,10 +134,10 @@ void PlayerController::update_controls(float delta){
|
||||
if (player->flight){
|
||||
hitbox->linear_damping = PLAYER_AIR_DAMPING;
|
||||
hitbox->velocity.y *= 1.0f - delta * 9;
|
||||
if (Events::pressed(keycode::SPACE)){
|
||||
if (Events::pressed(keycode::SPACE) && movement){
|
||||
hitbox->velocity.y += speed * delta * 9;
|
||||
}
|
||||
if (Events::pressed(keycode::LEFT_SHIFT)){
|
||||
if (Events::pressed(keycode::LEFT_SHIFT) && movement){
|
||||
hitbox->velocity.y -= speed * delta * 9;
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ public:
|
||||
glm::vec3 selectedBlockPosition;
|
||||
int selectedBlockId = -1;
|
||||
PlayerController(Level* level);
|
||||
void update_controls(float delta);
|
||||
void update_controls(float delta, bool movement);
|
||||
void update_interaction();
|
||||
};
|
||||
|
||||
|
||||
@ -3,211 +3,15 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
#include <exception>
|
||||
#include <filesystem>
|
||||
|
||||
// GLM
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/ext.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "coders/json.h"
|
||||
#include "files/files.h"
|
||||
#include "window/Window.h"
|
||||
#include "window/Events.h"
|
||||
#include "window/Camera.h"
|
||||
#include "window/input.h"
|
||||
#include "audio/Audio.h"
|
||||
#include "voxels/Chunk.h"
|
||||
#include "voxels/Chunks.h"
|
||||
#include "voxels/ChunksController.h"
|
||||
#include "voxels/ChunksStorage.h"
|
||||
#include "objects/Player.h"
|
||||
#include "world/Level.h"
|
||||
#include "world/World.h"
|
||||
#include "definitions.h"
|
||||
#include "assets/Assets.h"
|
||||
#include "assets/AssetsLoader.h"
|
||||
#include "frontend/world_render.h"
|
||||
#include "frontend/hud_render.h"
|
||||
|
||||
#define SETTINGS_FILE "settings.json"
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
|
||||
class initialize_error : public std::runtime_error {
|
||||
public:
|
||||
initialize_error(const std::string& message) : std::runtime_error(message) {}
|
||||
};
|
||||
|
||||
struct EngineSettings {
|
||||
/* Window width (pixels) */
|
||||
int displayWidth;
|
||||
/* Window height (pixels) */
|
||||
int displayHeight;
|
||||
/* Anti-aliasing samples */
|
||||
int displaySamples;
|
||||
/* GLFW swap interval value, 0 - unlimited fps, 1 - vsync*/
|
||||
int displaySwapInterval;
|
||||
/* Window title */
|
||||
const char* displayTitle;
|
||||
/* Max milliseconds that engine uses for chunks loading only */
|
||||
uint chunksLoadSpeed;
|
||||
/* Radius of chunks loading zone (chunk is unit) */
|
||||
uint chunksLoadDistance;
|
||||
/* Buffer zone where chunks are not unloading (chunk is unit)*/
|
||||
uint chunksPadding;
|
||||
};
|
||||
|
||||
void save_settings(EngineSettings& settings, std::string filename);
|
||||
|
||||
class Engine {
|
||||
Assets* assets;
|
||||
Level* level;
|
||||
EngineSettings settings;
|
||||
|
||||
uint64_t frame = 0;
|
||||
double lastTime = 0.0;
|
||||
double delta = 0.0;
|
||||
bool occlusion = true;
|
||||
public:
|
||||
Engine(const EngineSettings& settings);
|
||||
~Engine();
|
||||
|
||||
void updateTimers();
|
||||
void updateHotkeys();
|
||||
void mainloop();
|
||||
};
|
||||
|
||||
Engine::Engine(const EngineSettings& settings) {
|
||||
this->settings = settings;
|
||||
|
||||
Window::initialize(settings.displayWidth,
|
||||
settings.displayHeight,
|
||||
settings.displayTitle,
|
||||
settings.displaySamples);
|
||||
Window::swapInterval(settings.displaySwapInterval);
|
||||
|
||||
assets = new Assets();
|
||||
std::cout << "-- loading assets" << std::endl;
|
||||
AssetsLoader loader(assets);
|
||||
AssetsLoader::createDefaults(loader);
|
||||
AssetsLoader::addDefaults(loader);
|
||||
while (loader.hasNext()) {
|
||||
if (!loader.loadNext()) {
|
||||
delete assets;
|
||||
Window::terminate();
|
||||
throw initialize_error("could not to initialize assets");
|
||||
}
|
||||
}
|
||||
std::cout << "-- loading world" << std::endl;
|
||||
vec3 playerPosition = vec3(0, 64, 0);
|
||||
Camera* camera = new Camera(playerPosition, radians(90.0f));
|
||||
World* world = new World("world-1", "world/", 42);
|
||||
Player* player = new Player(playerPosition, 4.0f, camera);
|
||||
level = world->loadLevel(player, settings.chunksLoadDistance, settings.chunksPadding);
|
||||
|
||||
std::cout << "-- initializing finished" << std::endl;
|
||||
|
||||
Audio::initialize();
|
||||
}
|
||||
|
||||
void Engine::updateTimers() {
|
||||
frame++;
|
||||
double currentTime = Window::time();
|
||||
delta = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
}
|
||||
|
||||
void Engine::updateHotkeys() {
|
||||
if (Events::jpressed(keycode::TAB)) {
|
||||
Events::toggleCursor();
|
||||
}
|
||||
if (Events::jpressed(keycode::O)) {
|
||||
occlusion = !occlusion;
|
||||
}
|
||||
if (Events::jpressed(keycode::F3)) {
|
||||
level->player->debug = !level->player->debug;
|
||||
}
|
||||
if (Events::jpressed(keycode::F5)) {
|
||||
for (uint i = 0; i < level->chunks->volume; i++) {
|
||||
shared_ptr<Chunk> chunk = level->chunks->chunks[i];
|
||||
if (chunk != nullptr && chunk->isReady()) {
|
||||
chunk->setModified(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::mainloop() {
|
||||
Camera* camera = level->player->camera;
|
||||
std::cout << "-- preparing systems" << std::endl;
|
||||
WorldRenderer worldRenderer(level, assets);
|
||||
HudRenderer hud(assets);
|
||||
lastTime = Window::time();
|
||||
|
||||
while (!Window::isShouldClose()){
|
||||
updateTimers();
|
||||
updateHotkeys();
|
||||
|
||||
level->update(delta, Events::_cursor_locked);
|
||||
level->chunksController->update(settings.chunksLoadSpeed);
|
||||
|
||||
worldRenderer.draw(camera, occlusion);
|
||||
hud.draw(level);
|
||||
if (level->player->debug) {
|
||||
hud.drawDebug(level, 1 / delta, occlusion);
|
||||
}
|
||||
|
||||
Window::swapBuffers();
|
||||
Events::pullEvents();
|
||||
}
|
||||
}
|
||||
|
||||
Engine::~Engine() {
|
||||
Audio::finalize();
|
||||
|
||||
World* world = level->world;
|
||||
|
||||
std::cout << "-- saving world" << std::endl;
|
||||
world->write(level);
|
||||
|
||||
delete level;
|
||||
delete world;
|
||||
|
||||
std::cout << "-- shutting down" << std::endl;
|
||||
delete assets;
|
||||
Window::terminate();
|
||||
}
|
||||
|
||||
void load_settings(EngineSettings& settings, std::string filename) {
|
||||
std::string source = files::read_string(filename);
|
||||
std::unique_ptr<json::JObject> obj(json::parse(filename, source));
|
||||
obj->num("display-width", settings.displayWidth);
|
||||
obj->num("display-height", settings.displayHeight);
|
||||
obj->num("display-samples", settings.displaySamples);
|
||||
obj->num("display-swap-interval", settings.displaySwapInterval);
|
||||
obj->num("chunks-load-distance", settings.chunksLoadDistance);
|
||||
obj->num("chunks-load-speed", settings.chunksLoadSpeed);
|
||||
obj->num("chunks-padding", settings.chunksPadding);
|
||||
}
|
||||
|
||||
void save_settings(EngineSettings& settings, std::string filename) {
|
||||
json::JObject obj;
|
||||
obj.put("display-width", settings.displayWidth);
|
||||
obj.put("display-height", settings.displayHeight);
|
||||
obj.put("display-samples", settings.displaySamples);
|
||||
obj.put("display-swap-interval", settings.displaySwapInterval);
|
||||
obj.put("chunks-load-distance", settings.chunksLoadDistance);
|
||||
obj.put("chunks-load-speed", settings.chunksLoadSpeed);
|
||||
obj.put("chunks-padding", settings.chunksPadding);
|
||||
files::write_string(filename, json::stringify(&obj, true, " "));
|
||||
}
|
||||
#include "util/platform.h"
|
||||
#include "engine.h"
|
||||
|
||||
int main() {
|
||||
platform::configure_encoding();
|
||||
setup_definitions();
|
||||
try {
|
||||
EngineSettings settings;
|
||||
@ -219,12 +23,15 @@ int main() {
|
||||
settings.chunksLoadDistance = 12;
|
||||
settings.chunksPadding = 2;
|
||||
settings.displaySwapInterval = 1;
|
||||
settings.fogCurve = 1.6f;
|
||||
|
||||
if (std::filesystem::is_regular_file(SETTINGS_FILE)) {
|
||||
std::string settings_file = platform::get_settings_file();
|
||||
if (std::filesystem::is_regular_file(settings_file)) {
|
||||
std::cout << "-- loading settings" << std::endl;
|
||||
load_settings(settings, SETTINGS_FILE);
|
||||
load_settings(settings, settings_file);
|
||||
} else {
|
||||
save_settings(settings, SETTINGS_FILE);
|
||||
std::cout << "-- creating settings file " << settings_file << std::endl;
|
||||
save_settings(settings, settings_file);
|
||||
}
|
||||
Engine engine(settings);
|
||||
engine.mainloop();
|
||||
|
||||
@ -28,7 +28,6 @@ public:
|
||||
bool breakable = true;
|
||||
bool rotatable = false;
|
||||
float hitboxScale = 1;
|
||||
float hitboxY = 1;
|
||||
|
||||
Block(unsigned int id, int texture);
|
||||
};
|
||||
|
||||
@ -137,7 +137,7 @@ void WorldGenerator::generate(voxel* voxels, int cx, int cz, int seed){
|
||||
} else if (real_y < height){
|
||||
id = BLOCK_DIRT;
|
||||
} else {
|
||||
int tree = generate_tree(&noise, &randomtree, heights, real_x, real_y, real_z, 23);
|
||||
int tree = generate_tree(&noise, &randomtree, heights, real_x, real_y, real_z, 12);
|
||||
if (tree) {
|
||||
id = tree;
|
||||
states = 0x32;
|
||||
|
||||
@ -91,6 +91,8 @@ int Window::initialize(uint width, uint height, const char* title, int samples){
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
Window::width = width;
|
||||
@ -105,6 +107,10 @@ int Window::initialize(uint width, uint height, const char* title, int samples){
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Window::clear() {
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void Window::viewport(int x, int y, int width, int height){
|
||||
glViewport(x, y, width, height);
|
||||
}
|
||||
|
||||
@ -30,6 +30,8 @@ public:
|
||||
static void popScissor();
|
||||
static void resetScissor();
|
||||
|
||||
static void clear();
|
||||
|
||||
static double time();
|
||||
};
|
||||
|
||||
|
||||
@ -38,8 +38,8 @@ Level::~Level(){
|
||||
delete playerController;
|
||||
}
|
||||
|
||||
void Level::update(float delta, bool interactions) {
|
||||
playerController->update_controls(delta);
|
||||
void Level::update(float delta, bool updatePlayer, bool interactions) {
|
||||
playerController->update_controls(delta, updatePlayer);
|
||||
if (interactions) {
|
||||
playerController->update_interaction();
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ public:
|
||||
uint chunksPadding);
|
||||
~Level();
|
||||
|
||||
void update(float delta, bool interactions);
|
||||
void update(float delta, bool updatePlayer, bool interactions);
|
||||
};
|
||||
|
||||
#endif /* WORLD_LEVEL_H_ */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user