toml::Wrapper removed

This commit is contained in:
MihailRis 2024-04-28 17:23:52 +03:00
parent 184ecd88ba
commit c3b5576c02
22 changed files with 795 additions and 965 deletions

View File

@ -42,7 +42,10 @@ std::string parsing_error::errorLog() const {
return ss.str(); return ss.str();
} }
BasicParser::BasicParser(std::string file, std::string source) : filename(file), source(source) { BasicParser::BasicParser(
const std::string& file,
const std::string& source
) : filename(file), source(source) {
} }
void BasicParser::skipWhitespace() { void BasicParser::skipWhitespace() {

View File

@ -70,8 +70,8 @@ public:
class BasicParser { class BasicParser {
protected: protected:
std::string filename; const std::string& filename;
std::string source; const std::string& source;
uint pos = 0; uint pos = 0;
uint line = 1; uint line = 1;
uint linestart = 0; uint linestart = 0;
@ -96,7 +96,7 @@ protected:
parsing_error error(std::string message); parsing_error error(std::string message);
BasicParser(std::string filename, std::string source); BasicParser(const std::string& file, const std::string& source);
}; };
#endif // CODERS_COMMONS_H_ #endif // CODERS_COMMONS_H_

View File

@ -118,7 +118,7 @@ std::string json::stringify(
return ss.str(); return ss.str();
} }
Parser::Parser(std::string filename, std::string source) Parser::Parser(const std::string& filename, const std::string& source)
: BasicParser(filename, source) { : BasicParser(filename, source) {
} }
@ -244,11 +244,11 @@ Value* Parser::parseValue() {
throw error("unexpected character '"+std::string({next})+"'"); throw error("unexpected character '"+std::string({next})+"'");
} }
std::unique_ptr<Map> json::parse(std::string filename, std::string source) { std::unique_ptr<Map> json::parse(const std::string& filename, const std::string& source) {
Parser parser(filename, source); Parser parser(filename, source);
return std::unique_ptr<Map>(parser.parse()); return std::unique_ptr<Map>(parser.parse());
} }
std::unique_ptr<Map> json::parse(std::string source) { std::unique_ptr<Map> json::parse(const std::string& source) {
return parse("<string>", source); return parse("<string>", source);
} }

View File

@ -24,13 +24,13 @@ namespace json {
dynamic::Map* parseObject(); dynamic::Map* parseObject();
dynamic::Value* parseValue(); dynamic::Value* parseValue();
public: public:
Parser(std::string filename, std::string source); Parser(const std::string& filename, const std::string& source);
dynamic::Map* parse(); dynamic::Map* parse();
}; };
extern std::unique_ptr<dynamic::Map> parse(std::string filename, std::string source); extern std::unique_ptr<dynamic::Map> parse(const std::string& filename, const std::string& source);
extern std::unique_ptr<dynamic::Map> parse(std::string source); extern std::unique_ptr<dynamic::Map> parse(const std::string& source);
extern std::string stringify( extern std::string stringify(
const dynamic::Map* obj, const dynamic::Map* obj,

View File

@ -1,6 +1,8 @@
#include "toml.h" #include "toml.h"
#include "commons.h" #include "commons.h"
#include "../data/dynamic.h"
#include "../util/stringutil.h" #include "../util/stringutil.h"
#include "../files/settings_io.hpp"
#include <math.h> #include <math.h>
#include <iostream> #include <iostream>
@ -12,119 +14,10 @@
using namespace toml; using namespace toml;
Section::Section(std::string name) : name(name) { class Reader : public BasicParser {
} SettingsHandler& handler;
void Section::add(std::string name, Field field) { void skipWhitespace() override {
if (fields.find(name) != fields.end()) {
throw std::runtime_error("field duplication");
}
fields[name] = field;
keyOrder.push_back(name);
}
void Section::add(std::string name, bool* ptr) {
add(name, {fieldtype::ftbool, ptr});
}
void Section::add(std::string name, int* ptr) {
add(name, {fieldtype::ftint, ptr});
}
void Section::add(std::string name, uint* ptr) {
add(name, {fieldtype::ftuint, ptr});
}
void Section::add(std::string name, int64_t* ptr) {
add(name, {fieldtype::ftint64, ptr});
}
void Section::add(std::string name, float* ptr) {
add(name, {fieldtype::ftfloat, ptr});
}
void Section::add(std::string name, double* ptr) {
add(name, {fieldtype::ftdouble, ptr});
}
void Section::add(std::string name, std::string* ptr) {
add(name, {fieldtype::ftstring, ptr});
}
const std::string& Section::getName() const {
return name;
}
const Field* Section::field(const std::string& name) const {
auto found = fields.find(name);
if (found == fields.end()) {
return nullptr;
}
return &found->second;
}
const std::vector<std::string>& Section::keys() const {
return keyOrder;
}
Wrapper::~Wrapper() {
for (auto entry : sections) {
delete entry.second;
}
}
Section& Wrapper::add(std::string name) {
if (sections.find(name) != sections.end()) {
throw std::runtime_error("section duplication");
}
Section* section = new Section(name);
sections[name] = section;
keyOrder.push_back(name);
return *section;
}
Section* Wrapper::section(std::string name) {
auto found = sections.find(name);
if (found == sections.end()) {
return nullptr;
}
return found->second;
}
std::string Wrapper::write() const {
std::stringstream ss;
for (const std::string& key : keyOrder) {
const Section* section = sections.at(key);
ss << "[" << key << "]\n";
for (const std::string& key : section->keys()) {
ss << key << " = ";
const Field* field = section->field(key);
assert(field != nullptr);
switch (field->type) {
case fieldtype::ftbool:
ss << (*((bool*)field->ptr) ? "true" : "false");
break;
case fieldtype::ftint: ss << *((int*)field->ptr); break;
case fieldtype::ftuint: ss << *((uint*)field->ptr); break;
case fieldtype::ftint64: ss << *((int64_t*)field->ptr); break;
case fieldtype::ftfloat: ss << *((float*)field->ptr); break;
case fieldtype::ftdouble: ss << *((double*)field->ptr); break;
case fieldtype::ftstring:
ss << util::escape(*((const std::string*)field->ptr));
break;
}
ss << "\n";
}
ss << "\n";
}
return ss.str();
}
Reader::Reader(Wrapper* wrapper, std::string file, std::string source)
: BasicParser(file, source), wrapper(wrapper) {
}
void Reader::skipWhitespace() {
BasicParser::skipWhitespace(); BasicParser::skipWhitespace();
if (hasNext() && source[pos] == '#') { if (hasNext() && source[pos] == '#') {
skipLine(); skipLine();
@ -132,68 +25,8 @@ void Reader::skipWhitespace() {
skipWhitespace(); skipWhitespace();
} }
} }
}
void Reader::read() {
skipWhitespace();
if (!hasNext()) {
return;
} }
readSection(nullptr); void readSection(const std::string& section) {
}
void Section::set(const std::string& name, double value) {
const Field* field = this->field(name);
if (field == nullptr) {
std::cerr << "warning: unknown key '" << name << "'" << std::endl;
} else {
switch (field->type) {
case fieldtype::ftbool: *(bool*)(field->ptr) = fabs(value) > 0.0; break;
case fieldtype::ftint: *(int*)(field->ptr) = value; break;
case fieldtype::ftuint: *(uint*)(field->ptr) = value; break;
case fieldtype::ftint64: *(int64_t*)(field->ptr) = value; break;
case fieldtype::ftfloat: *(float*)(field->ptr) = value; break;
case fieldtype::ftdouble: *(double*)(field->ptr) = value; break;
case fieldtype::ftstring: *(std::string*)(field->ptr) = std::to_string(value); break;
default:
std::cerr << "error: type error for key '" << name << "'" << std::endl;
}
}
}
void Section::set(const std::string& name, bool value) {
const Field* field = this->field(name);
if (field == nullptr) {
std::cerr << "warning: unknown key '" << name << "'" << std::endl;
} else {
switch (field->type) {
case fieldtype::ftbool: *(bool*)(field->ptr) = value; break;
case fieldtype::ftint: *(int*)(field->ptr) = (int)value; break;
case fieldtype::ftuint: *(uint*)(field->ptr) = (uint)value; break;
case fieldtype::ftint64: *(int64_t*)(field->ptr) = (int64_t)value; break;
case fieldtype::ftfloat: *(float*)(field->ptr) = (float)value; break;
case fieldtype::ftdouble: *(double*)(field->ptr) = (double)value; break;
case fieldtype::ftstring: *(std::string*)(field->ptr) = value ? "true" : "false"; break;
default:
std::cerr << "error: type error for key '" << name << "'" << std::endl;
}
}
}
void Section::set(const std::string& name, std::string value) {
const Field* field = this->field(name);
if (field == nullptr) {
std::cerr << "warning: unknown key '" << name << "'" << std::endl;
} else {
switch (field->type) {
case fieldtype::ftstring: *(std::string*)(field->ptr) = value; break;
default:
std::cerr << "error: type error for key '" << name << "'" << std::endl;
}
}
}
void Reader::readSection(Section* section /*nullable*/) {
while (hasNext()) { while (hasNext()) {
skipWhitespace(); skipWhitespace();
if (!hasNext()) { if (!hasNext()) {
@ -202,60 +35,93 @@ void Reader::readSection(Section* section /*nullable*/) {
char c = nextChar(); char c = nextChar();
if (c == '[') { if (c == '[') {
std::string name = parseName(); std::string name = parseName();
Section* section = wrapper->section(name);
pos++; pos++;
readSection(section); readSection(name);
return; return;
} }
pos--; pos--;
std::string name = parseName(); std::string name = section+"."+parseName();
expect('='); expect('=');
c = peek(); c = peek();
if (is_digit(c)) { if (is_digit(c)) {
number_u num; number_u num;
if (parseNumber(1, num)) { parseNumber(1, num);
if (section) handler.setValue(name, *dynamic::Value::of(num));
section->set(name, (double)std::get<integer_t>(num));
} else {
if (section)
section->set(name, std::get<number_t>(num));
}
} else if (c == '-' || c == '+') { } else if (c == '-' || c == '+') {
int sign = c == '-' ? -1 : 1; int sign = c == '-' ? -1 : 1;
pos++; pos++;
number_u num; number_u num;
if (parseNumber(sign, num)) { parseNumber(sign, num);
if (section) handler.setValue(name, *dynamic::Value::of(num));
section->set(name, (double)std::get<integer_t>(num));
} else {
if (section)
section->set(name, std::get<number_t>(num));
}
} else if (is_identifier_start(c)) { } else if (is_identifier_start(c)) {
std::string identifier = parseName(); std::string identifier = parseName();
if (identifier == "true" || identifier == "false") { if (identifier == "true" || identifier == "false") {
bool flag = identifier == "true"; bool flag = identifier == "true";
if (section) { handler.setValue(name, *dynamic::Value::boolean(flag));
section->set(name, flag);
}
} else if (identifier == "inf") { } else if (identifier == "inf") {
if (section) { handler.setValue(name, *dynamic::Value::of(INFINITY));
section->set(name, INFINITY);
}
} else if (identifier == "nan") { } else if (identifier == "nan") {
if (section) { handler.setValue(name, *dynamic::Value::of(NAN));
section->set(name, NAN);
}
} }
} else if (c == '"' || c == '\'') { } else if (c == '"' || c == '\'') {
pos++; pos++;
std::string str = parseString(c); std::string str = parseString(c);
if (section) { handler.setValue(name, *dynamic::Value::of(str));
section->set(name, str);
}
} else { } else {
throw error("feature is not supported"); throw error("feature is not supported");
} }
expectNewLine(); expectNewLine();
} }
}
public:
Reader(
SettingsHandler& handler,
const std::string& file,
const std::string& source)
: BasicParser(file, source), handler(handler) {
}
void read() {
skipWhitespace();
if (!hasNext()) {
return;
}
readSection("");
}
};
void toml::parse(
SettingsHandler& handler,
const std::string& file,
const std::string& source
) {
Reader reader(handler, file, source);
reader.read();
}
std::string toml::stringify(SettingsHandler& handler) {
auto& sections = handler.getSections();
std::stringstream ss;
for (auto& section : sections) {
ss << "[" << section.name << "]\n";
for (const std::string& key : section.keys) {
ss << key << " = ";
auto setting = handler.getSetting(section.name+"."+key);
assert(setting != nullptr);
if (auto integer = dynamic_cast<IntegerSetting*>(setting)) {
ss << integer->get();
} else if (auto number = dynamic_cast<NumberSetting*>(setting)) {
ss << number->get();
} else if (auto flag = dynamic_cast<FlagSetting*>(setting)) {
ss << (flag->get() ? "true" : "false");
} else if (auto string = dynamic_cast<StringSetting*>(setting)) {
ss << util::escape(string->get());
}
ss << "\n";
}
ss << "\n";
}
return ss.str();
} }

View File

@ -7,66 +7,16 @@
#include "commons.h" #include "commons.h"
class SettingsHandler;
namespace toml { namespace toml {
enum class fieldtype { std::string stringify(SettingsHandler& handler);
ftbool,
ftint,
ftuint,
ftint64,
ftfloat,
ftdouble,
ftstring,
};
struct Field { void parse(
fieldtype type; SettingsHandler& handler,
void* ptr; const std::string& file,
}; const std::string& source
);
class Section {
std::unordered_map<std::string, Field> fields;
std::vector<std::string> keyOrder;
std::string name;
void add(std::string name, Field field);
public:
Section(std::string name);
void add(std::string name, bool* ptr);
void add(std::string name, int* ptr);
void add(std::string name, int64_t* ptr);
void add(std::string name, uint* ptr);
void add(std::string name, float* ptr);
void add(std::string name, double* ptr);
void add(std::string name, std::string* ptr);
const Field* field(const std::string& name) const;
void set(const std::string& name, double value);
void set(const std::string& name, bool value);
void set(const std::string& name, std::string value);
const std::string& getName() const;
const std::vector<std::string>& keys() const;
};
class Wrapper {
std::unordered_map<std::string, Section*> sections;
std::vector<std::string> keyOrder;
public:
~Wrapper();
Section& add(std::string section);
Section* section(std::string name);
std::string write() const;
};
class Reader : public BasicParser {
Wrapper* wrapper;
void skipWhitespace() override;
void readSection(Section* section);
public:
Reader(Wrapper* wrapper, std::string file, std::string source);
void read();
};
} }
#endif // CODERS_TOML_H_ #endif // CODERS_TOML_H_

View File

@ -176,7 +176,7 @@ const std::string& Document::getEncoding() const {
return encoding; return encoding;
} }
Parser::Parser(std::string filename, std::string source) Parser::Parser(const std::string& filename, const std::string& source)
: BasicParser(filename, source) { : BasicParser(filename, source) {
} }

View File

@ -118,7 +118,7 @@ namespace xml {
std::string parseText(); std::string parseText();
std::string parseXMLName(); std::string parseXMLName();
public: public:
Parser(std::string filename, std::string source); Parser(const std::string& filename, const std::string& source);
xmldocument parse(); xmldocument parse();
}; };

View File

@ -11,6 +11,7 @@
#include "content/ContentLoader.h" #include "content/ContentLoader.h"
#include "core_defs.h" #include "core_defs.h"
#include "files/files.h" #include "files/files.h"
#include "files/settings_io.hpp"
#include "frontend/locale/langs.h" #include "frontend/locale/langs.h"
#include "frontend/menu.hpp" #include "frontend/menu.hpp"
#include "frontend/screens/Screen.hpp" #include "frontend/screens/Screen.hpp"
@ -56,14 +57,14 @@ inline void create_channel(Engine* engine, std::string name, NumberSetting& sett
})); }));
} }
Engine::Engine(EngineSettings& settings, EnginePaths* paths) Engine::Engine(EngineSettings& settings, SettingsHandler& settingsHandler, EnginePaths* paths)
: settings(settings), settingsHandler(settings), paths(paths) : settings(settings), settingsHandler(settingsHandler), paths(paths)
{ {
controller = std::make_unique<EngineController>(this); controller = std::make_unique<EngineController>(this);
if (Window::initialize(&this->settings.display)){ if (Window::initialize(&this->settings.display)){
throw initialize_error("could not initialize window"); throw initialize_error("could not initialize window");
} }
audio::initialize(settings.audio.enabled); audio::initialize(settings.audio.enabled.get());
create_channel(this, "master", settings.audio.volumeMaster); create_channel(this, "master", settings.audio.volumeMaster);
create_channel(this, "regular", settings.audio.volumeRegular); create_channel(this, "regular", settings.audio.volumeRegular);
create_channel(this, "music", settings.audio.volumeMusic); create_channel(this, "music", settings.audio.volumeMusic);

View File

@ -10,7 +10,6 @@
#include "content/ContentPack.h" #include "content/ContentPack.h"
#include "content/PacksManager.hpp" #include "content/PacksManager.hpp"
#include "files/engine_paths.h" #include "files/engine_paths.h"
#include "files/settings_io.h"
#include "util/ObjectsKeeper.hpp" #include "util/ObjectsKeeper.hpp"
#include <filesystem> #include <filesystem>
@ -27,6 +26,7 @@ class EnginePaths;
class ResPaths; class ResPaths;
class Batch2D; class Batch2D;
class EngineController; class EngineController;
class SettingsHandler;
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -41,7 +41,7 @@ public:
class Engine : public util::ObjectsKeeper { class Engine : public util::ObjectsKeeper {
EngineSettings& settings; EngineSettings& settings;
SettingsHandler settingsHandler; SettingsHandler& settingsHandler;
EnginePaths* paths; EnginePaths* paths;
std::unique_ptr<Assets> assets = nullptr; std::unique_ptr<Assets> assets = nullptr;
@ -65,7 +65,7 @@ class Engine : public util::ObjectsKeeper {
void processPostRunnables(); void processPostRunnables();
void loadAssets(); void loadAssets();
public: public:
Engine(EngineSettings& settings, EnginePaths* paths); Engine(EngineSettings& settings, SettingsHandler& settingsHandler, EnginePaths* paths);
~Engine(); ~Engine();
/// @brief Start main engine input/update/render loop. /// @brief Start main engine input/update/render loop.

View File

@ -35,8 +35,8 @@ WorldFiles::WorldFiles(fs::path directory) : directory(directory), regions(direc
WorldFiles::WorldFiles(fs::path directory, const DebugSettings& settings) WorldFiles::WorldFiles(fs::path directory, const DebugSettings& settings)
: WorldFiles(directory) : WorldFiles(directory)
{ {
generatorTestMode = settings.generatorTestMode; generatorTestMode = settings.generatorTestMode.get();
doWriteLights = settings.doWriteLights; doWriteLights = settings.doWriteLights.get();
regions.generatorTestMode = generatorTestMode; regions.generatorTestMode = generatorTestMode;
regions.doWriteLights = doWriteLights; regions.doWriteLights = doWriteLights;
} }

View File

@ -1,4 +1,4 @@
#include "settings_io.h" #include "settings_io.hpp"
#include "../window/Events.h" #include "../window/Events.h"
#include "../window/input.h" #include "../window/input.h"
@ -10,30 +10,70 @@
static debug::Logger logger("settings_io"); static debug::Logger logger("settings_io");
struct SectionsBuilder {
std::unordered_map<std::string, Setting*>& map;
std::vector<Section>& sections;
SectionsBuilder(
std::unordered_map<std::string, Setting*>& map,
std::vector<Section>& sections
) : map(map), sections(sections) {
}
void section(std::string name) {
sections.push_back(Section {name, {}});
}
void add(std::string name, Setting* setting, bool writeable=true) {
Section& section = sections.at(sections.size()-1);
map[section.name+"."+name] = setting;
section.keys.push_back(name);
}
};
SettingsHandler::SettingsHandler(EngineSettings& settings) { SettingsHandler::SettingsHandler(EngineSettings& settings) {
// public settings SectionsBuilder builder(map, sections);
map.emplace("audio.volume-master", &settings.audio.volumeMaster);
map.emplace("audio.volume-regular", &settings.audio.volumeRegular);
map.emplace("audio.volume-ui", &settings.audio.volumeUI);
map.emplace("audio.volume-ambient", &settings.audio.volumeAmbient);
map.emplace("audio.volume-music", &settings.audio.volumeMusic);
map.emplace("display.vsync", &settings.display.vsync); builder.section("audio");
map.emplace("display.fullscreen", &settings.display.fullscreen); builder.add("enabled", &settings.audio.enabled, false);
builder.add("volume-master", &settings.audio.volumeMaster);
builder.add("volume-regular", &settings.audio.volumeRegular);
builder.add("volume-ui", &settings.audio.volumeUI);
builder.add("volume-ambient", &settings.audio.volumeAmbient);
builder.add("volume-music", &settings.audio.volumeMusic);
map.emplace("camera.sensitivity", &settings.camera.sensitivity); builder.section("display");
map.emplace("camera.fov", &settings.camera.fov); builder.add("width", &settings.display.width);
map.emplace("camera.fov-effects", &settings.camera.fovEffects); builder.add("height", &settings.display.height);
map.emplace("camera.shaking", &settings.camera.shaking); builder.add("samples", &settings.display.samples);
builder.add("vsync", &settings.display.vsync);
builder.add("fullscreen", &settings.display.fullscreen);
map.emplace("chunks.load-distance", &settings.chunks.loadDistance); builder.section("camera");
map.emplace("chunks.load-speed", &settings.chunks.loadSpeed); builder.add("sensitivity", &settings.camera.sensitivity);
builder.add("fov", &settings.camera.fov);
builder.add("fov-effects", &settings.camera.fovEffects);
builder.add("shaking", &settings.camera.shaking);
map.emplace("graphics.fog-curve", &settings.graphics.fogCurve); builder.section("chunks");
map.emplace("graphics.backlight", &settings.graphics.backlight); builder.add("load-distance", &settings.chunks.loadDistance);
map.emplace("graphics.gamma", &settings.graphics.gamma); builder.add("load-speed", &settings.chunks.loadSpeed);
builder.add("padding", &settings.chunks.padding);
map.emplace("ui.language", &settings.ui.language); builder.section("graphics");
builder.add("fog-curve", &settings.graphics.fogCurve);
builder.add("backlight", &settings.graphics.backlight);
builder.add("gamma", &settings.graphics.gamma);
builder.add("frustum-culling", &settings.graphics.frustumCulling);
builder.add("skybox-resolution", &settings.graphics.skyboxResolution);
builder.section("ui");
builder.add("language", &settings.ui.language);
builder.add("world-preview-size", &settings.ui.worldPreviewSize);
builder.section("debug");
builder.add("generator-test-mode", &settings.debug.generatorTestMode);
builder.add("do-write-lights", &settings.debug.doWriteLights);
} }
std::unique_ptr<dynamic::Value> SettingsHandler::getValue(const std::string& name) const { std::unique_ptr<dynamic::Value> SettingsHandler::getValue(const std::string& name) const {
@ -123,51 +163,8 @@ void SettingsHandler::setValue(const std::string& name, const dynamic::Value& va
} }
} }
toml::Wrapper* create_wrapper(EngineSettings& settings) { std::vector<Section>& SettingsHandler::getSections() {
auto wrapper = std::make_unique<toml::Wrapper>(); return sections;
toml::Section& audio = wrapper->add("audio");
audio.add("enabled", &settings.audio.enabled);
audio.add("volume-master", &*settings.audio.volumeMaster);
audio.add("volume-regular", &*settings.audio.volumeRegular);
audio.add("volume-ui", &*settings.audio.volumeUI);
audio.add("volume-ambient", &*settings.audio.volumeAmbient);
audio.add("volume-music", &*settings.audio.volumeMusic);
toml::Section& display = wrapper->add("display");
display.add("fullscreen", &*settings.display.fullscreen);
display.add("width", &settings.display.width);
display.add("height", &settings.display.height);
display.add("samples", &settings.display.samples);
display.add("vsync", &*settings.display.vsync);
toml::Section& chunks = wrapper->add("chunks");
chunks.add("load-distance", &*settings.chunks.loadDistance);
chunks.add("load-speed", &*settings.chunks.loadSpeed);
chunks.add("padding", &*settings.chunks.padding);
toml::Section& camera = wrapper->add("camera");
camera.add("fov-effects", &*settings.camera.fovEffects);
camera.add("fov", &*settings.camera.fov);
camera.add("shaking", &*settings.camera.shaking);
camera.add("sensitivity", &*settings.camera.sensitivity);
toml::Section& graphics = wrapper->add("graphics");
graphics.add("gamma", &*settings.graphics.gamma);
graphics.add("fog-curve", &*settings.graphics.fogCurve);
graphics.add("backlight", &*settings.graphics.backlight);
graphics.add("frustum-culling", &*settings.graphics.frustumCulling);
graphics.add("skybox-resolution", &*settings.graphics.skyboxResolution);
toml::Section& debug = wrapper->add("debug");
debug.add("generator-test-mode", &settings.debug.generatorTestMode);
debug.add("show-chunk-borders", &settings.debug.showChunkBorders);
debug.add("do-write-lights", &settings.debug.doWriteLights);
toml::Section& ui = wrapper->add("ui");
ui.add("language", &*settings.ui.language);
ui.add("world-preview-size", &*settings.ui.worldPreviewSize);
return wrapper.release();
} }
std::string write_controls() { std::string write_controls() {

View File

@ -1,18 +1,21 @@
#ifndef FILES_SETTINGS_IO_H_ #ifndef FILES_SETTINGS_IO_HPP_
#define FILES_SETTINGS_IO_H_ #define FILES_SETTINGS_IO_HPP_
#include <string> #include <string>
#include <memory> #include <memory>
#include <vector>
#include <unordered_map> #include <unordered_map>
#include "../settings.h" #include "../settings.h"
#include "../data/dynamic.h" #include "../data/dynamic.h"
namespace toml { struct Section {
class Wrapper; std::string name;
} std::vector<std::string> keys;
};
class SettingsHandler { class SettingsHandler {
std::unordered_map<std::string, Setting*> map; std::unordered_map<std::string, Setting*> map;
std::vector<Section> sections;
public: public:
SettingsHandler(EngineSettings& settings); SettingsHandler(EngineSettings& settings);
@ -20,10 +23,12 @@ public:
void setValue(const std::string& name, const dynamic::Value& value); void setValue(const std::string& name, const dynamic::Value& value);
std::string toString(const std::string& name) const; std::string toString(const std::string& name) const;
Setting* getSetting(const std::string& name) const; Setting* getSetting(const std::string& name) const;
std::vector<Section>& getSections();
}; };
extern std::string write_controls(); std::string write_controls();
extern toml::Wrapper* create_wrapper(EngineSettings& settings);
extern void load_controls(std::string filename, std::string source);
#endif // FILES_SETTINGS_IO_H_ void load_controls(std::string filename, std::string source);
#endif // FILES_SETTINGS_IO_HPP_

View File

@ -146,10 +146,10 @@ std::shared_ptr<UINode> create_debug_panel(
L"Show Chunk Borders", glm::vec2(400, 24) L"Show Chunk Borders", glm::vec2(400, 24)
); );
checkbox->setSupplier([=]() { checkbox->setSupplier([=]() {
return engine->getSettings().debug.showChunkBorders; return WorldRenderer::showChunkBorders;
}); });
checkbox->setConsumer([=](bool checked) { checkbox->setConsumer([=](bool checked) {
engine->getSettings().debug.showChunkBorders = checked; WorldRenderer::showChunkBorders = checked;
}); });
panel->add(checkbox); panel->add(checkbox);
} }

View File

@ -45,7 +45,7 @@ class Reader : public BasicParser {
} }
} }
public: public:
Reader(std::string file, std::string source) : BasicParser(file, source) { Reader(const std::string& file, const std::string& source) : BasicParser(file, source) {
} }
void read(langs::Lang& lang, std::string prefix) { void read(langs::Lang& lang, std::string prefix) {

View File

@ -35,6 +35,8 @@
#include <iostream> #include <iostream>
#include <memory> #include <memory>
bool WorldRenderer::showChunkBorders = false;
WorldRenderer::WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* player) WorldRenderer::WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* player)
: engine(engine), : engine(engine),
level(frontend->getLevel()), level(frontend->getLevel()),
@ -225,7 +227,7 @@ void WorldRenderer::renderDebugLines(
linesShader->use(); linesShader->use();
if (settings.debug.showChunkBorders){ if (showChunkBorders){
linesShader->uniformMatrix("u_projview", camera->getProjView()); linesShader->uniformMatrix("u_projview", camera->getProjView());
glm::vec3 coord = player->camera->position; glm::vec3 coord = player->camera->position;
if (coord.x < 0) coord.x--; if (coord.x < 0) coord.x--;

View File

@ -56,6 +56,8 @@ class WorldRenderer {
const EngineSettings& settings const EngineSettings& settings
); );
public: public:
static bool showChunkBorders;
WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* player); WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* player);
~WorldRenderer(); ~WorldRenderer();

View File

@ -2,6 +2,7 @@
#include "api_lua.h" #include "api_lua.h"
#include "../../../engine.h" #include "../../../engine.h"
#include "../../../files/settings_io.hpp"
#include "../../../files/engine_paths.h" #include "../../../files/engine_paths.h"
#include "../../../frontend/menu.hpp" #include "../../../frontend/menu.hpp"
#include "../../../frontend/screens/MenuScreen.hpp" #include "../../../frontend/screens/MenuScreen.hpp"

View File

@ -10,7 +10,7 @@
struct AudioSettings { struct AudioSettings {
/// @brief try to initialize AL backend /// @brief try to initialize AL backend
bool enabled = true; FlagSetting enabled {true};
NumberSetting volumeMaster {1.0f, 0.0f, 1.0f, setting_format::percent}; NumberSetting volumeMaster {1.0f, 0.0f, 1.0f, setting_format::percent};
NumberSetting volumeRegular {1.0f, 0.0f, 1.0f, setting_format::percent}; NumberSetting volumeRegular {1.0f, 0.0f, 1.0f, setting_format::percent};
@ -23,17 +23,13 @@ struct DisplaySettings {
/// @brief Is window in full screen mode /// @brief Is window in full screen mode
FlagSetting fullscreen {false}; FlagSetting fullscreen {false};
/// @brief Window width (pixels) /// @brief Window width (pixels)
int width = 1280; IntegerSetting width {1280};
/// @brief Window height (pixels) /// @brief Window height (pixels)
int height = 720; IntegerSetting height {720};
/// @brief Anti-aliasing samples /// @brief Anti-aliasing samples
int samples = 0; IntegerSetting samples {0};
/// @brief VSync on /// @brief VSync on
FlagSetting vsync {true}; FlagSetting vsync {true};
/// @brief Window title
std::string title = "VoxelEngine-Cpp v" +
std::to_string(ENGINE_VERSION_MAJOR) + "." +
std::to_string(ENGINE_VERSION_MINOR);
}; };
struct ChunksSettings { struct ChunksSettings {
@ -60,6 +56,7 @@ struct GraphicsSettings {
/// @brief Fog opacity is calculated as `pow(depth*k, fogCurve)` where k depends on chunksLoadDistance. /// @brief Fog opacity is calculated as `pow(depth*k, fogCurve)` where k depends on chunksLoadDistance.
/// 1.0 is linear, 2.0 is quadratic /// 1.0 is linear, 2.0 is quadratic
NumberSetting fogCurve {1.6f, 1.0f, 6.0f}; NumberSetting fogCurve {1.6f, 1.0f, 6.0f};
/// @brief Lighting gamma
NumberSetting gamma {1.0f, 0.5f, 2.0f}; NumberSetting gamma {1.0f, 0.5f, 2.0f};
/// @brief Enable blocks backlight to prevent complete darkness /// @brief Enable blocks backlight to prevent complete darkness
FlagSetting backlight {true}; FlagSetting backlight {true};
@ -70,9 +67,8 @@ struct GraphicsSettings {
struct DebugSettings { struct DebugSettings {
/// @brief Turns off chunks saving/loading /// @brief Turns off chunks saving/loading
bool generatorTestMode = false; FlagSetting generatorTestMode {false};
bool showChunkBorders = false; FlagSetting doWriteLights {true};
bool doWriteLights = true;
}; };
struct UiSettings { struct UiSettings {

View File

@ -9,7 +9,7 @@
#include "engine.h" #include "engine.h"
#include "coders/toml.h" #include "coders/toml.h"
#include "files/files.h" #include "files/files.h"
#include "files/settings_io.h" #include "files/settings_io.hpp"
#include "files/engine_paths.h" #include "files/engine_paths.h"
#include "util/platform.h" #include "util/platform.h"
#include "util/command_line.h" #include "util/command_line.h"
@ -33,18 +33,17 @@ int main(int argc, char** argv) {
fs::path userfiles = paths.getUserfiles(); fs::path userfiles = paths.getUserfiles();
try { try {
EngineSettings settings; EngineSettings settings;
std::unique_ptr<toml::Wrapper> wrapper (create_wrapper(settings)); SettingsHandler handler(settings);
fs::path settings_file = userfiles/fs::path(SETTINGS_FILE); fs::path settings_file = userfiles/fs::path(SETTINGS_FILE);
fs::path controls_file = userfiles/fs::path(CONTROLS_FILE); fs::path controls_file = userfiles/fs::path(CONTROLS_FILE);
if (fs::is_regular_file(settings_file)) { if (fs::is_regular_file(settings_file)) {
logger.info() << "loading settings"; logger.info() << "loading settings";
std::string text = files::read_string(settings_file); std::string text = files::read_string(settings_file);
toml::Reader reader(wrapper.get(), settings_file.string(), text); toml::parse(handler, settings_file.string(), text);
reader.read();
} }
corecontent::setup_bindings(); corecontent::setup_bindings();
Engine engine(settings, &paths); Engine engine(settings, handler, &paths);
if (fs::is_regular_file(controls_file)) { if (fs::is_regular_file(controls_file)) {
logger.info() << "loading controls"; logger.info() << "loading controls";
std::string text = files::read_string(controls_file); std::string text = files::read_string(controls_file);
@ -53,7 +52,7 @@ int main(int argc, char** argv) {
engine.mainloop(); engine.mainloop();
logger.info() << "saving settings"; logger.info() << "saving settings";
files::write_string(settings_file, wrapper->write()); files::write_string(settings_file, toml::stringify(handler));
files::write_string(controls_file, write_controls()); files::write_string(controls_file, write_controls());
} }
catch (const initialize_error& err) { catch (const initialize_error& err) {

View File

@ -72,8 +72,8 @@ void window_size_callback(GLFWwindow*, int width, int height) {
} }
if (!Window::isFullscreen() && !Window::isMaximized()) { if (!Window::isFullscreen() && !Window::isMaximized()) {
Window::getSettings()->width = width; Window::getSettings()->width.set(width);
Window::getSettings()->height = height; Window::getSettings()->height.set(height);
} }
} }
Window::resetScissor(); Window::resetScissor();
@ -110,8 +110,12 @@ void error_callback(int error, const char* description) {
int Window::initialize(DisplaySettings* settings){ int Window::initialize(DisplaySettings* settings){
Window::settings = settings; Window::settings = settings;
Window::width = settings->width; Window::width = settings->width.get();
Window::height = settings->height; Window::height = settings->height.get();
std::string title = "VoxelEngine-Cpp v" +
std::to_string(ENGINE_VERSION_MAJOR) + "." +
std::to_string(ENGINE_VERSION_MINOR);
glfwSetErrorCallback(error_callback); glfwSetErrorCallback(error_callback);
if (glfwInit() == GLFW_FALSE) { if (glfwInit() == GLFW_FALSE) {
@ -129,9 +133,9 @@ int Window::initialize(DisplaySettings* settings){
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
#endif #endif
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
glfwWindowHint(GLFW_SAMPLES, settings->samples); glfwWindowHint(GLFW_SAMPLES, settings->samples.get());
window = glfwCreateWindow(width, height, settings->title.c_str(), nullptr, nullptr); window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
if (window == nullptr){ if (window == nullptr){
logger.error() << "failed to create GLFW window"; logger.error() << "failed to create GLFW window";
glfwTerminate(); glfwTerminate();
@ -286,7 +290,11 @@ void Window::toggleFullscreen(){
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, GLFW_DONT_CARE); glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, GLFW_DONT_CARE);
} }
else { else {
glfwSetWindowMonitor(window, nullptr, posX, posY, settings->width, settings->height, GLFW_DONT_CARE); glfwSetWindowMonitor(window, nullptr,
posX, posY,
settings->width.get(), settings->height.get(),
GLFW_DONT_CARE
);
glfwSetWindowAttrib(window, GLFW_MAXIMIZED, GLFW_FALSE); glfwSetWindowAttrib(window, GLFW_MAXIMIZED, GLFW_FALSE);
} }

View File

@ -57,7 +57,7 @@ void World::write(Level* level) {
if (chunk == nullptr || !chunk->isLighted()) if (chunk == nullptr || !chunk->isLighted())
continue; continue;
bool lightsUnsaved = !chunk->isLoadedLights() && bool lightsUnsaved = !chunk->isLoadedLights() &&
settings.debug.doWriteLights; settings.debug.doWriteLights.get();
if (!chunk->isUnsaved() && !lightsUnsaved) if (!chunk->isUnsaved() && !lightsUnsaved)
continue; continue;
regions.put(chunk.get()); regions.put(chunk.get());