Skip to content

Commit 9723b2b

Browse files
jacobskyBromeon
andauthored
0.10.0 Migration Guide (#64)
* First draft of the migration guide. * Included specific examples of some migrations that I ran into when I was migrating my current project to 0.10.x * Made changes that should address the feedback provided. * Fixes related to PR review * Minor polish (punctuation, formatting etc.) Co-authored-by: Jan Haller <bromeon@gmail.com>
1 parent 69bc39f commit 9723b2b

File tree

3 files changed

+333
-1
lines changed

3 files changed

+333
-1
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@
4242
- [Advanced Guides](./advanced-guides.md)
4343
- [Using custom Godot versions](./advanced-guides/custom-godot.md)
4444
- [Migrating from godot-rust 0.8](advanced-guides/migrating-0-8.md)
45+
- [Migrating from godot-rust 0.9](advanced-guides/migrating-0-9.md)

src/advanced-guides/migrating-0-8.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Migrating from godot-rust 0.8
1+
# Migrating from godot-rust 0.8 to 0.9.x
22

33
In version 0.9, we are attempting to resolve many long-standing problems in the older API. As a result, there are many breaking changes in the public interface. This is a quick guide to the new API for users that have used older versions.
44

src/advanced-guides/migrating-0-9.md

Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
# Migrating from godot-rust 0.9.x to 0.10.x
2+
3+
Version 0.10 implements many improvements to ergonomics, naming consistency and bugfixes. Tooling and CI has been majorly overhauled, providing fast
4+
feedback cycles, higher confidence and easier-to-read documentation.
5+
6+
This guide outlines what actions users of godot-rust need to take to update their code.
7+
8+
9+
## Minimum supported Rust version
10+
11+
The MSRV has been increased to 1.56. When migrating, you will need to ensure that you are using **at least** Rust 1.56 or later or your projects may fail to build.
12+
13+
We use the Rust 2021 edition; in your own code you may use any edition.
14+
15+
16+
## Breaking API changes
17+
18+
This is a brief overview of the smaller breaking changes in the library API. Please refer to the [changelog](https://github.com/godot-rust/godot-rust/blob/master/CHANGELOG.md) for a comprehensive list.
19+
20+
More sophisticated breaking changes are explained further down in section [_Migrations_](#Migrations).
21+
22+
### Changes to modules
23+
24+
The module structure has been simplified to ensure there is only one module per symbol:
25+
- Module `nativescript` has been renamed to `export`.
26+
- Types `nativescript::{Instance, RefInstance}` have been moved to `object`.
27+
- Less often used macros `godot_gdnative_init`, `godot_gdnative_terminate`, `godot_nativescript_init`, `godot_site` have been removed from the prelude.
28+
- Unnecessarily nested modules have also been removed. If you were depending upon the exact path, you will need to use the new path.
29+
30+
### Changes to core types
31+
32+
- The euclid vector library has been removed and replaced with [glam](https://docs.rs/glam/latest/glam/).
33+
34+
- `Variant` has a redesigned conversion API.
35+
36+
- Matrix types -- `Transform2D`, `Transform` and `Basis` -- have had their basis vectors renamed from `x/y/z` to `a/b/c`, to avoid confusion with the `x/y/z` vector components.
37+
38+
- The following deprecated symbols have been removed:
39+
- `Reference::init_ref`(unsound)
40+
- `ClassBuilder::add_method`, `add_method_advanced`, `add_method_with_rpc_mode`
41+
- `ScriptMethod`
42+
- `ScriptMethodFn`
43+
- `ScriptMethodAttributes`
44+
45+
- The following methods were removed due to being redundant:
46+
- unsafe access methods for `VariantArray<Shared>` (available in `VariantArray<Unique>`)
47+
- `Basis::invert`
48+
- `Basis::orthonormalize`
49+
- `Basis::rotate`
50+
- `Basis::tdotx`
51+
- `Basis::tdoty`
52+
- `Basis::tdotz`
53+
- `Rid::operator_less`
54+
- `StringName::operator_less`
55+
56+
57+
Various type names have been changed to improve clarity and consistency:
58+
59+
| Old Type Name | New Type Name |
60+
|------------------|---------------|
61+
| `RefInstance` | `TInstance` |
62+
| `RefKind` | `Memory` |
63+
| `ThreadAccess` | `Ownership` |
64+
| `TypedArray` | `PoolArray` |
65+
| `Element` | `PoolElement` |
66+
| `SignalArgument` | `SignalParam` |
67+
| `Point2` | `Vector2` |
68+
| `Size2` | `Vector2` |
69+
70+
The following methods have been renamed:
71+
72+
| Old Method | New Method |
73+
|---------------------------------|------------------------|
74+
| `{String,Variant}::forget` | `leak` |
75+
| `Color::{rgb,rgba}` | `{from_rgb,from_rgba}` |
76+
| `Rid::is_valid` | `is_occupied` |
77+
| `Basis::to_scale` | `scale` |
78+
| `Basis::from_elements` | `from_rows` |
79+
| `Transform2D::from_axis_origin` | `from_basis_origin` |
80+
| `StringName::get_name` | `to_godot_string` |
81+
82+
83+
### Changes to procedural macros
84+
85+
- `#[inherit]` is now optional and defaults to `Reference` instead of `Node`.
86+
- `#[property(before_set)]` and its siblings are replaced with `#[property(set)]` etc.; see below.
87+
88+
### Ownership Changes
89+
90+
- `Instance` and `TInstance` now use `Own=Shared` by default. Some adjustments to your assumptions should be re-evaluated as needed.
91+
92+
93+
## New features
94+
95+
In addition to new functionality outlined here, it can be interesting to check the _Added_ section in the changelog.
96+
97+
### Cargo features
98+
99+
While these are not breaking changes, the following may be useful to consider when migrating, particularly if you were previously using a custom solution for either of the following:
100+
101+
- [serde](https://serde.rs/) is now supported for `VariantDispatch` and types in the `core_types` module.
102+
- Async Foundations have been completed, so you can now make use of Rust `async` runtimes with Godot more easily. We have a recipe for using [async with the tokio runtime](../recipes/async-tokio.md).
103+
- Custom Godot builds are now supported. The advanced guide for [Custom Godot](./custom-godot.md) has been updated accordingly.
104+
105+
### Custom property exports
106+
107+
In godot-rust 0.9, it was necessary to manually register properties using the class builder such as the following:
108+
109+
```rust
110+
#[derive(NativeClass)]
111+
#[inherit(Reference)]
112+
struct Foo {
113+
#[property]
114+
bar: i64,
115+
}
116+
117+
#[methods]
118+
impl Foo {
119+
fn register_properties(builder: &ClassBuilder<Foo>) {
120+
builder
121+
.add_property::<String>("bar")
122+
.with_getter(get_bar)
123+
.with_setter(set_bar)
124+
.with_default(0)
125+
.done();
126+
}
127+
#[export]
128+
fn set_bar(&mut self, _owner: &Reference, value: i64) {
129+
self.bar = value;
130+
}
131+
132+
#[export]
133+
fn get_bar(&mut self, _owner: &Reference) -> i64 {
134+
self.bar
135+
}
136+
}
137+
```
138+
139+
In 0.10, this can be automated with the `#[property]` procedural macro, such as the following:
140+
```rust
141+
#[derive(NativeClass)]
142+
#[inherit(Reference)]
143+
struct Foo {
144+
#[property(name = "bar", set = "set_bar", get = "get_bar", default = 0)]
145+
bar: i64,
146+
}
147+
148+
#[methods]
149+
impl Foo {
150+
#[export]
151+
fn set_bar(&mut self, _owner: &Reference, value: i64) {
152+
self.bar = value;
153+
}
154+
155+
#[export]
156+
fn get_bar(&mut self, _owner: &Reference) -> i64 {
157+
self.bar
158+
}
159+
}
160+
```
161+
162+
### `VariantDispatch`
163+
164+
`VariantDispatch` is an newly introduced type in godot-rust 0.10. This enum lets you treat `Variant` in a more rust-idiomatic way, e.g. by pattern-matching its contents:
165+
166+
```rust
167+
let variant = 42.to_variant();
168+
169+
let number_as_float = match variant.dispatch() {
170+
VariantDispatch::I64(i) => i as f64,
171+
VariantDispatch::F64(f) => f,
172+
_ => panic!("not a number"),
173+
};
174+
175+
approx::assert_relative_eq!(42.0, number_as_float);
176+
```
177+
178+
179+
## Migrations
180+
181+
This section elaborates on APIs with non-trivial changes and guides you through the process of updating your code.
182+
183+
### `Variant`
184+
185+
If you were using the `Variant::from_*` methods, those no longer exist.
186+
187+
In 0.9.x you would need to use the specific constructor, such as the following:
188+
189+
```rust
190+
let variant = Variant::from_i64(42);
191+
let variant = Variant::from_f64(42.0);
192+
let variant2 = Variant::from_object(object);
193+
```
194+
195+
In 0.10.x, `new()` is sufficient for any type that implements `ToVariant`, such as the following:
196+
197+
```rust
198+
let variant = Variant::new(42);
199+
let variant = Variant::new(42.0);
200+
let variant2 = Variant::new(object);
201+
```
202+
203+
When converting from a variant to a Rust type, it previously was necessary to do the following:
204+
205+
```rust
206+
let integer64 = i64::from_variant(&variant_i64).unwrap();
207+
let float64 = f64::from_variant(&variant_f64).unwrap();
208+
let object = ObjectType::from_variant(&variant_object).unwrap();
209+
```
210+
211+
In 0.10.x, you can now cast your variants by using the `to()` function on `FromVariant`-enabled types, such as the following:
212+
213+
```rust
214+
// Note: If the compiler can infer your type, the turbofish `::<T>` is optional
215+
let integer64 = variant.to::<i64>().unwrap();
216+
let float64 = variant.to::<f64>().unwrap();
217+
let object = variant.to_object::<ObjectType>().unwrap(); // returns Ref<ObjectType>
218+
```
219+
220+
221+
### Transforms
222+
223+
Previously, transforms were defined by the matrix identities such as `m11`, `m12`; now, they are referred by the vector name for consistency.
224+
225+
For example: When creating an identity `Transform2D` in 0.9.x, you would create it using the following code:
226+
227+
```rust
228+
let tform = Transform2D::new(1.0, 0.0, 0.0, 1.0, 1.0, 1.0);
229+
```
230+
231+
In 0.10.x you now need to create it using `from_basis_origin` and use `a`, `b`, and `origin` vectors, such as the following:
232+
233+
```rust
234+
let tform = Transform2D::from_basis_origin(
235+
Vector2::new(1.0, 0.0),
236+
Vector2::new(0.0, 1.0),
237+
Vector2::new(1.0, 1.0),
238+
);
239+
```
240+
241+
### Vector types
242+
243+
The underlying vector library as well as the implementation have been fundamentally replaced. In 0.9.x, many of the goemetric types were thinly wrapping a separate library. This led to several wrapping classes such as `Point2`, `Size2` being removed now. In addition, other geometric types -- for example `Rect2`, `Quat`, `Transform`, `Plane` -- have all been changed, and certain convenience functions may not be available anymore, depending upon the struct.
244+
245+
For example: `Rect2` no longer has `width()` or `height()`, but lets you directly access its `size.x` or `size.y` fields.
246+
247+
### `ClassBuilder`
248+
249+
The [`ClassBuilder`](https://docs.rs/gdnative/latest/gdnative/prelude/struct.ClassBuilder.html) type has been extended to use the builder pattern when registering signals and properties.
250+
251+
In 0.9, registering a signal would look like the following:
252+
253+
```rust
254+
fn register_signals(builder: &ClassBuilder<Self>) {
255+
builder.add_signal(
256+
Signal {
257+
name: "signal1",
258+
args: &[],
259+
}
260+
);
261+
builder.add_signal(
262+
Signal {
263+
name: "signal2",
264+
args: &[SignalArgument {
265+
name: "myArg",
266+
default: 42.0.to_variant(),
267+
export_info: ExportInfo::new(VariantType::F64),
268+
usage: PropertyUsage::DEFAULT,
269+
}],
270+
});
271+
}
272+
```
273+
274+
In 0.10, this changes to:
275+
276+
```rust
277+
fn register_signals(builder: &ClassBuilder<Self>) {
278+
builder.signal("signal1").done();
279+
280+
builder.signal("signal2")
281+
.with_param_custom(
282+
SignalParam {
283+
name: "myArg",
284+
default: 42.0.to_variant(),
285+
export_info: ExportInfo::new(VariantType::F64),
286+
usage: PropertyUsage::DEFAULT,
287+
},
288+
).done();
289+
290+
// If you only need a default value, you can also register a signal like this:
291+
builder.signal("signal3")
292+
.with_param_default("myArg", 42.0.to_variant())
293+
.done()
294+
}
295+
```
296+
297+
298+
### Server singletons
299+
300+
Godot's server singletons have received a safety overhaul. As a result, all functions that take one or more parameters of type `Rid` are now marked `unsafe` and thus require being used inside an `unsafe` block or `unsafe` function.
301+
302+
In 0.9.x, creating a canvas_item and attaching it to a parent would be done as follows:
303+
```rust
304+
let vs = unsafe { VisualServer::godot_singleton() };
305+
let canvas = vs.canvas_create();
306+
let ci = vs.canvas_item_create();
307+
vs.canvas_item_set_parent(ci, canvas);
308+
```
309+
310+
In 0.10.x, you now must wrap the `canvas_item_set_parent` function in an `unsafe` block, such as follows:
311+
312+
```rust
313+
let vs = unsafe { VisualServer::godot_singleton() };
314+
let canvas = vs.canvas_create();
315+
let ci = vs.canvas_item_create();
316+
unsafe {
317+
vs.canvas_item_set_parent(ci, canvas);
318+
}
319+
```
320+
321+
#### Additional UB notes
322+
323+
The reason for this change was due to [issue #836](https://github.com/godot-rust/godot-rust/issues/836) being raised. Developers were able to demonstrate that you could easily cause undefined behavior when using any function that accepted `Rid` as a parameter, such as the following:
324+
325+
```rust
326+
let vs = unsafe { VisualServer::godot_singleton() };
327+
let canvas = vs.canvas_create();
328+
let vp = vs.viewport_create();
329+
vs.canvas_item_set_parent(vp, canvas); // crashes immediately
330+
vs.canvas_item_set_parent(canvas, canvas); // crashes at shutdown
331+
```

0 commit comments

Comments
 (0)