GDExtension doesn't call methods from @tool script

Godot Version

4.4.1

Question

I’ve written a GDExtension that calculates and returns an Image. While I am able to call this from a script at runtime, when I try to call it from a script with a @tool annotation from within the editor, it fails with the errors like:

ERROR: Cannot call GDExtension method bind 'get_octaves' on placeholder instance.
  ERROR: Cannot call GDExtension method bind 'generate_height_map' on placeholder instance

I would like to use this extension from within the editor so that I can preview the generated images. I thought by changing the initialization level that this might get around this, but I’m still not able to call these methods from inside a @tool script.

Is there any way to do this?

void initialize_example_module(ModuleInitializationLevel p_level) {
	if (p_level != MODULE_INITIALIZATION_LEVEL_CORE) {
//	if (p_level != MODULE_INITIALIZATION_LEVEL_EDITOR) {
//	if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
		return;
	}
...
}

Is the script that you are trying to call also marked with @tool?

See the notice at Running code in the editor — Godot Engine (stable) documentation in English

Any other GDScript that your tool script uses must also be a tool. Any GDScript without @tool used by the editor will act like an empty file!

The only relevant GDScript file is marked with @tool. I’m just extending ImageTexture:

@tool
extends ImageTexture
class_name MyTexture2D

@export var noise_source:WorldSurfaceNoise:
	set(v):
		if v == noise_source:
			return
			
		noise_source = v
		update_image()

@export var image_size:Vector2i = Vector2i(512, 512):
	set(v):
		if v == image_size:
			return
			
		image_size = v
		update_image()
		

func update_image():
	if noise_source:
		#noise_source.octaves
		print("update_image()")
		var octaves:int = noise_source.get_octaves()
		print ("ocatves ", octaves)
		
		var img:Image = noise_source.generate_height_map(image_size, Rect2(0, 0, 1, 1))
		print("img ", img)
		set_image(img)
	pass

How does your extension register the WorldSurfaceNoise class?

According to GDExtension REGISTER_RUNTIME_CLASS - #2 by zoeren :

  • if your class should be active within the editor you should register the class using GDREGISTER_CLASS
  • if you register it using GDREGISTER_RUNTIME_CLASS it will only be active when the game is running
3 Likes