Skip to content

Commit f4e9e6b

Browse files
authored
Merge pull request #1556 from godot-rust/qol/non-null-error
Follow up Godot 4.7 nullability changes
2 parents f8a28c7 + 0dbbb1b commit f4e9e6b

5 files changed

Lines changed: 52 additions & 32 deletions

File tree

godot-core/src/obj/raw_gd.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,15 @@ impl<T: GodotClass> RawGd<T> {
126126
U: GodotClass,
127127
{
128128
self.is_null() // Null can be cast to anything.
129-
|| self.as_object_ref().is_class(&U::class_id().to_gstring())
129+
|| {
130+
// is_class() parameter changed from GString to StringName in Godot 4.7.
131+
#[cfg(since_api = "4.7")]
132+
let class_name = U::class_id().to_string_name();
133+
#[cfg(before_api = "4.7")]
134+
let class_name = U::class_id().to_gstring();
135+
136+
self.as_object_ref().is_class(&class_name)
137+
}
130138
}
131139

132140
/// Returns `Ok(cast_obj)` on success, `Err(self)` on error

godot-core/src/tools/autoload.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,13 @@ where
106106

107107
let autoload_path = NodePath::from(&format!("/root/{autoload_name}"));
108108

109+
// get_root() return type changed from Option<Gd<Window>> to Gd<Window> in Godot 4.7.
110+
#[cfg(before_api = "4.7")]
109111
let root = scene_tree
110112
.get_root()
111113
.ok_or_else(|| ConvertError::new("scene tree root not available"))?;
114+
#[cfg(since_api = "4.7")]
115+
let root = scene_tree.get_root();
112116

113117
let autoload_node = root
114118
.try_get_node_as::<Node>(&autoload_path)

itest/rust/src/engine_tests/native_st_niche_audio_test.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ fn native_audio_structure_out_parameter() {
116116
.unwrap()
117117
.cast::<SceneTree>();
118118

119+
#[cfg(since_api = "4.7")]
120+
tree.get_root().add_child(&player);
121+
#[cfg(before_api = "4.7")]
119122
tree.get_root().unwrap().add_child(&player);
120123
player.set_stream(&generator);
121124

itest/rust/src/object_tests/object_arg_test.rs

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

88
use godot::builtin::{Variant, vslice};
9-
use godot::classes::{ClassDb, Node, RefCounted, ResourceFormatLoader, ResourceLoader};
9+
use godot::classes::{ClassDb, Node, RefCounted, ResourceFormatLoader, ResourceLoader, Script};
1010
use godot::global;
1111
use godot::meta::ToGodot;
1212
use godot::obj::{Gd, NewAlloc, NewGd, Singleton};
@@ -65,12 +65,13 @@ fn object_arg_option_owned() {
6565

6666
#[itest]
6767
fn object_arg_option_borrowed() {
68-
with_objects(|manual, refc| {
69-
let db = ClassDb::singleton();
70-
let a = db.class_set_property(Some(&manual), "name", &Variant::from("hello"));
71-
let b = db.class_set_property(Some(&refc), "value", &Variant::from(-123));
72-
(a, b)
73-
});
68+
let mut node = Node::new_alloc();
69+
let script = create_gdscript("extends Node");
70+
71+
node.set_script(Some(&script));
72+
assert!(node.get_script().is_some());
73+
74+
node.free();
7475
}
7576

7677
/*
@@ -88,42 +89,43 @@ fn object_arg_option_borrowed_outer() {
8889
#[itest]
8990
fn object_arg_option_borrowed_mut() {
9091
// If you have an Option<&mut Gd<T>>, you can use as_deref() to get Option<&Gd<T>>.
92+
let mut node = Node::new_alloc();
93+
let mut script = create_gdscript("extends Node").upcast();
94+
let script_opt: Option<&mut Gd<Script>> = Some(&mut script);
9195

92-
with_objects(|mut manual, mut refc| {
93-
let db = ClassDb::singleton();
94-
95-
let manual_opt: Option<&mut Gd<Node>> = Some(&mut manual);
96-
let refc_opt: Option<&mut Gd<RefcPayload>> = Some(&mut refc);
96+
node.set_script(script_opt.as_deref());
97+
assert!(node.get_script().is_some());
9798

98-
let a = db.class_set_property(manual_opt.as_deref(), "name", &Variant::from("hello"));
99-
let b = db.class_set_property(refc_opt.as_deref(), "value", &Variant::from(-123));
100-
(a, b)
101-
});
99+
node.free();
102100
}
103101

104102
#[itest]
105103
fn object_arg_option_none() {
106-
let manual: Option<Gd<Node>> = None;
107-
let refc: Option<Gd<RefcPayload>> = None;
104+
let script = Some(create_gdscript("extends Node"));
105+
let no_script = None::<Gd<Script>>;
106+
107+
// Pass Some first, to change internal state.
108+
let mut node = Node::new_alloc();
109+
node.set_script(script.as_ref());
110+
assert_eq!(node.get_script(), script.map(|s| s.upcast()));
108111

109-
// Will emit errors but should not crash.
110-
let db = ClassDb::singleton();
111-
let error = db.class_set_property(manual.as_ref(), "name", &Variant::from("hello"));
112-
assert_eq!(error, global::Error::ERR_UNAVAILABLE);
112+
// Verify None option can be passed to an engine API accepting Option<Gd<T>>.
113+
node.set_script(no_script.as_ref());
114+
assert_eq!(node.get_script(), None);
113115

114-
let error = db.class_set_property(refc.as_ref(), "value", &Variant::from(-123));
115-
assert_eq!(error, global::Error::ERR_UNAVAILABLE);
116+
node.free();
116117
}
117118

118119
#[itest]
119120
fn object_arg_null_arg() {
120-
// Will emit errors but should not crash.
121-
let db = ClassDb::singleton();
122-
let error = db.class_set_property(Gd::null_arg(), "name", &Variant::from("hello"));
123-
assert_eq!(error, global::Error::ERR_UNAVAILABLE);
124-
125-
let error = db.class_set_property(Gd::null_arg(), "value", &Variant::from(-123));
126-
assert_eq!(error, global::Error::ERR_UNAVAILABLE);
121+
// Verify null_arg() can be passed to an engine API accepting Option<Gd<T>>.
122+
let mut node = Node::new_alloc();
123+
node.set_script(&create_gdscript("extends Node"));
124+
assert!(node.get_script().is_some());
125+
126+
node.set_script(Gd::<Script>::null_arg());
127+
assert_eq!(node.get_script(), None);
128+
node.free();
127129
}
128130

129131
// Regression test for https://github.com/godot-rust/gdext/issues/835.

itest/rust/src/register_tests/rpc_test.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ fn node_enters_tree() {
9797
.cast::<SceneTree>();
9898
scene_tree.set_multiplayer(MultiplayerApi::create_default_interface().as_ref());
9999

100+
#[cfg(since_api = "4.7")]
101+
let mut root = scene_tree.get_root();
102+
#[cfg(before_api = "4.7")]
100103
let mut root = scene_tree.get_root().unwrap();
101104
root.add_child(&node);
102105
root.remove_child(&node);

0 commit comments

Comments
 (0)