Toxin
A Godot Extension Wrapper written in Odin
Install / Use
/learn @Ferinzz/ToxinREADME
Forgive me Odin for I have sinned. Along with the creation of this repo I have summoned the deep inheritance system of a C++ application. Some will be shallow, some will be 7 layers deep. Most will create a system of triple procedure jumps. For that is the nature of interop with a game engine built up using a node system. Although I may have faltered I will not fall. Code which is used for Odin within Odin will remain pure. Standing strong on their own as they proceed through their lifetime within the applications they will reside within. Until the day of Ragnarok where all memory will be wiped.
This repo is to provide a wrapper and userspace in order to work with Godot's API. The goal is to avoid the need to preprocess the code and simply write what you need. The userspace starts at the Toxin package.
It may be better to work with Godot in a different manner. If you'd like to forge your own path you can start from the GD+Classes Package and the GDWrapper layer.
Current features include :
- entry point is included in Toxin package
- MainLoop callbacks initilized and be overridden
- Create custom class
- Create Signals
- Connect to Signals
- Convert to-from Godot's variants
- Define Godot's custom types
- Export class variables as Godot base types
- Parsers to create Builtins and Class files.
- Method Binds to all classes with their call signatures
- stress-tests to verify performance
Feel free to make suggestions
Most examples will not run unless the GDWrapper they were written with is included in their folder.
-Pre-req-
- Godot.
- Ideally compiled for debug mode to allow you to step through the code. (Godot only takes 5-10 minutes to compile.)
- Building Godot will require Python and scons...
- Set the path for Godot in your environment pointing to the compiled executable. In my build script I point to the exe itself because I have 2 versions of Godot... ** Performance is significantly impacted by a debug compilation of Godot.
- Odin-lang
- either run the classes_parser or download the classes package text
Setup
Import the GDWrapper folder into your code as you would any other package. Import the Toxin folder into your code. Import the GD_Classes folder into your code.
Make sure that the version you use is up to date with the version you want to method bind to. I have setup the method binds based on version 4.6.0 There is currently no version check in this package. //TODO: Check Version.
Building
GDExtensions are a shared library with a single exported procedure. Godot will call that procedure and you should provide the pointers to references to the init procedures as well as save the ClassLibrary pointer which Godot shares with you.
- The methods DO change on version changes. If you see a message from Godot stating that there is no fallback method it means that the method's hashid does not match what Godot expects it to be. Open an issue on Godot_Odin_Binds and I will update it.
- If you are not using Toxin you will need to setup your own init procedure. You will need to provide Godot with the name of a proc that it will use as an entry point and set that proc as @(export).
- This you specify in the .gdextension file provided to Godot.
- Compile your Odin code as a dynamic library. Place it somewhere in the Godot project's folder alongside the .gdextension file.
- Make sure the name matches what you specify in the .gdextension file. build.sh and build.cmd script changes the name and then copies it to the correct godot project folder based on what I'm working on. Update as needed.
In addition to the shared lib which you will compile, you will also need to provide Godot with the information about your shared lib in the form of a *.gdextension file. This can (apparently) be placed anywhere in the project file and must include:
- the file name of your GDExtension lib
- the procedure name of the exported procedure
- the types of builds that this extension should be loaded for and the different libs each version should use.
For more details on the *.gdextension file please check the official docs.
https://docs.godotengine.org/en/stable/tutorials/scripting/gdextension/gdextension_file.html
I recommend checking Godot's own documentation if you are trying to understand what methods and classes are needed in Godot in order to achieve a certain result. The c# examples are often fairly close to what you will want to do. It's not a perfect match but it's better than C++ code examples which have a lot of magic behind the steps they take. C++'s extension seems to do a lot of work processing files to add the necessary extra bindings that Godot needs. C# is a bit more direct.
Sometimes it's difficult to find the exact correct page of Godot Docs you want/need so I've done my best to include links to those pages when I remember to. (for example render server doesn't find the page I want but renderingserver does.)
Templates
There is a templates folder which contains the barebones configs to get an extension up and running with a custom class. (excluding the GDWrapper package) If you import Toxin it will already have the main entry configured to initialize GDWrapper as well as the setup for the MainLoop callbacks. The stress-tests are rather simple, so it's good place to check for example code.
Debugger
DEFINITELY get this setup if you're having bugs and don't know why. Stepping through what Godot does is a lot easier to figure out than trying to piece together the five different c++ files required to init one class or variable. Also helps when matching pointer mem locations.
VSCode Setup instructions. Requires building from source : https://godotforums.org/d/32073-debug-c-gdextension/16 (Sia2005's comment adds more context) https://www.reddit.com/r/godot/comments/11d56t1/gdextension_how_to_get_debugger_working_when/
The project includes a .vscode folder which has the current debug launch configs I'm using. There is also build.cmd which has the compilation steps in addition to the steps to rename and move the built shared lib to a corresponding project folder which would be the Godot game project folder.
Debugging will work with Raddebugger
Why so many packages?
To keep myself somewhat sane. There's 1k classes in Godot. Separating those into individual files will mean nesting them all over and extra packages simply to manage the init procedures. That's not where the big work of getting Godot to play nice is.
- gdextension is the core bindings. They don't offer much because Godot does not expose much.
- gdAPI is an organization of those method signatures in order to fetch them. This is still barely anything because most are simply pointers to methods which fetch the correct methods.
- GDWrapper is where things start to take off. It sets up the builtin types and a few core helper functions to allow for simpler fetching of values. StringName compares, StringName creators, a procedure to fetch method binds.
- GD_Classes is just a list of all the classes, their constants, enums and an init procedure to generate all the methods they may or may not have.
- Toxin will be the main userspace. Code there allows an easier way create a custom class, export types, and the entrypoint already setup.
Terminology
Variant. A c++ class which represents a type. Examples are Float, Array, String.
PropertyHint. A combo of enum and string which tells Godot's editor how to handle a property. This does not affect behaviour in the Script.
Node. A 'thing' which can be included in a tree-like structure of inheritance.
Class. An encapsulation of data and procedures. A class exported to Godot to be 'exposed' will be available as a Node in Godot's editor and scripts.
Object. The most rudimentary Class in Godot.
Method. A method will refer to a function which is associated with one of Godot's C++ classes.
Bind. The act of importing or exporting something between the GDExtension library and Godot's.
MethodBind. A class that Godot has created which stores information about a method. This includes parameter info, class, and a pointer to the method. Part of this class handles calling the method.
Extend. Include an additional class into the one you are working with. This will provide access to all the public variables and methods.
Virtual. A Class method which uses data specific to a class instance. Often times these will be called automatically by Godot. For example the _process virtual method.
Signal. An event driven notification system to communicate an event between Nodes.
Connect. The act which sets a Node to listen for an event from a specific Signal.
Reference Count (RefCount). A Class which wraps around another Class in order to count the amount of times the Class has been passed to another Class as a pointer. Once RefCount hits 0 the Class and RefCounter are destroyed. Initializes at 1.
Singleton. A globally available class. Examples are RenderServer, Input, Engine.
Resource. A Class which contains and knows how to manage specific data. This could be a resource from disk or an engine resource such as the body of a physics object.
Resource ID. A runtime identifier to a Resource. This is not a pointer.
Callable. A method or procedure packaged in a struct which can be shared with other Classes at runtime. These callables are most often associated with Signals. There should be enough data on a Callable for Godot to call it.
Server. A system which controls a type of activity such as rendering, sound, etc.
MainLoop. The core loop which will call the servers and trigger the SceneTree.
SceneTree. The main structure which Scenes and Nodes are typically attached to.
GDScript. Godot's own scripting language. These are not compiled unless you turn them into tools.
StringName. A specially hashed string which is refCounted and stored in a its own bucket of memory. Often used as an identifier
Related Skills
node-connect
343.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
92.1kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
343.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
343.3kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
