1 #include "lxgui/gui_addon_registry.hpp"
3 #include "lxgui/gui_event_emitter.hpp"
4 #include "lxgui/gui_localizer.hpp"
5 #include "lxgui/gui_out.hpp"
6 #include "lxgui/utils_file_system.hpp"
7 #include "lxgui/utils_range.hpp"
8 #include "lxgui/utils_std.hpp"
9 #include "lxgui/utils_string.hpp"
12 #include <lxgui/extern_sol2_state.hpp>
17 const char* lxgui_ui_version =
"0001";
24 lua_(lua), localizer_(loc), event_emitter_(emitter), root_(r), virtual_root_(vr) {}
26 void addon_registry::load_addon_toc_(
27 const std::string& addon_name,
const std::string& addon_directory) {
28 auto& addons = addon_list_[addon_directory];
29 if (addons.find(addon_name) != addons.end())
35 a.
directory = addon_directory +
"/" + addon_name;
37 std::string toc_file = a.
directory +
"/" + addon_name +
".toc";
38 std::ifstream file(toc_file);
43 while (std::getline(file, line)) {
44 utils::replace(line,
"\r",
"");
48 std::string_view line_view = line;
50 if (line_view.size() >= 2 && line_view[0] ==
'#' && line_view[1] ==
'#') {
51 line_view = line_view.substr(2);
52 line_view = utils::trim(line_view,
' ');
53 auto args = utils::cut_first(line_view,
":");
54 if (!args.first.empty() && !args.second.empty()) {
55 std::string_view key = utils::trim(args.first,
' ');
56 std::string_view value = utils::trim(args.second,
' ');
58 if (key ==
"Interface") {
65 <<
"Wrong UI version for \"" << addon_name
67 <<
", expected: " << lxgui_ui_version <<
"). AddOn disabled."
71 }
else if (key ==
"Title")
73 else if (key ==
"Version")
75 else if (key ==
"Author")
77 else if (key ==
"SavedVariables") {
78 for (
auto var : utils::cut(value,
",")) {
79 var = utils::trim(var,
' ');
80 if (!utils::has_no_content(var))
86 line_view = utils::trim(line_view,
' ');
87 if (!utils::has_no_content(line_view))
96 addons[addon_name] = a;
99 void addon_registry::load_addon_files_(
const addon& a) {
103 for (
const auto& file : a.file_list) {
105 if (extension ==
".lua") {
106 auto result = lua_.do_file(file);
107 if (!result.valid()) {
108 std::string err = result.get<sol::error>().what();
110 event_emitter_.
fire_event(
"LUA_ERROR", {err});
113 this->parse_layout_file_(file, a);
117 std::string saved_variables_file =
118 "saves/interface/" + a.main_directory +
"/" + a.name +
".lua";
121 auto result = lua_.do_file(saved_variables_file);
122 if (!result.valid()) {
123 std::string err = result.get<sol::error>().what();
125 event_emitter_.
fire_event(
"LUA_ERROR", {err});
129 event_emitter_.
fire_event(
"ADDON_LOADED", {a.name});
134 this->load_addon_toc_(sub_dir, directory);
136 std::vector<addon*> core_addon_stack;
137 std::vector<addon*> addon_stack;
140 auto& addons = addon_list_[directory];
142 std::ifstream file(directory +
"/addons.txt");
143 if (file.is_open()) {
145 while (std::getline(file, line)) {
146 utils::replace(line,
"\r",
"");
150 std::string_view line_view = line;
152 if (line_view[0] ==
'#') {
153 line_view = line_view.substr(1);
154 line_view = utils::trim(line_view,
' ');
155 core = line_view ==
"Core";
157 auto args = utils::cut_first(line_view,
":");
158 if (!args.first.empty() && !args.second.empty()) {
159 std::string_view key = utils::trim(args.first,
' ');
160 std::string_view value = utils::trim(args.second,
' ');
161 auto iter = addons.find(std::string{key});
162 if (iter != addons.end()) {
164 core_addon_stack.push_back(&iter->second);
166 addon_stack.push_back(&iter->second);
168 iter->second.enabled = value ==
"1";
176 for (
auto* a : core_addon_stack) {
178 this->load_addon_files_(*a);
181 for (
auto* a : addon_stack) {
183 this->load_addon_files_(*a);
186 current_addon_ =
nullptr;
189 std::string
serialize(
const std::string& tab,
const sol::object& value) noexcept {
190 if (value.is<
double>()) {
191 return utils::to_string(value.as<
double>());
192 }
else if (value.is<
int>()) {
193 return utils::to_string(value.as<
int>());
194 }
else if (value.is<std::string>()) {
195 return "\"" + utils::to_string(value.as<std::string>()) +
"\"";
196 }
else if (value.is<sol::table>()) {
201 sol::table table = value.as<sol::table>();
202 for (
const auto& key_value : table) {
203 content += tab +
" [" +
serialize(
"", key_value.first) +
204 "] = " +
serialize(tab +
" ", key_value.second) +
",\n";
207 if (!content.empty())
208 result +=
"\n" + content + tab;
218 sol::object value = lua.globals()[variable];
223 for (
const auto& directory : addon_list_) {
229 void addon_registry::save_variables_(
const addon& a)
const noexcept {
230 if (!a.saved_variable_list.empty()) {
233 <<
"gui::addon_registry: unable to create directory 'saves/interface/"
234 << a.main_directory <<
"'" << std::endl;
238 std::ofstream file(
"saves/interface/" + a.main_directory +
"/" + a.name +
".lua");
239 for (
const auto& variable : a.saved_variable_list) {
241 if (!serialized.empty())
242 file << serialized <<
"\n";
248 return current_addon_;
const addon * get_current_addon()
Returns the addon that is being parsed.
void save_variables() const
Save Lua variables registred for saving for all addons.
void set_current_addon(const addon *a)
Sets the current addon.
void load_addon_directory(const std::string &directory)
Parse all addons inside a directory.
addon_registry(sol::state &lua, localizer &loc, event_emitter &emitter, root &r, virtual_root &vr)
Constructor.
Generates events and keep tracks of registered callbacks.
void fire_event(const std::string &event_name, event_data data=event_data{})
Emmit a new event.
Utility class to translate strings for display in GUI.
void load_translations(const std::string &folder_path)
Loads new translations from a folder, selecting the language automatically.
Root of the UI object hierarchy.
Root of the virtual UI object hierarchy.
std::string serialize_global(sol::state &lua, const std::string &variable) noexcept
std::string serialize(const std::string &tab, const sol::object &value) noexcept
const std::string warning
range_impl::value_range< T > value(T &container)
Expose the value rather than the (key,value) pair.
bool make_directory(const std::string &path)
string_vector get_directory_list(const std::string &rel_path)
std::string get_file_extension(const std::string &file)
bool file_exists(const std::string &file)
A piece of the user interface.
std::string main_directory
std::vector< std::string > saved_variable_list
std::vector< std::string > file_list