godot-cpp icon indicating copy to clipboard operation
godot-cpp copied to clipboard

not able to pass arguments to object during construction

Open valentinAlkan opened this issue 2 years ago • 8 comments

Unless I'm mistaken, it appears to not be possible to pass arguments to a constructor (new/_init) from gdscript.

one would think you could bind _init and pass arguments to new() from GDscript but that does not seem to be the case.

This is kind of a big deal since it breaks RAII which is one of the most fundamental features of C++. Having to call a function after a class is built, or it is malformed, is not good.

If this is currently possible, it should be added to the example as it will be used by nearly everyone who uses c++.

valentinAlkan avatar Dec 07 '22 18:12 valentinAlkan

Related to https://github.com/godotengine/godot-proposals/issues/1513.

Which Godot version are you using? Which class is your extension extending from?

Calinou avatar Dec 07 '22 19:12 Calinou

Godot v4 Beta7 (godot-cpp f1d501f)

Extending from Node.

Using this code, which compiles and links perfectly:

class TileDataInterface : public godot::Node {
    GDCLASS(TileDataInterface, godot::Node)

protected:
    static void _bind_methods();
    TileData* tileData = nullptr;

public:
    TileDataInterface(){};
    ~TileDataInterface(){};
    void _init(int id, int tileType);
};
void TileDataInterface::_bind_methods(){
    ClassDB::bind_method(D_METHOD("_init", "a", "b"), &TileDataInterface::_init, DEFVAL(0), DEFVAL(0));
}

void TileDataInterface::_init(int id, int tileType){
    tileData = new TileData((TileId)id, (TileType)tileType);
}

produces this error in GDScript

var data = TileDataInterface.new(0, 0)

Too many arguments for "new()" call. Expected at most 0 but received 2.

valentinAlkan avatar Dec 08 '22 02:12 valentinAlkan

Still not possible. It would be useful in some cases.

DmitriySalnikov avatar Aug 04 '23 06:08 DmitriySalnikov

I am curious, what if you declared the TileDataInterface class with two constructors, making one private, i.e.:

private:
  TileDataInterface() {}
public:
  TileDataInterface(int id, int tileType) 

In this case, drop the _init method in favor of the class' ctor, does that work?

Naros avatar Nov 01 '23 18:11 Naros

Is this possible yet with GDExtensions or not?

voylin avatar Apr 10 '24 09:04 voylin

No, it's still not possible.

Side note: Is this even possible for classes added in Godot modules? The only classes I can think of with proper constructors are variant types, like Vector3(), etc, but I haven't gone digging into the code yet.

dsnopek avatar Apr 10 '24 12:04 dsnopek

Side note: Is this even possible for classes added in Godot modules?

Yes, see Label for an example:

memnew(Label("Hello world!"))

However, these (optional) parameters can't be exposed for nodes in the scripting API.

Calinou avatar Apr 16 '24 01:04 Calinou