From 61c5880c925960f2fdd0f7513c7ea24de08c508f Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Mon, 24 Jun 2024 21:22:29 +0200 Subject: [PATCH] Devlog: June 2024 article --- .../dev/2024-06-24-june-2024-update.md | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 website/content/dev/2024-06-24-june-2024-update.md diff --git a/website/content/dev/2024-06-24-june-2024-update.md b/website/content/dev/2024-06-24-june-2024-update.md new file mode 100644 index 00000000000..2d67f5c37d2 --- /dev/null +++ b/website/content/dev/2024-06-24-june-2024-update.md @@ -0,0 +1,170 @@ ++++ +# Copyright (c) godot-rust; Bromeon and contributors. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. + +title = "June 2024 dev update" +authors = ["Bromeon"] + +[extra] +summary = "Crates.io release, ScriptInstance, nicer errors and more!" +tags = ["dev-update"] ++++ + +We'll start our summer with another development update on godot-rust. + + +## Crates.io release + +Let's begin with the biggest one: we released on crates.io! + +Aptly named `godot`, you can immediately start using the crate: + +```toml +[dependencies] +godot = "0.1" +``` + +This may come a bit late for some, however there weren't many benefits for crate releases in the early stages, whereas Cargo has integrated well with Git repos. In 2023, the library [quickly progressed][dev-update-2023], and a more relaxed versioning approach enabled fast prototyping. Experimentation still happens, but things are a bit more stable now. + +Unlike typical Rust projects, our dependency setup is relatively complex: besides Rust crate version, we also account for an orthogonal Godot version. It is a declared goal of godot-rust to provide compatibility with multiple Godot versions _at the same time_. For this, we have converged towards a very flexible approach (see next section), however this needed a lot of design work, as well as a great deal of automation to cover 13+ individual Godot stable releases. + + +## Selecting an API level + +The API level specifies the minimum version of GDExtension (and the Godot class API) with which gdext is compatible. This is especially important for plugin writers who want to support multiple Godot versions; more details in the [book][book-select-version]. + +The API level previously required a `[patch]` statement on a top-level `Cargo.toml` to bend dependencies to comply. Now, this is much simpler, just set the `api-*` feature when adding the godot-rust dependency. By default, a recent stable minor release is used (currently 4.2). + +```toml +[dependencies] +godot = { version = "0.1", features = ["api-4.1"] } # Compatible with 4.1+ +``` + + +## Streamlined modules + +The old module structure grew organically as we mapped more and more Godot APIs, thus a lot of new symbols were just added where it was convenient to develop, rather than where they made sense from a user perspective. A good example was the `godot::engine` god module which contained everything from Godot classes/enums/utility functions over `GFile` and `ScriptInstance` high-level APIs, to translation macros. + +The most important modules are now: + +- Godot API: `builtin` types, `classes`, `global` enums/utilities/print +- Extra functionality on top of Godot: `tools` +- Object-related: `obj`, and `obj::script` for script instances +- Registration of Rust symbols: `register` +- Entry point and type meta-information: `init` and `meta` + +The refactoring details are listed in [#729], [#732], [#733], [#735], and [#738]. + + +## Script instance API + +Script instances are a relatively unknown but very powerful GDExtension feature that allows custom implementations of _scripts_, in our case Rust-based ones. This means you can attach a Rust script to scene nodes, like you would do with GDScript or C# scripts. + +TitanNano has done groundbreaking work on that front, improving UX by [enabling re-entrancy][#671], [fixing property/method accessors][#670] or [properly handling size changes][#650]. His improvements have led to `ScriptInstance` implementations behaving more and more like `GodotClass` ones, thus feeling very natural within gdext. + + +## Multithreading fixes + +Situations where Godot accesses Rust code from different threads (e.g. in callbacks) has sometimes caused panics, because access went through naive dynamic borrow-checks (à la `RefCell`). Thanks to TitanNano and lilizoey, these obstacles have been removed with [proper synchronization][#736]. + + +## Collection accessors + +Arrays and dictionaries received [better accessors][#720], for example an `at(index)` function. Even untyped `Dictionaries` are quite ergonomic to use, if you know the element types: + +```rust +// Create empty dictionary and add key-value pairs. +let dict = dict! { + "key": "some value", + "key2": 345, + "key2": Vector2i::new(1, 2), +}; + +// Access elements, typed and untyped. +let value: Variant = dict.at("key"); +let value: GString = dict.at("key").to(); // Variant::to() extracts GString. +let maybe: Option = dict.get("absent_key"); // None. + +// Iterate as (Variant, Variant). +for (key, value) in dict.iter_shared() { ... } + +// Key type is known -- iterate over (String, Variant). +for (key, value) in dict.iter_shared().typed::() { ... } +``` + +On the packed side, `Packed*Array` types now have an API which is more consistent with `Array`. In PR [#725], I added the `Index`/`IndexMut` traits which allow -- unlike `Array`/`Dictionary` -- direct element referencing via `array[index]` syntax. + + +## Geometric API consistency + +The user joriskleiber has recently contributed two important refactorings to the geometric types in `godot::builtin`. On one hand, more of the vector API was [moved to macros][#721], which ensures that function signatures and implementation are identical for the 6 vector types (`Vector2`, `Vector2i`, `Vector3`, `Vector3i`, `Vector4`, `Vector4i`). + +On the other, there was quite an inconsistent handling of by-ref and by-value parameters, most notably `self` vs `&self` in operations that don't modify the instance. Joris addressed this in [#751], so that all geometric primities in one "group" (e.g. vector, matrix, bounding box) now have the same signatures. Furthermore, there is [an ongoing PR][#761] to add functions such as `normalized_or_zero()` to vectors. + + +## Error messages + +Rust 1.78 [added `#[diagnostic::on_unimplemented]`][rust-on-unimplemented], a feature that allows customizing trait error messages. We immediately implemented this in [#692], as it benefits user-facing error messages in many places. + +As an example, the following class should have either `#[class(init)]` or a manual `init` function, or alternatively `#[class(no_init)]` to disable the constructor. +```rust +#[derive(GodotClass)] +struct MyClass {} +``` + +Previously, the error message was: +```md +error[E0277]: the trait bound `MyClass: GodotDefault` is not satisfied +--> path/to/file.rs:123:4 + | +123 | struct MyClass {} + | ^^^^^^^ the trait `GodotDefault` is not implemented for `MyClass` + | +``` + +After the change: +```md +error[E0277]: Class `MyClass` requires either an `init` constructor, or + explicit opt-out +--> path/to/file.rs:123:4 + | +123 | struct MyClass {} + | ^^^^^^^ needs `init` + | += help: the trait `GodotDefault` is not implemented for `MyClass` += note: To provide a default constructor, use `#[class(init)]` or implement + an `init` method += note: To opt out, use `#[class(no_init)]` += note: see also: https://godot-rust.github.io/book/register/constructors.html +``` +There are now very concrete notes to guide the user, and even a link for further reading. + + +## More to come + +The complete list of merged pull request is available [on GitHub][pull-requests]. + +Now that a lot of the tooling aspects around godot-rust publishing are taken care of, we can focus even more on features. If you are interested in the development, take a look at the [issue tracker][issues] and voice your opinion on GitHub or Discord! + +[#650]: https://github.com/godot-rust/gdext/pull/650 +[#670]: https://github.com/godot-rust/gdext/pull/670 +[#671]: https://github.com/godot-rust/gdext/pull/671 +[#692]: https://github.com/godot-rust/gdext/pull/692 +[#720]: https://github.com/godot-rust/gdext/pull/720 +[#721]: https://github.com/godot-rust/gdext/pull/721 +[#725]: https://github.com/godot-rust/gdext/pull/725 +[#729]: https://github.com/godot-rust/gdext/pull/729 +[#732]: https://github.com/godot-rust/gdext/pull/732 +[#733]: https://github.com/godot-rust/gdext/pull/733 +[#735]: https://github.com/godot-rust/gdext/pull/735 +[#736]: https://github.com/godot-rust/gdext/pull/736 +[#738]: https://github.com/godot-rust/gdext/pull/738 +[#751]: https://github.com/godot-rust/gdext/pull/751 +[#761]: https://github.com/godot-rust/gdext/pull/761 +[book-select-version]: https://godot-rust.github.io/book/toolchain/godot-version.html +[dev-update-2023]: 2023-12-31-godot-rust-2023-review.md +[issues]: https://github.com/godot-rust/gdext/issues +[pull-requests]: https://github.com/godot-rust/gdext/pulls?q=is%3Apr+is%3Amerged +[rust-on-unimplemented]: https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#diagnostic-attributes