'dynamic' namespace refactor + sensitivity is a NumberSetting now

This commit is contained in:
MihailRis 2024-03-31 17:30:02 +03:00
parent 398347bd81
commit 48982e3478
14 changed files with 168 additions and 140 deletions

View File

@ -117,11 +117,12 @@ void AssetsLoader::processPreloadList(AssetType tag, dynamic::List* list) {
auto value = list->get(i);
switch (value->type) {
case dynamic::valtype::string:
processPreload(tag, *value->value.str, nullptr);
processPreload(tag, std::get<std::string>(value->value), nullptr);
break;
case dynamic::valtype::map: {
auto name = value->value.map->getStr("name");
processPreload(tag, name, value->value.map);
auto map = std::get<dynamic::Map*>(value->value);
auto name = map->getStr("name");
processPreload(tag, name, map);
break;
}
default:

View File

@ -10,20 +10,22 @@ using namespace dynamic;
static void to_binary(ByteBuilder& builder, const Value* value) {
switch (value->type) {
case valtype::none:
throw std::runtime_error("none value is not implemented");
case valtype::map: {
std::vector<ubyte> bytes = to_binary(value->value.map);
std::vector<ubyte> bytes = to_binary(std::get<Map*>(value->value));
builder.put(bytes.data(), bytes.size());
break;
}
case valtype::list:
builder.put(BJSON_TYPE_LIST);
for (auto& element : value->value.list->values) {
for (auto& element : std::get<List*>(value->value)->values) {
to_binary(builder, element.get());
}
builder.put(BJSON_END);
break;
case valtype::integer: {
int64_t val = value->value.integer;
auto val = std::get<integer_t>(value->value);
if (val >= 0 && val <= 255) {
builder.put(BJSON_TYPE_BYTE);
builder.put(val);
@ -41,14 +43,14 @@ static void to_binary(ByteBuilder& builder, const Value* value) {
}
case valtype::number:
builder.put(BJSON_TYPE_NUMBER);
builder.putFloat64(value->value.decimal);
builder.putFloat64(std::get<number_t>(value->value));
break;
case valtype::boolean:
builder.put(BJSON_TYPE_FALSE + value->value.boolean);
builder.put(BJSON_TYPE_FALSE + std::get<bool>(value->value));
break;
case valtype::string:
builder.put(BJSON_TYPE_STRING);
builder.put(*value->value.str);
builder.put(std::get<std::string>(value->value));
break;
}
}
@ -88,40 +90,40 @@ static Value* value_from_binary(ByteReader& reader) {
case BJSON_TYPE_DOCUMENT:
type = valtype::map;
reader.getInt32();
val.map = object_from_binary(reader);
val = object_from_binary(reader);
break;
case BJSON_TYPE_LIST:
type = valtype::list;
val.list = array_from_binary(reader);
val = array_from_binary(reader);
break;
case BJSON_TYPE_BYTE:
type = valtype::integer;
val.integer = reader.get();
val = reader.get();
break;
case BJSON_TYPE_INT16:
type = valtype::integer;
val.integer = reader.getInt16();
val = reader.getInt16();
break;
case BJSON_TYPE_INT32:
type = valtype::integer;
val.integer = reader.getInt32();
val = reader.getInt32();
break;
case BJSON_TYPE_INT64:
type = valtype::integer;
val.integer = reader.getInt64();
val = reader.getInt64();
break;
case BJSON_TYPE_NUMBER:
type = valtype::number;
val.decimal = reader.getFloat64();
val = reader.getFloat64();
break;
case BJSON_TYPE_FALSE:
case BJSON_TYPE_TRUE:
type = valtype::boolean;
val.boolean = typecode - BJSON_TYPE_FALSE;
val = typecode - BJSON_TYPE_FALSE;
break;
case BJSON_TYPE_STRING:
type = valtype::string;
val.str = new std::string(reader.getString());
val = reader.getString();
break;
default:
throw std::runtime_error(
@ -166,8 +168,8 @@ std::unique_ptr<Map> json::from_binary(const ubyte* src, size_t size) {
if (value->type != valtype::map) {
throw std::runtime_error("root value is not an object");
}
std::unique_ptr<Map> obj (value->value.map);
value->value.map = nullptr;
std::unique_ptr<Map> obj (std::get<Map*>(value->value));
value->value = (Map*)nullptr;
return obj;
}
}

View File

@ -42,10 +42,11 @@ void stringify(const Value* value,
const std::string& indentstr,
bool nice) {
if (value->type == valtype::map) {
stringifyObj(value->value.map, ss, indent, indentstr, nice);
auto map = std::get<Map*>(value->value);
stringifyObj(map, ss, indent, indentstr, nice);
}
else if (value->type == valtype::list) {
auto list = value->value.list;
auto list = std::get<List*>(value->value);
if (list->size() == 0) {
ss << "[]";
return;
@ -66,14 +67,14 @@ void stringify(const Value* value,
}
ss << ']';
} else if (value->type == valtype::boolean) {
ss << (value->value.boolean ? "true" : "false");
ss << (std::get<bool>(value->value) ? "true" : "false");
} else if (value->type == valtype::number) {
ss << std::setprecision(15);
ss << value->value.decimal;
ss << std::get<number_t>(value->value);
} else if (value->type == valtype::integer) {
ss << value->value.integer;
ss << std::get<integer_t>(value->value);
} else if (value->type == valtype::string) {
ss << escape_string(*value->value.str);
ss << escape_string(std::get<std::string>(value->value));
}
}
@ -189,10 +190,10 @@ Value* Parser::parseValue() {
number_u num;
valtype type;
if (parseNumber(next == '-' ? -1 : 1, num)) {
val.integer = num.ival;
val = num.ival;
type = valtype::integer;
} else {
val.decimal = num.fval;
val = num.fval;
type = valtype::number;
}
return new Value(type, val);
@ -200,43 +201,43 @@ Value* Parser::parseValue() {
if (is_identifier_start(next)) {
std::string literal = parseName();
if (literal == "true") {
val.boolean = true;
val = true;
return new Value(valtype::boolean, val);
} else if (literal == "false") {
val.boolean = false;
val = false;
return new Value(valtype::boolean, val);
} else if (literal == "inf") {
val.decimal = INFINITY;
val = INFINITY;
return new Value(valtype::number, val);
} else if (literal == "nan") {
val.decimal = NAN;
val = NAN;
return new Value(valtype::number, val);
}
throw error("invalid literal ");
}
if (next == '{') {
val.map = parseObject();
val = parseObject();
return new Value(valtype::map, val);
}
if (next == '[') {
val.list = parseList();
val = parseList();
return new Value(valtype::list, val);
}
if (is_digit(next)) {
number_u num;
valtype type;
if (parseNumber(1, num)) {
val.integer = num.ival;
val = num.ival;
type = valtype::integer;
} else {
val.decimal = num.fval;
val = num.fval;
type = valtype::number;
}
return new Value(type, val);
}
if (next == '"' || next == '\'') {
pos++;
val.str = new std::string(parseString(next));
val = parseString(next);
return new Value(valtype::string, val);
}
throw error("unexpected character '"+std::string({next})+"'");

View File

@ -10,34 +10,34 @@ List::~List() {
std::string List::str(size_t index) const {
const auto& val = values[index];
switch (val->type) {
case valtype::string: return *val->value.str;
case valtype::boolean: return val->value.boolean ? "true" : "false";
case valtype::number: return std::to_string(val->value.decimal);
case valtype::integer: return std::to_string(val->value.integer);
case valtype::string: return std::get<std::string>(val->value);
case valtype::boolean: return std::get<bool>(val->value) ? "true" : "false";
case valtype::number: return std::to_string(std::get<double>(val->value));
case valtype::integer: return std::to_string(std::get<int64_t>(val->value));
default:
throw std::runtime_error("type error");
}
}
double List::num(size_t index) const {
number_t List::num(size_t index) const {
const auto& val = values[index];
switch (val->type) {
case valtype::number: return val->value.decimal;
case valtype::integer: return val->value.integer;
case valtype::string: return std::stoll(*val->value.str);
case valtype::boolean: return val->value.boolean;
case valtype::number: return std::get<number_t>(val->value);
case valtype::integer: return std::get<integer_t>(val->value);
case valtype::string: return std::stoll(std::get<std::string>(val->value));
case valtype::boolean: return std::get<bool>(val->value);
default:
throw std::runtime_error("type error");
}
}
int64_t List::integer(size_t index) const {
integer_t List::integer(size_t index) const {
const auto& val = values[index];
switch (val->type) {
case valtype::number: return val->value.decimal;
case valtype::integer: return val->value.integer;
case valtype::string: return std::stoll(*val->value.str);
case valtype::boolean: return val->value.boolean;
case valtype::number: return std::get<number_t>(val->value);
case valtype::integer: return std::get<integer_t>(val->value);
case valtype::string: return std::stoll(std::get<std::string>(val->value));
case valtype::boolean: return std::get<bool>(val->value);
default:
throw std::runtime_error("type error");
}
@ -47,21 +47,21 @@ Map* List::map(size_t index) const {
if (values[index]->type != valtype::map) {
throw std::runtime_error("type error");
}
return values[index]->value.map;
return std::get<Map*>(values[index]->value);
}
List* List::list(size_t index) const {
if (values[index]->type != valtype::list) {
throw std::runtime_error("type error");
}
return values[index]->value.list;
return std::get<List*>(values[index]->value);
}
bool List::flag(size_t index) const {
const auto& val = values[index];
switch (val->type) {
case valtype::integer: return val->value.integer;
case valtype::boolean: return val->value.boolean;
case valtype::integer: return std::get<integer_t>(val->value);
case valtype::boolean: return std::get<bool>(val->value);
default:
throw std::runtime_error("type error");
}
@ -75,9 +75,7 @@ Value* List::getValueWriteable(size_t index) const {
}
List& List::put(std::string value) {
valvalue val;
val.str = new std::string(value);
values.push_back(std::make_unique<Value>(valtype::string, val));
values.push_back(std::make_unique<Value>(valtype::string, value));
return *this;
}
@ -90,9 +88,7 @@ List& List::put(int value) {
}
List& List::put(int64_t value) {
valvalue val;
val.integer = value;
values.push_back(std::make_unique<Value>(valtype::integer, val));
values.push_back(std::make_unique<Value>(valtype::integer, value));
return *this;
}
@ -101,9 +97,7 @@ List& List::put(uint64_t value) {
}
List& List::put(double value) {
valvalue val;
val.decimal = value;
values.push_back(std::make_unique<Value>(valtype::number, val));
values.push_back(std::make_unique<Value>(valtype::number, value));
return *this;
}
@ -112,23 +106,17 @@ List& List::put(float value) {
}
List& List::put(bool value) {
valvalue val;
val.boolean = value;
values.push_back(std::make_unique<Value>(valtype::boolean, val));
values.push_back(std::make_unique<Value>(valtype::boolean, value));
return *this;
}
List& List::put(Map* value) {
valvalue val;
val.map = value;
values.push_back(std::make_unique<Value>(valtype::map, val));
values.push_back(std::make_unique<Value>(valtype::map, value));
return *this;
}
List& List::put(List* value) {
valvalue val;
val.list = value;
values.push_back(std::make_unique<Value>(valtype::list, val));
values.push_back(std::make_unique<Value>(valtype::list, value));
return *this;
}
@ -189,38 +177,38 @@ std::string Map::getStr(std::string key, const std::string& def) const {
return def;
auto& val = found->second;
switch (val->type) {
case valtype::string: return *val->value.str;
case valtype::boolean: return val->value.boolean ? "true" : "false";
case valtype::number: return std::to_string(val->value.decimal);
case valtype::integer: return std::to_string(val->value.integer);
case valtype::string: return std::get<std::string>(val->value);
case valtype::boolean: return std::get<bool>(val->value) ? "true" : "false";
case valtype::number: return std::to_string(std::get<number_t>(val->value));
case valtype::integer: return std::to_string(std::get<integer_t>(val->value));
default: throw std::runtime_error("type error");
}
}
double Map::getNum(std::string key, double def) const {
number_t Map::getNum(std::string key, double def) const {
auto found = values.find(key);
if (found == values.end())
return def;
auto& val = found->second;
switch (val->type) {
case valtype::number: return val->value.decimal;
case valtype::integer: return val->value.integer;
case valtype::string: return std::stoull(*val->value.str);
case valtype::boolean: return val->value.boolean;
case valtype::number: return std::get<number_t>(val->value);
case valtype::integer: return std::get<integer_t>(val->value);
case valtype::string: return std::stoull(std::get<std::string>(val->value));
case valtype::boolean: return std::get<bool>(val->value);
default: throw std::runtime_error("type error");
}
}
int64_t Map::getInt(std::string key, int64_t def) const {
integer_t Map::getInt(std::string key, integer_t def) const {
auto found = values.find(key);
if (found == values.end())
return def;
auto& val = found->second;
switch (val->type) {
case valtype::number: return val->value.decimal;
case valtype::integer: return val->value.integer;
case valtype::string: return std::stoull(*val->value.str);
case valtype::boolean: return val->value.boolean;
case valtype::number: return std::get<number_t>(val->value);
case valtype::integer: return std::get<integer_t>(val->value);
case valtype::string: return std::stoull(std::get<std::string>(val->value));
case valtype::boolean: return std::get<bool>(val->value);
default: throw std::runtime_error("type error");
}
}
@ -231,8 +219,8 @@ bool Map::getBool(std::string key, bool def) const {
return def;
auto& val = found->second;
switch (val->type) {
case valtype::integer: return val->value.integer;
case valtype::boolean: return val->value.boolean;
case valtype::integer: return std::get<integer_t>(val->value);
case valtype::boolean: return std::get<bool>(val->value);
default: throw std::runtime_error("type error");
}
}
@ -271,7 +259,7 @@ Map* Map::map(std::string key) const {
auto& val = found->second;
if (val->type != valtype::map)
return nullptr;
return val->value.map;
return std::get<Map*>(val->value);
}
return nullptr;
}
@ -279,7 +267,7 @@ Map* Map::map(std::string key) const {
List* Map::list(std::string key) const {
auto found = values.find(key);
if (found != values.end())
return found->second->value.list;
return std::get<List*>(found->second->value);
return nullptr;
}
@ -296,9 +284,7 @@ Map& Map::put(std::string key, int value) {
}
Map& Map::put(std::string key, int64_t value) {
valvalue val;
val.integer = value;
values[key] = std::make_unique<Value>(valtype::integer, val);
values[key] = std::make_unique<Value>(valtype::integer, value);
return *this;
}
@ -311,16 +297,12 @@ Map& Map::put(std::string key, float value) {
}
Map& Map::put(std::string key, double value) {
valvalue val;
val.decimal = value;
values[key] = std::make_unique<Value>(valtype::number, val);
values[key] = std::make_unique<Value>(valtype::number, value);
return *this;
}
Map& Map::put(std::string key, std::string value){
valvalue val;
val.str = new std::string(value);
values[key] = std::make_unique<Value>(valtype::string, val);
values[key] = std::make_unique<Value>(valtype::string, value);
return *this;
}
@ -329,23 +311,17 @@ Map& Map::put(std::string key, const char* value) {
}
Map& Map::put(std::string key, Map* value){
valvalue val;
val.map = value;
values[key] = std::make_unique<Value>(valtype::map, val);
values[key] = std::make_unique<Value>(valtype::map, value);
return *this;
}
Map& Map::put(std::string key, List* value){
valvalue val;
val.list = value;
values[key] = std::make_unique<Value>(valtype::list, val);
values[key] = std::make_unique<Value>(valtype::list, value);
return *this;
}
Map& Map::put(std::string key, bool value){
valvalue val;
val.boolean = value;
values[key] = std::make_unique<Value>(valtype::boolean, val);
values[key] = std::make_unique<Value>(valtype::boolean, value);
return *this;
}
@ -370,9 +346,8 @@ Value::Value(valtype type, valvalue value) : type(type), value(value) {
Value::~Value() {
switch (type) {
case valtype::map: delete value.map; break;
case valtype::list: delete value.list; break;
case valtype::string: delete value.str; break;
case valtype::map: delete std::get<Map*>(value); break;
case valtype::list: delete std::get<List*>(value); break;
default:
break;
}

View File

@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include <memory>
#include <variant>
#include <unordered_map>
#include "../typedefs.h"
@ -12,18 +13,21 @@ namespace dynamic {
class List;
class Value;
using number_t = double;
using integer_t = int64_t;
enum class valtype {
map, list, number, integer, string, boolean
none, map, list, number, integer, string, boolean
};
union valvalue {
Map* map;
List* list;
std::string* str;
double decimal;
int64_t integer;
uint64_t boolean;
};
using valvalue = std::variant<
Map*,
List*,
std::string,
number_t,
bool,
integer_t
>;
class Value {
public:
@ -39,8 +43,8 @@ namespace dynamic {
~List();
std::string str(size_t index) const;
double num(size_t index) const;
int64_t integer(size_t index) const;
number_t num(size_t index) const;
integer_t integer(size_t index) const;
Map* map(size_t index) const;
List* list(size_t index) const;
bool flag(size_t index) const;
@ -78,13 +82,13 @@ namespace dynamic {
~Map();
std::string getStr(std::string key) const;
double getNum(std::string key) const;
int64_t getInt(std::string key) const;
number_t getNum(std::string key) const;
integer_t getInt(std::string key) const;
bool getBool(std::string key) const;
std::string getStr(std::string key, const std::string& def) const;
double getNum(std::string key, double def) const;
int64_t getInt(std::string key, int64_t def) const;
number_t getNum(std::string key, double def) const;
integer_t getInt(std::string key, integer_t def) const;
bool getBool(std::string key, bool def) const;
void str(std::string key, std::string& dst) const;

View File

@ -52,7 +52,7 @@ void addWorldGenerators() {
}
Engine::Engine(EngineSettings& settings, EnginePaths* paths)
: settings(settings), paths(paths)
: settings(settings), settingsHandler(settings), paths(paths)
{
if (Window::initialize(settings.display)){
throw initialize_error("could not initialize window");
@ -335,3 +335,7 @@ void Engine::postRunnable(runnable callback) {
std::lock_guard<std::recursive_mutex> lock(postRunnablesMutex);
postRunnables.push(callback);
}
SettingsHandler& Engine::getSettingsHandler() {
return settingsHandler;
}

View File

@ -9,6 +9,7 @@
#include "content/Content.h"
#include "content/ContentPack.h"
#include "files/engine_paths.h"
#include "files/settings_io.h"
#include <filesystem>
#include <memory>
@ -37,6 +38,7 @@ public:
class Engine {
EngineSettings& settings;
SettingsHandler settingsHandler;
EnginePaths* paths;
std::unique_ptr<Assets> assets = nullptr;
@ -118,6 +120,8 @@ public:
/// @brief Enqueue function call to the end of current frame in draw thread
void postRunnable(runnable callback);
SettingsHandler& getSettingsHandler();
};
#endif // SRC_ENGINE_H_

View File

@ -608,7 +608,7 @@ void WorldFiles::removePack(const World* world, const std::string& id) {
if (name.find(prefix) != 0)
continue;
auto value = blocks->getValueWriteable(i);
*value->value.str = "core:air";
value->value = "core:air";
}
auto items = root->list("items");
@ -617,7 +617,7 @@ void WorldFiles::removePack(const World* world, const std::string& id) {
if (name.find(prefix) != 0)
continue;
auto value = items->getValueWriteable(i);
*value->value.str = "core:empty";
value->value = "core:empty";
}
files::write_json(getIndicesFile(), root.get());
}

View File

@ -9,7 +9,33 @@
#include "../coders/toml.h"
#include "../coders/json.h"
#include "../data/dynamic.h"
SettingsHandler::SettingsHandler(EngineSettings& 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);
map.emplace("camera.sensitivity", &settings.camera.sensitivity);
}
dynamic::Value SettingsHandler::getValue(std::string name) const {
using dynamic::valtype;
auto found = map.find(name);
if (found == map.end()) {
return dynamic::Value(valtype::none, 0);
}
auto setting = found->second;
if (auto number = dynamic_cast<NumberSetting<float>*>(setting)) {
return dynamic::Value(valtype::number, number->get());
} else if (auto number = dynamic_cast<NumberSetting<double>*>(setting)) {
return dynamic::Value(valtype::number, number->get());
}
return dynamic::Value(valtype::none, 0);
}
toml::Wrapper* create_wrapper(EngineSettings& settings) {
std::unique_ptr<toml::Wrapper> wrapper (new toml::Wrapper());
@ -38,7 +64,7 @@ toml::Wrapper* create_wrapper(EngineSettings& settings) {
camera.add("fov-effects", &settings.camera.fovEvents);
camera.add("fov", &settings.camera.fov);
camera.add("shaking", &settings.camera.shaking);
camera.add("sensitivity", &settings.camera.sensitivity);
camera.add("sensitivity", &*settings.camera.sensitivity);
toml::Section& graphics = wrapper->add("graphics");
graphics.add("gamma", &settings.graphics.gamma);

View File

@ -2,14 +2,24 @@
#define FILES_SETTINGS_IO_H_
#include <string>
#include <unordered_map>
#include "../settings.h"
#include "../data/dynamic.h"
namespace toml {
class Wrapper;
}
class SettingsHandler {
std::unordered_map<std::string, Setting*> map;
public:
SettingsHandler(EngineSettings& settings);
dynamic::Value getValue(std::string name) const;
};
extern 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_
#endif // FILES_SETTINGS_IO_H_

View File

@ -78,7 +78,7 @@ void langs::loadLocalesInfo(const fs::path& resdir, std::string& fallback) {
std::string name;
if (langInfo->type == dynamic::valtype::map) {
name = langInfo->value.map->getStr("name", "none");
name = std::get<dynamic::Map*>(langInfo->value)->getStr("name", "none");
} else {
continue;
}

View File

@ -51,14 +51,14 @@ static void create_controls_panel(Engine* engine) {
/* Camera sensitivity setting track bar */{
panel->add(menus::create_label([=]() {
float s = engine->getSettings().camera.sensitivity;
float s = engine->getSettings().camera.sensitivity.get();
return langs::get(L"Mouse Sensitivity", L"settings")+L": "+
util::to_wstring(s, 1);
}));
auto trackbar = std::make_shared<TrackBar>(0.1, 10.0, 2.0, 0.1, 4);
trackbar->setSupplier([=]() {
return engine->getSettings().camera.sensitivity;
return engine->getSettings().camera.sensitivity.get();
});
trackbar->setConsumer([=](double value) {
engine->getSettings().camera.sensitivity = value;

View File

@ -50,8 +50,8 @@ void CameraControl::updateMouse(PlayerInput& input) {
glm::vec2& cam = player->cam;
float sensitivity = (input.zoom
? settings.sensitivity / 4.f
: settings.sensitivity);
? settings.sensitivity.get() / 4.f
: settings.sensitivity.get());
cam -= glm::degrees(Events::delta / (float)Window::height * sensitivity);

View File

@ -2,6 +2,7 @@
#define SRC_SETTINGS_H_
#include <string>
#include <unordered_map>
#include "data/setting.h"
#include "constants.h"
@ -52,7 +53,7 @@ struct CameraSettings {
/// @brief Camera field of view
float fov = 90.0f;
/// @brief Camera sensitivity
float sensitivity = 2.0f;
NumberSetting<float> sensitivity {2.0f, 0.1f, 10.0f};
};
struct GraphicsSettings {
@ -62,7 +63,7 @@ struct GraphicsSettings {
float gamma = 1.0f;
/// @brief Enable blocks backlight to prevent complete darkness
bool backlight = true;
/// @brief Enable chunks frustum culling */
/// @brief Enable chunks frustum culling
bool frustumCulling = true;
int skyboxResolution = 64 + 32;
};