Coder Social home page Coder Social logo

godot-rust / gdext Goto Github PK

View Code? Open in Web Editor NEW
2.5K 2.5K 157.0 4.12 MB

Rust bindings for Godot 4

Home Page: https://mastodon.gamedev.place/@GodotRust

License: Mozilla Public License 2.0

GDScript 1.40% Rust 98.21% Shell 0.39%
game-development gamedev godot rust

gdext's Introduction

GDNative bindings for Rust

crates.io stable docs master docs book website

godot-rust is a Rust library that implements native bindings for the Godot game engine. This allows you to develop games or other applications in Godot, while benefiting from Rust's strengths, such as its type system, scalability and performance.

Note: if you are looking for a Rust binding for GDExtension (Godot 4), checkout gdext.

Maintenance Policy

gdnative is considered mostly feature complete, and is maintained with a focus on API stability. We try to avoid unnecessary breaking changes, and try to limit their end-user impact to a minimum whenever we have to make them.

We adhere to Cargo's semantic versioning as the means to convey changes in the public API between versions. Future releases are planned publicly on GitHub, with the milestone feature. Note that we use the breaking-change label to indicate the existence of any technical breakage, regardless of the expected impact on end user programs.

If you are looking to contribute, but are not sure if what you want to do falls in the scope of the project and is permitted by our maintenance policy, feel free to get in touch with the project maintainers before you start.

Toolchain compatibility

gdnative currently has a minimum supported Rust version (MSRV) of 1.70. We use the Rust 2021 Edition.

Warning: Linux users: Be aware of the source of your Godot binary! Binary distributions of Godot using a container-based format may ship versions of dependencies that may not be compatible with GDNative libraries built directly from your base system. Examples of such formats include Flatpak, Snap, and AppImage.

As of 2023, some package managers might silently install one of these instead of a normal package when Godot is requested, which can then cause bizarre compatibility issues with your GDNative libraries. We recommend using the official binaries from godotengine.org for both the editor and the export templates.

Due to GDNative API not strictly following SemVer and some concepts not mapping 1:1 to Rust (default parameters), it is difficult for a godot-rust version to remain compatible with multiple Godot versions simultaneously.

However, we support the latest stable Godot 3 minor release out-of-the-box, and allow to easily use custom engine versions using the custom-godot feature flag (see below).

Compatibility list:

  • Godot 3.5.1 (works with gdnative 0.11)
  • Godot 3.4 (works with gdnative 0.10, custom build for 0.11)
  • Godot 3.3 (custom build)
  • Godot 3.2 (custom build)

The bindings do not support Godot 4. If you are looking for a Rust binding for GDExtension (Godot 4), checkout gdextension.

Getting started

Detailed setup is explained in the Getting Started section of the book. In case of problems, consider also reading the FAQ.

Latest released version

This is the recommended way of using godot-rust. After bindgen dependencies and a current Godot version are installed, add the gdnative crate as a dependency, and set the crate type to cdylib:

[dependencies]
gdnative = "0.11"

[lib]
crate-type = ["cdylib"]

Latest GitHub version

If you would like to benefit from cutting-edge features and bugfixes, you can use the GitHub version. We have a relatively sophisticated CI and test suite for basic stability, but the GitHub version is typically more experimental and less battle-tested than a crates.io release. We also do not guarantee any SemVer compatibility here.

[dependencies]
gdnative = { git = "https://github.com/godot-rust/godot-rust.git" }

[lib]
crate-type = ["cdylib"]

Custom builds

To use the bindings with a different Godot version or a custom build of the engine, see Custom Godot builds in the user guide.

Async/yield support

Async support is a work-in-progress, with a low-level API available in gdnative::tasks, if the async feature is enabled on gdnative. See this page in the book for an introduction to use the async feature with Tokio.

Example

A typical use case is to expose your own Native Class, a Rust API that can be invoked from the Godot engine. The resulting native script can be attached to the scene tree, just like GDScript (.gd files).

This happens via dynamic libraries and the GDNative interface, which will be loaded from Godot. The necessary wiring is done behind the scenes by godot-rust. A simple "Hello world" application could look like this:

use gdnative::prelude::*;

#[derive(NativeClass)]
#[inherit(Node)]
pub struct HelloWorld;

#[methods]
impl HelloWorld {
    fn new(_base: &Node) -> Self {
        HelloWorld
    }

    #[method]
    fn _ready(&self, #[base] _base: &Node) {
        godot_print!("Hello, world.");
    }
}

fn init(handle: InitHandle) {
    handle.add_class::<HelloWorld>();
}

godot_init!(init);

Further examples

Important note:

To run or edit an example, you need to build the native library for it first. Otherwise, the project will be broken. You can do so manually with cargo build, or use the example.sh shell script for convenience: ./example.sh run hello-world or ./example.sh edit hello-world for the editor.

The /examples directory contains several ready to use examples, complete with Godot projects and setup for easy compilation from Cargo:

At startup, the Godot editor tries to load all resources used by the project, including the native library. If the latter isn't present, the editor will skip properties or signals associated with the missing native scripts in the scene. This causes the scene tree to be non-functional for any sample that relies on properties or signals configured in the editor.

Third-party projects

To see a list of games and integrations developed on top of godot-rust, have a look at our list of third-party projects in the book.

Contributing

See the contribution guidelines.

License

Any contribution submitted for inclusion in the work by you shall be licensed under the MIT license, without any additional terms or conditions.

gdext's People

Contributors

0awful avatar bors[bot] avatar bromeon avatar cuddlefishie avatar dataphract avatar gg-yb avatar henrywconklin avatar jrockett6 avatar juliohq avatar kkolyan avatar kuruk-mm avatar lamby777 avatar leaoluciano avatar lemiczek avatar lilizoey avatar mercerenies avatar mhoff12358 avatar mio991 avatar pgbiel avatar realastolfo avatar statismike avatar t4rmin avatar tcroc avatar titannano avatar ttencate avatar vortexofdoom avatar waridley avatar winstonhartnett avatar yannick-was-taken avatar you-win avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gdext's Issues

Attaching a Rust script to nodes of different types

I'm working on a planet-scale game, for which Godot's 32-bit Vector3 type is not precise enough. (I know about precision=double but it's pretty new, so I don't want to rely on it yet.)

The way I can deal with this is Godot 3 using GDNative is, I create a native Transform64 class in Rust that contains the transform in 64-bit precision. In Transform64::_process, it will call set_transform() on its base node with the latest transform, suitably shifted to some origin that is close to the player before rounding to 32-bits. Transform64 also offers an API containing e.g. distance64(other: Transform64): float.

The key here is that Transform64 can be added to any node that inherits from Spatial. It could be a RigidBody, a Camera or Spatial itself. Essentially it acts as a mixin. Presumably, I can also inherit GDScripts from it, so I can write the higher-level functionality in GDScript (but I haven't tried this).

This doesn't seem to be so easy to do with GDExtension. My current workaround is to inherit Transform64 from Node and add it as a child on any Spatial-derived node, reaching up with get_parent() to set the transform. The drawback is that distance64() and all the other methods can't be called on the root of the scene anymore, because it now lives in a child node. I have to write self.transform64.distance64(other.transform64) instead of simply self.distance64(other).

According to this comment, it should already be possible to create your own scripting language, so maybe that API could be used to make certain Rust classes "act" like a script.

Static methods in Godot API

Some Godot types are only constructible through static factory methods, e.g. DirAccess.open().

We could provide a method without self parameter, possibly reusing the singleton functionality.

let dir: Gd<DirAccess> = DirAccess::open("path".into());

We could in a later step also consider static user-provided methods (#[func]), in case GDExtension allows that.

Does not work on Godot 4 beta 5 (but does with beta4)

Hey, first, just wanted to say this is an amazing project, thank you for doing this!

I just started looking at the project yesterday and was able to get my extension to compile and imported into Godot 4 beta 5 with this

use godot::prelude::*;

struct MyProject;

#[gdextension]
unsafe impl ExtensionLibrary for MyProject {}

However, once I added my first struct it caused Godot to crash

use godot::engine::Control;
use godot::prelude::*;

#[derive(GodotClass)]
#[class(base = Control)]
pub struct MainMenu {
    #[base]
    base: Base<Control>,
}

#[godot_api]
impl MainMenu {
}

I tried downloading the example and got the same results. I downgraded to beta 4 and both the example and my code ran ok. (Again, love how this works, seeing my MainMenu type in Godot was a thrill)

Other pertinent info is I'm running this on macos x86_64 (sorry I can't help with the mac arm64 question in #21)

Utilities to work with the node tree

Similar to the old NodeResolveExt, utility methods would allow more idiomatic access to the scene tree.
Those could be provided as an extension trait or in a dedicated module/struct.

Examples:

  • get_node<T>
  • find_node<T> (optional) -- implemented as try_get_node
  • load<T>
  • PackedScene::instance<T>

Project status overview

This issue gives a broad overview over features that are already implemented, those that aren't, and links to the respective issues.

See also: blog post about 2023 achievements ๐Ÿš€

This list is not going into too much detail; for that, consult the issue tracker. It focuses on features only, while bugfixes, refactors, documentation and other quality-of-life improvements are omitted. This is meant to be a read-only issue; for questions, contact us on Discord.

Please note that the GDExtension port for Rust is still early-stage. In general, if you think something is not yet implemented, it likely isn't ๐Ÿ™‚

Legend

๐ŸŒ‘ -- not available
๐Ÿš -- very early-stage, barely usable
๐Ÿšง -- in development
๐ŸŒฒ -- somewhat usable (doesn't mean finished, and API likely still changes)

Built-in types

See also #310

ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  Feature ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  Status Issue PRs
Scalars (i64, bool, ...) ๐ŸŒฒ
User objects ๐ŸŒฒ
Engine objects ๐ŸŒฒ
String, StringName ๐Ÿšง
Variant ๐ŸŒฒ
Arrays ๐ŸŒฒ #33 #85 #101
Packed arrays ๐ŸŒฒ #6 #91
Dictionaries ๐ŸŒฒ #6 #92 #99
Vectors ๐ŸŒฒ #6 #71 #67
Matrix types ๐ŸŒฒ #124
Geometric types ๐Ÿšง #209 #180 #218
Quaternions ๐ŸŒฒ #68
Color ๐ŸŒฒ #123
Callable ๐Ÿšง #6 #231
Signal ๐Ÿš #8
Rid ๐ŸŒฒ #102 #171

Registration (export Rust to GDScript)

ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  Feature ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  Status Issue PRs
Classes ๐ŸŒฒ
Functions ๐ŸŒฒ
Properties ๐ŸŒฒ #3 #31 #147 #177 #198
Signals ๐Ÿšง #8 #279
Enums ๐ŸŒฒ #7 #371
Builder API ๐ŸŒ‘ #4
Docs visible in Godot ๐ŸŒ‘ #178
Virtual Methods (_ready, ...) ๐ŸŒฒ #191 #136 #207 #223
Script virtual methods (Rust based) ๐ŸŒฒ #606
@onready support ๐Ÿšง #130 #534

Engine interaction (call Godot from Rust)

ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  Feature ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  Status Issue PRs
Printing ๐ŸŒฒ
Variant conversions ๐ŸŒฒ #452 #421
Object FFI ๐ŸŒฒ #156
Class method calls ๐ŸŒฒ
Static method calls ๐ŸŒฒ #43
Utility method calls ๐ŸŒฒ #382
Property access ๐ŸŒ‘
Constants ๐ŸŒฒ
Enums + bitfields ๐Ÿšง #185
Double precision ๐ŸŒฒ #149
Copy Godot docs ๐ŸŒ‘

Platform support

ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  Feature ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  Status Issue PRs
Linux ๐ŸŒฒ
Windows ๐ŸŒฒ
macOS ๐ŸŒฒ
Android ๐ŸŒ‘ #470
iOS ๐ŸŒ‘ #498
WebAssembly ๐Ÿš #438 #493

Builder API to register classes, functions, properties, signals

Functionality that is currently available through proc-macros should ideally be exposed in a programmatic builder API, too.

Some challenges:

  • The proc-macros combined with the plugin system detect very fine-grained customization, e.g. every single method in GodotExt.
    • This would have to be manually annotated in a builder, possibly using static type information (generic arguments).
  • Some of the traits and functions generated by proc-macros are internal.
    • The builder API could be more high-level and stable.
  • Functions are rather verbose to register through builders, with generic-tuples. Think about ways to provide a simple interface.
    • In GDNative, this was done via Method trait, which is very flexible and general, but required full implementation for every single type. This might serve as a basis, with more higher-level concretizations.

Rust compilation requires Godot editor restart

Upstream issue: godotengine/godot#66231

On Windows, the Godot editor "locks" a DLL containing a GDExtension library and releases it only after shutdown. Native code can thus not be recompiled as long as the editor remains open. Behavior on Linux and Mac is unclear (please let me know about your experiences).

This is a considerable limitation for game developers using GDExtension. Requiring the user to reload the editor on every change not only makes a very common workflow impossible, but is also a regression from GDNative, where reloading (for non-tool classes) could be achieved while the editor was out of focus -- even if it had its bugs.

We depend on Godot to provide a mechanism that allows dynamic libraries to be recompiled. Even without a full-featured hot reloading, a bit part of the problem could be alleviated by using the recompiled dynamic library for the launched application (not in-editor).

Array Functions(new and append)

Hi there,

In the spirit of starting a discussion first rather than just implementing(potentially the wrong thing), I'm sharing my progress in this issue.

I started using the port and realized that Arrays are not complete. So I took a stab at implementing a ::new function and this is what I got so far:

    pub fn new() -> Array {
        // For now, this unnit business seems to be required. But I'd like to study it more
        //and really understand what it does.
        let mut uninit = std::mem::MaybeUninit::<Array>::uninit();
        unsafe {
            let self_ptr = (*uninit.as_mut_ptr()).sys_mut();
            let ctor = sys::method_table().array_construct_default;
            ctor(self_ptr, std::ptr::null_mut());

            uninit.assume_init()
        }
    }

This seems to work from GdScript.

From Rust code I'm sticking to the following pattern(not sure if this is the best way of doing this):

let mut points = Array::new();
let v = Vector2Array::from(&points);

Ok, so we can create an empty array. So the next question is how do we append items to it? I thought that I might be able to do something like the following:

    pub fn append(&mut self, v: Vector2) -> () {
        unsafe {
            let class_name = StringName::from("PackedVector2Array");
            let method_name = StringName::from("append");
            let method_bind = {
                unsafe {
                    ::godot_ffi::get_interface()
                        .classdb_get_method_bind
                        .unwrap_unchecked()
                }
            }(
                class_name.string_sys(),
                method_name.string_sys(),
                4188891560i64,
            );
            let call_fn = {
                unsafe {
                    ::godot_ffi::get_interface()
                        .object_method_bind_ptrcall
                        .unwrap_unchecked()
                }
            };
            let args = [
                <Vector2 as sys::GodotFfi>::sys(&v),
            ];
            let args_ptr = args.as_ptr();
            <Vector2Array as sys::GodotFfi>::from_sys_init(|return_ptr| {
                call_fn(method_bind, self.sys() as GDNativeObjectPtr, args_ptr, return_ptr);
            });

        }
    }

But it looks like ClassDB does not have "non-Node" classes such as Arrays? So I can't really just reach out to the engine and have it "append" something for me.

Or am I wrong about that?
Is there a way to call the append/push_back functions from Rust at the moment? It seems like Rust GDNative did something similar with the godot_pool_vector2_array_append_array family of functions? But there might be something else going in the case of GDNative that I don't know since these are new APIs to me.

Hope this is clear enough.

Thanks in advance.

Editor crashes while loading gdextension

I'm trying to get a basic Hello World sort of extension running, but I'm getting this error when launching my project from 4.0.beta5.official.89a33d28f.

Initialize GDExtension interface: Godot Engine v4.0.beta5.official
ERROR: Index p_constructor = 6 is out of bounds ((int)construct_data[p_type].size() = 6).
   at: get_ptr_constructor (core/variant/variant_construct.cpp:298)
thread '<unnamed>' panicked at 'failed to load GDExtension function `quaternion_from_euler_yxz`', /home/fp/.cargo/git/checkouts/gdextension-25c68fb170a9fb9d/522dda7/godot-ffi/../target/godot-gen/sys/central.rs:1:54858
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 5

I do not get this error with the same project on godot 4.0.beta.custom_build.01ae26d31 (the same commit as beta 4). However, this build doesn't seem to actually load the extension.

I have the same <extension>.gdextension, extension_list.cfg, and lib.rs with the exception of different names for the stuff that's mine and I've flattened the project structure so there's no godot/ or rust folders, e.g. cargo.toml and godot.project are in the same directory. I've changed all the relevant paths in the previously mentioned files to reflect this.

I reckon I must be doing something wrong, but as far as I can see from the instructions, I can't find what.

Building with Docker

Hi there,

Thanks a lot for the wonderful rust port! Have been poking around with it and everything worked fine; was able to build and run it in godot4. Then I tried building inside docker and got the following error:

lgomez@de48fee90037:~/rsty_physics$ GODOT4_BIN=/home/lgomez/Godot_v4.0-beta6_linux.x86_64 cargo build
   Compiling proc-macro2 v1.0.47
   Compiling unicode-ident v1.0.5
   Compiling quote v1.0.21
   Compiling libc v0.2.137
   Compiling glob v0.3.0
   Compiling memchr v2.5.0
   Compiling minimal-lexical v0.2.1
   Compiling regex-syntax v0.6.28
   Compiling nanoserde-derive v0.1.19
   Compiling either v1.8.0
   Compiling bindgen v0.60.1
   Compiling bitflags v1.3.2
   Compiling rustc-hash v1.1.0
   Compiling lazycell v1.3.0
   Compiling peeking_take_while v0.1.2
   Compiling shlex v1.1.0
   Compiling lazy_static v1.4.0
   Compiling paste v1.0.9
   Compiling glam v0.22.0
   Compiling once_cell v1.16.0
   Compiling clang-sys v1.4.0
   Compiling nanoserde v0.1.32
   Compiling nom v7.1.1
   Compiling venial v0.5.0
   Compiling which v4.3.0
   Compiling godot-macros v0.1.0 (https://github.com/godot-rust/gdextension?branch=master#5a8a0007)
   Compiling regex v1.7.0
   Compiling godot-codegen v0.1.0 (https://github.com/godot-rust/gdextension?branch=master#5a8a0007)
   Compiling cexpr v0.6.0
   Compiling godot-ffi v0.1.0 (https://github.com/godot-rust/gdextension?branch=master#5a8a0007)
error: failed to run custom build command for `godot-ffi v0.1.0 (https://github.com/godot-rust/gdextension?branch=master#5a8a0007)`

Caused by:
  process didn't exit successfully: `/home/lgomez/rsty_physics/target/debug/build/godot-ffi-73a26c1996e8846a/build-script-build` (exit status: 101)
  --- stdout
  cargo:rerun-if-changed=../godot-codegen/input/gdnative_interface.h
  cargo:rerun-if-changed=/usr/lib/llvm-11/lib/clang/11.0.1/include/stddef.h
  cargo:rerun-if-changed=/usr/lib/llvm-11/lib/clang/11.0.1/include/__stddef_max_align_t.h
  cargo:rerun-if-changed=/usr/lib/llvm-11/lib/clang/11.0.1/include/stdint.h
  cargo:rerun-if-changed=/usr/include/stdint.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/libc-header-start.h
  cargo:rerun-if-changed=/usr/include/features.h
  cargo:rerun-if-changed=/usr/include/stdc-predef.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/sys/cdefs.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/wordsize.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/long-double.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/gnu/stubs.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/gnu/stubs-64.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types.h
  cargo:rerun-if-changed=/usr/include/features.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/wordsize.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/timesize.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/typesizes.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/time64.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/wchar.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/wordsize.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/stdint-intn.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/stdint-uintn.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types.h
  cargo:rerun-if-changed=/usr/include/stdio.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/libc-header-start.h
  cargo:rerun-if-changed=/usr/include/features.h
  cargo:rerun-if-changed=/usr/lib/llvm-11/lib/clang/11.0.1/include/stddef.h
  cargo:rerun-if-changed=/usr/lib/llvm-11/lib/clang/11.0.1/include/stdarg.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types/__FILE.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types/FILE.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/types.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/stdio_lim.h
  cargo:rerun-if-changed=/usr/include/x86_64-linux-gnu/bits/sys_errlist.h
  cargo:rerun-if-changed=/home/lgomez/.cargo/git/checkouts/gdextension-25c68fb170a9fb9d/5a8a000/godot-codegen/input/gen/extension_api.json
  Found GODOT4_BIN with path to executable: '/home/lgomez/Godot_v4.0-beta6_linux.x86_64'
  cargo:rerun-if-changed=/home/lgomez/Godot_v4.0-beta6_linux.x86_64
  cargo:rerun-if-changed=/home/lgomez/.cargo/git/checkouts/gdextension-25c68fb170a9fb9d/5a8a000/godot-codegen/input/gen/godot_version.txt
  Godot version: 

  --- stderr
  Build selected for Linux/Windows.
  thread 'main' panicked at 'failed to parse Godot version '': Regex capture failed', /home/lgomez/.cargo/git/checkouts/gdextension-25c68fb170a9fb9d/5a8a000/godot-codegen/src/godot_exe.rs:84:13
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Dockerfile:

FROM rust:1.64
RUN apt update &&  \
    apt-get -y install clang && \
    apt-get -y install libclang-dev && \
    apt-get install -y llvm && \
    apt-get install -y sudo

RUN useradd -ms /bin/bash -G sudo lgomez
USER lgomez
WORKDIR /home/lgomez
COPY --chown=lgomez:lgomez . /home/lgomez
RUN rustup component add rustfmt
RUN rustfmt --check /home/lgomez/rsty_physics/src/*.rs
RUN cd /home/lgomez/ && wget https://downloads.tuxfamily.org/godotengine/4.0/beta6/Godot_v4.0-beta6_linux.x86_64.zip  \
    && unzip Godot_v4.0-beta6_linux.x86_64.zip
#These might be useful for wasm deployments in the future.
#RUN rustup target add wasm32-unknown-unknown
#RUN cargo install trunk
RUN cd /home/lgomez/rsty_physics && cargo clean && GODOT4_BIN=/home/lgomez/Godot_v4.0-beta6_linux.x86_64 cargo build

Cargo.toml:

[package]
name = "rsty_physics"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]


# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
godot = { git = "https://github.com/godot-rust/gdextension", branch = "master" , features = ["minimal"]}

I've tried comparing my host environment to the docker environment and can't seem to crack it.

Any ideas?

Thanks in advance.

Cheers,
Lorenzo

Implement core types

Core structs (GodotString, Vector2, Vector3 etc.) are currently stubs that lack functionality.

To make them useful, expose (parts of) the Godot API via Rust methods.
Several options:

  1. Call Godot equivalents through FFI (slower and less idiomatic, but automatable and fast to implement)
  2. Implement them in Rust (for geometric primitives)
  3. Reuse implementation from GDNative-Rust (needs author permission for license)

Dictionary support

Like #33, but for Dictionary instead of Array.

The challenge will be to find an idiomatic API in Rust (similar to HashMap) while also providing Godot features.
This will need some up-front design before jumping into implementation.

Godot artifacts cannot be downloaded from pull requests

Example: PR #13, CI run 3405280647

Downloading artifacts from other repositories requires a personal access token (PAT), which I have supplied for gdextension as a secret. However, security policy disallows access to secrets from pull requests by non-collaborators, so this PAT cannot be read if someone opens a PR, and thus the artifact download and integration test simply fails.

GitHub doesn't seem to be willing to make artifacts accessible without authentication (see actions/upload-artifact#51), as such we need a way to work around this.

https://nightly.link/ looks like a promising solution. This might even remove the need for dawidd6/action-download-artifact as a GitHub action to pull artifacts.

Feature Request: Abstractable Types for unit testing

One of the big reasons to choose Rust for game dev is its incredibly good built in testing tools.

Currently, the way that we wire custom classes, its not possible to write unit tests as the struct depends on the godot engine being present.

Take this overly simplified class:

#[derive(GodotClass, Debug)]
#[class(base = Node)]
pub struct AppState<'b> {
    #[base]
    base: Base<Node>,
    // some other fields
}

#[godot_api]
impl AppState {
    #[signal]
    fn paused();

    #[func]
    pub fn pause(&mut self) {
        // some other logic
        self.base.emit_signal("paused".into(), &[]);
    }
}

You might want to check that the logic in pause works and that emit_signal was called with paused as a parameter.

One way we could do this is by passing AppState a version of Base that stores what signals have been called:

#[cfg(test)]
mod tests {
    use super::*;

    // todo
    #[test]
    fn test_app_can_be_paused() {
        let base = InMemoryBase::new();
        {
            let mut app_state = AppState::new(&mut base);
            app_state.pause()
        }
        assert!(base.get_signals().contains("paused")); 
    }
}

I've tried a few of the suggestions for abstraction to allow my core logic to be tested but largely means writing a second struct with the same function names and then just having one call the other, meaning not only is it a lot of extra work to do this, but still leaves large parts of the code untestable, not to mention things like signals which can't be called from the other structs. For things like AppState it really doesn't make sense to have separate logic as all its doing is managing the changing of state and allowing other things to query the state so there's no way for me to test it.

I would love to help on this, but don't really know where to start in the codebase. It seems like we'd have to make a Trait around godot::engine::Object, then somehow allow Custom Class's to take other things that impl that trait without breaking the custom macro's ability to wire the struct.

I'm sure there are other ways to get the same results too.

Thoughts?

Custom GodotClass construction impossible, due to interaction between Gd::new and base fields

We'd like to figure out how to handle custom construction of a GodotClass that requires access to the base object. Currently, it's unclear how the base field should be populated on the Rust side:

#[derive(GodotClass)]
#[class(base=Reference)]
pub struct Thing {
    // We need this to we available at all times, and do not want to write a lot of `unwrap`s
    pub options: Options,

    #[base]
    base: Base<Reference>,
}

#[derive(FromVariant)]
pub struct Options {
    // Imagine that this is something you can't default construct, and don't want to clone/drop either
    pub very_important_number: Box<i32>,
}

#[derive(GodotClass)]
#[class(base=Reference)]
pub struct ThingFactory {
    #[base]
    base: Base<Reference>,
}


#[godot_api]
impl Thing {
    #[func]
    fn do_stuff(&self) {
        do_stuff_with(&self.options) // No `unwrap` necessary
    }
}

#[godot_api]
impl ThingFactory {
    #[func]
    fn create_thing(&self, options: Options) -> Gd<Thing> {
        Gd::new(Thing {
            options,
            base: todo!("what goes in here?"),
        })
    }
}

Bromeon mentioned on Discord that it could be an option to allow Option<Base<T>> for the base field. It's also possible to move the base pointer into the argument position instead.

Detected GDExtension class but not allowing it to be extended.

Disclaimer: I don't know if this is a rust gdextension issue, or godot issue, so Ill post it on both

In this repo, the ArtistCredit script along with other scripts have compiled successfully.

The thing is, I cannot extend the node off like this, because it doesn't exist.
image

So I decided to see if I can extend it via a script. They are detected in Godot as valid classes to extend off of.
image

But then hell breaks loose, because it now says its invalid.
image

Pre-generate bindgen file

Bindgen not only adds a ton of dependencies that slow down initial compilation, but it is regularly an obstacle for users to get started, because they don't have LLVM installed or correctly configured.

We could generate the bindings Rust file on developer machines and ship it. CI could be used to enforce that bindings are up-to-date.

If it turns out that different platforms have different binding files, conditional compilation is an option. Would add a bit of development of maintenance effort, but probably worth the easier and faster setup process for everyone.

Godot passes an Object Variant with a null value when clearing Object subclass properties

Given an exported property like this:

#[export(
    getter = "get_building_pattern",
    setter = "set_building_pattern",
    variant_type = "::godot::sys::VariantType::Object"
)]
building_pattern: Option<Gd<TileMapPattern>>,

with a setter like this:

#[func]
pub fn set_building_pattern(&mut self, value: Variant) {
    let converted: Result<Gd<TileMapPattern>, VariantConversionError> = value.try_to();
}

This will crash during try_to because it creates a Gd with the null pointer inside it and then it calls ready on it.

Signals

See how we can support signal registration, in the builder API and/or proc-macros.

Documentation for often-used APIs

Several APIs are currently undocumented. We should prioritize symbols which will definitely be manually maintained (e.g. geometric types in godot::builtin might get some docs from Godot later).

Examples:

  • godot::log
  • godot::bind -- maybe provide small usage examples of the proc-macros
  • select types from godot::builtin
    • Variant
    • Array
    • Dictionary
    • Signal
    • Callable

Generated `new()` function collides with `CSharpScript::new()`

   Compiling godot-core v0.1.0 (https://github.com/godot-rust/gdextension?branch=master#6d0507e8)
error[E0201]: duplicate definitions with name `new`:
 --> /home/coder2195/.cargo/git/checkouts/gdextension-25c68fb170a9fb9d/6d0507e/godot-core/src/gen/classes/csharp_script.rs:1:530
  |
1 | ... { pub fn new () -> Gd < Self > { unsafe { let __class_name = StringName :: from ("CSharpScript") ; let __object_ptr = sys :: interface_fn ! (classdb_construct_object) (__class_name . string_sys ()) ; Gd :: from_obj_sys (__object_ptr) } } pub fn new (& mut self , varargs : & [Variant]) -> Variant { unsafe { let __class_name = StringName :: from ("CSharpScript") ; let __method_name = StringName :: from ("new") ; let __method_bind = sys :: interface_fn ! (classdb_get_method_bind) (__class_name . string_sys () , __method_name . string_sys () , 1545262638i64) ; let __call_fn = sys :: interface_fn ! (object_method_bind_call) ; let __explicit_args = [] ; let mut __args = Vec :: new () ; __args . extend (__explicit_args . iter () . map (Variant :: var_sys_const)) ; __args . extend (varargs . iter () . map (Variant :: var_sys_const)) ; let __args_ptr = __args . as_ptr () ; let variant = Variant :: from_var_sys_init (| return_ptr | { let mut __err = sys :: default_call_error () ; __call_fn (__method_bind , self . object_ptr , __args_ptr , __args . len () as i64 , return_ptr , std :: ptr :: addr_of_mut ! (__err)) ; assert_eq ! (__err . error , sys :: GDEXTENSION_CALL_OK) ; }) ; variant } } } ...
  |       ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
  |       |
  |       previous definition of `new` here

For more information about this error, try `rustc --explain E0201`.
error: could not compile `godot-core` due to previous error

Export properties

Allow a way to export Rust fields as GDScript properties, e.g.:

#[export]
my_field: i32,

This tracks the basic feature, all the customization around GDScript's @export can come later.

Until this is implemented, #[func] functions can serve as a workaround to pass data back and forth.

Autocompletion doesn't work for generated files

In the absence of documentation, the best way to figure things out is IDE autocompletion. Sadly, for generated files it doesn't work (at least in vscode on windows).

I've opened the issue here, please check it out:

rust-lang/rust-analyzer#13711

Long story short, generated files are located in a different package from where they are included (godot-codegen vs godot-core). And that makes them invisible as far as autocompletion is concerned.

Not sure if it's intentional or not on the part of rust-analyzer, so opening an issue on both places.

Access is denied when running cargo build on gdextension folder

Issue:
I'm getting a error when running "cargo build" command in the gdextension folder. Seems like windows is blocking the access to godot but not really sure how to resolve it. I've tried running the command from command prompt in both admin mode and non-admin mode and tried the same thing via powershell. Also tried restarting my computer to make sure windows wasn't locking the godot executable for some reason.

Clang Version:
clang version 15.0.6
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin

Rust Version:
rustc 1.65.0 (897e37553 2022-11-02)

Full error:
error: failed to run custom build command for godot-ffi v0.1.0 (D:\Godot\gdextension\godot-ffi)

Caused by:
process didn't exit successfully: D:\Godot\gdextension\target\debug\build\godot-ffi-82ae7c24a43616ed\build-script-build (exit code: 101)
--- stdout
cargo:rerun-if-changed=../godot-codegen/input/gdnative_interface.h
cargo:rerun-if-changed=C:\Program Files\LLVM\lib\clang\15.0.6\include\stddef.h
cargo:rerun-if-changed=C:\Program Files\LLVM\lib\clang\15.0.6\include/__stddef_max_align_t.h
cargo:rerun-if-changed=C:\Program Files\LLVM\lib\clang\15.0.6\include\stdint.h
cargo:rerun-if-changed=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\stdint.h
cargo:rerun-if-changed=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\vcruntime.h
cargo:rerun-if-changed=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\sal.h
cargo:rerun-if-changed=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\concurrencysal.h
cargo:rerun-if-changed=C:\Program Files\LLVM\lib\clang\15.0.6\include\vadefs.h
cargo:rerun-if-changed=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\vadefs.h
cargo:rerun-if-changed=C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt\stdio.h
cargo:rerun-if-changed=C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt.h
cargo:rerun-if-changed=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\vcruntime.h
cargo:rerun-if-changed=C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_wstdio.h
cargo:rerun-if-changed=C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt.h
cargo:rerun-if-changed=C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt_stdio_config.h
cargo:rerun-if-changed=C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt.h
cargo:rerun-if-changed=D:\Godot\gdextension\godot-codegen/input/gen/extension_api.json
Found GODOT4_BIN with path to executable: 'D:\Godot\Godot_v4.0-beta1_win64.exe'
cargo:rerun-if-changed=D:\Godot\Godot_v4.0-beta1_win64.exe

--- stderr
Build selected for Linux/Windows.
thread 'main' panicked at 'failed to invoke Godot executable 'D:\Godot\Godot_v4.0-beta1_win64.exe': Os { code: 5, kind: PermissionDenied, message: "Access is denied." }', godot-codegen\src\godot_exe.rs:66:10
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace

Everything is successful unless version number screws up

  --- stderr
  Build selected for Linux/Windows.
  thread 'main' panicked at 'failed to parse Godot version '4.0.beta8.mono.official.45cac42c0
  ': Regex capture failed', /home/coder2195/.cargo/git/checkouts/gdextension-25c68fb170a9fb9d/eaefd45/godot-codegen/src/godot_exe.rs:87:13
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

#[godot_api] function or associated item not found in `godot::prelude::StringName`

error[E0599]: no function or associated item named `new` found for struct `godot::prelude::StringName` in the current scope
  --> examples/dodge-the-creeps/rust/src/hud.rs:11:1
   |
11 | #[godot_api]
   | ^^^^^^^^^^^^ function or associated item not found in `godot::prelude::StringName`
   |
   = note: this error originates in the attribute macro `godot_api` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: no function or associated item named `new` found for struct `godot::prelude::StringName` in the current scope
  --> examples/dodge-the-creeps/rust/src/player.rs:14:1
   |
14 | #[godot_api]
   | ^^^^^^^^^^^^ function or associated item not found in `godot::prelude::StringName`
   |
   = note: this error originates in the attribute macro `godot_api` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0599`.
error: could not compile `dodge-the-creeps` due to 2 previous errors

I think #27 might have introduced this ๐Ÿค”

Is broken in my code and the example.

Publish to crates.io

As soon as the library becomes a bit more stable, we can release our first 0.x versions to crates.io.

Crate publishing was in the past blocked by unreleased dependencies, see PoignardAzur/venial#32. Should be good now.

The codegen approach from "output directly in dependent crate" needs to be modified, so that all files are output in the own crate.

Custom mainloop can't work

Custom mainloop can't work properly. Refers to this issue. kleonc's solution can work with gdscript mainloop, but rust's failed.

The minimal reproduction project is in the linked issue above. And the rust part is simply add these:

Here is my_main_loop.rs:

use godot::prelude::*;

#[derive(GodotClass, Debug)]
#[class(base=SceneTree)]
pub struct MyMainLoop {
    #[base]
    base: Base<SceneTree>,
}

#[godot_api]
impl MyMainLoop {
    #[func]
    fn say_hello(&self) {
        godot::prelude::godot_print!("hello world!");
    }
}

#[godot_api]
impl GodotExt for MyMainLoop {

}

Here lib.rs:

use godot::prelude::*;

struct ExtMain;

mod my_mainloop;

#[gdextension]
unsafe impl ExtensionLibrary for ExtMain {}

Array support

Implement a richer API for arrays -- both Array (containing Variant) and TypedArray<T> (containing concrete types).

Inspiration can be found in gdnative::core_types::PoolArray, as well as Godot's Array documentation.

Some ideas, can also be implemented as separate pull requests:

  1. Basic methods: insertion, removal, random access, etc.
  2. Trait support: Index, IntoIterator, PartialEq, PartialOrd
    • ideally use impl_builtin_traits! for the "object relation" traits
  3. Conversions, e.g. From<Vec<T>>, also between Array and TypedArray (one way fallible)
  4. Godot special methods like shuffle(), get_typed_builtin(), ...
    • would be good to discuss this first
    • lots of Godot methods have a more idiomatic approach or name in Rust: slice(), size(), sort_custom(), ...

If possible, additions should be accompanied by unit tests. Rather less functionality but properly tested than feature-creep ๐Ÿ™‚

Performance optimizations

There are some low-hanging fruits for making the library faster, this issue tracks such approaches.

Codegen

  • Check rustfmt performance -- parallelize or allow skipping
  • Cache intermediate results in Context, e.g. to_rust_type

Runtime

  • Cache function pointers used by engine + builtin classes in a global method table
  • Provide maximum type information to GDScript, so it can use ptrcalls whenever possible
  • Benchmark if #[inline] has a true impact (otherwise don't clutter the whole codebase)
  • Varargs (e.g. Object::call) could use impl AsVararg + passing as tuple, to allocate argument array on the stack

Not building in current version

Here's the stack trace. Built with Godot 4 beta 10 on the GODOT4_BIN path.

  -- add engine class MeshTexture
    -- inherits Texture2D
  -- add engine class MethodTweener
    -- inherits Tweener
  -- add engine class MissingNode
    -- inherits Node
  -- add engine class MissingResource
    -- inherits Resource
  -- add engine class MobileVRInterface
    -- inherits XRInterface
  -- add engine class MovieWriter
    -- inherits Object
  -- add engine class MovieWriterMJPEG
    -- inherits MovieWriter
  -- add engine class MovieWriterPNGWAV
    -- inherits MovieWriter
  -- add engine class MultiMesh
    -- inherits Resource
  -- add engine class MultiMeshInstance2D
    -- inherits Node2D
  -- add engine class MultiMeshInstance3D
    -- inherits GeometryInstance3D
  -- add engine class MultiplayerAPI
    -- inherits RefCounted
  -- add engine class MultiplayerAPIExtension
    -- inherits MultiplayerAPI
  -- add engine class MultiplayerPeer
    -- inherits PacketPeer
  -- add engine class MultiplayerPeerExtension
    -- inherits MultiplayerPeer
  -- add engine class MultiplayerSpawner
    -- inherits Node
  -- add engine class MultiplayerSynchronizer
    -- inherits Node
  -- add engine class Mutex
    -- inherits RefCounted
  -- add engine class NavigationAgent2D
    -- inherits Node
  -- add engine class NavigationAgent3D
    -- inherits Node
  -- add engine class NavigationLink2D
    -- inherits Node2D
  -- add engine class NavigationLink3D
    -- inherits Node3D
  -- add engine class NavigationMesh
    -- inherits Resource
  -- add engine class NavigationMeshGenerator
    -- inherits Object
  -- add engine class NavigationObstacle2D
    -- inherits Node
  -- add engine class NavigationObstacle3D
    -- inherits Node
  -- add engine class NavigationPathQueryParameters2D
    -- inherits RefCounted
  -- add engine class NavigationPathQueryParameters3D
    -- inherits RefCounted
  -- add engine class NavigationPathQueryResult2D
    -- inherits RefCounted
  -- add engine class NavigationPathQueryResult3D
    -- inherits RefCounted
  -- add engine class NavigationPolygon
    -- inherits Resource
  -- add engine class NavigationRegion2D
    -- inherits Node2D
  -- add engine class NavigationRegion3D
    -- inherits Node3D
  -- add engine class NavigationServer2D
    -- inherits Object
  -- add engine class NavigationServer3D
    -- inherits Object
  -- add engine class NinePatchRect
    -- inherits Control
  -- add engine class Node
    -- inherits Object
  -- add engine class Node2D
    -- inherits CanvasItem
  -- add engine class Node3D
    -- inherits Node
  -- add engine class Node3DGizmo
    -- inherits RefCounted
  -- add engine class Noise
    -- inherits Resource
  -- add engine class NoiseTexture2D
    -- inherits Texture2D
  -- add engine class ORMMaterial3D
    -- inherits BaseMaterial3D
  -- add engine class OS
    -- inherits Object
  -- add engine class Object
  -- add engine class Occluder3D
    -- inherits Resource
  -- add engine class OccluderInstance3D
    -- inherits Node3D
  -- add engine class OccluderPolygon2D
    -- inherits Resource
  -- add engine class OfflineMultiplayerPeer
    -- inherits MultiplayerPeer
  -- add engine class OggPacketSequence
    -- inherits Resource
  -- add engine class OggPacketSequencePlayback
    -- inherits RefCounted
  -- add engine class OmniLight3D
    -- inherits Light3D
  -- add engine class OpenXRAction
    -- inherits Resource
  -- add engine class OpenXRActionMap
    -- inherits Resource
  -- add engine class OpenXRActionSet
    -- inherits Resource
  -- add engine class OpenXRHand
    -- inherits Node3D
  -- add engine class OpenXRIPBinding
    -- inherits Resource
  -- add engine class OpenXRInteractionProfile
    -- inherits Resource
  -- add engine class OpenXRInterface
    -- inherits XRInterface
  -- add engine class OptimizedTranslation
    -- inherits Translation
  -- add engine class OptionButton
    -- inherits Button
  -- add engine class PCKPacker
    -- inherits RefCounted
  -- add engine class PackedDataContainer
    -- inherits Resource
  -- add engine class PackedDataContainerRef
    -- inherits RefCounted
  -- add engine class PackedScene
    -- inherits Resource
  -- add engine class PacketPeer
    -- inherits RefCounted
  -- add engine class PacketPeerDTLS
    -- inherits PacketPeer
  -- add engine class PacketPeerExtension
    -- inherits PacketPeer
  -- add engine class PacketPeerStream
    -- inherits PacketPeer
  -- add engine class PacketPeerUDP
    -- inherits PacketPeer
  -- add engine class Panel
    -- inherits Control
  -- add engine class PanelContainer
    -- inherits Container
  -- add engine class PanoramaSkyMaterial
    -- inherits Material
  -- add engine class ParallaxBackground
    -- inherits CanvasLayer
  -- add engine class ParallaxLayer
    -- inherits Node2D
  -- add engine class ParticleProcessMaterial
    -- inherits Material
  -- add engine class Path2D
    -- inherits Node2D
  -- add engine class Path3D
    -- inherits Node3D
  -- add engine class PathFollow2D
    -- inherits Node2D
  -- add engine class PathFollow3D
    -- inherits Node3D
  -- add engine class Performance
    -- inherits Object
  -- add engine class PhysicalBone2D
    -- inherits RigidBody2D
  -- add engine class PhysicalBone3D
    -- inherits PhysicsBody3D
  -- add engine class PhysicalSkyMaterial
    -- inherits Material
  -- add engine class PhysicsBody2D
    -- inherits CollisionObject2D
  -- add engine class PhysicsBody3D
    -- inherits CollisionObject3D
  -- add engine class PhysicsDirectBodyState2D
    -- inherits Object
  -- add engine class PhysicsDirectBodyState2DExtension
    -- inherits PhysicsDirectBodyState2D
  -- add engine class PhysicsDirectBodyState3D
    -- inherits Object
  -- add engine class PhysicsDirectBodyState3DExtension
    -- inherits PhysicsDirectBodyState3D
  -- add engine class PhysicsDirectSpaceState2D
    -- inherits Object
  -- add engine class PhysicsDirectSpaceState2DExtension
    -- inherits PhysicsDirectSpaceState2D
  -- add engine class PhysicsDirectSpaceState3D
    -- inherits Object
  -- add engine class PhysicsDirectSpaceState3DExtension
    -- inherits PhysicsDirectSpaceState3D
  -- add engine class PhysicsMaterial
    -- inherits Resource
  -- add engine class PhysicsPointQueryParameters2D
    -- inherits RefCounted
  -- add engine class PhysicsPointQueryParameters3D
    -- inherits RefCounted
  -- add engine class PhysicsRayQueryParameters2D
    -- inherits RefCounted
  -- add engine class PhysicsRayQueryParameters3D
    -- inherits RefCounted
  -- add engine class PhysicsServer2D
    -- inherits Object
  -- add engine class PhysicsServer2DExtension
    -- inherits PhysicsServer2D
  -- add engine class PhysicsServer2DManager
    -- inherits Object
  -- add engine class PhysicsServer3D
    -- inherits Object
  -- add engine class PhysicsServer3DExtension
    -- inherits PhysicsServer3D
  -- add engine class PhysicsServer3DManager
    -- inherits Object
  -- add engine class PhysicsServer3DRenderingServerHandler
    -- inherits Object
  -- add engine class PhysicsShapeQueryParameters2D
    -- inherits RefCounted
  -- add engine class PhysicsShapeQueryParameters3D
    -- inherits RefCounted
  -- add engine class PhysicsTestMotionParameters2D
    -- inherits RefCounted
  -- add engine class PhysicsTestMotionParameters3D
    -- inherits RefCounted
  -- add engine class PhysicsTestMotionResult2D
    -- inherits RefCounted
  -- add engine class PhysicsTestMotionResult3D
    -- inherits RefCounted
  -- add engine class PinJoint2D
    -- inherits Joint2D
  -- add engine class PinJoint3D
    -- inherits Joint3D
  -- add engine class PlaceholderCubemap
    -- inherits PlaceholderTextureLayered
  -- add engine class PlaceholderCubemapArray
    -- inherits PlaceholderTextureLayered
  -- add engine class PlaceholderMaterial
    -- inherits Material
  -- add engine class PlaceholderMesh
    -- inherits Mesh
  -- add engine class PlaceholderTexture2D
    -- inherits Texture2D
  -- add engine class PlaceholderTexture2DArray
    -- inherits PlaceholderTextureLayered
  -- add engine class PlaceholderTexture3D
    -- inherits Texture3D
  -- add engine class PlaceholderTextureLayered
    -- inherits TextureLayered
  -- add engine class PlaneMesh
    -- inherits PrimitiveMesh
  -- add engine class PointLight2D
    -- inherits Light2D
  -- add engine class PointMesh
    -- inherits PrimitiveMesh
  -- add engine class Polygon2D
    -- inherits Node2D
  -- add engine class PolygonOccluder3D
    -- inherits Occluder3D
  -- add engine class PolygonPathFinder
    -- inherits Resource
  -- add engine class Popup
    -- inherits Window
  -- add engine class PopupMenu
    -- inherits Popup
  -- add engine class PopupPanel
    -- inherits Popup
  -- add engine class PortableCompressedTexture2D
    -- inherits Texture2D
  -- add engine class PrimitiveMesh
    -- inherits Mesh
  -- add engine class PrismMesh
    -- inherits PrimitiveMesh
  -- add engine class ProceduralSkyMaterial
    -- inherits Material
  -- add engine class ProgressBar
    -- inherits Range
  -- add engine class ProjectSettings
    -- inherits Object
  -- add engine class PropertyTweener
    -- inherits Tweener
  -- add engine class QuadMesh
    -- inherits PlaneMesh
  -- add engine class QuadOccluder3D
    -- inherits Occluder3D
  -- add engine class RDAttachmentFormat
    -- inherits RefCounted
  -- add engine class RDFramebufferPass
    -- inherits RefCounted
  -- add engine class RDPipelineColorBlendState
    -- inherits RefCounted
  -- add engine class RDPipelineColorBlendStateAttachment
    -- inherits RefCounted
  -- add engine class RDPipelineDepthStencilState
    -- inherits RefCounted
  -- add engine class RDPipelineMultisampleState
    -- inherits RefCounted
  -- add engine class RDPipelineRasterizationState
    -- inherits RefCounted
  -- add engine class RDPipelineSpecializationConstant
    -- inherits RefCounted
  -- add engine class RDSamplerState
    -- inherits RefCounted
  -- add engine class RDShaderFile
    -- inherits Resource
  -- add engine class RDShaderSPIRV
    -- inherits Resource
  -- add engine class RDShaderSource
    -- inherits RefCounted
  -- add engine class RDTextureFormat
    -- inherits RefCounted
  -- add engine class RDTextureView
    -- inherits RefCounted
  -- add engine class RDUniform
    -- inherits RefCounted
  -- add engine class RDVertexAttribute
    -- inherits RefCounted
  -- add engine class RandomNumberGenerator
    -- inherits RefCounted
  -- add engine class Range
    -- inherits Control
  -- add engine class RayCast2D
    -- inherits Node2D
  -- add engine class RayCast3D
    -- inherits Node3D
  -- add engine class RectangleShape2D
    -- inherits Shape2D
  -- add engine class RefCounted
    -- inherits Object
  -- add engine class ReferenceRect
    -- inherits Control
  -- add engine class ReflectionProbe
    -- inherits VisualInstance3D
  -- add engine class RegEx
    -- inherits RefCounted
  -- add engine class RegExMatch
    -- inherits RefCounted
  -- add engine class RemoteTransform2D
    -- inherits Node2D
  -- add engine class RemoteTransform3D
    -- inherits Node3D
  -- add engine class RenderingDevice
    -- inherits Object
  -- add engine class RenderingServer
    -- inherits Object
  -- add engine class Resource
    -- inherits RefCounted
  -- add engine class ResourceFormatLoader
    -- inherits RefCounted
  -- add engine class ResourceFormatSaver
    -- inherits RefCounted
  -- add engine class ResourceImporter
    -- inherits RefCounted
  -- add engine class ResourceLoader
    -- inherits Object
  -- add engine class ResourcePreloader
    -- inherits Node
  -- add engine class ResourceSaver
    -- inherits Object
  -- add engine class ResourceUID
    -- inherits Object
  -- add engine class RibbonTrailMesh
    -- inherits PrimitiveMesh
  -- add engine class RichTextEffect
    -- inherits Resource
  -- add engine class RichTextLabel
    -- inherits Control
  -- add engine class RigidBody2D
    -- inherits PhysicsBody2D
  -- add engine class RigidBody3D
    -- inherits PhysicsBody3D
  -- add engine class RootMotionView
    -- inherits VisualInstance3D
  -- add engine class SceneMultiplayer
    -- inherits MultiplayerAPI
  -- add engine class SceneReplicationConfig
    -- inherits Resource
  -- add engine class SceneState
    -- inherits RefCounted
  -- add engine class SceneTree
    -- inherits MainLoop
  -- add engine class SceneTreeTimer
    -- inherits RefCounted
  -- add engine class Script
    -- inherits Resource
  -- add engine class ScriptCreateDialog
    -- inherits ConfirmationDialog
  -- add engine class ScriptEditor
    -- inherits PanelContainer
  -- add engine class ScriptEditorBase
    -- inherits VBoxContainer
  -- add engine class ScriptExtension
    -- inherits Script
  -- add engine class ScriptLanguage
    -- inherits Object
  -- add engine class ScriptLanguageExtension
    -- inherits ScriptLanguage
  -- add engine class ScrollBar
    -- inherits Range
  -- add engine class ScrollContainer
    -- inherits Container
  -- add engine class SegmentShape2D
    -- inherits Shape2D
  -- add engine class Semaphore
    -- inherits RefCounted
  -- add engine class SeparationRayShape2D
    -- inherits Shape2D
  -- add engine class SeparationRayShape3D
    -- inherits Shape3D
  -- add engine class Separator
    -- inherits Control
  -- add engine class Shader
    -- inherits Resource
  -- add engine class ShaderGlobalsOverride
    -- inherits Node
  -- add engine class ShaderInclude
    -- inherits Resource
  -- add engine class ShaderMaterial
    -- inherits Material
  -- add engine class Shape2D
    -- inherits Resource
  -- add engine class Shape3D
    -- inherits Resource
  -- add engine class ShapeCast2D
    -- inherits Node2D
  -- add engine class ShapeCast3D
    -- inherits Node3D
  -- add engine class Shortcut
    -- inherits Resource
  -- add engine class Skeleton2D
    -- inherits Node2D
  -- add engine class Skeleton3D
    -- inherits Node3D
  -- add engine class SkeletonIK3D
    -- inherits Node
  -- add engine class SkeletonModification2D
    -- inherits Resource
  -- add engine class SkeletonModification2DCCDIK
    -- inherits SkeletonModification2D
  -- add engine class SkeletonModification2DFABRIK
    -- inherits SkeletonModification2D
  -- add engine class SkeletonModification2DJiggle
    -- inherits SkeletonModification2D
  -- add engine class SkeletonModification2DLookAt
    -- inherits SkeletonModification2D
  -- add engine class SkeletonModification2DPhysicalBones
    -- inherits SkeletonModification2D
  -- add engine class SkeletonModification2DStackHolder
    -- inherits SkeletonModification2D
  -- add engine class SkeletonModification2DTwoBoneIK
    -- inherits SkeletonModification2D
  -- add engine class SkeletonModification3D
    -- inherits Resource
  -- add engine class SkeletonModification3DCCDIK
    -- inherits SkeletonModification3D
  -- add engine class SkeletonModification3DFABRIK
    -- inherits SkeletonModification3D
  -- add engine class SkeletonModification3DJiggle
    -- inherits SkeletonModification3D
  -- add engine class SkeletonModification3DLookAt
    -- inherits SkeletonModification3D
  -- add engine class SkeletonModification3DStackHolder
    -- inherits SkeletonModification3D
  -- add engine class SkeletonModification3DTwoBoneIK
    -- inherits SkeletonModification3D
  -- add engine class SkeletonModificationStack2D
    -- inherits Resource
  -- add engine class SkeletonModificationStack3D
    -- inherits Resource
  -- add engine class SkeletonProfile
    -- inherits Resource
  -- add engine class SkeletonProfileHumanoid
    -- inherits SkeletonProfile
  -- add engine class Skin
    -- inherits Resource
  -- add engine class SkinReference
    -- inherits RefCounted
  -- add engine class Sky
    -- inherits Resource
  -- add engine class Slider
    -- inherits Range
  -- add engine class SliderJoint3D
    -- inherits Joint3D
  -- add engine class SoftBody3D
    -- inherits MeshInstance3D
  -- add engine class SphereMesh
    -- inherits PrimitiveMesh
  -- add engine class SphereOccluder3D
    -- inherits Occluder3D
  -- add engine class SphereShape3D
    -- inherits Shape3D
  -- add engine class SpinBox
    -- inherits Range
  -- add engine class SplitContainer
    -- inherits Container
  -- add engine class SpotLight3D
    -- inherits Light3D
  -- add engine class SpringArm3D
    -- inherits Node3D
  -- add engine class Sprite2D
    -- inherits Node2D
  -- add engine class Sprite3D
    -- inherits SpriteBase3D
  -- add engine class SpriteBase3D
    -- inherits GeometryInstance3D
  -- add engine class SpriteFrames
    -- inherits Resource
  -- add engine class StandardMaterial3D
    -- inherits BaseMaterial3D
  -- add engine class StaticBody2D
    -- inherits PhysicsBody2D
  -- add engine class StaticBody3D
    -- inherits PhysicsBody3D
  -- add engine class StreamPeer
    -- inherits RefCounted
  -- add engine class StreamPeerBuffer
    -- inherits StreamPeer
  -- add engine class StreamPeerExtension
    -- inherits StreamPeer
  -- add engine class StreamPeerGZIP
    -- inherits StreamPeer
  -- add engine class StreamPeerTCP
    -- inherits StreamPeer
  -- add engine class StreamPeerTLS
    -- inherits StreamPeer
  -- add engine class StyleBox
    -- inherits Resource
  -- add engine class StyleBoxEmpty
    -- inherits StyleBox
  -- add engine class StyleBoxFlat
    -- inherits StyleBox
  -- add engine class StyleBoxLine
    -- inherits StyleBox
  -- add engine class StyleBoxTexture
    -- inherits StyleBox
  -- add engine class SubViewport
    -- inherits Viewport
  -- add engine class SubViewportContainer
    -- inherits Container
  -- add engine class SurfaceTool
    -- inherits RefCounted
  -- add engine class SyntaxHighlighter
    -- inherits Resource
  -- add engine class SystemFont
    -- inherits Font
  -- add engine class TCPServer
    -- inherits RefCounted
  -- add engine class TabBar
    -- inherits Control
  -- add engine class TabContainer
    -- inherits Container
  -- add engine class TextEdit
    -- inherits Control
  -- add engine class TextLine
    -- inherits RefCounted
  -- add engine class TextMesh
    -- inherits PrimitiveMesh
  -- add engine class TextParagraph
    -- inherits RefCounted
  -- add engine class TextServer
    -- inherits RefCounted
  -- add engine class TextServerAdvanced
    -- inherits TextServerExtension
  -- add engine class TextServerDummy
    -- inherits TextServerExtension
  -- add engine class TextServerExtension
    -- inherits TextServer
  -- add engine class TextServerManager
    -- inherits Object
  -- add engine class Texture
    -- inherits Resource
  -- add engine class Texture2D
    -- inherits Texture
  -- add engine class Texture2DArray
    -- inherits ImageTextureLayered
  -- add engine class Texture3D
    -- inherits Texture
  -- add engine class TextureButton
    -- inherits BaseButton
  -- add engine class TextureLayered
    -- inherits Texture
  -- add engine class TextureProgressBar
    -- inherits Range
  -- add engine class TextureRect
    -- inherits Control
  -- add engine class Theme
    -- inherits Resource
  -- add engine class ThemeDB
    -- inherits Object
  -- add engine class Thread
    -- inherits RefCounted
  -- add engine class TileData
    -- inherits Object
  -- add engine class TileMap
    -- inherits Node2D
  -- add engine class TileMapPattern
    -- inherits Resource
  -- add engine class TileSet
    -- inherits Resource
  -- add engine class TileSetAtlasSource
    -- inherits TileSetSource
  -- add engine class TileSetScenesCollectionSource
    -- inherits TileSetSource
  -- add engine class TileSetSource
    -- inherits Resource
  -- add engine class Time
    -- inherits Object
  -- add engine class Timer
    -- inherits Node
  -- add engine class TorusMesh
    -- inherits PrimitiveMesh
  -- add engine class TouchScreenButton
    -- inherits Node2D
  -- add engine class Translation
    -- inherits Resource
  -- add engine class TranslationServer
    -- inherits Object
  -- add engine class Tree
    -- inherits Control
  -- add engine class TreeItem
    -- inherits Object
  -- add engine class TriangleMesh
    -- inherits RefCounted
  -- add engine class TubeTrailMesh
    -- inherits PrimitiveMesh
  -- add engine class Tween
    -- inherits RefCounted
  -- add engine class Tweener
    -- inherits RefCounted
  -- add engine class UDPServer
    -- inherits RefCounted
  -- add engine class UPNP
    -- inherits RefCounted
  -- add engine class UPNPDevice
    -- inherits RefCounted
  -- add engine class UndoRedo
    -- inherits Object
  -- add engine class VBoxContainer
    -- inherits BoxContainer
  -- add engine class VFlowContainer
    -- inherits FlowContainer
  -- add engine class VScrollBar
    -- inherits ScrollBar
  -- add engine class VSeparator
    -- inherits Separator
  -- add engine class VSlider
    -- inherits Slider
  -- add engine class VSplitContainer
    -- inherits SplitContainer
  -- add engine class VehicleBody3D
    -- inherits RigidBody3D
  -- add engine class VehicleWheel3D
    -- inherits Node3D
  -- add engine class VideoStream
    -- inherits Resource
  -- add engine class VideoStreamPlayer
    -- inherits Control
  -- add engine class VideoStreamTheora
    -- inherits VideoStream
  -- add engine class Viewport
    -- inherits Node
  -- add engine class ViewportTexture
    -- inherits Texture2D
  -- add engine class VisibleOnScreenEnabler2D
    -- inherits VisibleOnScreenNotifier2D
  -- add engine class VisibleOnScreenEnabler3D
    -- inherits VisibleOnScreenNotifier3D
  -- add engine class VisibleOnScreenNotifier2D
    -- inherits Node2D
  -- add engine class VisibleOnScreenNotifier3D
    -- inherits VisualInstance3D
  -- add engine class VisualInstance3D
    -- inherits Node3D
  -- add engine class VisualShader
    -- inherits Shader
  -- add engine class VisualShaderNode
    -- inherits Resource
  -- add engine class VisualShaderNodeBillboard
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeBooleanConstant
    -- inherits VisualShaderNodeConstant
  -- add engine class VisualShaderNodeBooleanParameter
    -- inherits VisualShaderNodeParameter
  -- add engine class VisualShaderNodeClamp
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeColorConstant
    -- inherits VisualShaderNodeConstant
  -- add engine class VisualShaderNodeColorFunc
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeColorOp
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeColorParameter
    -- inherits VisualShaderNodeParameter
  -- add engine class VisualShaderNodeComment
    -- inherits VisualShaderNodeResizableBase
  -- add engine class VisualShaderNodeCompare
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeConstant
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeCubemap
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeCubemapParameter
    -- inherits VisualShaderNodeTextureParameter
  -- add engine class VisualShaderNodeCurveTexture
    -- inherits VisualShaderNodeResizableBase
  -- add engine class VisualShaderNodeCurveXYZTexture
    -- inherits VisualShaderNodeResizableBase
  -- add engine class VisualShaderNodeCustom
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeDerivativeFunc
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeDeterminant
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeDistanceFade
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeDotProduct
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeExpression
    -- inherits VisualShaderNodeGroupBase
  -- add engine class VisualShaderNodeFaceForward
    -- inherits VisualShaderNodeVectorBase
  -- add engine class VisualShaderNodeFloatConstant
    -- inherits VisualShaderNodeConstant
  -- add engine class VisualShaderNodeFloatFunc
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeFloatOp
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeFloatParameter
    -- inherits VisualShaderNodeParameter
  -- add engine class VisualShaderNodeFresnel
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeGlobalExpression
    -- inherits VisualShaderNodeExpression
  -- add engine class VisualShaderNodeGroupBase
    -- inherits VisualShaderNodeResizableBase
  -- add engine class VisualShaderNodeIf
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeInput
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeIntConstant
    -- inherits VisualShaderNodeConstant
  -- add engine class VisualShaderNodeIntFunc
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeIntOp
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeIntParameter
    -- inherits VisualShaderNodeParameter
  -- add engine class VisualShaderNodeIs
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeLinearSceneDepth
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeMix
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeMultiplyAdd
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeOuterProduct
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeOutput
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeParameter
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeParameterRef
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeParticleAccelerator
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeParticleBoxEmitter
    -- inherits VisualShaderNodeParticleEmitter
  -- add engine class VisualShaderNodeParticleConeVelocity
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeParticleEmit
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeParticleEmitter
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeParticleMeshEmitter
    -- inherits VisualShaderNodeParticleEmitter
  -- add engine class VisualShaderNodeParticleMultiplyByAxisAngle
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeParticleOutput
    -- inherits VisualShaderNodeOutput
  -- add engine class VisualShaderNodeParticleRandomness
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeParticleRingEmitter
    -- inherits VisualShaderNodeParticleEmitter
  -- add engine class VisualShaderNodeParticleSphereEmitter
    -- inherits VisualShaderNodeParticleEmitter
  -- add engine class VisualShaderNodeProximityFade
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeRandomRange
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeRemap
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeResizableBase
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeSDFRaymarch
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeSDFToScreenUV
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeSample3D
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeScreenUVToSDF
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeSmoothStep
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeStep
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeSwitch
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeTexture
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeTexture2DArray
    -- inherits VisualShaderNodeSample3D
  -- add engine class VisualShaderNodeTexture2DArrayParameter
    -- inherits VisualShaderNodeTextureParameter
  -- add engine class VisualShaderNodeTexture2DParameter
    -- inherits VisualShaderNodeTextureParameter
  -- add engine class VisualShaderNodeTexture3D
    -- inherits VisualShaderNodeSample3D
  -- add engine class VisualShaderNodeTexture3DParameter
    -- inherits VisualShaderNodeTextureParameter
  -- add engine class VisualShaderNodeTextureParameter
    -- inherits VisualShaderNodeParameter
  -- add engine class VisualShaderNodeTextureParameterTriplanar
    -- inherits VisualShaderNodeTextureParameter
  -- add engine class VisualShaderNodeTextureSDF
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeTextureSDFNormal
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeTransformCompose
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeTransformConstant
    -- inherits VisualShaderNodeConstant
  -- add engine class VisualShaderNodeTransformDecompose
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeTransformFunc
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeTransformOp
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeTransformParameter
    -- inherits VisualShaderNodeParameter
  -- add engine class VisualShaderNodeTransformVecMult
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeUVFunc
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeUVPolarCoord
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeVarying
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeVaryingGetter
    -- inherits VisualShaderNodeVarying
  -- add engine class VisualShaderNodeVaryingSetter
    -- inherits VisualShaderNodeVarying
  -- add engine class VisualShaderNodeVec2Constant
    -- inherits VisualShaderNodeConstant
  -- add engine class VisualShaderNodeVec2Parameter
    -- inherits VisualShaderNodeParameter
  -- add engine class VisualShaderNodeVec3Constant
    -- inherits VisualShaderNodeConstant
  -- add engine class VisualShaderNodeVec3Parameter
    -- inherits VisualShaderNodeParameter
  -- add engine class VisualShaderNodeVec4Constant
    -- inherits VisualShaderNodeConstant
  -- add engine class VisualShaderNodeVec4Parameter
    -- inherits VisualShaderNodeParameter
  -- add engine class VisualShaderNodeVectorBase
    -- inherits VisualShaderNode
  -- add engine class VisualShaderNodeVectorCompose
    -- inherits VisualShaderNodeVectorBase
  -- add engine class VisualShaderNodeVectorDecompose
    -- inherits VisualShaderNodeVectorBase
  -- add engine class VisualShaderNodeVectorDistance
    -- inherits VisualShaderNodeVectorBase
  -- add engine class VisualShaderNodeVectorFunc
    -- inherits VisualShaderNodeVectorBase
  -- add engine class VisualShaderNodeVectorLen
    -- inherits VisualShaderNodeVectorBase
  -- add engine class VisualShaderNodeVectorOp
    -- inherits VisualShaderNodeVectorBase
  -- add engine class VisualShaderNodeVectorRefract
    -- inherits VisualShaderNodeVectorBase
  -- add engine class VoxelGI
    -- inherits VisualInstance3D
  -- add engine class VoxelGIData
    -- inherits Resource
  -- add engine class WeakRef
    -- inherits RefCounted
  -- add engine class WebRTCDataChannel
    -- inherits PacketPeer
  -- add engine class WebRTCDataChannelExtension
    -- inherits WebRTCDataChannel
  -- add engine class WebRTCMultiplayerPeer
    -- inherits MultiplayerPeer
  -- add engine class WebRTCPeerConnection
    -- inherits RefCounted
  -- add engine class WebRTCPeerConnectionExtension
    -- inherits WebRTCPeerConnection
  -- add engine class WebSocketMultiplayerPeer
    -- inherits MultiplayerPeer
  -- add engine class WebSocketPeer
    -- inherits PacketPeer
  -- add engine class WebXRInterface
    -- inherits XRInterface
  -- add engine class Window
    -- inherits Viewport
  -- add engine class WorkerThreadPool
    -- inherits Object
  -- add engine class World2D
    -- inherits Resource
  -- add engine class World3D
    -- inherits Resource
  -- add engine class WorldBoundaryShape2D
    -- inherits Shape2D
  -- add engine class WorldBoundaryShape3D
    -- inherits Shape3D
  -- add engine class WorldEnvironment
    -- inherits Node
  -- add engine class X509Certificate
    -- inherits Resource
  -- add engine class XMLParser
    -- inherits RefCounted
  -- add engine class XRAnchor3D
    -- inherits XRNode3D
  -- add engine class XRCamera3D
    -- inherits Camera3D
  -- add engine class XRController3D
    -- inherits XRNode3D
  -- add engine class XRInterface
    -- inherits RefCounted
  -- add engine class XRInterfaceExtension
    -- inherits XRInterface
  -- add engine class XRNode3D
    -- inherits Node3D
  -- add engine class XROrigin3D
    -- inherits Node3D
  -- add engine class XRPose
    -- inherits RefCounted
  -- add engine class XRPositionalTracker
    -- inherits RefCounted
  -- add engine class XRServer
    -- inherits Object
  -- add engine class ZIPPacker
    -- inherits RefCounted
  -- add engine class ZIPReader
    -- inherits RefCounted
  Format 2 generated files...
    Format 2 files...

  --- stderr
  Build selected for Linux/Windows.
  thread 'main' panicked at 'during godot-rust codegen, rustfmt failed:
     No such file or directory (os error 2)', godot-codegen/src/lib.rs:113:35
  stack backtrace:
     0:     0x55cfb9c0e283 - std::backtrace_rs::backtrace::libunwind::trace::h6982528d5cca6f90
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
     1:     0x55cfb9c0e283 - std::backtrace_rs::backtrace::trace_unsynchronized::h061c47d064ba9746
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
     2:     0x55cfb9c0e283 - std::sys_common::backtrace::_print_fmt::h340e5b18fcf1338e
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys_common/backtrace.rs:65:5
     3:     0x55cfb9c0e283 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h411b55ca01d935c2
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys_common/backtrace.rs:44:22
     4:     0x55cfb9c3412c - core::fmt::write::hd3958a6cee3e08c1
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/fmt/mod.rs:1209:17
     5:     0x55cfb9c0b2c5 - std::io::Write::write_fmt::hf48b1a8a092a15e1
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/io/mod.rs:1682:15
     6:     0x55cfb9c0e041 - std::sys_common::backtrace::_print::h47b4320fc34f81e5
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys_common/backtrace.rs:47:5
     7:     0x55cfb9c0e041 - std::sys_common::backtrace::print::h69fe66b3b80a68d1
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys_common/backtrace.rs:34:9
     8:     0x55cfb9c0f8df - std::panicking::default_hook::{{closure}}::h4332630e65e37bf3
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:267:22
     9:     0x55cfb9c0f60e - std::panicking::default_hook::h3433d803896c8bd9
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:286:9
    10:     0x55cfb9c0ffd2 - std::panicking::rust_panic_with_hook::he522607577f60554
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:688:13
    11:     0x55cfb9c0fd67 - std::panicking::begin_panic_handler::{{closure}}::ha5dcf4cab1a8dbd6
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:579:13
    12:     0x55cfb9c0e734 - std::sys_common::backtrace::__rust_end_short_backtrace::hd6b58a543a780286
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys_common/backtrace.rs:137:18
    13:     0x55cfb9c0fa92 - rust_begin_unwind
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:575:5
    14:     0x55cfb96f61c3 - core::panicking::panic_fmt::h13f856077d656cf7
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/panicking.rs:65:14
    15:     0x55cfb9ae05f6 - godot_codegen::rustfmt_if_needed::h89caef714082dc01
    16:     0x55cfb9ae008b - godot_codegen::generate_sys_files::h8ac1bc243ea70084
    17:     0x55cfb96fd16d - build_script_build::main::h27a6ed1d7deaa0ca
                                 at /home/jabcross/godot-projects/gdextension/godot-ffi/build.rs:21:5
    18:     0x55cfb96f919b - core::ops::function::FnOnce::call_once::he6106a57f9e804f2
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ops/function.rs:251:5
    19:     0x55cfb96f7a4e - std::sys_common::backtrace::__rust_begin_short_backtrace::he86a7f75d433899e
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys_common/backtrace.rs:121:18
    20:     0x55cfb96f6d21 - std::rt::lang_start::{{closure}}::h2d08870f1171d818
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/rt.rs:166:18
    21:     0x55cfb9c06cd2 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::ha85d5df2caa75024
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ops/function.rs:286:13
    22:     0x55cfb9c06cd2 - std::panicking::try::do_call::hd6a00ca559d131da
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:483:40
    23:     0x55cfb9c06cd2 - std::panicking::try::h6c7fb03809cd999f
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:447:19
    24:     0x55cfb9c06cd2 - std::panic::catch_unwind::haa1c169a126b107b
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panic.rs:137:14
    25:     0x55cfb9c06cd2 - std::rt::lang_start_internal::{{closure}}::he1bb37712a4677d2
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/rt.rs:148:48
    26:     0x55cfb9c06cd2 - std::panicking::try::do_call::h7653bb225f455bb9
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:483:40
    27:     0x55cfb9c06cd2 - std::panicking::try::h6d3f980794c03502
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:447:19
    28:     0x55cfb9c06cd2 - std::panic::catch_unwind::h8053e638e36e25f1
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panic.rs:137:14
    29:     0x55cfb9c06cd2 - std::rt::lang_start_internal::hbeb6491328c2152f
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/rt.rs:148:20
    30:     0x55cfb96f6cfa - std::rt::lang_start::hcd8fd1592b496745
                                 at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/rt.rs:165:17
    31:     0x55cfb96fe07e - main
    32:     0x7f52e7a22290 - <unknown>
    33:     0x7f52e7a2234a - __libc_start_main
    34:     0x55cfb96f6665 - _start
                                 at /build/glibc/src/glibc/csu/../sysdeps/x86_64/start.S:115
    35:                0x0 - <unknown>

Deal with cross-thread access to user-defined GodotClass instances

Currently, RefCell and i32 are used to store user-defined GodotClass instances and their reference counts:

https://github.com/godot-rust/gdextension/blob/a64f22409e05d1353492fded4aa36a4b4e6b710d/godot-core/src/storage.rs#L15-L21

In a multi-threaded configuration of the engine, this may lead to unsoundness when the instances are accessed by GDScript or engine code. Noting that GodotClass does not have a Send or Sync requirement, this can be as simple as a non-Send field in the type.

@Bromeon in Discord:

I plan to have a mix of multiple things:

  • the "you need to take some responsibility of the non-Rust code"
  • no access to Godot thread APIs as direct Rust classes (Thread, Mutex, Semaphore) by default, and > unsafe access when there is a threads feature enabled
  • GDScript->Rust calls could validate the thread ID and compare it with the one through which the extension library was initialized (which I hope is the main thread)
    A Cargo feature thread would loosen those restrictions and give access to multithreading, in an unsafe way.
    We could then either conditionally implement Send/Sync on Gd, or maybe better, provide an explicit Send/Sync type to transport references across thread boundaries.
    Users would still need to adhere to the Godot thread guidelines.

As prior art, the GDNative bindings deals with the problem with the user-data wrapper system.

Extension classes running in editor may be undesired

C++ binding: godotengine/godot-cpp#709.

Several users have already complained about this independently. The behavior that all classes run in the Godot editor can be unintuitive, especially when coming from Godot 3.

Needs investigation if Engine::singleton().is_editor_hint() (see link) can be used to disable user code outside the game.
We could add an opt-in at global entry point (unsafe impl ExtensionLib).

CI coverage

Several things are not yet automated via Continuous Integration.
This issue can be updated as this changes.

  • Rust checks
  • Ecosystem checks
    • cargo-deny
    • cargo-machete
  • Godot integration tests
    • macOS support
    • compilation of examples
    • test against Godot beta releases (in addition to nightly builds)
      - Wontfix as per Compatibility > Out of scope.
    • run Godot address sanitizers to detect UB
  • Docs generation + publishing
  • Godot release/export builds

Review safety in low-level code

The current low-level implementation has some rough edges, such as unnecessary unsafe or possible UB. This issue tracks several code locations, in which robustness could be improved. A lot of those are marked with TODO or FIXME in code.

Soundness:

  • Global access to everything uses static mut
  • Global string registry (returning *const i8) hands out &mut at will
    • This was removed a long time ago, as I found out we don't need to retain the memory on our side.
  • as_storage() not only hands out &mut, but also leaves them unbounded

Test coverage:

  • Ptrcalls and pointer conversions
  • Varcalls and variant conversions
  • Reference-counter increments and decrements across several types
  • Deref and cast between smart pointers/references to Godot objects
  • Memory leak checks (mem::forget, missing dec_ref, etc.)

Could not find `Month` in `os` error.

I pull this repository (version: edf2fe5) and ran cargo build on macOS.
The following errors appeared:

62 |     months.insert(os::Month::MONTH_AUGUST);                                                              [0/1850]
   |                       ^^^^^ could not find `Month` in `os`

error[E0433]: failed to resolve: could not find `Month` in `os`
  --> itest/rust/src/enum_test.rs:63:23
   |
63 |     months.insert(os::Month::MONTH_SEPTEMBER);
   |                       ^^^^^ could not find `Month` in `os`

error[E0433]: failed to resolve: could not find `Month` in `os`
  --> itest/rust/src/enum_test.rs:64:23
   |
64 |     months.insert(os::Month::MONTH_OCTOBER);
   |                       ^^^^^ could not find `Month` in `os`

error[E0433]: failed to resolve: could not find `Month` in `os`
  --> itest/rust/src/enum_test.rs:65:23
   |
65 |     months.insert(os::Month::MONTH_NOVEMBER);
   |                       ^^^^^ could not find `Month` in `os`

error[E0433]: failed to resolve: could not find `Month` in `os`
  --> itest/rust/src/enum_test.rs:66:23
   |
66 |     months.insert(os::Month::MONTH_DECEMBER);
   |                       ^^^^^ could not find `Month` in `os`

Error when building dodge the creeps

Getting this error when trying to build the example.

PS D:\rust\gdextension\examples\dodge-the-creeps\rust> cargo build --verbose
       Fresh unicode-ident v1.0.5
       Fresh glob v0.3.0
       Fresh minimal-lexical v0.2.1
       Fresh regex-syntax v0.6.28
       Fresh once_cell v1.16.0
       Fresh nanoserde-derive v0.1.19
       Fresh either v1.8.0
       Fresh peeking_take_while v0.1.2
       Fresh shlex v1.1.0
       Fresh bitflags v1.3.2
       Fresh rustc-hash v1.1.0
       Fresh lazycell v1.3.0
       Fresh lazy_static v1.4.0
       Fresh cfg-if v1.0.0
       Fresh paste v1.0.9
       Fresh proc-macro2 v1.0.47
       Fresh regex v1.7.0
       Fresh nanoserde v0.1.32
       Fresh getrandom v0.2.8
       Fresh ppv-lite86 v0.2.17
       Fresh glam v0.22.0
       Fresh libc v0.2.137
       Fresh quote v1.0.21
       Fresh memchr v2.5.0
       Fresh rand_core v0.6.4
       Fresh nom v7.1.1
       Fresh which v4.3.0
       Fresh clang-sys v1.4.0
       Fresh venial v0.5.0
       Fresh rand_chacha v0.3.1
       Fresh cexpr v0.6.0
       Fresh godot-codegen v0.1.0 (D:\rust\gdextension\godot-codegen)
       Fresh godot-macros v0.1.0 (D:\rust\gdextension\godot-macros)
       Fresh rand v0.8.5
       Fresh bindgen v0.60.1
   Compiling godot-ffi v0.1.0 (D:\rust\gdextension\godot-ffi)
     Running `D:\rust\gdextension\target\debug\build\godot-ffi-2f5b66ebb5f4b903\build-script-build`
error: failed to run custom build command for `godot-ffi v0.1.0 (D:\rust\gdextension\godot-ffi)`

Caused by:
  process didn't exit successfully: `D:\rust\gdextension\target\debug\build\godot-ffi-2f5b66ebb5f4b903\build-script-build` (exit code: 0xc0000135, STATUS_DLL_NOT_FOUND)
PS D:\rust\gdextension\examples\dodge-the-creeps\rust> rustup show
Default host: x86_64-pc-windows-msvc
rustup home:  C:\Users\danph\.rustup

installed toolchains
--------------------

stable-x86_64-pc-windows-gnu
stable-x86_64-pc-windows-msvc (default)
beta-x86_64-pc-windows-msvc
nightly-x86_64-pc-windows-gnu
nightly-x86_64-pc-windows-msvc

active toolchain
----------------

stable-x86_64-pc-windows-msvc (default)
rustc 1.65.0 (897e37553 2022-11-02)

using Godot 4 beta 5 win64

Encounter the problem of cargo build

error: failed to run custom build command for godot-ffi v0.1.0 (https://github.com/godot-rust/gdextension?branch=master#eaefd45d)

Caused by:
process didn't exit successfully: /Users/outao/Documents/GoDotRust/JumpNewGame/game-lib/target/debug/build/godot-ffi-f35a8badc2c742e5/build-script-build (exit status: 101)
--- stdout
cargo:rerun-if-changed=../godot-codegen/input/gdnative_interface.h

--- stderr
Build selected for macOS.
thread 'main' panicked at 'env var 'LLVM_PATH' not set: NotPresent', /Users/outao/.cargo/git/checkouts/gdextension-25c68fb170a9fb9d/eaefd45/godot-ffi/build.rs:64:42
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.