Skip to content

Commit 139a251

Browse files
committed
- Add missing TypeStringHint impls so we can export Array<T> for all relevant types.
- Add test to ensure that GDScript and gdext properties are exported the same way
1 parent 43f5d2f commit 139a251

File tree

11 files changed

+802
-21
lines changed

11 files changed

+802
-21
lines changed

godot-core/src/builtin/array.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,12 @@ impl<T: GodotType + TypeStringHint> TypeStringHint for Array<T> {
682682
}
683683
}
684684

685+
impl TypeStringHint for VariantArray {
686+
fn type_string() -> String {
687+
format!("{}:Array", VariantType::Array as i32)
688+
}
689+
}
690+
685691
impl<T: GodotType> Property for Array<T> {
686692
type Intermediate = Self;
687693

godot-core/src/builtin/dictionary.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ use godot_ffi as sys;
99
use crate::builtin::meta::{FromGodot, ToGodot};
1010
use crate::builtin::{inner, Variant};
1111
use crate::obj::Share;
12-
use crate::property::{Export, ExportInfo, Property};
12+
use crate::property::{Export, ExportInfo, Property, TypeStringHint};
1313
use std::fmt;
1414
use std::marker::PhantomData;
1515
use std::ptr::addr_of_mut;
1616
use sys::types::OpaqueDictionary;
17-
use sys::{ffi_methods, interface_fn, AsUninit, GodotFfi};
17+
use sys::{ffi_methods, interface_fn, AsUninit, GodotFfi, VariantType};
1818

1919
use super::meta::impl_godot_as_self;
2020
use super::VariantArray;
@@ -344,6 +344,12 @@ impl Property for Dictionary {
344344
}
345345
}
346346

347+
impl TypeStringHint for Dictionary {
348+
fn type_string() -> String {
349+
format!("{}:Dictionary", VariantType::Dictionary as i32)
350+
}
351+
}
352+
347353
impl Export for Dictionary {
348354
fn default_export_info() -> ExportInfo {
349355
ExportInfo::with_hint_none()

godot-core/src/property.rs

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -312,15 +312,29 @@ pub mod export_info_functions {
312312
mod export_impls {
313313
use super::*;
314314
use crate::builtin::*;
315+
use godot_ffi as sys;
315316

316317
macro_rules! impl_property_by_clone {
317-
($Ty:ty => $variant_type:ident, no_export) => {
318+
($Ty:ty => $variant_type:ident; no_export) => {
318319
impl_property_by_clone!(@property $Ty => $variant_type);
320+
impl_property_by_clone!(@type_string_hint $Ty, $variant_type);
321+
};
322+
323+
($Ty:ty => $variant_type:ident, $type_string_name:ident; no_export) => {
324+
impl_property_by_clone!(@property $Ty => $variant_type);
325+
impl_property_by_clone!(@type_string_hint $Ty, $type_string_name);
319326
};
320327

321328
($Ty:ty => $variant_type:ident) => {
322329
impl_property_by_clone!(@property $Ty => $variant_type);
323330
impl_property_by_clone!(@export $Ty);
331+
impl_property_by_clone!(@type_string_hint $Ty, $variant_type);
332+
};
333+
334+
($Ty:ty => $variant_type:ident, $type_string_name:ident) => {
335+
impl_property_by_clone!(@property $Ty => $variant_type);
336+
impl_property_by_clone!(@export $Ty);
337+
impl_property_by_clone!(@type_string_hint $Ty, $type_string_name);
324338
};
325339

326340
(@property $Ty:ty => $variant_type:ident) => {
@@ -344,10 +358,20 @@ mod export_impls {
344358
}
345359
}
346360
};
361+
362+
(@type_string_hint $Ty:ty, $type_string_name:ident) => {
363+
impl TypeStringHint for $Ty {
364+
fn type_string() -> String {
365+
use sys::GodotFfi;
366+
let variant_type = <$Ty as $crate::builtin::meta::GodotType>::Ffi::variant_type();
367+
format!("{}:{}", variant_type as i32, stringify!($type_string_name))
368+
}
369+
}
370+
}
347371
}
348372

349373
// Bounding Boxes
350-
impl_property_by_clone!(Aabb => Aabb);
374+
impl_property_by_clone!(Aabb => Aabb, AABB);
351375
impl_property_by_clone!(Rect2 => Rect2);
352376
impl_property_by_clone!(Rect2i => Rect2i);
353377

@@ -388,28 +412,28 @@ mod export_impls {
388412
impl_property_by_clone!(PackedColorArray => PackedColorArray);
389413

390414
// Primitives
391-
impl_property_by_clone!(f64 => Float);
392-
impl_property_by_clone!(i64 => Int);
393-
impl_property_by_clone!(bool => Bool);
415+
impl_property_by_clone!(f64 => Float, float);
416+
impl_property_by_clone!(i64 => Int, int);
417+
impl_property_by_clone!(bool => Bool, bool);
394418

395419
// Godot uses f64 internally for floats, and if Godot tries to pass an invalid f32 into a rust property
396420
// then the property will just round the value or become inf.
397-
impl_property_by_clone!(f32 => Float);
421+
impl_property_by_clone!(f32 => Float, float);
398422

399423
// Godot uses i64 internally for integers, and if Godot tries to pass an invalid integer into a property
400424
// accepting one of the below values then rust will panic. In the editor this will appear as the property
401425
// failing to be set to a value and an error printed in the console. During runtime this will crash the
402426
// program and print the panic from rust stating that the property cannot store the value.
403-
impl_property_by_clone!(i32 => Int);
404-
impl_property_by_clone!(i16 => Int);
405-
impl_property_by_clone!(i8 => Int);
406-
impl_property_by_clone!(u32 => Int);
407-
impl_property_by_clone!(u16 => Int);
408-
impl_property_by_clone!(u8 => Int);
427+
impl_property_by_clone!(i32 => Int, int);
428+
impl_property_by_clone!(i16 => Int, int);
429+
impl_property_by_clone!(i8 => Int, int);
430+
impl_property_by_clone!(u32 => Int, int);
431+
impl_property_by_clone!(u16 => Int, int);
432+
impl_property_by_clone!(u8 => Int, int);
409433

410434
// Callables are useless when exported to the editor, so we only need to make them available as
411435
// properties.
412-
impl_property_by_clone!(Callable => Callable, no_export);
436+
impl_property_by_clone!(Callable => Callable; no_export);
413437

414438
// RIDs when exported act slightly weird. They are largely read-only, however you can reset them to their
415439
// default value. This seems to me very unintuitive. Since if we are storing an RID we would likely not
@@ -418,7 +442,7 @@ mod export_impls {
418442
//
419443
// Additionally, RIDs aren't persistent, and can sometimes behave a bit weirdly when passed from the
420444
// editor to the runtime.
421-
impl_property_by_clone!(Rid => Rid, no_export);
445+
impl_property_by_clone!(Rid => Rid, RID; no_export);
422446

423447
// impl_property_by_clone!(Signal => Signal);
424448
}

itest/godot/.godot/global_script_class_cache.cfg

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ list=Array[Dictionary]([{
55
"language": &"GDScript",
66
"path": "res://TestRunner.gd"
77
}, {
8+
"base": &"Node",
9+
"class": &"PropertyTemplateGDScript",
10+
"icon": "",
11+
"language": &"GDScript",
12+
"path": "res://PropertyTemplate.gd"
13+
}, {
814
"base": &"RefCounted",
915
"class": &"TestStats",
1016
"icon": "",

itest/godot/PropertyTemplate.gd

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# This Source Code Form is subject to the terms of the Mozilla Public
2+
# License, v. 2.0. If a copy of the MPL was not distributed with this
3+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
class_name PropertyTemplateGDScript
6+
extends Node
7+
8+
# Base types
9+
10+
var property_bool: bool
11+
var property_i64: int
12+
var property_i32: int
13+
var property_i16: int
14+
var property_i8: int
15+
var property_u32: int
16+
var property_u16: int
17+
var property_u8: int
18+
var property_f64: float
19+
var property_f32: float
20+
var property_GodotString: String
21+
var property_Vector2: Vector2
22+
var property_Vector2i: Vector2i
23+
var property_Rect2: Rect2
24+
var property_Rect2i: Rect2i
25+
var property_Vector3: Vector3
26+
var property_Vector3i: Vector3i
27+
var property_Transform2D: Transform2D
28+
var property_Vector4: Vector4
29+
var property_Vector4i: Vector4i
30+
var property_Plane: Plane
31+
var property_Quaternion: Quaternion
32+
var property_Aabb: AABB
33+
var property_Basis: Basis
34+
var property_Transform3D: Transform3D
35+
var property_Projection: Projection
36+
var property_Color: Color
37+
var property_StringName: StringName
38+
var property_NodePath: NodePath
39+
var property_Rid: RID
40+
var property_Gd_Node: Node
41+
var property_Gd_Resource: Resource
42+
var property_Callable: Callable
43+
var property_Dictionary: Dictionary
44+
var property_VariantArray: Array
45+
var property_PackedByteArray: PackedByteArray
46+
var property_PackedInt32Array: PackedInt32Array
47+
var property_PackedInt64Array: PackedInt64Array
48+
var property_PackedFloat32Array: PackedFloat32Array
49+
var property_PackedFloat64Array: PackedFloat64Array
50+
var property_PackedStringArray: PackedStringArray
51+
var property_PackedVector2Array: PackedVector2Array
52+
var property_PackedVector3Array: PackedVector3Array
53+
var property_PackedColorArray: PackedColorArray
54+
55+
# Types nested in arrays
56+
57+
var property_array_bool: Array[bool]
58+
var property_array_i64: Array[int]
59+
var property_array_i32: Array[int]
60+
var property_array_i16: Array[int]
61+
var property_array_i8: Array[int]
62+
var property_array_u32: Array[int]
63+
var property_array_u16: Array[int]
64+
var property_array_u8: Array[int]
65+
var property_array_f64: Array[float]
66+
var property_array_f32: Array[float]
67+
var property_array_GodotString: Array[String]
68+
var property_array_Vector2: Array[Vector2]
69+
var property_array_Vector2i: Array[Vector2i]
70+
var property_array_Rect2: Array[Rect2]
71+
var property_array_Rect2i: Array[Rect2i]
72+
var property_array_Vector3: Array[Vector3]
73+
var property_array_Vector3i: Array[Vector3i]
74+
var property_array_Transform2D: Array[Transform2D]
75+
var property_array_Vector4: Array[Vector4]
76+
var property_array_Vector4i: Array[Vector4i]
77+
var property_array_Plane: Array[Plane]
78+
var property_array_Quaternion: Array[Quaternion]
79+
var property_array_Aabb: Array[AABB]
80+
var property_array_Basis: Array[Basis]
81+
var property_array_Transform3D: Array[Transform3D]
82+
var property_array_Projection: Array[Projection]
83+
var property_array_Color: Array[Color]
84+
var property_array_StringName: Array[StringName]
85+
var property_array_NodePath: Array[NodePath]
86+
var property_array_Rid: Array[RID]
87+
var property_array_Gd_Node: Array[Node]
88+
var property_array_Gd_Resource: Array[Resource]
89+
var property_array_Callable: Array[Callable]
90+
var property_array_Dictionary: Array[Dictionary]
91+
var property_array_VariantArray: Array[Array]
92+
var property_array_PackedByteArray: Array[PackedByteArray]
93+
var property_array_PackedInt32Array: Array[PackedInt32Array]
94+
var property_array_PackedInt64Array: Array[PackedInt64Array]
95+
var property_array_PackedFloat32Array: Array[PackedFloat32Array]
96+
var property_array_PackedFloat64Array: Array[PackedFloat64Array]
97+
var property_array_PackedStringArray: Array[PackedStringArray]
98+
var property_array_PackedVector2Array: Array[PackedVector2Array]
99+
var property_array_PackedVector3Array: Array[PackedVector3Array]
100+
var property_array_PackedColorArray: Array[PackedColorArray]
101+
102+
# Exporting base types
103+
104+
@export var export_bool: bool
105+
@export var export_i64: int
106+
@export var export_i32: int
107+
@export var export_i16: int
108+
@export var export_i8: int
109+
@export var export_u32: int
110+
@export var export_u16: int
111+
@export var export_u8: int
112+
@export var export_f64: float
113+
@export var export_f32: float
114+
@export var export_GodotString: String
115+
@export var export_Vector2: Vector2
116+
@export var export_Vector2i: Vector2i
117+
@export var export_Rect2: Rect2
118+
@export var export_Rect2i: Rect2i
119+
@export var export_Vector3: Vector3
120+
@export var export_Vector3i: Vector3i
121+
@export var export_Transform2D: Transform2D
122+
@export var export_Vector4: Vector4
123+
@export var export_Vector4i: Vector4i
124+
@export var export_Plane: Plane
125+
@export var export_Quaternion: Quaternion
126+
@export var export_Aabb: AABB
127+
@export var export_Basis: Basis
128+
@export var export_Transform3D: Transform3D
129+
@export var export_Projection: Projection
130+
@export var export_Color: Color
131+
@export var export_StringName: StringName
132+
@export var export_NodePath: NodePath
133+
@export var export_Rid: RID
134+
@export var export_Gd_Node: Node
135+
@export var export_Gd_Resource: Resource
136+
@export var export_Callable: Callable
137+
@export var export_Dictionary: Dictionary
138+
@export var export_VariantArray: Array
139+
@export var export_PackedByteArray: PackedByteArray
140+
@export var export_PackedInt32Array: PackedInt32Array
141+
@export var export_PackedInt64Array: PackedInt64Array
142+
@export var export_PackedFloat32Array: PackedFloat32Array
143+
@export var export_PackedFloat64Array: PackedFloat64Array
144+
@export var export_PackedStringArray: PackedStringArray
145+
@export var export_PackedVector2Array: PackedVector2Array
146+
@export var export_PackedVector3Array: PackedVector3Array
147+
@export var export_PackedColorArray: PackedColorArray
148+
149+
# Exporting types nested in arrays
150+
151+
@export var export_array_bool: Array[bool]
152+
@export var export_array_i64: Array[int]
153+
@export var export_array_i32: Array[int]
154+
@export var export_array_i16: Array[int]
155+
@export var export_array_i8: Array[int]
156+
@export var export_array_u32: Array[int]
157+
@export var export_array_u16: Array[int]
158+
@export var export_array_u8: Array[int]
159+
@export var export_array_f64: Array[float]
160+
@export var export_array_f32: Array[float]
161+
@export var export_array_GodotString: Array[String]
162+
@export var export_array_Vector2: Array[Vector2]
163+
@export var export_array_Vector2i: Array[Vector2i]
164+
@export var export_array_Rect2: Array[Rect2]
165+
@export var export_array_Rect2i: Array[Rect2i]
166+
@export var export_array_Vector3: Array[Vector3]
167+
@export var export_array_Vector3i: Array[Vector3i]
168+
@export var export_array_Transform2D: Array[Transform2D]
169+
@export var export_array_Vector4: Array[Vector4]
170+
@export var export_array_Vector4i: Array[Vector4i]
171+
@export var export_array_Plane: Array[Plane]
172+
@export var export_array_Quaternion: Array[Quaternion]
173+
@export var export_array_Aabb: Array[AABB]
174+
@export var export_array_Basis: Array[Basis]
175+
@export var export_array_Transform3D: Array[Transform3D]
176+
@export var export_array_Projection: Array[Projection]
177+
@export var export_array_Color: Array[Color]
178+
@export var export_array_StringName: Array[StringName]
179+
@export var export_array_NodePath: Array[NodePath]
180+
@export var export_array_Rid: Array[RID]
181+
@export var export_array_Gd_Node: Array[Node]
182+
@export var export_array_Gd_Resource: Array[Resource]
183+
@export var export_array_Callable: Array[Callable]
184+
@export var export_array_Dictionary: Array[Dictionary]
185+
@export var export_array_VariantArray: Array[Array]
186+
@export var export_array_PackedByteArray: Array[PackedByteArray]
187+
@export var export_array_PackedInt32Array: Array[PackedInt32Array]
188+
@export var export_array_PackedInt64Array: Array[PackedInt64Array]
189+
@export var export_array_PackedFloat32Array: Array[PackedFloat32Array]
190+
@export var export_array_PackedFloat64Array: Array[PackedFloat64Array]
191+
@export var export_array_PackedStringArray: Array[PackedStringArray]
192+
@export var export_array_PackedVector2Array: Array[PackedVector2Array]
193+
@export var export_array_PackedVector3Array: Array[PackedVector3Array]
194+
@export var export_array_PackedColorArray: Array[PackedColorArray]
195+
196+
# Exporting with custom hints
197+
198+
@export_file var export_file: String
199+
@export_file("*.txt") var export_file_wildcard_txt: String
200+
@export_global_file var export_global_file: String
201+
@export_global_file("*.png") var export_global_file_wildcard_png: String
202+
@export_dir var export_dir: String
203+
@export_global_dir var export_global_dir: String
204+
@export_multiline var export_multiline: String
205+
@export_range(0, 20) var export_range_float_0_20: float
206+
@export_range(-10, 20, 0.2) var export_range_float_neg_10_20_02: float
207+
@export_range(0, 100, 1, "or_greater", "or_less") var export_range_int_0_100_1_or_greater_or_less: int
208+
@export_exp_easing var export_exp_easing: float
209+
@export_color_no_alpha var export_color_no_alpha: Color
210+
@export_node_path("Button", "TouchScreenButton") var export_node_path_button_touch_screen_button: NodePath
211+
@export_flags("Fire", "Water", "Earth", "Wind") var export_flags_fire_water_earth_wind: int
212+
@export_flags("Self:4", "Allies:8", "Foes:16") var export_flags_self_4_allies_8_foes_16: int
213+
@export_flags_2d_physics var export_flags_2d_physics: int
214+
@export_flags_2d_render var export_flags_2d_render: int
215+
@export_flags_2d_navigation var export_flags_2d_navigation: int
216+
@export_flags_3d_physics var export_flags_3d_physics: int
217+
@export_flags_3d_render var export_flags_3d_render: int
218+
@export_flags_3d_navigation var export_flags_3d_navigation: int
219+
@export_enum("Warrior", "Magician", "Thief") var export_enum_int_warrior_magician_thief: int
220+
@export_enum("Slow:30", "Average:60", "VeryFast:200") var export_enum_int_slow_30_average_60_very_fast_200: int
221+
@export_enum("Rebecca", "Mary", "Leah") var export_enum_string_rebecca_mary_leah: String

itest/godot/TestRunner.gd

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,15 @@ func _ready():
5353
if method_name.begins_with("test_"):
5454
gdscript_tests.push_back(await suite.run_test(suite, method_name))
5555

56+
var property_template = PropertyTemplateGDScript.new()
57+
5658
var success: bool = rust_runner.run_all_tests(
5759
gdscript_tests,
5860
gdscript_suites.size(),
5961
allow_focus,
6062
self,
61-
filters
63+
filters,
64+
property_template
6265
)
6366

6467
if success:

0 commit comments

Comments
 (0)