toml::Wrapper removed
This commit is contained in:
parent
184ecd88ba
commit
c3b5576c02
@ -1,320 +1,323 @@
|
||||
#include "commons.h"
|
||||
|
||||
#include "../util/stringutil.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <math.h>
|
||||
|
||||
inline double power(double base, int64_t power) {
|
||||
double result = 1.0;
|
||||
for (int64_t i = 0; i < power; i++) {
|
||||
result *= base;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
parsing_error::parsing_error(
|
||||
std::string message,
|
||||
std::string filename,
|
||||
std::string source,
|
||||
uint pos,
|
||||
uint line,
|
||||
uint linestart)
|
||||
: std::runtime_error(message), filename(filename), source(source),
|
||||
pos(pos), line(line), linestart(linestart) {
|
||||
}
|
||||
|
||||
std::string parsing_error::errorLog() const {
|
||||
std::stringstream ss;
|
||||
uint linepos = pos - linestart;
|
||||
ss << "parsing error in file '" << filename;
|
||||
ss << "' at " << (line+1) << ":" << linepos << ": " << this->what() << "\n";
|
||||
size_t end = source.find("\n", linestart);
|
||||
if (end == std::string::npos) {
|
||||
end = source.length();
|
||||
}
|
||||
ss << source.substr(linestart, end-linestart) << "\n";
|
||||
for (uint i = 0; i < linepos; i++) {
|
||||
ss << " ";
|
||||
}
|
||||
ss << "^";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
BasicParser::BasicParser(std::string file, std::string source) : filename(file), source(source) {
|
||||
}
|
||||
|
||||
void BasicParser::skipWhitespace() {
|
||||
while (hasNext()) {
|
||||
char next = source[pos];
|
||||
if (next == '\n') {
|
||||
line++;
|
||||
linestart = ++pos;
|
||||
continue;
|
||||
}
|
||||
if (is_whitespace(next)) {
|
||||
pos++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BasicParser::skip(size_t n) {
|
||||
n = std::min(n, source.length()-pos);
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
char next = source[pos++];
|
||||
if (next == '\n') {
|
||||
line++;
|
||||
linestart = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BasicParser::skipLine() {
|
||||
while (hasNext()) {
|
||||
if (source[pos] == '\n') {
|
||||
pos++;
|
||||
linestart = pos;
|
||||
line++;
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicParser::skipTo(const std::string& substring) {
|
||||
size_t idx = source.find(substring, pos);
|
||||
if (idx == std::string::npos) {
|
||||
skip(source.length()-pos);
|
||||
return false;
|
||||
} else {
|
||||
skip(idx-pos);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicParser::hasNext() {
|
||||
return pos < source.length();
|
||||
}
|
||||
|
||||
bool BasicParser::isNext(const std::string& substring) {
|
||||
if (source.length() - pos < substring.length()) {
|
||||
return false;
|
||||
}
|
||||
return source.substr(pos, substring.length()) == substring;
|
||||
}
|
||||
|
||||
char BasicParser::nextChar() {
|
||||
if (!hasNext()) {
|
||||
throw error("unexpected end");
|
||||
}
|
||||
return source[pos++];
|
||||
}
|
||||
|
||||
void BasicParser::expect(char expected) {
|
||||
char c = peek();
|
||||
if (c != expected) {
|
||||
throw error("'"+std::string({expected})+"' expected");
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
void BasicParser::expect(const std::string& substring) {
|
||||
if (substring.empty())
|
||||
return;
|
||||
for (uint i = 0; i < substring.length(); i++) {
|
||||
if (source.length() <= pos + i || source[pos+i] != substring[i]) {
|
||||
throw error(util::quote(substring)+" expected");
|
||||
}
|
||||
}
|
||||
pos += substring.length();
|
||||
}
|
||||
|
||||
void BasicParser::expectNewLine() {
|
||||
while (hasNext()) {
|
||||
char next = source[pos];
|
||||
if (next == '\n') {
|
||||
line++;
|
||||
linestart = ++pos;
|
||||
return;
|
||||
}
|
||||
if (is_whitespace(next)) {
|
||||
pos++;
|
||||
} else {
|
||||
throw error("line separator expected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BasicParser::goBack() {
|
||||
if (pos) pos--;
|
||||
}
|
||||
|
||||
char BasicParser::peek() {
|
||||
skipWhitespace();
|
||||
if (pos >= source.length()) {
|
||||
throw error("unexpected end");
|
||||
}
|
||||
return source[pos];
|
||||
}
|
||||
|
||||
std::string BasicParser::parseName() {
|
||||
char c = peek();
|
||||
if (!is_identifier_start(c)) {
|
||||
if (c == '"') {
|
||||
pos++;
|
||||
return parseString(c);
|
||||
}
|
||||
throw error("identifier expected");
|
||||
}
|
||||
int start = pos;
|
||||
while (hasNext() && is_identifier_part(source[pos])) {
|
||||
pos++;
|
||||
}
|
||||
return source.substr(start, pos-start);
|
||||
}
|
||||
|
||||
int64_t BasicParser::parseSimpleInt(int base) {
|
||||
char c = peek();
|
||||
int index = hexchar2int(c);
|
||||
if (index == -1 || index >= base) {
|
||||
throw error("invalid number literal");
|
||||
}
|
||||
int64_t value = index;
|
||||
pos++;
|
||||
while (hasNext()) {
|
||||
c = source[pos];
|
||||
while (c == '_') {
|
||||
c = source[++pos];
|
||||
}
|
||||
index = hexchar2int(c);
|
||||
if (index == -1 || index >= base) {
|
||||
return value;
|
||||
}
|
||||
value *= base;
|
||||
value += index;
|
||||
pos++;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool BasicParser::parseNumber(int sign, number_u& out) {
|
||||
char c = peek();
|
||||
int base = 10;
|
||||
if (c == '0' && pos + 1 < source.length() &&
|
||||
(base = is_box(source[pos+1])) != 10) {
|
||||
pos += 2;
|
||||
out = parseSimpleInt(base);
|
||||
return true;
|
||||
} else if (c == 'i' && pos + 2 < source.length() && source[pos+1] == 'n' && source[pos+2] == 'f') {
|
||||
pos += 3;
|
||||
out = INFINITY * sign;
|
||||
return false;
|
||||
} else if (c == 'n' && pos + 2 < source.length() && source[pos+1] == 'a' && source[pos+2] == 'n') {
|
||||
pos += 3;
|
||||
out = NAN * sign;
|
||||
return false;
|
||||
}
|
||||
int64_t value = parseSimpleInt(base);
|
||||
if (!hasNext()) {
|
||||
out = value * sign;
|
||||
return true;
|
||||
}
|
||||
c = source[pos];
|
||||
if (c == 'e' || c == 'E') {
|
||||
pos++;
|
||||
int s = 1;
|
||||
if (peek() == '-') {
|
||||
s = -1;
|
||||
pos++;
|
||||
} else if (peek() == '+'){
|
||||
pos++;
|
||||
}
|
||||
out = sign * value * power(10.0, s * parseSimpleInt(10));
|
||||
return false;
|
||||
}
|
||||
if (c == '.') {
|
||||
pos++;
|
||||
int64_t expo = 1;
|
||||
while (hasNext() && source[pos] == '0') {
|
||||
expo *= 10;
|
||||
pos++;
|
||||
}
|
||||
int64_t afterdot = 0;
|
||||
if (hasNext() && is_digit(source[pos])) {
|
||||
afterdot = parseSimpleInt(10);
|
||||
}
|
||||
expo *= power(10, fmax(0, log10(afterdot) + 1));
|
||||
c = source[pos];
|
||||
|
||||
double dvalue = (value + (afterdot / (double)expo));
|
||||
if (c == 'e' || c == 'E') {
|
||||
pos++;
|
||||
int s = 1;
|
||||
if (peek() == '-') {
|
||||
s = -1;
|
||||
pos++;
|
||||
} else if (peek() == '+'){
|
||||
pos++;
|
||||
}
|
||||
out = sign * dvalue * power(10.0, s * parseSimpleInt(10));
|
||||
return false;
|
||||
}
|
||||
out = sign * dvalue;
|
||||
return false;
|
||||
}
|
||||
out = sign * value;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string BasicParser::parseString(char quote, bool closeRequired) {
|
||||
std::stringstream ss;
|
||||
while (hasNext()) {
|
||||
char c = source[pos];
|
||||
if (c == quote) {
|
||||
pos++;
|
||||
return ss.str();
|
||||
}
|
||||
if (c == '\\') {
|
||||
pos++;
|
||||
c = nextChar();
|
||||
if (c >= '0' && c <= '7') {
|
||||
pos--;
|
||||
ss << (char)parseSimpleInt(8);
|
||||
continue;
|
||||
}
|
||||
switch (c) {
|
||||
case 'n': ss << '\n'; break;
|
||||
case 'r': ss << '\r'; break;
|
||||
case 'b': ss << '\b'; break;
|
||||
case 't': ss << '\t'; break;
|
||||
case 'f': ss << '\f'; break;
|
||||
case '\'': ss << '\\'; break;
|
||||
case '"': ss << '"'; break;
|
||||
case '\\': ss << '\\'; break;
|
||||
case '/': ss << '/'; break;
|
||||
case '\n': pos++; continue;
|
||||
default:
|
||||
throw error("'\\" + std::string({c}) +
|
||||
"' is an illegal escape");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c == '\n' && closeRequired) {
|
||||
throw error("non-closed string literal");
|
||||
}
|
||||
ss << c;
|
||||
pos++;
|
||||
}
|
||||
if (closeRequired) {
|
||||
throw error("unexpected end");
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
parsing_error BasicParser::error(std::string message) {
|
||||
return parsing_error(message, filename, source, pos, line, linestart);
|
||||
}
|
||||
#include "commons.h"
|
||||
|
||||
#include "../util/stringutil.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <math.h>
|
||||
|
||||
inline double power(double base, int64_t power) {
|
||||
double result = 1.0;
|
||||
for (int64_t i = 0; i < power; i++) {
|
||||
result *= base;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
parsing_error::parsing_error(
|
||||
std::string message,
|
||||
std::string filename,
|
||||
std::string source,
|
||||
uint pos,
|
||||
uint line,
|
||||
uint linestart)
|
||||
: std::runtime_error(message), filename(filename), source(source),
|
||||
pos(pos), line(line), linestart(linestart) {
|
||||
}
|
||||
|
||||
std::string parsing_error::errorLog() const {
|
||||
std::stringstream ss;
|
||||
uint linepos = pos - linestart;
|
||||
ss << "parsing error in file '" << filename;
|
||||
ss << "' at " << (line+1) << ":" << linepos << ": " << this->what() << "\n";
|
||||
size_t end = source.find("\n", linestart);
|
||||
if (end == std::string::npos) {
|
||||
end = source.length();
|
||||
}
|
||||
ss << source.substr(linestart, end-linestart) << "\n";
|
||||
for (uint i = 0; i < linepos; i++) {
|
||||
ss << " ";
|
||||
}
|
||||
ss << "^";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
BasicParser::BasicParser(
|
||||
const std::string& file,
|
||||
const std::string& source
|
||||
) : filename(file), source(source) {
|
||||
}
|
||||
|
||||
void BasicParser::skipWhitespace() {
|
||||
while (hasNext()) {
|
||||
char next = source[pos];
|
||||
if (next == '\n') {
|
||||
line++;
|
||||
linestart = ++pos;
|
||||
continue;
|
||||
}
|
||||
if (is_whitespace(next)) {
|
||||
pos++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BasicParser::skip(size_t n) {
|
||||
n = std::min(n, source.length()-pos);
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
char next = source[pos++];
|
||||
if (next == '\n') {
|
||||
line++;
|
||||
linestart = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BasicParser::skipLine() {
|
||||
while (hasNext()) {
|
||||
if (source[pos] == '\n') {
|
||||
pos++;
|
||||
linestart = pos;
|
||||
line++;
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicParser::skipTo(const std::string& substring) {
|
||||
size_t idx = source.find(substring, pos);
|
||||
if (idx == std::string::npos) {
|
||||
skip(source.length()-pos);
|
||||
return false;
|
||||
} else {
|
||||
skip(idx-pos);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicParser::hasNext() {
|
||||
return pos < source.length();
|
||||
}
|
||||
|
||||
bool BasicParser::isNext(const std::string& substring) {
|
||||
if (source.length() - pos < substring.length()) {
|
||||
return false;
|
||||
}
|
||||
return source.substr(pos, substring.length()) == substring;
|
||||
}
|
||||
|
||||
char BasicParser::nextChar() {
|
||||
if (!hasNext()) {
|
||||
throw error("unexpected end");
|
||||
}
|
||||
return source[pos++];
|
||||
}
|
||||
|
||||
void BasicParser::expect(char expected) {
|
||||
char c = peek();
|
||||
if (c != expected) {
|
||||
throw error("'"+std::string({expected})+"' expected");
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
void BasicParser::expect(const std::string& substring) {
|
||||
if (substring.empty())
|
||||
return;
|
||||
for (uint i = 0; i < substring.length(); i++) {
|
||||
if (source.length() <= pos + i || source[pos+i] != substring[i]) {
|
||||
throw error(util::quote(substring)+" expected");
|
||||
}
|
||||
}
|
||||
pos += substring.length();
|
||||
}
|
||||
|
||||
void BasicParser::expectNewLine() {
|
||||
while (hasNext()) {
|
||||
char next = source[pos];
|
||||
if (next == '\n') {
|
||||
line++;
|
||||
linestart = ++pos;
|
||||
return;
|
||||
}
|
||||
if (is_whitespace(next)) {
|
||||
pos++;
|
||||
} else {
|
||||
throw error("line separator expected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BasicParser::goBack() {
|
||||
if (pos) pos--;
|
||||
}
|
||||
|
||||
char BasicParser::peek() {
|
||||
skipWhitespace();
|
||||
if (pos >= source.length()) {
|
||||
throw error("unexpected end");
|
||||
}
|
||||
return source[pos];
|
||||
}
|
||||
|
||||
std::string BasicParser::parseName() {
|
||||
char c = peek();
|
||||
if (!is_identifier_start(c)) {
|
||||
if (c == '"') {
|
||||
pos++;
|
||||
return parseString(c);
|
||||
}
|
||||
throw error("identifier expected");
|
||||
}
|
||||
int start = pos;
|
||||
while (hasNext() && is_identifier_part(source[pos])) {
|
||||
pos++;
|
||||
}
|
||||
return source.substr(start, pos-start);
|
||||
}
|
||||
|
||||
int64_t BasicParser::parseSimpleInt(int base) {
|
||||
char c = peek();
|
||||
int index = hexchar2int(c);
|
||||
if (index == -1 || index >= base) {
|
||||
throw error("invalid number literal");
|
||||
}
|
||||
int64_t value = index;
|
||||
pos++;
|
||||
while (hasNext()) {
|
||||
c = source[pos];
|
||||
while (c == '_') {
|
||||
c = source[++pos];
|
||||
}
|
||||
index = hexchar2int(c);
|
||||
if (index == -1 || index >= base) {
|
||||
return value;
|
||||
}
|
||||
value *= base;
|
||||
value += index;
|
||||
pos++;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool BasicParser::parseNumber(int sign, number_u& out) {
|
||||
char c = peek();
|
||||
int base = 10;
|
||||
if (c == '0' && pos + 1 < source.length() &&
|
||||
(base = is_box(source[pos+1])) != 10) {
|
||||
pos += 2;
|
||||
out = parseSimpleInt(base);
|
||||
return true;
|
||||
} else if (c == 'i' && pos + 2 < source.length() && source[pos+1] == 'n' && source[pos+2] == 'f') {
|
||||
pos += 3;
|
||||
out = INFINITY * sign;
|
||||
return false;
|
||||
} else if (c == 'n' && pos + 2 < source.length() && source[pos+1] == 'a' && source[pos+2] == 'n') {
|
||||
pos += 3;
|
||||
out = NAN * sign;
|
||||
return false;
|
||||
}
|
||||
int64_t value = parseSimpleInt(base);
|
||||
if (!hasNext()) {
|
||||
out = value * sign;
|
||||
return true;
|
||||
}
|
||||
c = source[pos];
|
||||
if (c == 'e' || c == 'E') {
|
||||
pos++;
|
||||
int s = 1;
|
||||
if (peek() == '-') {
|
||||
s = -1;
|
||||
pos++;
|
||||
} else if (peek() == '+'){
|
||||
pos++;
|
||||
}
|
||||
out = sign * value * power(10.0, s * parseSimpleInt(10));
|
||||
return false;
|
||||
}
|
||||
if (c == '.') {
|
||||
pos++;
|
||||
int64_t expo = 1;
|
||||
while (hasNext() && source[pos] == '0') {
|
||||
expo *= 10;
|
||||
pos++;
|
||||
}
|
||||
int64_t afterdot = 0;
|
||||
if (hasNext() && is_digit(source[pos])) {
|
||||
afterdot = parseSimpleInt(10);
|
||||
}
|
||||
expo *= power(10, fmax(0, log10(afterdot) + 1));
|
||||
c = source[pos];
|
||||
|
||||
double dvalue = (value + (afterdot / (double)expo));
|
||||
if (c == 'e' || c == 'E') {
|
||||
pos++;
|
||||
int s = 1;
|
||||
if (peek() == '-') {
|
||||
s = -1;
|
||||
pos++;
|
||||
} else if (peek() == '+'){
|
||||
pos++;
|
||||
}
|
||||
out = sign * dvalue * power(10.0, s * parseSimpleInt(10));
|
||||
return false;
|
||||
}
|
||||
out = sign * dvalue;
|
||||
return false;
|
||||
}
|
||||
out = sign * value;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string BasicParser::parseString(char quote, bool closeRequired) {
|
||||
std::stringstream ss;
|
||||
while (hasNext()) {
|
||||
char c = source[pos];
|
||||
if (c == quote) {
|
||||
pos++;
|
||||
return ss.str();
|
||||
}
|
||||
if (c == '\\') {
|
||||
pos++;
|
||||
c = nextChar();
|
||||
if (c >= '0' && c <= '7') {
|
||||
pos--;
|
||||
ss << (char)parseSimpleInt(8);
|
||||
continue;
|
||||
}
|
||||
switch (c) {
|
||||
case 'n': ss << '\n'; break;
|
||||
case 'r': ss << '\r'; break;
|
||||
case 'b': ss << '\b'; break;
|
||||
case 't': ss << '\t'; break;
|
||||
case 'f': ss << '\f'; break;
|
||||
case '\'': ss << '\\'; break;
|
||||
case '"': ss << '"'; break;
|
||||
case '\\': ss << '\\'; break;
|
||||
case '/': ss << '/'; break;
|
||||
case '\n': pos++; continue;
|
||||
default:
|
||||
throw error("'\\" + std::string({c}) +
|
||||
"' is an illegal escape");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c == '\n' && closeRequired) {
|
||||
throw error("non-closed string literal");
|
||||
}
|
||||
ss << c;
|
||||
pos++;
|
||||
}
|
||||
if (closeRequired) {
|
||||
throw error("unexpected end");
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
parsing_error BasicParser::error(std::string message) {
|
||||
return parsing_error(message, filename, source, pos, line, linestart);
|
||||
}
|
||||
|
||||
@ -70,8 +70,8 @@ public:
|
||||
|
||||
class BasicParser {
|
||||
protected:
|
||||
std::string filename;
|
||||
std::string source;
|
||||
const std::string& filename;
|
||||
const std::string& source;
|
||||
uint pos = 0;
|
||||
uint line = 1;
|
||||
uint linestart = 0;
|
||||
@ -96,7 +96,7 @@ protected:
|
||||
|
||||
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_
|
||||
|
||||
@ -118,8 +118,8 @@ std::string json::stringify(
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
Parser::Parser(std::string filename, std::string source)
|
||||
: BasicParser(filename, source) {
|
||||
Parser::Parser(const std::string& filename, const std::string& source)
|
||||
: BasicParser(filename, source) {
|
||||
}
|
||||
|
||||
Map* Parser::parse() {
|
||||
@ -244,11 +244,11 @@ Value* Parser::parseValue() {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -24,13 +24,13 @@ namespace json {
|
||||
dynamic::Map* parseObject();
|
||||
dynamic::Value* parseValue();
|
||||
public:
|
||||
Parser(std::string filename, std::string source);
|
||||
Parser(const std::string& filename, const std::string& source);
|
||||
|
||||
dynamic::Map* parse();
|
||||
};
|
||||
|
||||
extern std::unique_ptr<dynamic::Map> parse(std::string filename, std::string source);
|
||||
extern std::unique_ptr<dynamic::Map> parse(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(const std::string& source);
|
||||
|
||||
extern std::string stringify(
|
||||
const dynamic::Map* obj,
|
||||
@ -38,4 +38,4 @@ namespace json {
|
||||
const std::string& indent);
|
||||
}
|
||||
|
||||
#endif // CODERS_JSON_H_
|
||||
#endif // CODERS_JSON_H_
|
||||
|
||||
@ -1,261 +1,127 @@
|
||||
#include "toml.h"
|
||||
#include "commons.h"
|
||||
#include "../util/stringutil.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <assert.h>
|
||||
|
||||
// FIXME: refactor this monster
|
||||
|
||||
using namespace toml;
|
||||
|
||||
Section::Section(std::string name) : name(name) {
|
||||
}
|
||||
|
||||
void Section::add(std::string name, Field field) {
|
||||
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();
|
||||
if (hasNext() && source[pos] == '#') {
|
||||
skipLine();
|
||||
if (hasNext() && is_whitespace(peek())) {
|
||||
skipWhitespace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reader::read() {
|
||||
skipWhitespace();
|
||||
if (!hasNext()) {
|
||||
return;
|
||||
}
|
||||
readSection(nullptr);
|
||||
}
|
||||
|
||||
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()) {
|
||||
skipWhitespace();
|
||||
if (!hasNext()) {
|
||||
break;
|
||||
}
|
||||
char c = nextChar();
|
||||
if (c == '[') {
|
||||
std::string name = parseName();
|
||||
Section* section = wrapper->section(name);
|
||||
pos++;
|
||||
readSection(section);
|
||||
return;
|
||||
}
|
||||
pos--;
|
||||
std::string name = parseName();
|
||||
expect('=');
|
||||
c = peek();
|
||||
if (is_digit(c)) {
|
||||
number_u num;
|
||||
if (parseNumber(1, num)) {
|
||||
if (section)
|
||||
section->set(name, (double)std::get<integer_t>(num));
|
||||
} else {
|
||||
if (section)
|
||||
section->set(name, std::get<number_t>(num));
|
||||
}
|
||||
} else if (c == '-' || c == '+') {
|
||||
int sign = c == '-' ? -1 : 1;
|
||||
pos++;
|
||||
number_u num;
|
||||
if (parseNumber(sign, num)) {
|
||||
if (section)
|
||||
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)) {
|
||||
std::string identifier = parseName();
|
||||
if (identifier == "true" || identifier == "false") {
|
||||
bool flag = identifier == "true";
|
||||
if (section) {
|
||||
section->set(name, flag);
|
||||
}
|
||||
} else if (identifier == "inf") {
|
||||
if (section) {
|
||||
section->set(name, INFINITY);
|
||||
}
|
||||
} else if (identifier == "nan") {
|
||||
if (section) {
|
||||
section->set(name, NAN);
|
||||
}
|
||||
}
|
||||
} else if (c == '"' || c == '\'') {
|
||||
pos++;
|
||||
std::string str = parseString(c);
|
||||
if (section) {
|
||||
section->set(name, str);
|
||||
}
|
||||
} else {
|
||||
throw error("feature is not supported");
|
||||
}
|
||||
expectNewLine();
|
||||
}
|
||||
}
|
||||
#include "toml.h"
|
||||
#include "commons.h"
|
||||
#include "../data/dynamic.h"
|
||||
#include "../util/stringutil.h"
|
||||
#include "../files/settings_io.hpp"
|
||||
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <assert.h>
|
||||
|
||||
// FIXME: refactor this monster
|
||||
|
||||
using namespace toml;
|
||||
|
||||
class Reader : public BasicParser {
|
||||
SettingsHandler& handler;
|
||||
|
||||
void skipWhitespace() override {
|
||||
BasicParser::skipWhitespace();
|
||||
if (hasNext() && source[pos] == '#') {
|
||||
skipLine();
|
||||
if (hasNext() && is_whitespace(peek())) {
|
||||
skipWhitespace();
|
||||
}
|
||||
}
|
||||
}
|
||||
void readSection(const std::string& section) {
|
||||
while (hasNext()) {
|
||||
skipWhitespace();
|
||||
if (!hasNext()) {
|
||||
break;
|
||||
}
|
||||
char c = nextChar();
|
||||
if (c == '[') {
|
||||
std::string name = parseName();
|
||||
pos++;
|
||||
readSection(name);
|
||||
return;
|
||||
}
|
||||
pos--;
|
||||
std::string name = section+"."+parseName();
|
||||
expect('=');
|
||||
c = peek();
|
||||
if (is_digit(c)) {
|
||||
number_u num;
|
||||
parseNumber(1, num);
|
||||
handler.setValue(name, *dynamic::Value::of(num));
|
||||
} else if (c == '-' || c == '+') {
|
||||
int sign = c == '-' ? -1 : 1;
|
||||
pos++;
|
||||
number_u num;
|
||||
parseNumber(sign, num);
|
||||
handler.setValue(name, *dynamic::Value::of(num));
|
||||
} else if (is_identifier_start(c)) {
|
||||
std::string identifier = parseName();
|
||||
if (identifier == "true" || identifier == "false") {
|
||||
bool flag = identifier == "true";
|
||||
handler.setValue(name, *dynamic::Value::boolean(flag));
|
||||
} else if (identifier == "inf") {
|
||||
handler.setValue(name, *dynamic::Value::of(INFINITY));
|
||||
} else if (identifier == "nan") {
|
||||
handler.setValue(name, *dynamic::Value::of(NAN));
|
||||
}
|
||||
} else if (c == '"' || c == '\'') {
|
||||
pos++;
|
||||
std::string str = parseString(c);
|
||||
handler.setValue(name, *dynamic::Value::of(str));
|
||||
} else {
|
||||
throw error("feature is not supported");
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
@ -1,72 +1,22 @@
|
||||
#ifndef CODERS_TOML_H_
|
||||
#define CODERS_TOML_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "commons.h"
|
||||
|
||||
namespace toml {
|
||||
enum class fieldtype {
|
||||
ftbool,
|
||||
ftint,
|
||||
ftuint,
|
||||
ftint64,
|
||||
ftfloat,
|
||||
ftdouble,
|
||||
ftstring,
|
||||
};
|
||||
|
||||
struct Field {
|
||||
fieldtype type;
|
||||
void* ptr;
|
||||
};
|
||||
|
||||
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_
|
||||
#ifndef CODERS_TOML_H_
|
||||
#define CODERS_TOML_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "commons.h"
|
||||
|
||||
class SettingsHandler;
|
||||
|
||||
namespace toml {
|
||||
std::string stringify(SettingsHandler& handler);
|
||||
|
||||
void parse(
|
||||
SettingsHandler& handler,
|
||||
const std::string& file,
|
||||
const std::string& source
|
||||
);
|
||||
}
|
||||
|
||||
#endif // CODERS_TOML_H_
|
||||
|
||||
@ -176,7 +176,7 @@ const std::string& Document::getEncoding() const {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
Parser::Parser(std::string filename, std::string source)
|
||||
Parser::Parser(const std::string& filename, const std::string& source)
|
||||
: BasicParser(filename, source) {
|
||||
}
|
||||
|
||||
|
||||
@ -118,7 +118,7 @@ namespace xml {
|
||||
std::string parseText();
|
||||
std::string parseXMLName();
|
||||
public:
|
||||
Parser(std::string filename, std::string source);
|
||||
Parser(const std::string& filename, const std::string& source);
|
||||
|
||||
xmldocument parse();
|
||||
};
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "content/ContentLoader.h"
|
||||
#include "core_defs.h"
|
||||
#include "files/files.h"
|
||||
#include "files/settings_io.hpp"
|
||||
#include "frontend/locale/langs.h"
|
||||
#include "frontend/menu.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)
|
||||
: settings(settings), settingsHandler(settings), paths(paths)
|
||||
Engine::Engine(EngineSettings& settings, SettingsHandler& settingsHandler, EnginePaths* paths)
|
||||
: settings(settings), settingsHandler(settingsHandler), paths(paths)
|
||||
{
|
||||
controller = std::make_unique<EngineController>(this);
|
||||
if (Window::initialize(&this->settings.display)){
|
||||
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, "regular", settings.audio.volumeRegular);
|
||||
create_channel(this, "music", settings.audio.volumeMusic);
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
#include "content/ContentPack.h"
|
||||
#include "content/PacksManager.hpp"
|
||||
#include "files/engine_paths.h"
|
||||
#include "files/settings_io.h"
|
||||
#include "util/ObjectsKeeper.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
@ -27,6 +26,7 @@ class EnginePaths;
|
||||
class ResPaths;
|
||||
class Batch2D;
|
||||
class EngineController;
|
||||
class SettingsHandler;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@ -41,7 +41,7 @@ public:
|
||||
|
||||
class Engine : public util::ObjectsKeeper {
|
||||
EngineSettings& settings;
|
||||
SettingsHandler settingsHandler;
|
||||
SettingsHandler& settingsHandler;
|
||||
EnginePaths* paths;
|
||||
|
||||
std::unique_ptr<Assets> assets = nullptr;
|
||||
@ -65,7 +65,7 @@ class Engine : public util::ObjectsKeeper {
|
||||
void processPostRunnables();
|
||||
void loadAssets();
|
||||
public:
|
||||
Engine(EngineSettings& settings, EnginePaths* paths);
|
||||
Engine(EngineSettings& settings, SettingsHandler& settingsHandler, EnginePaths* paths);
|
||||
~Engine();
|
||||
|
||||
/// @brief Start main engine input/update/render loop.
|
||||
|
||||
@ -35,8 +35,8 @@ WorldFiles::WorldFiles(fs::path directory) : directory(directory), regions(direc
|
||||
WorldFiles::WorldFiles(fs::path directory, const DebugSettings& settings)
|
||||
: WorldFiles(directory)
|
||||
{
|
||||
generatorTestMode = settings.generatorTestMode;
|
||||
doWriteLights = settings.doWriteLights;
|
||||
generatorTestMode = settings.generatorTestMode.get();
|
||||
doWriteLights = settings.doWriteLights.get();
|
||||
regions.generatorTestMode = generatorTestMode;
|
||||
regions.doWriteLights = doWriteLights;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#include "settings_io.h"
|
||||
#include "settings_io.hpp"
|
||||
|
||||
#include "../window/Events.h"
|
||||
#include "../window/input.h"
|
||||
@ -10,30 +10,70 @@
|
||||
|
||||
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) {
|
||||
// public settings
|
||||
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);
|
||||
SectionsBuilder builder(map, sections);
|
||||
|
||||
map.emplace("display.vsync", &settings.display.vsync);
|
||||
map.emplace("display.fullscreen", &settings.display.fullscreen);
|
||||
builder.section("audio");
|
||||
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);
|
||||
map.emplace("camera.fov", &settings.camera.fov);
|
||||
map.emplace("camera.fov-effects", &settings.camera.fovEffects);
|
||||
map.emplace("camera.shaking", &settings.camera.shaking);
|
||||
builder.section("display");
|
||||
builder.add("width", &settings.display.width);
|
||||
builder.add("height", &settings.display.height);
|
||||
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);
|
||||
map.emplace("chunks.load-speed", &settings.chunks.loadSpeed);
|
||||
builder.section("camera");
|
||||
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);
|
||||
map.emplace("graphics.backlight", &settings.graphics.backlight);
|
||||
map.emplace("graphics.gamma", &settings.graphics.gamma);
|
||||
builder.section("chunks");
|
||||
builder.add("load-distance", &settings.chunks.loadDistance);
|
||||
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 {
|
||||
@ -123,51 +163,8 @@ void SettingsHandler::setValue(const std::string& name, const dynamic::Value& va
|
||||
}
|
||||
}
|
||||
|
||||
toml::Wrapper* create_wrapper(EngineSettings& settings) {
|
||||
auto wrapper = std::make_unique<toml::Wrapper>();
|
||||
|
||||
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::vector<Section>& SettingsHandler::getSections() {
|
||||
return sections;
|
||||
}
|
||||
|
||||
std::string write_controls() {
|
||||
|
||||
@ -1,18 +1,21 @@
|
||||
#ifndef FILES_SETTINGS_IO_H_
|
||||
#define FILES_SETTINGS_IO_H_
|
||||
#ifndef FILES_SETTINGS_IO_HPP_
|
||||
#define FILES_SETTINGS_IO_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include "../settings.h"
|
||||
#include "../data/dynamic.h"
|
||||
|
||||
namespace toml {
|
||||
class Wrapper;
|
||||
}
|
||||
struct Section {
|
||||
std::string name;
|
||||
std::vector<std::string> keys;
|
||||
};
|
||||
|
||||
class SettingsHandler {
|
||||
std::unordered_map<std::string, Setting*> map;
|
||||
std::vector<Section> sections;
|
||||
public:
|
||||
SettingsHandler(EngineSettings& settings);
|
||||
|
||||
@ -20,10 +23,12 @@ public:
|
||||
void setValue(const std::string& name, const dynamic::Value& value);
|
||||
std::string toString(const std::string& name) const;
|
||||
Setting* getSetting(const std::string& name) const;
|
||||
|
||||
std::vector<Section>& getSections();
|
||||
};
|
||||
|
||||
extern std::string write_controls();
|
||||
extern toml::Wrapper* create_wrapper(EngineSettings& settings);
|
||||
extern void load_controls(std::string filename, std::string source);
|
||||
std::string write_controls();
|
||||
|
||||
#endif // FILES_SETTINGS_IO_H_
|
||||
void load_controls(std::string filename, std::string source);
|
||||
|
||||
#endif // FILES_SETTINGS_IO_HPP_
|
||||
@ -146,10 +146,10 @@ std::shared_ptr<UINode> create_debug_panel(
|
||||
L"Show Chunk Borders", glm::vec2(400, 24)
|
||||
);
|
||||
checkbox->setSupplier([=]() {
|
||||
return engine->getSettings().debug.showChunkBorders;
|
||||
return WorldRenderer::showChunkBorders;
|
||||
});
|
||||
checkbox->setConsumer([=](bool checked) {
|
||||
engine->getSettings().debug.showChunkBorders = checked;
|
||||
WorldRenderer::showChunkBorders = checked;
|
||||
});
|
||||
panel->add(checkbox);
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ class Reader : public BasicParser {
|
||||
}
|
||||
}
|
||||
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) {
|
||||
|
||||
@ -35,6 +35,8 @@
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
bool WorldRenderer::showChunkBorders = false;
|
||||
|
||||
WorldRenderer::WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* player)
|
||||
: engine(engine),
|
||||
level(frontend->getLevel()),
|
||||
@ -225,7 +227,7 @@ void WorldRenderer::renderDebugLines(
|
||||
|
||||
linesShader->use();
|
||||
|
||||
if (settings.debug.showChunkBorders){
|
||||
if (showChunkBorders){
|
||||
linesShader->uniformMatrix("u_projview", camera->getProjView());
|
||||
glm::vec3 coord = player->camera->position;
|
||||
if (coord.x < 0) coord.x--;
|
||||
|
||||
@ -56,6 +56,8 @@ class WorldRenderer {
|
||||
const EngineSettings& settings
|
||||
);
|
||||
public:
|
||||
static bool showChunkBorders;
|
||||
|
||||
WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* player);
|
||||
~WorldRenderer();
|
||||
|
||||
|
||||
@ -1,189 +1,190 @@
|
||||
#include "lua_commons.h"
|
||||
#include "api_lua.h"
|
||||
|
||||
#include "../../../engine.h"
|
||||
#include "../../../files/engine_paths.h"
|
||||
#include "../../../frontend/menu.hpp"
|
||||
#include "../../../frontend/screens/MenuScreen.hpp"
|
||||
#include "../../../logic/LevelController.h"
|
||||
#include "../../../logic/EngineController.hpp"
|
||||
#include "../../../window/Events.h"
|
||||
#include "../../../window/Window.h"
|
||||
#include "../../../world/WorldGenerators.h"
|
||||
#include "../scripting.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace scripting {
|
||||
extern lua::LuaState* state;
|
||||
}
|
||||
|
||||
static int l_new_world(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto seed = lua_tostring(L, 2);
|
||||
auto generator = lua_tostring(L, 3);
|
||||
auto controller = scripting::engine->getController();
|
||||
controller->createWorld(name, seed, generator);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_open_world(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
|
||||
auto controller = scripting::engine->getController();
|
||||
controller->openWorld(name, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_close_world(lua_State* L) {
|
||||
if (scripting::controller == nullptr) {
|
||||
luaL_error(L, "no world open");
|
||||
}
|
||||
bool save_world = lua_toboolean(L, 1);
|
||||
if (save_world) {
|
||||
scripting::controller->saveWorld();
|
||||
}
|
||||
// destroy LevelScreen and run quit callbacks
|
||||
scripting::engine->setScreen(nullptr);
|
||||
// create and go to menu screen
|
||||
scripting::engine->setScreen(std::make_shared<MenuScreen>(scripting::engine));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_delete_world(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto controller = scripting::engine->getController();
|
||||
controller->deleteWorld(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_remove_packs(lua_State* L) {
|
||||
if (!lua_istable(L, 1)) {
|
||||
luaL_error(L, "strings array expected as an argument");
|
||||
}
|
||||
std::vector<std::string> packs;
|
||||
int len = lua_objlen(L, 1);
|
||||
for (int i = 0; i < len; i++) {
|
||||
lua_rawgeti(L, -1, i+1);
|
||||
packs.push_back(lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
auto controller = scripting::engine->getController();
|
||||
controller->removePacks(scripting::controller, packs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_add_packs(lua_State* L) {
|
||||
if (!lua_istable(L, 1)) {
|
||||
luaL_error(L, "strings array expected as an argument");
|
||||
}
|
||||
std::vector<std::string> packs;
|
||||
int len = lua_objlen(L, 1);
|
||||
for (int i = 0; i < len; i++) {
|
||||
lua_rawgeti(L, -1, i+1);
|
||||
packs.push_back(lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
auto controller = scripting::engine->getController();
|
||||
controller->addPacks(scripting::controller, packs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_bindings(lua_State* L) {
|
||||
auto& bindings = Events::bindings;
|
||||
lua_createtable(L, bindings.size(), 0);
|
||||
|
||||
int i = 0;
|
||||
for (auto& entry : bindings) {
|
||||
lua_pushstring(L, entry.first.c_str());
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
i++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_setting(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
const auto value = scripting::engine->getSettingsHandler().getValue(name);
|
||||
scripting::state->pushvalue(*value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_set_setting(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
const auto value = scripting::state->tovalue(2);
|
||||
scripting::engine->getSettingsHandler().setValue(name, *value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_str_setting(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
const auto string = scripting::engine->getSettingsHandler().toString(name);
|
||||
scripting::state->pushstring(string);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_setting_info(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto setting = scripting::engine->getSettingsHandler().getSetting(name);
|
||||
lua_createtable(L, 0, 1);
|
||||
if (auto number = dynamic_cast<NumberSetting*>(setting)) {
|
||||
lua_pushnumber(L, number->getMin());
|
||||
lua_setfield(L, -2, "min");
|
||||
lua_pushnumber(L, number->getMax());
|
||||
lua_setfield(L, -2, "max");
|
||||
return 1;
|
||||
}
|
||||
if (auto integer = dynamic_cast<IntegerSetting*>(setting)) {
|
||||
lua_pushinteger(L, integer->getMin());
|
||||
lua_setfield(L, -2, "min");
|
||||
lua_pushinteger(L, integer->getMax());
|
||||
lua_setfield(L, -2, "max");
|
||||
return 1;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
luaL_error(L, "unsupported setting type");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_quit(lua_State* L) {
|
||||
Window::setShouldClose(true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_default_generator(lua_State* L) {
|
||||
lua_pushstring(L, WorldGenerators::getDefaultGeneratorID().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_generators(lua_State* L) {
|
||||
const auto& generators = WorldGenerators::getGeneratorsIDs();
|
||||
lua_createtable(L, generators.size(), 0);
|
||||
|
||||
int i = 0;
|
||||
for (auto& id : generators) {
|
||||
lua_pushstring(L, id.c_str());
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
i++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg corelib [] = {
|
||||
{"new_world", lua_wrap_errors<l_new_world>},
|
||||
{"open_world", lua_wrap_errors<l_open_world>},
|
||||
{"close_world", lua_wrap_errors<l_close_world>},
|
||||
{"delete_world", lua_wrap_errors<l_delete_world>},
|
||||
{"add_packs", lua_wrap_errors<l_add_packs>},
|
||||
{"remove_packs", lua_wrap_errors<l_remove_packs>},
|
||||
{"get_bindings", lua_wrap_errors<l_get_bindings>},
|
||||
{"get_setting", lua_wrap_errors<l_get_setting>},
|
||||
{"set_setting", lua_wrap_errors<l_set_setting>},
|
||||
{"str_setting", lua_wrap_errors<l_str_setting>},
|
||||
{"get_setting_info", lua_wrap_errors<l_get_setting_info>},
|
||||
{"quit", lua_wrap_errors<l_quit>},
|
||||
{"get_default_generator", lua_wrap_errors<l_get_default_generator>},
|
||||
{"get_generators", lua_wrap_errors<l_get_generators>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
#include "lua_commons.h"
|
||||
#include "api_lua.h"
|
||||
|
||||
#include "../../../engine.h"
|
||||
#include "../../../files/settings_io.hpp"
|
||||
#include "../../../files/engine_paths.h"
|
||||
#include "../../../frontend/menu.hpp"
|
||||
#include "../../../frontend/screens/MenuScreen.hpp"
|
||||
#include "../../../logic/LevelController.h"
|
||||
#include "../../../logic/EngineController.hpp"
|
||||
#include "../../../window/Events.h"
|
||||
#include "../../../window/Window.h"
|
||||
#include "../../../world/WorldGenerators.h"
|
||||
#include "../scripting.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace scripting {
|
||||
extern lua::LuaState* state;
|
||||
}
|
||||
|
||||
static int l_new_world(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto seed = lua_tostring(L, 2);
|
||||
auto generator = lua_tostring(L, 3);
|
||||
auto controller = scripting::engine->getController();
|
||||
controller->createWorld(name, seed, generator);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_open_world(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
|
||||
auto controller = scripting::engine->getController();
|
||||
controller->openWorld(name, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_close_world(lua_State* L) {
|
||||
if (scripting::controller == nullptr) {
|
||||
luaL_error(L, "no world open");
|
||||
}
|
||||
bool save_world = lua_toboolean(L, 1);
|
||||
if (save_world) {
|
||||
scripting::controller->saveWorld();
|
||||
}
|
||||
// destroy LevelScreen and run quit callbacks
|
||||
scripting::engine->setScreen(nullptr);
|
||||
// create and go to menu screen
|
||||
scripting::engine->setScreen(std::make_shared<MenuScreen>(scripting::engine));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_delete_world(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto controller = scripting::engine->getController();
|
||||
controller->deleteWorld(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_remove_packs(lua_State* L) {
|
||||
if (!lua_istable(L, 1)) {
|
||||
luaL_error(L, "strings array expected as an argument");
|
||||
}
|
||||
std::vector<std::string> packs;
|
||||
int len = lua_objlen(L, 1);
|
||||
for (int i = 0; i < len; i++) {
|
||||
lua_rawgeti(L, -1, i+1);
|
||||
packs.push_back(lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
auto controller = scripting::engine->getController();
|
||||
controller->removePacks(scripting::controller, packs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_add_packs(lua_State* L) {
|
||||
if (!lua_istable(L, 1)) {
|
||||
luaL_error(L, "strings array expected as an argument");
|
||||
}
|
||||
std::vector<std::string> packs;
|
||||
int len = lua_objlen(L, 1);
|
||||
for (int i = 0; i < len; i++) {
|
||||
lua_rawgeti(L, -1, i+1);
|
||||
packs.push_back(lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
auto controller = scripting::engine->getController();
|
||||
controller->addPacks(scripting::controller, packs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_bindings(lua_State* L) {
|
||||
auto& bindings = Events::bindings;
|
||||
lua_createtable(L, bindings.size(), 0);
|
||||
|
||||
int i = 0;
|
||||
for (auto& entry : bindings) {
|
||||
lua_pushstring(L, entry.first.c_str());
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
i++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_setting(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
const auto value = scripting::engine->getSettingsHandler().getValue(name);
|
||||
scripting::state->pushvalue(*value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_set_setting(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
const auto value = scripting::state->tovalue(2);
|
||||
scripting::engine->getSettingsHandler().setValue(name, *value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_str_setting(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
const auto string = scripting::engine->getSettingsHandler().toString(name);
|
||||
scripting::state->pushstring(string);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_setting_info(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto setting = scripting::engine->getSettingsHandler().getSetting(name);
|
||||
lua_createtable(L, 0, 1);
|
||||
if (auto number = dynamic_cast<NumberSetting*>(setting)) {
|
||||
lua_pushnumber(L, number->getMin());
|
||||
lua_setfield(L, -2, "min");
|
||||
lua_pushnumber(L, number->getMax());
|
||||
lua_setfield(L, -2, "max");
|
||||
return 1;
|
||||
}
|
||||
if (auto integer = dynamic_cast<IntegerSetting*>(setting)) {
|
||||
lua_pushinteger(L, integer->getMin());
|
||||
lua_setfield(L, -2, "min");
|
||||
lua_pushinteger(L, integer->getMax());
|
||||
lua_setfield(L, -2, "max");
|
||||
return 1;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
luaL_error(L, "unsupported setting type");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_quit(lua_State* L) {
|
||||
Window::setShouldClose(true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_default_generator(lua_State* L) {
|
||||
lua_pushstring(L, WorldGenerators::getDefaultGeneratorID().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_generators(lua_State* L) {
|
||||
const auto& generators = WorldGenerators::getGeneratorsIDs();
|
||||
lua_createtable(L, generators.size(), 0);
|
||||
|
||||
int i = 0;
|
||||
for (auto& id : generators) {
|
||||
lua_pushstring(L, id.c_str());
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
i++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg corelib [] = {
|
||||
{"new_world", lua_wrap_errors<l_new_world>},
|
||||
{"open_world", lua_wrap_errors<l_open_world>},
|
||||
{"close_world", lua_wrap_errors<l_close_world>},
|
||||
{"delete_world", lua_wrap_errors<l_delete_world>},
|
||||
{"add_packs", lua_wrap_errors<l_add_packs>},
|
||||
{"remove_packs", lua_wrap_errors<l_remove_packs>},
|
||||
{"get_bindings", lua_wrap_errors<l_get_bindings>},
|
||||
{"get_setting", lua_wrap_errors<l_get_setting>},
|
||||
{"set_setting", lua_wrap_errors<l_set_setting>},
|
||||
{"str_setting", lua_wrap_errors<l_str_setting>},
|
||||
{"get_setting_info", lua_wrap_errors<l_get_setting_info>},
|
||||
{"quit", lua_wrap_errors<l_quit>},
|
||||
{"get_default_generator", lua_wrap_errors<l_get_default_generator>},
|
||||
{"get_generators", lua_wrap_errors<l_get_generators>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
struct AudioSettings {
|
||||
/// @brief try to initialize AL backend
|
||||
bool enabled = true;
|
||||
FlagSetting enabled {true};
|
||||
|
||||
NumberSetting volumeMaster {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
|
||||
FlagSetting fullscreen {false};
|
||||
/// @brief Window width (pixels)
|
||||
int width = 1280;
|
||||
IntegerSetting width {1280};
|
||||
/// @brief Window height (pixels)
|
||||
int height = 720;
|
||||
IntegerSetting height {720};
|
||||
/// @brief Anti-aliasing samples
|
||||
int samples = 0;
|
||||
IntegerSetting samples {0};
|
||||
/// @brief VSync on
|
||||
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 {
|
||||
@ -60,6 +56,7 @@ struct GraphicsSettings {
|
||||
/// @brief Fog opacity is calculated as `pow(depth*k, fogCurve)` where k depends on chunksLoadDistance.
|
||||
/// 1.0 is linear, 2.0 is quadratic
|
||||
NumberSetting fogCurve {1.6f, 1.0f, 6.0f};
|
||||
/// @brief Lighting gamma
|
||||
NumberSetting gamma {1.0f, 0.5f, 2.0f};
|
||||
/// @brief Enable blocks backlight to prevent complete darkness
|
||||
FlagSetting backlight {true};
|
||||
@ -70,9 +67,8 @@ struct GraphicsSettings {
|
||||
|
||||
struct DebugSettings {
|
||||
/// @brief Turns off chunks saving/loading
|
||||
bool generatorTestMode = false;
|
||||
bool showChunkBorders = false;
|
||||
bool doWriteLights = true;
|
||||
FlagSetting generatorTestMode {false};
|
||||
FlagSetting doWriteLights {true};
|
||||
};
|
||||
|
||||
struct UiSettings {
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#include "engine.h"
|
||||
#include "coders/toml.h"
|
||||
#include "files/files.h"
|
||||
#include "files/settings_io.h"
|
||||
#include "files/settings_io.hpp"
|
||||
#include "files/engine_paths.h"
|
||||
#include "util/platform.h"
|
||||
#include "util/command_line.h"
|
||||
@ -33,18 +33,17 @@ int main(int argc, char** argv) {
|
||||
fs::path userfiles = paths.getUserfiles();
|
||||
try {
|
||||
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 controls_file = userfiles/fs::path(CONTROLS_FILE);
|
||||
if (fs::is_regular_file(settings_file)) {
|
||||
logger.info() << "loading settings";
|
||||
std::string text = files::read_string(settings_file);
|
||||
toml::Reader reader(wrapper.get(), settings_file.string(), text);
|
||||
reader.read();
|
||||
toml::parse(handler, settings_file.string(), text);
|
||||
}
|
||||
corecontent::setup_bindings();
|
||||
Engine engine(settings, &paths);
|
||||
Engine engine(settings, handler, &paths);
|
||||
if (fs::is_regular_file(controls_file)) {
|
||||
logger.info() << "loading controls";
|
||||
std::string text = files::read_string(controls_file);
|
||||
@ -53,7 +52,7 @@ int main(int argc, char** argv) {
|
||||
engine.mainloop();
|
||||
|
||||
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());
|
||||
}
|
||||
catch (const initialize_error& err) {
|
||||
|
||||
@ -72,8 +72,8 @@ void window_size_callback(GLFWwindow*, int width, int height) {
|
||||
}
|
||||
|
||||
if (!Window::isFullscreen() && !Window::isMaximized()) {
|
||||
Window::getSettings()->width = width;
|
||||
Window::getSettings()->height = height;
|
||||
Window::getSettings()->width.set(width);
|
||||
Window::getSettings()->height.set(height);
|
||||
}
|
||||
}
|
||||
Window::resetScissor();
|
||||
@ -110,8 +110,12 @@ void error_callback(int error, const char* description) {
|
||||
|
||||
int Window::initialize(DisplaySettings* settings){
|
||||
Window::settings = settings;
|
||||
Window::width = settings->width;
|
||||
Window::height = settings->height;
|
||||
Window::width = settings->width.get();
|
||||
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);
|
||||
if (glfwInit() == GLFW_FALSE) {
|
||||
@ -129,9 +133,9 @@ int Window::initialize(DisplaySettings* settings){
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
|
||||
#endif
|
||||
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){
|
||||
logger.error() << "failed to create GLFW window";
|
||||
glfwTerminate();
|
||||
@ -286,7 +290,11 @@ void Window::toggleFullscreen(){
|
||||
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, GLFW_DONT_CARE);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ void World::write(Level* level) {
|
||||
if (chunk == nullptr || !chunk->isLighted())
|
||||
continue;
|
||||
bool lightsUnsaved = !chunk->isLoadedLights() &&
|
||||
settings.debug.doWriteLights;
|
||||
settings.debug.doWriteLights.get();
|
||||
if (!chunk->isUnsaved() && !lightsUnsaved)
|
||||
continue;
|
||||
regions.put(chunk.get());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user