[C++] How to make setter for Camera* valid to binding in ClassDB?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By MegaGeneral

Hello.
I have custom module which contains class:

class Player : public Spatial

And this contains:

private:
	Camera* _camera;
public:
	Camera* get_camera() const;
	void set_camera(Camera* p_camera);

(it just get/set the camera field)

The binding code:

ClassDB::bind_method(D_METHOD("get_camera"), &Player::get_camera);
ClassDB::bind_method(D_METHOD("set_camera", "camera"), &Player::set_camera);

When i try bind the set_camera method, the engine with module does not compile with error:

C2440
return: ���������� �८�ࠧ����� “const Variant” � “T” godot Q:\Games\GodotProjects\godot-master\core\method_bind.h 65

(debug/win32)

What i am missing?
Thank for help. (And sorry if my english not so good.)

P.S. And other question: what must be implemented for some engine class to can converted to Variant?

:bust_in_silhouette: Reply From: Zylann

I had the same problem: Cannot bind function accepting a `TreeItem*` · Issue #21160 · godotengine/godot · GitHub
Looks like it’s just not possible at the moment. A workaround is to accept Object*, cast it with Object::cast_to and check if the result is not null.

Thank you, it is good idea while we wait for update.
I just do so:

void Player::set_camera(Object* p_camera) 
{ _camera = p_camera ? cast_to<Camera>(p_camera) : nullptr; }

And it working.

MegaGeneral | 2020-03-16 10:34

:bust_in_silhouette: Reply From: marthvon

I suggest using NodePaths or Ref. But using Ref here isn’t really that great since I’m assuming that the camera is inside the tree, so it already exist outside of the class. Only use refs for stuff that doesn’t use the _notification method because if that method is use that means it must have some functions that won’t work outside of the tree. I mean you can probably still attach this Ref<Node> to the tree but I feel like that goes against how you’re suppose to structure your scene trees. The great thing about nodepaths is that when you call it by:

void MyClass::function_that_uses_camera() {
   Camera* camera= Object::cast_to<Camera>(get_node_or_null(MyNodePathCamera));
   if(camera)
      //do stuff here
}

get_node_or_null check if the object still exist inside the ObjectDB. I mean you don’t want to call an object that’s already been deallocated.
also, since you’re using nodepaths you have to check before setting it in your setter that it does point to a Camera Object, otherwise you can create a String warning; variable and override the virtual String get_configuration_warning() const; function to report the warning to the editor.

You can also use emit signals. It depends on what you’re using the Camera for.
You don’t ever use raw pointers when programming in Godot.