-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathconfig.cpp
124 lines (112 loc) · 4.87 KB
/
config.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "config.hpp"
#include <filesystem>
#include <string_view>
#include <vector>
#include "toml.hpp" // IWYU pragma: keep; supress warning from clangd.
#include "util.hpp"
namespace {
inline glm::vec2 toVec2(const std::array<float, 2> a) {
return glm::vec2(a[0], a[1]);
}
inline glm::vec3 toVec3(const std::array<float, 3> a) {
return glm::vec3(a[0], a[1], a[2]);
}
} // namespace
Config::Config() :
simulationFPS(60.0f),
gravity(9.8f),
lightDirection(-0.5f, -1.0f, -0.5f),
defaultModelPosition(0.0f, 0.0f),
defaultScale(1.0f),
defaultCameraPosition(0, 10, 50),
defaultGazePosition(0, 10, 0),
defaultScreenNumber(std::nullopt) {}
Config Config::Parse(const std::filesystem::path& configFile) {
namespace fs = std::filesystem;
constexpr auto warnUnsupportedKey = [](const toml::value::key_type& k,
const toml::value& v) {
// TODO: Error message should point key, not its value
constexpr std::string_view header = "[error]";
const std::string rawmsg = toml::format_error(
"Ignoring unsupported config key.", v, "Key is not supported: " + k);
std::string_view errmsg = rawmsg;
if (errmsg.starts_with(header)) {
errmsg.remove_prefix(header.size());
while (errmsg.front() == ' ')
errmsg.remove_prefix(1);
}
Err::Log("[warning]", errmsg);
};
Config config;
const auto configDir = fs::path(configFile).parent_path();
try {
const auto entire = toml::parse(configFile);
// Ensure all the required keys appear in config.toml
(void)toml::find(entire, "model");
for (const auto& [k, v] : entire.as_table()) {
if (k == "model") {
const auto path = toml::get<std::u8string>(v);
config.model = ::Path::makeAbsolute(fs::path(path), configDir);
} else if (k == "default-model-position") {
const auto pos = toml::get<std::array<float, 2>>(v);
config.defaultModelPosition = toVec2(pos);
} else if (k == "default-camera-position") {
const auto pos = toml::get<std::array<float, 3>>(v);
config.defaultCameraPosition = toVec3(pos);
} else if (k == "default-gaze-position") {
const auto pos = toml::get<std::array<float, 3>>(v);
config.defaultGazePosition = toVec3(pos);
} else if (k == "default-scale") {
config.defaultScale = v.as_floating();
} else if (k == "simulation-fps") {
config.simulationFPS = v.as_floating();
} else if (k == "gravity") {
config.gravity = v.as_floating();
} else if (k == "light-direction") {
const auto d = toml::get<std::array<float, 3>>(v);
config.lightDirection = toVec3(d);
} else if (k == "default-screen-number") {
config.defaultScreenNumber = v.as_integer();
} else if (k == "motion") {
for (const auto& m : v.as_array()) {
// Ensure all the required key appear in "motion" table.
(void)toml::find(m, "path");
Motion c = {.disabled = false, .weight = 1};
for (const auto& [k, v] : m.as_table()) {
if (k == "path") {
const auto raw_path = toml::get<std::vector<std::u8string>>(v);
std::vector<fs::path> path;
for (const auto& p : raw_path) {
path.push_back(::Path::makeAbsolute(fs::path(p), configDir));
}
c.paths = std::move(path);
} else if (k == "weight") {
c.weight = v.as_integer();
if (c.weight <= 0) {
const auto errmsg = toml::format_error(
"Invalid value for \"weight\"", v,
"Value must be bigger than or equals to 1.");
Err::Log(errmsg);
}
} else if (k == "disabled") {
c.disabled = v.as_boolean();
} else {
warnUnsupportedKey(k, v);
}
}
config.motions.push_back(std::move(c));
}
} else {
warnUnsupportedKey(k, v);
}
}
} catch (std::runtime_error& e) {
// File open error, file read error, etc...
Err::Exit(e.what());
} catch (std::out_of_range& e) {
Err::Log(e.what());
} catch (std::exception& e) {
Err::Log(e.what());
}
return config;
}