@@ -21,7 +21,9 @@ pub use signature::*;
21
21
pub ( crate ) use godot_convert:: convert_error:: * ;
22
22
23
23
use crate :: builtin:: * ;
24
- use crate :: engine:: global;
24
+ use crate :: engine:: global:: { self , PropertyHint , PropertyUsageFlags } ;
25
+ use crate :: property:: Var ;
26
+ use crate :: property:: { Export , PropertyHintInfo } ;
25
27
use godot_ffi as sys;
26
28
use registration:: method:: MethodParamOrReturnInfo ;
27
29
use sys:: { GodotFfi , GodotNullableFfi } ;
@@ -268,15 +270,119 @@ pub trait ArrayElement: GodotType {}
268
270
#[ derive( Debug , Clone ) ]
269
271
// Note: is not #[non_exhaustive], so adding fields is a breaking change. Mostly used internally at the moment though.
270
272
pub struct PropertyInfo {
273
+ /// Which type this property has.
274
+ ///
275
+ /// For objects this should be set to [`VariantType::Object`], and the `class_name` field to the actual name of the class.
276
+ ///
277
+ /// For [`Variant`] this should be set to [`VariantType::Nil`].
271
278
pub variant_type : VariantType ,
279
+
280
+ /// Which class this property is.
281
+ ///
282
+ /// This should be set to [`ClassName::none()`] unless the variant type is `Object`. You can use
283
+ /// [`GodotClass::class_name()`](crate::obj::GodotClass::class_name()) to get the right name to use here.
272
284
pub class_name : ClassName ,
285
+
286
+ /// The name of this property in Godot.
273
287
pub property_name : StringName ,
288
+
289
+ /// How the property is meant to be edited. See also [`PropertyHint`] in the Godot docs.
290
+ ///
291
+ /// [`PropertyHint`]: https://docs.godotengine.org/en/latest/classes/class_%40globalscope.html#enum-globalscope-propertyhint
274
292
pub hint : global:: PropertyHint ,
293
+
294
+ /// Extra information passed to Godot for this property, what this means depends on the `hint` value.
275
295
pub hint_string : GString ,
296
+
297
+ /// How this property should be used. See [`PropertyUsageFlags`] in Godot for the meaning.
298
+ ///
299
+ /// [`PropertyUsageFlags`]: https://docs.godotengine.org/en/latest/classes/class_%40globalscope.html#enum-globalscope-propertyusageflags
276
300
pub usage : global:: PropertyUsageFlags ,
277
301
}
278
302
279
303
impl PropertyInfo {
304
+ /// Create a new `PropertyInfo` representing a property named `property_name` with type `T`.
305
+ ///
306
+ /// This will generate property info equivalent to what a `#[var]` attribute would.
307
+ pub fn new_var < T : Var > ( property_name : & str ) -> Self {
308
+ <T as GodotConvert >:: Via :: property_info ( property_name) . with_hint_info ( T :: property_hint ( ) )
309
+ }
310
+
311
+ /// Create a new `PropertyInfo` representing an exported property named `property_name` with type `T`.
312
+ ///
313
+ /// This will generate property info equivalent to what an `#[export]` attribute would.
314
+ pub fn new_export < T : Export > ( property_name : & str ) -> Self {
315
+ <T as GodotConvert >:: Via :: property_info ( property_name)
316
+ . with_hint_info ( T :: default_export_info ( ) )
317
+ }
318
+
319
+ /// Change the `hint` and `hint_string` to be the given `hint_info`.
320
+ ///
321
+ /// See [`export_info_functions`](crate::property::export_info_functions) for functions that return appropriate `PropertyHintInfo`s for
322
+ /// various Godot annotations.
323
+ ///
324
+ /// # Examples
325
+ ///
326
+ /// Creating an `@export_range` property.
327
+ ///
328
+ // TODO: Make this nicer to use.
329
+ /// ```no_run
330
+ /// use godot::register::property::export_info_functions;
331
+ /// use godot::builtin::meta::PropertyInfo;
332
+ ///
333
+ /// let property = PropertyInfo::new_export::<f64>("my_range_property")
334
+ /// .with_hint_info(export_info_functions::export_range(
335
+ /// 0.0,
336
+ /// 10.0,
337
+ /// Some(0.1),
338
+ /// false,
339
+ /// false,
340
+ /// false,
341
+ /// false,
342
+ /// false,
343
+ /// false,
344
+ /// ));
345
+ /// ```
346
+ pub fn with_hint_info ( self , hint_info : PropertyHintInfo ) -> Self {
347
+ let PropertyHintInfo { hint, hint_string } = hint_info;
348
+
349
+ Self {
350
+ hint,
351
+ hint_string,
352
+ ..self
353
+ }
354
+ }
355
+
356
+ /// Create a new `PropertyInfo` representing a group in Godot.
357
+ ///
358
+ /// See [`EditorInspector`](https://docs.godotengine.org/en/latest/classes/class_editorinspector.html#class-editorinspector) in Godot for
359
+ /// more information.
360
+ pub fn new_group ( group_name : & str , group_prefix : & str ) -> Self {
361
+ Self {
362
+ variant_type : VariantType :: Nil ,
363
+ class_name : ClassName :: none ( ) ,
364
+ property_name : group_name. into ( ) ,
365
+ hint : PropertyHint :: NONE ,
366
+ hint_string : group_prefix. into ( ) ,
367
+ usage : PropertyUsageFlags :: GROUP ,
368
+ }
369
+ }
370
+
371
+ /// Create a new `PropertyInfo` representing a subgroup in Godot.
372
+ ///
373
+ /// See [`EditorInspector`](https://docs.godotengine.org/en/latest/classes/class_editorinspector.html#class-editorinspector) in Godot for
374
+ /// more information.
375
+ pub fn new_subgroup ( subgroup_name : & str , subgroup_prefix : & str ) -> Self {
376
+ Self {
377
+ variant_type : VariantType :: Nil ,
378
+ class_name : ClassName :: none ( ) ,
379
+ property_name : subgroup_name. into ( ) ,
380
+ hint : PropertyHint :: NONE ,
381
+ hint_string : subgroup_prefix. into ( ) ,
382
+ usage : PropertyUsageFlags :: SUBGROUP ,
383
+ }
384
+ }
385
+
280
386
/// Converts to the FFI type. Keep this object allocated while using that!
281
387
pub fn property_sys ( & self ) -> sys:: GDExtensionPropertyInfo {
282
388
use crate :: obj:: EngineBitfield as _;
@@ -305,6 +411,40 @@ impl PropertyInfo {
305
411
usage : global:: PropertyUsageFlags :: NONE . ord ( ) as u32 ,
306
412
}
307
413
}
414
+
415
+ /// Consumes self and turns it into a `sys::GDExtensionPropertyInfo`, should be used together with
416
+ /// [`free_owned_property_sys`](Self::free_owned_property_sys).
417
+ ///
418
+ /// This will leak memory unless used together with `free_owned_property_sys`.
419
+ pub ( crate ) fn into_owned_property_sys ( self ) -> sys:: GDExtensionPropertyInfo {
420
+ use crate :: obj:: EngineBitfield as _;
421
+ use crate :: obj:: EngineEnum as _;
422
+
423
+ sys:: GDExtensionPropertyInfo {
424
+ type_ : self . variant_type . sys ( ) ,
425
+ name : self . property_name . into_owned_string_sys ( ) ,
426
+ class_name : sys:: SysPtr :: force_mut ( self . class_name . string_sys ( ) ) ,
427
+ hint : u32:: try_from ( self . hint . ord ( ) ) . expect ( "hint.ord()" ) ,
428
+ hint_string : self . hint_string . into_owned_string_sys ( ) ,
429
+ usage : u32:: try_from ( self . usage . ord ( ) ) . expect ( "usage.ord()" ) ,
430
+ }
431
+ }
432
+
433
+ /// Properly frees a `sys::GDExtensionPropertyInfo` created by [`into_owned_property_sys`](Self::into_owned_property_sys).
434
+ ///
435
+ /// # Safety
436
+ ///
437
+ /// * Must only be used on a struct returned from a call to `into_owned_property_sys`, without modification.
438
+ /// * Must not be called more than once on a `sys::GDExtensionPropertyInfo` struct.
439
+ pub ( crate ) unsafe fn free_owned_property_sys ( info : sys:: GDExtensionPropertyInfo ) {
440
+ // SAFETY: This function was called on a pointer returned from `into_owned_property_sys`, thus both `info.name` and
441
+ // `info.hint_string` were created from calls to `into_owned_string_sys` on their respective types.
442
+ // Additionally this function isn't called more than once on a struct containing the same `name` or `hint_string` pointers.
443
+ unsafe {
444
+ let _name = StringName :: from_owned_string_sys ( info. name ) ;
445
+ let _hint_string = GString :: from_owned_string_sys ( info. hint_string ) ;
446
+ }
447
+ }
308
448
}
309
449
310
450
// ----------------------------------------------------------------------------------------------------------------------------------------------
0 commit comments