templated and custom-named classes support and test
parent
0ddef6ed96
commit
e2402d8bfb
|
@ -142,10 +142,9 @@ struct EngineClassRegistration {
|
|||
#define _GDCLASS_RECREATE(m_class, m_inherits) return nullptr;
|
||||
#endif
|
||||
|
||||
// Use this on top of your own classes.
|
||||
// Note: the trail of `***` is to keep sane diffs in PRs, because clang-format otherwise moves every `\` which makes
|
||||
// every line of the macro different
|
||||
#define GDCLASS(m_class, m_inherits) /***********************************************************************************************************************************************/ \
|
||||
#define GDCLASS_NAME(m_class, m_inherits, m_class_name) /****************************************************************************************************************************/ \
|
||||
private: \
|
||||
void operator=(const m_class &p_rval) {} \
|
||||
friend class ::godot::ClassDB; \
|
||||
|
@ -196,9 +195,9 @@ protected:
|
|||
return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \
|
||||
} \
|
||||
\
|
||||
template <class T, class B> \
|
||||
template <class GODOTCPP_T, class GODOTCPP_B> \
|
||||
static void register_virtuals() { \
|
||||
m_inherits::register_virtuals<T, B>(); \
|
||||
m_inherits::register_virtuals<GODOTCPP_T, GODOTCPP_B>(); \
|
||||
} \
|
||||
\
|
||||
public: \
|
||||
|
@ -218,7 +217,7 @@ public:
|
|||
} \
|
||||
\
|
||||
static ::godot::StringName &get_class_static() { \
|
||||
static ::godot::StringName string_name = ::godot::StringName(#m_class); \
|
||||
static ::godot::StringName string_name = ::godot::StringName(m_class_name); \
|
||||
return string_name; \
|
||||
} \
|
||||
\
|
||||
|
@ -369,6 +368,32 @@ public:
|
|||
\
|
||||
private:
|
||||
|
||||
// Use this on top of your own classes.
|
||||
#define GDCLASS(m_class, m_inherits) GDCLASS_NAME(m_class, m_inherits, #m_class)
|
||||
|
||||
/* Use this to create templated class
|
||||
You need to initialize `static const char *_template_class_name` with custom name
|
||||
outside of class for every template instatiation you use
|
||||
|
||||
Example:
|
||||
|
||||
// in .h:
|
||||
template<class T>
|
||||
class ExampleTemplated : public Object {
|
||||
GDCLASS_TEMPLATED(ExampleTemplated, Object);
|
||||
};
|
||||
|
||||
// in .cpp:
|
||||
template<>
|
||||
const char * ExampleTemplated<int>::_template_class_name = "ExampleTemplatedInt";
|
||||
template<>
|
||||
const char * ExampleTemplated<float>::_template_class_name = "ExampleTemplatedFloat";
|
||||
*/
|
||||
#define GDCLASS_TEMPLATE(m_class, m_inherits) /*************************/ \
|
||||
private: \
|
||||
static const char *_template_class_name; \
|
||||
GDCLASS_NAME(m_class, m_inherits, _template_class_name)
|
||||
|
||||
// Don't use this for your classes, use GDCLASS() instead.
|
||||
#define GDEXTENSION_CLASS_ALIAS(m_class, m_alias_for, m_inherits) /******************************************************************************************************************/ \
|
||||
private: \
|
||||
|
|
|
@ -241,6 +241,10 @@ func _ready():
|
|||
assert_equal(new_example_ref.was_post_initialized(), true)
|
||||
assert_equal(example.test_post_initialize(), true)
|
||||
|
||||
# Check templated classes
|
||||
var i = ExampleTemplatedInt.new()
|
||||
var f = ExampleTemplatedFloat.new()
|
||||
assert_equal(i.get_number() == 42 and is_equal_approx(f.get_number(), 42), true)
|
||||
exit_with_status()
|
||||
|
||||
func _on_Example_custom_signal(signal_name, value):
|
||||
|
|
|
@ -626,3 +626,21 @@ void Example::_input(const Ref<InputEvent> &event) {
|
|||
emit_custom_signal(String("_input: ") + key_event->get_key_label(), key_event->get_unicode());
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
const char *ExampleTemplated<int>::_template_class_name = "ExampleTemplatedInt";
|
||||
template class ExampleTemplated<int>;
|
||||
|
||||
template <>
|
||||
const char *ExampleTemplated<float>::_template_class_name = "ExampleTemplatedFloat";
|
||||
template class ExampleTemplated<float>;
|
||||
|
||||
template <class T>
|
||||
void ExampleTemplated<T>::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_number"), &ExampleTemplated::get_number);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T ExampleTemplated<T>::get_number() {
|
||||
return number;
|
||||
}
|
||||
|
|
|
@ -205,4 +205,20 @@ protected:
|
|||
static void _bind_methods() {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class ExampleTemplated : public Object {
|
||||
GDCLASS_TEMPLATE(ExampleTemplated, Object);
|
||||
|
||||
T number = (T)42;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
T get_number();
|
||||
};
|
||||
|
||||
// To suppress warning: instantiation of variable 'ExampleTemplated<int>::_template_class_name' required here, but no definition is available [-Wundefined-var-template]
|
||||
template <typename T>
|
||||
const char *ExampleTemplated<T>::_template_class_name;
|
||||
|
||||
#endif // EXAMPLE_CLASS_H
|
||||
|
|
|
@ -26,6 +26,9 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
|
|||
ClassDB::register_class<Example>();
|
||||
ClassDB::register_class<ExampleVirtual>(true);
|
||||
ClassDB::register_abstract_class<ExampleAbstract>();
|
||||
|
||||
ClassDB::register_class<ExampleTemplated<int>>();
|
||||
ClassDB::register_class<ExampleTemplated<float>>();
|
||||
}
|
||||
|
||||
void uninitialize_example_module(ModuleInitializationLevel p_level) {
|
||||
|
|
Loading…
Reference in New Issue