Skip to content

Commit 677684c

Browse files
bors[bot]toasteater
andauthored
Merge #615
615: Made Instance::new use NativeScript::new instead r=toasteater a=toasteater Unlike `Object::set_script`, this will also work in editors even if the script isn't registered as a tool script. Also modified CI to run tests in editor mode as well. Close #614 Co-authored-by: toasteater <[email protected]>
2 parents dfadfe1 + d1e2895 commit 677684c

File tree

8 files changed

+93
-33
lines changed

8 files changed

+93
-33
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,5 @@ script:
153153
mkdir ./project/lib;
154154
cp ../target/debug/libgdnative_test.so ./project/lib/;
155155
"Godot_v${GODOT_VER}-${GODOT_REL}_linux_headless.64" --path ./project/;
156+
"Godot_v${GODOT_VER}-${GODOT_REL}_linux_headless.64" -e --path ./project/ --run-editor-tests;
156157
fi

bindings_generator/src/api.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,10 @@ impl GodotClass {
137137

138138
pub fn is_singleton_thread_safe(&self) -> bool {
139139
assert!(self.singleton, "class is not a singleton");
140-
match self.name.as_str() {
141-
"VisualServer" | "PhysicsServer" | "Physics3DServer" | "Physics2DServer" => false,
142-
_ => true,
143-
}
140+
!matches!(
141+
self.name.as_str(),
142+
"VisualServer" | "PhysicsServer" | "Physics3DServer" | "Physics2DServer"
143+
)
144144
}
145145

146146
/// Returns the base class from `api` if `base_class` is not empty. Returns `None` otherwise.

gdnative-core/src/nativescript/class.rs

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -178,15 +178,26 @@ impl<T: NativeClass> Instance<T, Unique> {
178178
let gd_api = get_api();
179179
let nativescript_methods = crate::private::NativeScriptMethodTable::get(gd_api);
180180

181+
assert_ne!(
182+
std::ptr::null(),
183+
nativescript_methods.set_class_name,
184+
"NativeScript::set_class_name must be available"
185+
);
186+
assert_ne!(
187+
std::ptr::null(),
188+
nativescript_methods.set_library,
189+
"NativeScript::set_library must be available"
190+
);
191+
assert_ne!(
192+
std::ptr::null(),
193+
nativescript_methods.new,
194+
"NativeScript::new must be available"
195+
);
196+
181197
// The API functions take NUL-terminated C strings. &CStr is not used for its runtime cost.
182198
let class_name = b"NativeScript\0".as_ptr() as *const libc::c_char;
183199
let ctor = (gd_api.godot_get_class_constructor)(class_name).unwrap();
184200

185-
let set_class_name = nativescript_methods.set_class_name;
186-
let set_library = nativescript_methods.set_library;
187-
188-
let object_set_script = crate::private::ObjectMethodTable::get(gd_api).set_script;
189-
190201
let native_script =
191202
NonNull::new(ctor()).expect("NativeScript constructor should not return null");
192203
let native_script =
@@ -198,43 +209,43 @@ impl<T: NativeClass> Instance<T, Unique> {
198209
let script_class_name = GodotString::from(T::class_name());
199210
let mut args: [*const libc::c_void; 1] = [script_class_name.sys() as *const _];
200211
(gd_api.godot_method_bind_ptrcall)(
201-
set_class_name,
212+
nativescript_methods.set_class_name,
202213
native_script.sys().as_ptr(),
203214
args.as_mut_ptr(),
204215
std::ptr::null_mut(),
205216
);
206217

207218
let mut args: [*const libc::c_void; 1] = [crate::private::get_gdnative_library_sys()];
208219
(gd_api.godot_method_bind_ptrcall)(
209-
set_library,
220+
nativescript_methods.set_library,
210221
native_script.sys().as_ptr(),
211222
args.as_mut_ptr(),
212223
std::ptr::null_mut(),
213224
);
214225

215-
let owner = T::Base::construct();
216-
217-
assert_ne!(
218-
std::ptr::null_mut(),
219-
owner.sys(),
220-
"base object should not be null"
221-
);
222-
223-
let mut args: [*const libc::c_void; 1] = [native_script.sys().as_ptr()];
224-
(gd_api.godot_method_bind_ptrcall)(
225-
object_set_script,
226-
owner.sys(),
226+
let mut args: [*const sys::godot_variant; 0] = [];
227+
let variant = (gd_api.godot_method_bind_call)(
228+
nativescript_methods.new,
229+
native_script.sys().as_ptr(),
227230
args.as_mut_ptr(),
231+
0,
228232
std::ptr::null_mut(),
229233
);
230234

235+
let variant = Variant::from_sys(variant);
236+
237+
let owner = variant
238+
.try_to_object::<T::Base>()
239+
.expect("base object should be of the correct type (is the script registered?)")
240+
.assume_unique();
241+
231242
let script_ptr =
232243
(gd_api.godot_nativescript_get_userdata)(owner.sys()) as *const libc::c_void;
233244

234245
assert_ne!(
235246
std::ptr::null(),
236247
script_ptr,
237-
"script instance should not be null"
248+
"script instance should not be null (did the constructor fail?)"
238249
);
239250

240251
let script = T::UserData::clone_from_user_data_unchecked(script_ptr);

gdnative-core/src/private.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ macro_rules! make_method_table {
209209
}
210210

211211
make_method_table!(struct ObjectMethodTable for Object {
212-
set_script,
213212
get_class,
214213
is_class,
215214
});
@@ -226,4 +225,5 @@ make_method_table!(struct ReferenceMethodTable for Reference {
226225
make_method_table!(struct NativeScriptMethodTable for NativeScript {
227226
set_class_name,
228227
set_library,
228+
new,
229229
});

gdnative-derive/src/methods.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -209,12 +209,7 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
209209

210210
// only allow the "outer" style, aka #[thing] item.
211211
method.attrs.retain(|attr| {
212-
let correct_style = match attr.style {
213-
syn::AttrStyle::Outer => true,
214-
_ => false,
215-
};
216-
217-
if correct_style {
212+
if matches!(attr.style, syn::AttrStyle::Outer) {
218213
let last_seg = attr
219214
.path
220215
.segments
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[plugin]
2+
3+
name="editor_test_runner"
4+
description=""
5+
author=""
6+
version=""
7+
script="plugin.gd"
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
tool
2+
extends EditorPlugin
3+
4+
var gdn
5+
6+
func _enter_tree():
7+
var run_tests = false
8+
for arg in OS.get_cmdline_args():
9+
if arg == "--run-editor-tests":
10+
run_tests = true
11+
break
12+
if run_tests:
13+
_run_tests()
14+
else:
15+
print("Opening editor normally for the test project. To run tests, pass `--run-editor-tests` to the executable.")
16+
17+
func _run_tests():
18+
print(" -- Rust gdnative test suite:")
19+
gdn = GDNative.new()
20+
var status = false;
21+
22+
gdn.library = load("res://gdnative.gdnlib")
23+
24+
if gdn.initialize():
25+
status = gdn.call_native("standard_varcall", "run_tests", [])
26+
27+
gdn.terminate()
28+
else:
29+
print(" -- Could not load the gdnative library.")
30+
31+
if status:
32+
print(" -- Test run completed successfully.")
33+
else:
34+
print(" -- Test run completed with errors.")
35+
OS.exit_code = 1
36+
37+
print(" -- exiting.")
38+
get_tree().quit()
39+

test/project/project.godot

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,18 @@
66
; [section] ; section goes between []
77
; param=value ; assign values to parameters
88

9-
config_version=3
9+
config_version=4
10+
11+
_global_script_classes=[ ]
12+
_global_script_class_icons={
13+
14+
}
1015

1116
[application]
1217

1318
config/name="GodotRustTests"
1419
run/main_scene="res://Scene.tscn"
1520

16-
[rendering]
21+
[editor_plugins]
22+
23+
enabled=PoolStringArray( "editor_test_runner" )

0 commit comments

Comments
 (0)