lxgui
Loading...
Searching...
No Matches
gui_region_tpl.hpp
1#ifndef LXGUI_GUI_REGION_TPL_HPP
2#define LXGUI_GUI_REGION_TPL_HPP
3
4#include "lxgui/gui_frame.hpp"
5#include "lxgui/gui_manager.hpp"
6#include "lxgui/gui_region.hpp"
7#include "lxgui/gui_registry.hpp"
8#include "lxgui/gui_root.hpp"
9#include "lxgui/lxgui.hpp"
10#include "lxgui/utils_observer.hpp"
11#include "lxgui/utils_string.hpp"
12
13#include <lxgui/extern_sol2_state.hpp>
14
17namespace sol {
18
19template<typename T>
20struct unique_usertype_traits<lxgui::utils::observer_ptr<T>> {
21 static T* get(lua_State*, const lxgui::utils::observer_ptr<T>& pointer) noexcept {
22 return pointer.get();
23 }
24
25 static bool is_null(lua_State*, const lxgui::utils::observer_ptr<T>& pointer) noexcept {
26 return pointer.expired();
27 }
28};
29
30} // namespace sol
34namespace lxgui::gui {
35
36template<typename T>
38 sol::types<T>, lua_State* lua, int index, sol::stack::record& /*tracking*/) {
39 // NB: not sure why, but using tracking here leads to issues later on, so
40 // ignore it for now.
41
42 using RegionType = std::remove_pointer_t<T>;
43
44 sol::optional<lxgui::utils::observer_ptr<RegionType>&> optional =
45 sol::stack::check_get<lxgui::utils::observer_ptr<RegionType>&>(
46 lua, index, sol::no_panic /*, tracking*/);
47
48 if (!optional.has_value())
49 return;
50
51 if (optional->expired())
52 throw sol::error("object has been deleted");
53}
54
55inline utils::observer_ptr<region>
56get_object(manager& mgr, const std::variant<std::string, region*>& parent) {
57 return std::visit(
58 [&](const auto& value) -> utils::observer_ptr<region> {
59 using data_type = std::decay_t<decltype(value)>;
60 if constexpr (std::is_same_v<data_type, std::string>) {
61 if (utils::has_no_content(value))
62 return nullptr;
63
64 auto parent_obj = mgr.get_root().get_registry().get_region_by_name(value);
65 if (!parent_obj)
66 throw sol::error("no region with name \"" + value + "\"");
67
68 return parent_obj;
69 } else {
70 return observer_from(value);
71 }
72 },
73 parent);
74}
75
76template<typename T>
77utils::observer_ptr<T> get_object(manager& mgr, const std::variant<std::string, T*>& parent) {
78 return std::visit(
79 [&](const auto& value) -> utils::observer_ptr<T> {
80 using data_type = std::decay_t<decltype(value)>;
81 if constexpr (std::is_same_v<data_type, std::string>) {
82 if (utils::has_no_content(value))
83 return nullptr;
84
85 auto parent_object = mgr.get_root().get_registry().get_region_by_name(value);
86 if (!parent_object)
87 throw sol::error("no region with name \"" + value + "\"");
88
89 auto parent_obj = down_cast<T>(parent_object);
90 if (!parent_obj)
91 throw sol::error(
92 "region \"" + value + "\" is not a " + std::string(T::class_name));
93
94 return parent_obj;
95 } else {
96 return observer_from(value);
97 }
98 },
99 parent);
100}
101
102#if defined(LXGUI_COMPILER_EMSCRIPTEN)
103// Workaround for compiler crash in Emscripten; explicitly convert member
104// function pointers to free functions. sol2 is able to do this automatically,
105// but Emscripten/clang is not happy about it.
106template<typename T, T F>
107struct member_function_holder;
108
109template<typename R, typename T, typename... Args, R (T::*Function)(Args...)>
110struct member_function_holder<R (T::*)(Args...), Function> {
111 static constexpr auto make_free_function() {
112 return [](T& self, Args... args) { return (self.*Function)(std::move(args)...); };
113 }
114};
115
116template<typename R, typename T, typename... Args, R (T::*Function)(Args...) const>
117struct member_function_holder<R (T::*)(Args...) const, Function> {
118 static constexpr auto make_free_function() {
119 return [](const T& self, Args... args) { return (self.*Function)(std::move(args)...); };
120 }
121};
122
123template<auto T>
124constexpr auto member_function() {
125 return member_function_holder<decltype(T), T>::make_free_function();
126}
127#else
128// Simply use the member function pointer directly for all other compilers.
129template<auto T>
130constexpr auto member_function() {
131 return T;
132}
133#endif
134
135template<typename T>
136void region::create_glue_(T& self) {
137 get_lua_().globals()[get_name()] = observer_from(&self);
138}
139
140template<typename T>
141void region::initialize_(T& self, const region_core_attributes& /*attr*/) {
142 if (!is_virtual())
143 create_glue_(self);
144}
145
146template<typename T>
147const std::vector<std::string>& region::get_type_list_impl_() {
148 if constexpr (std::is_same_v<T, region>) {
149 static const std::vector<std::string> type = {region::class_name};
150
151 return type;
152 } else {
153 static const std::vector<std::string> type = []() {
154 using child_base = typename T::base;
155 auto list = get_type_list_impl_<child_base>();
156 list.push_back(T::class_name);
157 return list;
158 }();
159
160 return type;
161 }
162}
163
164} // namespace lxgui::gui
165
166#endif
Manages the user interface.
root & get_root()
Returns the UI root object, which contains root frames.
void create_glue_(T &self)
void initialize_(T &self, const region_core_attributes &attr)
Set up function to call in all derived class constructors.
bool is_virtual() const
Checks if this region is virtual.
const std::string & get_name() const
Returns this region's name.
static const std::vector< std::string > & get_type_list_impl_()
static constexpr const char * class_name
sol::state & get_lua_()
utils::observer_ptr< const region > get_region_by_name(std::string_view name) const
Returns the region associated with the given name.
registry & get_registry()
Returns the UI object registry, which keeps track of all objects in the UI.
Definition gui_root.hpp:261
utils::observer_ptr< ObjectType > observer_from(ObjectType *self)
Obtain an observer pointer from a raw pointer (typically 'this')
utils::observer_ptr< region > get_object(manager &mgr, const std::variant< std::string, region * > &parent)
void sol_lua_check_access(sol::types< T >, lua_State *lua, int index, sol::stack::record &)
constexpr auto member_function()
T & get(variant &value)
Retrieve the value stored in an utils::variant.
Struct holding all the core information about a region necessary for its creation.