Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove #[base] attribute #29

Merged
merged 1 commit into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions src/intro/hello-world.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,6 @@ struct Player {
speed: f64,
angular_speed: f64,

#[base]
base: Base<Sprite2D>
}
```
Expand All @@ -268,12 +267,11 @@ Let's break this down.

4. We define two fields `speed` and `angular_speed` for the logic. These are regular Rust fields, no magic involved. More about their use later.

5. The `#[base]` attribute declares the `base` field, which allows `self` to access the base instance (via composition, as Rust does not have
5. The `Base<T>` type is used for the `base` field, which allows `self` to access the base instance (via composition, as Rust does not have
native inheritance). This enables two methods that can be accessed as `self.base()` and `self.base_mut()` on your type (through an extension
trait).

- The field must have type `Base<T>`.
- `T` must match the declared base class. For example, `#[class(base=Sprite2D)]` implies `Base<Sprite2D>`.
- `T` must match the declared base class. For example, `#[class(base=Sprite2D)]` implies `Base<Sprite2D>`.
- The name can be freely chosen, but `base` is a common convention.
- You do not _have to_ declare this field. If it is absent, you cannot access the base object from within `self`.
This is often not a problem, e.g. in data bundles inheriting `RefCounted`.
Expand Down Expand Up @@ -345,7 +343,7 @@ impl ISprite2D for Player {
```

GDScript uses property syntax here; Rust requires explicit method calls instead. Also, access to base class methods -- such as `rotate()`
in this example -- is done via the `#[base]` field.
in this example -- is done via `base()` and `base_mut()` methods.

```admonish warning title="Direct field access"
Do not use the `self.base` field directly. Use `self.base()` or `self.base_mut()` instead, otherwise you won't be able to access and call
Expand Down
2 changes: 1 addition & 1 deletion src/intro/objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ constructor list.
fully-constructed `Player` instance.
```

If your `T` contains a `#[base]` field, you cannot create a standalone `T` object -- you must encapsulate it in `Gd<T>`.
If your `T` contains a `Base<T>` field, you cannot create a standalone `T` object -- you must encapsulate it in `Gd<T>`.
You can also not extract a `T` from a `Gd<T>` smart pointer anymore; since it has potentially been shared with the Godot engine, this would
not be a safe operation.

Expand Down
1 change: 0 additions & 1 deletion src/recipes/custom-resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ This workflow is similar to the [Hello World example][hello]:
#[derive(GodotClass)]
#[class(tool, init, base=Resource)]
struct ResourceType {
#[base]
base: Base<Resource>,
}
```
Expand Down
1 change: 0 additions & 1 deletion src/recipes/editor-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ you cannot introduce compile-time errors.
#[derive(GodotClass)]
#[class(tool, init, editor_plugin, base=EditorPlugin)]
struct MyEditorPlugin {
#[base]
base: Base<EditorPlugin>,
}

Expand Down
1 change: 0 additions & 1 deletion src/recipes/engine-singleton.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ Defining a singleton is the same as registering a custom class.
#[derive(GodotClass)]
#[class(tool, init, base=Object)]
struct MyEditorSingleton {
#[base]
base: Base<Object>,
}

Expand Down
20 changes: 10 additions & 10 deletions src/register/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,15 @@ store the instance of the Godot superclass (base class) as a field in our `Monst
struct Monster {
name: String,
hitpoints: i32,

#[base]
base: Base<Node3D>,
}
```

The `#[base]` attribute is currently necessary (as of January 2024), but will likely disappear in the future.

The important part is the `Base<T>` type. `T` must match the base class you specified in the `#[class(base=...)]` attribute.
You can also use the associated type `Self::Base` for `T`.

When you declare a base field in your struct, you can access the `Node` API through provided methods `self.base()` and `self.base_mut()`, but
more on this later.
When you declare a base field in your struct, the `#[derive]` procedural macro will automatically detect the `Base<T>` type.[^inference]
This lets you access the `Node` API through provided methods `self.base()` and `self.base_mut()`, but more on this later.


## Default constructor
Expand All @@ -121,8 +117,6 @@ You can use `#[class(init)]` to generate a constructor for you. This is limited
struct Monster {
name: String,
hitpoints: i32,

#[base]
base: Base<Node3D>,
}
```
Expand Down Expand Up @@ -157,8 +151,6 @@ We can provide a manually-defined constructor by overriding the trait's associat
struct Monster {
name: String,
hitpoints: i32,

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

Expand Down Expand Up @@ -190,6 +182,14 @@ More on this topic in the next chapter.
You learned how to define a Rust class and register it with Godot. You now know how to select a base class and how to define a constructor.
The next chapter will allow you to implement logic by providing functions.

<br>

---

[^inference] You can tweak the type detection using the `#[hint]` attribute, see [the corresponding docs][api-derive-godotclass-inference].


[api-derive-godotclass]: https://godot-rust.github.io/docs/gdext/master/godot/register/derive.GodotClass.html
[api-derive-godotclass-inference]: https://godot-rust.github.io/docs/gdext/master/godot/register/derive.GodotClass.html#fine-grained-inference-hints
[api-godot-api]: https://godot-rust.github.io/docs/gdext/master/godot/register/attr.godot_api.html
[godot-gdscript-classes]: https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#classes
2 changes: 0 additions & 2 deletions src/register/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ So let's implement `to_string()`, here again showing the class definition for qu
struct Monster {
name: String,
hitpoints: i32,

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

Expand Down
Loading