Godot: [GDNative] Cannot instance GDNativeScript using `new`

Created on 17 Apr 2017  路  4Comments  路  Source: godotengine/godot

Godot 3.0 pre-alpha master
Windows 10 64 bits MSVC

I am making an opensimplex GDNative plugin that registers a Noise class inheriting Reference (not a node script, unlike the news shows).
So I compiled my library as a .dll using the C++ kit, and put it in the project with GDNaive libraries as well.

Then I created these resources:
opensimplex.tres, which references my .dll (and other platforms in the future),
noise.gdn, which is a resource referencing the Noise class within my library.

However, the following didn't work:

const OsnNoise = preload("res://addons/zylann.opensimplex/noise.gdn")

func _ready():
    var noise = OsnNoise.new()

Invalid call. Nonexistent function 'new' in base 'GDNativeScript'.

@karroffel told me the new method might indeed be missing.


The following is wrong due to earlier confusion based on a wrong guess.

However, I got confused when I went to create an instance of my class in GDScript. Apparently, as @karroffel told me, the .gdn already is an instance of the Noise class. So getting the instance looks like this:

var noise = load("noise.gdn")

But there are numerous things I find wrong with it:

1) It is inconsistent compared to how GDScript classes usually work. From my experience using GDScript, a .gd file behaves as a Resource containing a class, not an instance. So instancing it actually look like this:

const Klass = preload("klass.gd")
var obj = Klass.new()

And if the Klass inherit a Node, you should get a node instance with the script on it. Same for Resources I guess.

2) It makes class constants harder to access, because they are usually bound as "static" members of the class. However with this you are forced to get the constant from an instance of the class, instead of the class itself. Again, in GDScript, this is how it looks:

const Klass = preload("klass.gd")
print(Klass.SOME_CONSTANT)
# or
print(Mesh.PRIMITIVE_TRIANGLES)

3) Creating an instance from scratch is too complicated, or requires to create a .gdn file which would look like a singleton.
Without a file, this is the code required (pure guess, this code actually doesn't work for some reason, although the same process happens in the editor when creating a .gdn file. @karroffel tell me if I'm wrong on this one):

var noise = GDNativeScript.new()
noise.library = preload("opensimplex.tres")
noise.script_name = "Noise"

What I would expect is for the .gdn file to represent a class, not an instance, and to be able to create instances the following way:

gdscript const Noise = preload("noise.gdn") var noise = Noise.new() ~~

bug gdnative

Most helpful comment

BTW, this could have been workarounded as:

var noise = Reference.new()
noise.set_script(Noise)

All 4 comments

I'm probably wrong about this, never tried it actually 馃槃

@Zylann I think you have a small mistake.
You should use this to create a new instance of the Noise class:

var Noise = GDNativeScript.new()
Noise.library = preload("opensimplex.tres")
Noise.script_name = "Noise"
var noise = Noise.new()

Otherwise, it would be a GDNativeScript rather than a Object or Reference.

And, .gdn files should just contain a GDNativeScript resource (no instances there), so the other one should work fine too:

const Noise = preload("noise.gdn")
var noise = Noise.new()

I might be wrong, but that's how it used to work when I wrote the code (except that there were no static members, but that's a seperate issue I guess).
@Zylann Are you sure you tested this before opening the issue? :smiley:

That's the first thing I tested, and it didn't work. The fact .gdn might be the instance is wrong indeed, that was a guess we both got wrong about, so I'll change the title of the issue to "cannot instance GDNativeScript class. I was told it's because the new implementation is missing :p

BTW, this could have been workarounded as:

var noise = Reference.new()
noise.set_script(Noise)
Was this page helpful?
0 / 5 - 0 ratings