Skip to content

Commit e2402d8

Browse files
author
Vano
committed
templated and custom-named classes support and test
1 parent 0ddef6e commit e2402d8

File tree

5 files changed

+71
-5
lines changed

5 files changed

+71
-5
lines changed

include/godot_cpp/classes/wrapped.hpp

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,9 @@ struct EngineClassRegistration {
142142
#define _GDCLASS_RECREATE(m_class, m_inherits) return nullptr;
143143
#endif
144144

145-
// Use this on top of your own classes.
146145
// Note: the trail of `***` is to keep sane diffs in PRs, because clang-format otherwise moves every `\` which makes
147146
// every line of the macro different
148-
#define GDCLASS(m_class, m_inherits) /***********************************************************************************************************************************************/ \
147+
#define GDCLASS_NAME(m_class, m_inherits, m_class_name) /****************************************************************************************************************************/ \
149148
private: \
150149
void operator=(const m_class &p_rval) {} \
151150
friend class ::godot::ClassDB; \
@@ -196,9 +195,9 @@ protected:
196195
return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \
197196
} \
198197
\
199-
template <class T, class B> \
198+
template <class GODOTCPP_T, class GODOTCPP_B> \
200199
static void register_virtuals() { \
201-
m_inherits::register_virtuals<T, B>(); \
200+
m_inherits::register_virtuals<GODOTCPP_T, GODOTCPP_B>(); \
202201
} \
203202
\
204203
public: \
@@ -218,7 +217,7 @@ public:
218217
} \
219218
\
220219
static ::godot::StringName &get_class_static() { \
221-
static ::godot::StringName string_name = ::godot::StringName(#m_class); \
220+
static ::godot::StringName string_name = ::godot::StringName(m_class_name); \
222221
return string_name; \
223222
} \
224223
\
@@ -369,6 +368,32 @@ public:
369368
\
370369
private:
371370

371+
// Use this on top of your own classes.
372+
#define GDCLASS(m_class, m_inherits) GDCLASS_NAME(m_class, m_inherits, #m_class)
373+
374+
/* Use this to create templated class
375+
You need to initialize `static const char *_template_class_name` with custom name
376+
outside of class for every template instatiation you use
377+
378+
Example:
379+
380+
// in .h:
381+
template<class T>
382+
class ExampleTemplated : public Object {
383+
GDCLASS_TEMPLATED(ExampleTemplated, Object);
384+
};
385+
386+
// in .cpp:
387+
template<>
388+
const char * ExampleTemplated<int>::_template_class_name = "ExampleTemplatedInt";
389+
template<>
390+
const char * ExampleTemplated<float>::_template_class_name = "ExampleTemplatedFloat";
391+
*/
392+
#define GDCLASS_TEMPLATE(m_class, m_inherits) /*************************/ \
393+
private: \
394+
static const char *_template_class_name; \
395+
GDCLASS_NAME(m_class, m_inherits, _template_class_name)
396+
372397
// Don't use this for your classes, use GDCLASS() instead.
373398
#define GDEXTENSION_CLASS_ALIAS(m_class, m_alias_for, m_inherits) /******************************************************************************************************************/ \
374399
private: \

test/project/main.gd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,10 @@ func _ready():
241241
assert_equal(new_example_ref.was_post_initialized(), true)
242242
assert_equal(example.test_post_initialize(), true)
243243

244+
# Check templated classes
245+
var i = ExampleTemplatedInt.new()
246+
var f = ExampleTemplatedFloat.new()
247+
assert_equal(i.get_number() == 42 and is_equal_approx(f.get_number(), 42), true)
244248
exit_with_status()
245249

246250
func _on_Example_custom_signal(signal_name, value):

test/src/example.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,3 +626,21 @@ void Example::_input(const Ref<InputEvent> &event) {
626626
emit_custom_signal(String("_input: ") + key_event->get_key_label(), key_event->get_unicode());
627627
}
628628
}
629+
630+
template <>
631+
const char *ExampleTemplated<int>::_template_class_name = "ExampleTemplatedInt";
632+
template class ExampleTemplated<int>;
633+
634+
template <>
635+
const char *ExampleTemplated<float>::_template_class_name = "ExampleTemplatedFloat";
636+
template class ExampleTemplated<float>;
637+
638+
template <class T>
639+
void ExampleTemplated<T>::_bind_methods() {
640+
ClassDB::bind_method(D_METHOD("get_number"), &ExampleTemplated::get_number);
641+
}
642+
643+
template <class T>
644+
T ExampleTemplated<T>::get_number() {
645+
return number;
646+
}

test/src/example.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,20 @@ class ExampleAbstract : public Object {
205205
static void _bind_methods() {}
206206
};
207207

208+
template <class T>
209+
class ExampleTemplated : public Object {
210+
GDCLASS_TEMPLATE(ExampleTemplated, Object);
211+
212+
T number = (T)42;
213+
214+
protected:
215+
static void _bind_methods();
216+
217+
T get_number();
218+
};
219+
220+
// To suppress warning: instantiation of variable 'ExampleTemplated<int>::_template_class_name' required here, but no definition is available [-Wundefined-var-template]
221+
template <typename T>
222+
const char *ExampleTemplated<T>::_template_class_name;
223+
208224
#endif // EXAMPLE_CLASS_H

test/src/register_types.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
2626
ClassDB::register_class<Example>();
2727
ClassDB::register_class<ExampleVirtual>(true);
2828
ClassDB::register_abstract_class<ExampleAbstract>();
29+
30+
ClassDB::register_class<ExampleTemplated<int>>();
31+
ClassDB::register_class<ExampleTemplated<float>>();
2932
}
3033

3134
void uninitialize_example_module(ModuleInitializationLevel p_level) {

0 commit comments

Comments
 (0)