@@ -16,6 +16,23 @@ using namespace unrealsdk::unreal;
1616
1717namespace pyunrealsdk ::unreal {
1818
19+ namespace {
20+
21+ /* *
22+ * @brief Gets the ignore struct sentinel.
23+ *
24+ * @return The ignore struct sentinel.
25+ */
26+ py::object get_ignore_struct_sentinel (void ) {
27+ PYBIND11_CONSTINIT static py::gil_safe_call_once_and_store<py::object> storage;
28+ return storage
29+ .call_once_and_store_result (
30+ []() { return py::module_::import (" builtins" ).attr (" object" )(); })
31+ .get_stored ();
32+ }
33+
34+ } // namespace
35+
1936WrappedStruct make_struct (
2037 std::variant<const unrealsdk::unreal::UFunction*, const unrealsdk::unreal::UScriptStruct*> type,
2138 const py::args& args,
@@ -27,7 +44,14 @@ WrappedStruct make_struct(
2744 std::visit ([&struct_type](auto && val) { struct_type = val; }, type);
2845
2946 WrappedStruct new_struct{struct_type};
47+ make_struct (new_struct, args, kwargs);
48+
49+ return new_struct;
50+ }
3051
52+ void make_struct (unrealsdk::unreal::WrappedStruct& out_struct,
53+ const py::args& args,
54+ const py::kwargs& kwargs) {
3155 // Convert the kwarg keys to FNames, to make them case insensitive
3256 // This should also in theory speed up lookups, since hashing is simpler
3357 std::unordered_map<FName, py::object> converted_kwargs{};
@@ -38,15 +62,15 @@ WrappedStruct make_struct(
3862 });
3963
4064 size_t arg_idx = 0 ;
41- for (auto prop : struct_type ->properties ()) {
65+ for (auto prop : out_struct. type ->properties ()) {
4266 if (arg_idx != args.size ()) {
43- py_setattr_direct (prop, reinterpret_cast <uintptr_t >(new_struct .base .get ()),
67+ py_setattr_direct (prop, reinterpret_cast <uintptr_t >(out_struct .base .get ()),
4468 args[arg_idx++]);
4569
4670 if (converted_kwargs.contains (prop->Name )) {
4771 throw py::type_error (
4872 unrealsdk::fmt::format (" {}.__init__() got multiple values for argument '{}'" ,
49- struct_type ->Name , prop->Name ));
73+ out_struct. type ->Name , prop->Name ));
5074 }
5175
5276 continue ;
@@ -56,7 +80,7 @@ WrappedStruct make_struct(
5680 auto iter = converted_kwargs.find (prop->Name );
5781 if (iter != converted_kwargs.end ()) {
5882 // Use extract to also remove the value from the map, so we can ensure it's empty later
59- py_setattr_direct (prop, reinterpret_cast <uintptr_t >(new_struct .base .get ()),
83+ py_setattr_direct (prop, reinterpret_cast <uintptr_t >(out_struct .base .get ()),
6084 converted_kwargs.extract (iter).mapped ());
6185 continue ;
6286 }
@@ -66,15 +90,16 @@ WrappedStruct make_struct(
6690 // Copying python, we only need to warn about one extra kwarg
6791 throw py::type_error (
6892 unrealsdk::fmt::format (" {}.__init__() got an unexpected keyword argument '{}'" ,
69- struct_type ->Name , converted_kwargs.begin ()->first ));
93+ out_struct. type ->Name , converted_kwargs.begin ()->first ));
7094 }
71-
72- return new_struct;
7395}
7496
7597void register_wrapped_struct (py::module_& mod) {
7698 py::class_<WrappedStruct>(mod, " WrappedStruct" )
77- .def (py::init (&make_struct),
99+ .def (py::init ([](std::variant<const unrealsdk::unreal::UFunction*,
100+ const unrealsdk::unreal::UScriptStruct*> type,
101+ const py::args& args,
102+ const py::kwargs& kwargs) { return make_struct (type, args, kwargs); }),
78103 " Creates a new wrapped struct.\n "
79104 " \n "
80105 " Args:\n "
@@ -236,6 +261,12 @@ void register_wrapped_struct(py::module_& mod) {
236261 " Returns:\n "
237262 " This struct's address." )
238263 .def_readwrite (" _type" , &WrappedStruct::type);
264+
265+ mod.attr (" IGNORE_STRUCT" ) = get_ignore_struct_sentinel ();
266+ }
267+
268+ bool is_ignore_struct_sentinel (const py::object& obj) {
269+ return obj.is (get_ignore_struct_sentinel ());
239270}
240271
241272} // namespace pyunrealsdk::unreal
0 commit comments