Merge branch 'MihailRis:main' into main

This commit is contained in:
clasher113 2023-11-20 09:18:11 +02:00 committed by GitHub
commit aa03757f29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 881 additions and 245 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
res/textures/block.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 257 KiB

After

Width:  |  Height:  |  Size: 257 KiB

View File

@ -2,9 +2,12 @@
#include "Assets.h"
#include <iostream>
#include <memory>
#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<ImageData> 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;
}
@ -101,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");
}

View File

@ -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;

View File

@ -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);

View File

@ -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<ImageData> 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) {

View File

@ -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_

21
src/core_defs.h Normal file
View File

@ -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_

View File

@ -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,18 @@ 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);
Events::bind(BIND_HUD_INVENTORY, inputtype::keyboard, keycode::TAB);
}

View File

@ -2,8 +2,8 @@
#define DECLARATIONS_H
#include <iostream>
#include "core_defs.h"
#define BLOCK_AIR 0
#define BLOCK_DIRT 1
#define BLOCK_GRASS_BLOCK 2
#define BLOCK_LAMP 3
@ -21,7 +21,8 @@
#define BLOCK_METAL 15
#define BLOCK_RUST 16
void setup_definitions();
extern void setup_bindings();
extern void setup_definitions();
#endif // DECLARATIONS_H

View File

@ -59,8 +59,6 @@ Engine::Engine(EngineSettings& settings) : settings(settings) {
Audio::initialize();
gui = new GUI();
std::cout << "-- initializing finished" << std::endl;
setScreen(shared_ptr<Screen>(new MenuScreen(this)));
}
void Engine::updateTimers() {
@ -81,6 +79,8 @@ void Engine::updateHotkeys() {
}
void Engine::mainloop() {
setScreen(shared_ptr<Screen>(new MenuScreen(this)));
std::cout << "-- preparing systems" << std::endl;
Batch2D batch(1024);

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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<UINode> 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<UINode>(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<UINode>(label));
}
shared_ptr<UINode> InputBindBox::getAt(vec2 pos, shared_ptr<UINode> 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::mouse;
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));
}

View File

@ -8,6 +8,7 @@
#include <glm/glm.hpp>
#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<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> 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};

View File

@ -1,15 +1,14 @@
#include "panels.h"
#include <stdexcept>
#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,53 @@ void Panel::lock(){
node->lock();
}
resizing_ = false;
}
PagesControl::PagesControl() : Container(vec2(), vec2(1)){
}
void PagesControl::add(std::string name, std::shared_ptr<UINode> panel) {
pages[name] = Page{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) {
Container::remove(current_.panel);
}
if (history) {
pageStack.push(curname_);
}
curname_ = name;
current_ = found->second;
Container::add(current_.panel);
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<std::string>();
}
void PagesControl::reset() {
clearHistory();
if (current_.panel) {
curname_ = "";
Container::remove(current_.panel);
current_ = Page{nullptr};
}
}

View File

@ -3,6 +3,8 @@
#include <glm/glm.hpp>
#include <vector>
#include <stack>
#include <string>
#include <memory>
#include "UINode.h"
@ -56,5 +58,27 @@ namespace gui {
virtual void refresh() override;
virtual void lock() override;
};
struct Page {
std::shared_ptr<UINode> panel = nullptr;
};
class PagesControl : public Container {
protected:
std::unordered_map<std::string, Page> pages;
std::stack<std::string> pageStack;
Page current_;
std::string curname_ = "";
public:
PagesControl();
void set(std::string name, bool history=true);
void add(std::string name, std::shared_ptr<UINode> panel);
void back();
void clearHistory();
void reset();
Page current();
};
}
#endif // FRONTEND_GUI_PANELS_H_

View File

@ -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;
@ -44,12 +45,15 @@ 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;
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<UINode>(panel);
panel->listenInterval(1.0f, [this]() {
@ -115,37 +119,35 @@ HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(en
panel->refresh();
panel = new Panel(vec2(350, 200));
pauseMenu = shared_ptr<UINode>(panel);
auto pauseMenu = shared_ptr<UINode>(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<UINode>(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<Screen>(new MenuScreen(engine)));
});
panel->add(shared_ptr<UINode>(button));
}
panel->visible(false);
guiController->add(this->debugPanel);
guiController->add(this->pauseMenu);
pages->reset();
pages->add("pause", pauseMenu);
gui->add(this->debugPanel);
}
HudRenderer::~HudRenderer() {
guiController->remove(debugPanel);
guiController->remove(pauseMenu);
gui->remove(debugPanel);
//gui->remove(gui->get("pages"));
delete batch;
delete uicamera;
}
@ -157,7 +159,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 +171,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;
@ -221,8 +227,7 @@ void HudRenderer::drawInventory(Player* player) {
if (Events::jclicked(GLFW_MOUSE_BUTTON_LEFT)) {
player->choosenBlock = i+1;
}
} else
{
} else {
tint = vec4(1.0f);
}
@ -234,17 +239,38 @@ void HudRenderer::drawInventory(Player* player) {
}
}
void HudRenderer::draw(){
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((Window::size() - pauseMenu->size()) / 2.0f);
pages->setCoord((viewport.size() - pages->size()) / 2.0f);
auto settingsPanel = guiController->get("settings");
settingsPanel->setCoord((Window::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 +282,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 +290,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,39 +312,19 @@ 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 (pause) {
pause = false;
pauseMenu->visible(false);
settingsPanel->visible(false);
} else if (inventoryOpen) {
inventoryOpen = false;
} else {
pause = true;
pauseMenu->visible(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);
batch->rect(0, 0, width, height);
}
if (inventoryOpen) {
drawInventory(player);
drawInventory(ctx, player);
}
batch->render();
}

View File

@ -4,6 +4,8 @@
#include <string>
#include <memory>
#include "../graphics/GfxContext.h"
class Batch2D;
class Camera;
class Level;
@ -32,13 +34,14 @@ class HudRenderer {
bool pause = false;
std::shared_ptr<gui::UINode> debugPanel;
std::shared_ptr<gui::UINode> pauseMenu;
gui::GUI* guiController;
gui::GUI* gui;
public:
HudRenderer(Engine* engine, Level* level);
~HudRenderer();
void drawInventory(Player* player);
void draw();
void update();
void drawInventory(const GfxContext& ctx, Player* player);
void draw(const GfxContext& context);
void drawDebug(int fps, bool occlusion);
bool isInventoryOpen() const;

View File

@ -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"
@ -28,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;
@ -39,53 +41,52 @@ using std::filesystem::u8path;
using std::filesystem::directory_iterator;
using namespace gui;
shared_ptr<UINode> create_main_menu_panel(Engine* engine) {
shared_ptr<UINode> create_main_menu_panel(Engine* engine, PagesControl* pages) {
Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 1.0f);
shared_ptr<UINode> 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));
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>(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>(screen));
});
worldsPanel->add(button);
}
}
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<UINode> create_new_world_panel(Engine* engine) {
shared_ptr<UINode> create_new_world_panel(Engine* engine, PagesControl* pages) {
Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 1.0f);
shared_ptr<UINode> panelptr(panel);
panel->color(vec4(0.0f));
panel->setCoord(vec2(10, 10));
TextBox* worldNameInput;
{
@ -163,17 +164,43 @@ shared_ptr<UINode> 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;
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<UINode> 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<UINode> panelptr(panel);
/* Load Distance setting track bar */{
panel->add((new Label(L""))->textSupplier([=]() {
@ -228,30 +255,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<UINode>(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<UINode>(create_settings_panel(engine, pages));
auto controlsPanel = shared_ptr<UINode>(create_controls_panel(engine, pages));
pages->add("new-world", newWorldPanel);
pages->add("settings", settingsPanel);
pages->add("controls", controlsPanel);
this->pages = shared_ptr<UINode>(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);
@ -260,13 +301,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;
}
@ -275,11 +309,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));
@ -348,13 +378,18 @@ void LevelScreen::update(float delta) {
level->update();
level->chunksController->update(settings.chunks.loadSpeed);
hud->update();
}
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);
}

View File

@ -28,8 +28,7 @@ public:
};
class MenuScreen : public Screen {
std::shared_ptr<gui::UINode> panel;
std::shared_ptr<gui::UINode> newWorldPanel;
std::shared_ptr<gui::UINode> pages;
Batch2D* batch;
Camera* uicamera;
public:

View File

@ -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<size_t> indices;
for (size_t i = 0; i < chunks->volume; i++){
shared_ptr<Chunk> 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);

View File

@ -10,6 +10,8 @@
#include <glm/ext.hpp>
#include <glm/gtc/matrix_transform.hpp>
#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);
};

View File

@ -361,3 +361,7 @@ void Batch2D::render(unsigned int gl_primitive) {
void Batch2D::render() {
render(GL_TRIANGLES);
}
void Batch2D::lineWidth(float width) {
glLineWidth(width);
}

View File

@ -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_ */

View File

@ -0,0 +1,59 @@
#include "GfxContext.h"
#include <GL/glew.h>
#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);
}
}

27
src/graphics/GfxContext.h Normal file
View File

@ -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_

13
src/graphics/Viewport.cpp Normal file
View File

@ -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;
}

22
src/graphics/Viewport.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef GRAPHICS_VIEWPORT_H_
#define GRAPHICS_VIEWPORT_H_
#include <glm/glm.hpp>
#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_

View File

@ -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.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(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::jpressed(keycode::N);
input.flight = Events::jpressed(keycode::F);
input.noclip = Events::jactive(BIND_PLAYER_NOCLIP);
input.flight = Events::jactive(BIND_PLAYER_FLIGHT);
// block choice
for (int i = 1; i < 10; i++){
@ -215,8 +217,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 +253,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);

View File

@ -1,3 +1,6 @@
#ifndef VOX_TYPEDEFS_H
#define VOX_TYPEDEFS_H
#include <stdlib.h>
#include <stdint.h>
@ -6,3 +9,5 @@ typedef unsigned char ubyte;
typedef uint8_t blockid_t;
typedef uint16_t light_t;
#endif

View File

@ -1,19 +1,23 @@
#include "platform.h"
#include <sstream>
#include <filesystem>
#include <iomanip>
#include <time.h>
#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

View File

@ -2,10 +2,12 @@
#define UTIL_PLATFORM_H_
#include <string>
#include <filesystem>
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_

View File

@ -1,9 +1,9 @@
#include <iostream>
#include <cmath>
#include <stdint.h>
#include <memory>
#include <filesystem>
#include <stdexcept>
#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::mouse: jentry->put("type", "mouse"); 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 == "mouse") {
type = inputtype::mouse;
} 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;

View File

@ -14,6 +14,7 @@ bool Events::_cursor_locked = false;
bool Events::_cursor_started = false;
std::vector<uint> Events::codepoints;
std::vector<int> Events::pressedKeys;
std::unordered_map<std::string, Binding> 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::mouse: 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();
}

View File

@ -2,6 +2,11 @@
#define WINDOW_EVENTS_H_
#include "Window.h"
#include "input.h"
#include <string>
#include <vector>
#include <unordered_map>
typedef unsigned int uint;
@ -18,6 +23,7 @@ public:
static bool _cursor_started;
static std::vector<uint> codepoints;
static std::vector<int> pressedKeys;
static std::unordered_map<std::string, Binding> bindings;
static int initialize();
static void finalize();
@ -30,6 +36,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

View File

@ -65,7 +65,81 @@ 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));
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";
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";
}
}
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";
}

View File

@ -66,12 +66,59 @@ 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);
}
namespace mousecode {
extern int BUTTON_1;
extern int BUTTON_2;
extern int BUTTON_3;
extern const char* name(int code);
}
enum class inputtype {
keyboard,
mouse,
};
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::mouse: return mousecode::name(code);
}
return "<unknown input type>";
}
};
#endif // WINDOW_INPUT_H_