XUtils

Godot-D

D language bindings for the Godot Engine's GDNative API


Project setup

The easiest way to build your library is to use D’s package/build manager, DUB. Create a DUB project in a file called dub.json in your Godot project folder:

{
	"name": "asteroids-demo",
	"sourcePaths": ["asteroids"],
	"importPaths": ["asteroids"],
	"targetType": "dynamicLibrary",
	"dependencies": {
		"godot-d": "~>0.1.4"
	},
	"preGenerateCommands": [
		"dub run godot-d:pregenerate"
	]
}

Your project will usually be organized like this:

asteroids-demo
├─ project.godot         Godot project
├─ <other Godot assets>
│
├─ addons
│  └─ godot-d-importer   D editor plugin
│
├─ dub.json              DUB project
├─ *.dll / .so           Compiled libraries for each platform
└─ asteroids
   ├─ *.d                D source files
   └─ entrypoint.d       Entry point (auto-generated)

The location of the D source files is up to you. In this example, we use a subfolder with the game’s name to keep them neatly organized, since the file path is used as both the D module name and the Godot resource path.

D native scripts

In Godot, a “script” is an object that exposes methods, properties, and signals to the engine. It is always attached to one of the engine’s own C++ classes, listed in the class reference.
To expose a D class to the engine as a native script, inherit from GodotScript with the Godot class the script should be attached to:

import godot, godot.button;

class TestButton : GodotScript!Button
{
	@Property(Property.Hint.range, "1,10") int number = 9;
	
	@Signal static void function(String message, int num) sendMessage;
	
	@Method void _pressed()
	{
		print("Button was pressed. `number` is currently ", number);
		emitSignal("send_message", "`number` is currently ", number);
	}
	
	...
}

Properties and methods can be exposed to Godot with the Property and Method UDAs. Exposed properties will be saved/loaded along with instances of the class and can be modified in the Godot editor. The optional hint parameter can specify how the editor should treat the property, for example limiting a number to the range 1-10.

Library initialization

Your library needs to expose an entry point through which Godot will load and initialize it:

1: Automatic entry point generator

Add godot-d:pregenerate to your DUB project’s preGenerateCommands:

	"preGenerateCommands": [ "dub run godot-d:pregenerate" ],

The pregenerate tool will create the entry point entrypoint.d in your source directory and a list of script classes in your string import directory (views by default).

Your GDNativeLibrary’s symbol_prefix will be the name of your DUB project, with symbols like - replaced by underscores.

2: Manual entry point mixin

Put the GodotNativeLibrary mixin into one of your files:

import godot.d.register;

mixin GodotNativeLibrary!
(
	// your GDNativeLibrary resource's symbol_prefix
	"platformer",
	
	// a list of all of your script classes
	Player,
	Enemy,
	Level,
	
	// functions to call at initialization and termination (both optional)
	(GodotInitOptions o){ writeln("Library initialized"); },
	(GodotTerminateOptions o){ writeln("Library terminated"); }
);
3: Both

You can manually create the GodotNativeLibrary mixin while still using the pregenerate tool. It will not create a new entrypoint.d if the mixin already exists. You no longer need to list your script classes, but can still use GodotNativeLibrary to configure your library.


Articles

  • coming soon...