Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

can GDVIRTUAL_BIND and GDVIRTUAL_CALL be added to the lib? #1072

Closed
RonYanDaik opened this issue Mar 22, 2023 · 10 comments · Fixed by #1377
Closed

can GDVIRTUAL_BIND and GDVIRTUAL_CALL be added to the lib? #1072

RonYanDaik opened this issue Mar 22, 2023 · 10 comments · Fixed by #1377

Comments

@RonYanDaik
Copy link

Looks like these two macroses are used by godot to call gdscript methods.
Can these two be added into godot-cpp?

@RonYanDaik
Copy link
Author

I see BIND_VIRTUAL_METHOD exists.
Can we somehow use it with custom classes creating custom virtual functions?

@Daylily-Zeleen
Copy link
Contributor

These infomations are added to ClassDB, but not be used in godot editor, I guess.

@RonYanDaik
Copy link
Author

GDCLASS macross has inside it:

template <class T, class B>                                                                                                                                                        \
	static void register_virtuals() {                                                                                                                                                  \
		m_inherits::register_virtuals<T, B>();                                                                                                                                         \
	}      

so you can't add this function in your class to bind your virtuals.
Maybe we can create another macros without declared register_virtuals in it?

@Daylily-Zeleen
Copy link
Contributor

GDCLASS macross has inside it:

template <class T, class B>                                                                                                                                                        \
	static void register_virtuals() {                                                                                                                                                  \
		m_inherits::register_virtuals<T, B>();                                                                                                                                         \
	}      

so you can't add this function in your class to bind your virtuals. Maybe we can create another macros without declared register_virtuals in it?

I'm dont't not the function of this template method.
It seem do nothing form parent class to child class recursively, and just be called after _bind_methods.

Ignoring the call order, for your custom virtual methods, you can bind them in _bind_methods directly.

BIND_VIRTUAL_METHOD call ClassDB::bind_virtual_method

void ClassDB::bind_virtual_method(const StringName &p_class, const StringName &p_method, GDExtensionClassCallVirtual p_call) {
	std::unordered_map<StringName, ClassInfo>::iterator type_it = classes.find(p_class);
	ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(Array::make(p_class)));

	ClassInfo &type = type_it->second;

	ERR_FAIL_COND_MSG(type.method_map.find(p_method) != type.method_map.end(), String("Method '{0}::{1}()' already registered as non-virtual.").format(Array::make(p_class, p_method)));
	ERR_FAIL_COND_MSG(type.virtual_methods.find(p_method) != type.virtual_methods.end(), String("Virtual '{0}::{1}()' method already registered.").format(Array::make(p_class, p_method)));

	type.virtual_methods[p_method] = p_call;
}

As you can see. it is added to virtual_methods, so the infomation of custom virtual methods are existed in ClassDB. Just not be used in Document( to refer) and LSP( to code hint).

Currently, you can use Object::call() instead of GDVIRTUAL_CALL.
I don't know there has a better way or not.

@RonYanDaik
Copy link
Author

Thank you. It does call function in the script.

@RonYanDaik
Copy link
Author

But it turns out than you cant call function ,declared this way, from GDScript. It cant find it.

@Daylily-Zeleen
Copy link
Contributor

But it turns out than you cant call function ,declared this way, from GDScript. It cant find it.

I think you should call call("virtul_method_bind_in_cpp") in GDScript, too.

@Remi123
Copy link

Remi123 commented May 9, 2023

Hi @Daylily-Zeleen @RonYanDaik ,
I need more detail on the workaround you mentioned. I'm want to create a plugin that allows users to override my methods in gdscript, but calling those function in gdextension.

// in gdextension
struct BaseFeature : Resource{ // registered with ClassDB::register_class<BaseFeature >(true); for virtual
GDCLASS(BaseFeature,Resource)
 virtual void my_function() {} // Will be overwrited in gdscript.

 static void _bind_methods(){
  ClassDB::bind_method(D_METHOD("my_function"), &BaseFeature ::my_function); 
}
};

my goal is to have an array of them, and call them like this in gdextension :

      for(auto i = 0; i < array_of_features.size(); ++i )
      {            
          BaseFeature * f = Object::cast_to<BaseFeature >(array_of_features[i]);
          f->my_function(); // Call the overrided function in a gdscript.
       }

For now it only call the base version of the functions, but I created a new resource from a children class.

class_name MyFeature  extends BaseFeature
func my_function(): # I has the sign that it override a function
   print("hello world")

My code is very data intensive, but I would like to override a few functions in gdscript for configuration and let the bulk of the work be done in c++.

Thank you, any help is useful

1 similar comment
@Remi123
Copy link

Remi123 commented May 9, 2023

Hi @Daylily-Zeleen @RonYanDaik ,
I need more detail on the workaround you mentioned. I'm want to create a plugin that allows users to override my methods in gdscript, but calling those function in gdextension.

// in gdextension
struct BaseFeature : Resource{ // registered with ClassDB::register_class<BaseFeature >(true); for virtual
GDCLASS(BaseFeature,Resource)
 virtual void my_function() {} // Will be overwrited in gdscript.

 static void _bind_methods(){
  ClassDB::bind_method(D_METHOD("my_function"), &BaseFeature ::my_function); 
}
};

my goal is to have an array of them, and call them like this in gdextension :

      for(auto i = 0; i < array_of_features.size(); ++i )
      {            
          BaseFeature * f = Object::cast_to<BaseFeature >(array_of_features[i]);
          f->my_function(); // Call the overrided function in a gdscript.
       }

For now it only call the base version of the functions, but I created a new resource from a children class.

class_name MyFeature  extends BaseFeature
func my_function(): # I has the sign that it override a function
   print("hello world")

My code is very data intensive, but I would like to override a few functions in gdscript for configuration and let the bulk of the work be done in c++.

Thank you, any help is useful

@Daylily-Zeleen
Copy link
Contributor

Just use 'call()' both c++ and gds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants