godot-core 0.5.1

Internal crate used by godot-rust
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
/*
 * Copyright (c) godot-rust; Bromeon and contributors.
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

use std::{fmt, ops};

use godot_ffi::is_main_thread;

use crate::builtin::{Callable, Variant};
use crate::meta::error::ConvertError;
use crate::meta::shape::GodotShape;
use crate::meta::{ClassId, FromGodot, GodotConvert, ToGodot};
use crate::obj::guards::DynGdRef;
use crate::obj::{AsDyn, Bounds, DynGdMut, Gd, GodotClass, Inherits, OnEditor, bounds};
use crate::registry::class::{get_dyn_implementor_class_ids, try_dynify_object};
use crate::registry::info::PropertyHintInfo;
use crate::registry::property::{Export, Var};
use crate::{meta, sys};

/// Smart pointer integrating Rust traits via `dyn` dispatch.
///
/// `DynGd<T, D>` extends a Godot object [`Gd<T>`] with functionality for Rust's trait dynamic dispatch.  \
/// In this context, the type parameters have the following meaning:
/// - `T` is the Godot class.
/// - `D` is a trait object `dyn Trait`, where `T: Trait`.
///
/// To register the `T` -> `D` relation with godot-rust, `T` must implement [`AsDyn<D>`]. This can be automated with the
/// [`#[godot_dyn]`](../register/attr.godot_dyn.html) attribute macro.
///
/// # Construction and API
///
/// You can convert between `Gd` and `DynGd` using [`Gd::into_dyn()`] and [`DynGd::into_gd()`]. The former sometimes needs an explicit
/// `::<dyn Trait>` type argument, but can often be inferred.
///
/// The `DynGd` API is very close to `Gd`. In fact, both `Deref` and `DerefMut` are implemented for `DynGd` -> `Gd`, so you can access all the
/// underlying `Gd` methods as well as Godot class APIs directly.
///
/// The main new parts are two methods [`dyn_bind()`][Self::dyn_bind] and [`dyn_bind_mut()`][Self::dyn_bind_mut]. These are very similar to `Gd`'s
/// [`bind()`][Gd::bind] and [`bind_mut()`][Gd::bind_mut], but return a reference guard to the trait object `D` instead of the Godot class `T`.
///
/// # Example
///
/// ```no_run
/// use godot::obj::{Gd, DynGd,NewGd};
/// use godot::register::{godot_dyn, GodotClass};
/// use godot::classes::RefCounted;
///
/// #[derive(GodotClass)]
/// #[class(init)]
/// struct Monster {
///     #[init(val = 100)]
///     hitpoints: u16,
/// }
///
/// trait Health {
///     fn is_alive(&self) -> bool;
///     fn deal_damage(&mut self, damage: u16);
/// }
///
/// // The #[godot_dyn] attribute macro registers the dynamic relation in godot-rust.
/// // Traits are implemented as usual.
/// #[godot_dyn]
/// impl Health for Monster {
///     fn is_alive(&self) -> bool {
///         self.hitpoints > 0
///     }
///
///     fn deal_damage(&mut self, damage: u16) {
///         self.hitpoints = self.hitpoints.saturating_sub(damage);
///     }
/// }
///
/// // Create a Gd<Monster> and convert it -> DynGd<Monster, dyn Health>.
/// let monster = Monster::new_gd();
/// let dyn_monster = monster.into_dyn::<dyn Health>();
///
/// // Now upcast it to its base class -> type is DynGd<RefCounted, dyn Health>.
/// let mut dyn_monster = dyn_monster.upcast::<RefCounted>();
///
/// // Due to RefCounted abstraction, you can no longer access concrete Monster properties.
/// // However, the trait Health is still accessible through dyn_bind().
/// assert!(dyn_monster.dyn_bind().is_alive());
///
/// // To mutate the object, call dyn_bind_mut(). Rust borrow rules apply.
/// let mut guard = dyn_monster.dyn_bind_mut();
/// guard.deal_damage(120);
/// assert!(!guard.is_alive());
/// ```
///
/// # Polymorphic `dyn` re-enrichment
///
/// When passing `DynGd<T, D>` to Godot, you will lose the `D` part of the type inside the engine, because Godot doesn't know about Rust traits.
/// The trait methods won't be accessible through GDScript, either.
///
/// When _receiving_ objects from Godot, the [`FromGodot`] trait is used to convert values to their Rust counterparts. `FromGodot` allows you to
/// use types in `#[func]` parameters or extract elements from arrays, among others. If you now receive a trait-enabled object back from Godot,
/// you can easily obtain it as `Gd<T>` -- but what if you need the original `DynGd<T, D>` back? If `T` is concrete and directly implements `D`,
/// then [`Gd::into_dyn()`] is of course possible. But in reality, you may have a polymorphic base class such as `RefCounted` or `Node` and
/// want to ensure that trait object `D` dispatches to the correct subclass, without manually checking every possible candidate.
///
/// To stay with the above example: let's say `Health` is implemented for two classes `Monster` and `Knight`. You now have a
/// `DynGd<RefCounted, dyn Health>`, which can represent either of the two classes. We pass this to Godot (e.g. as a `Variant`), and then back.
///
/// ```no_run
/// # use godot::prelude::*;
/// trait Health { /* ... */ }
///
/// #[derive(GodotClass)]
/// # #[class(init)]
/// struct Monster { /* ... */ }
/// #[godot_dyn]
/// impl Health for Monster { /* ... */ }
///
/// #[derive(GodotClass)]
/// # #[class(init)]
/// struct Knight { /* ... */ }
/// #[godot_dyn]
/// impl Health for Knight { /* ... */ }
///
/// // Let's construct a DynGd, and pass it to Godot as a Variant.
/// # let runtime_condition = true;
/// let variant = if runtime_condition {
///     // DynGd<Knight, dyn Health>
///     Knight::new_gd().into_dyn::<dyn Health>().to_variant()
/// } else {
///     // DynGd<Monster, dyn Health>
///     Monster::new_gd().into_dyn::<dyn Health>().to_variant()
/// };
///
/// // Now convert back into a DynGd -- but we don't know the concrete type.
/// // We can still represent it as DynGd<RefCounted, dyn Health>.
/// let dyn_gd: DynGd<RefCounted, dyn Health> = variant.to();
/// // Now work with the abstract object as usual.
/// ```
///
/// Any `Gd<T>` where `T` is an engine class can attempt conversion to `DynGd<T, D>` with [`Gd::try_dynify()`] as well.
///
/// ```no_run
/// # use godot::prelude::*;
/// # use godot::classes::Node2D;
/// # // ShapeCast2D is marked as experimental and thus not included in the doctests.
/// # // We use this mock to showcase some real-world usage.
/// # struct FakeShapeCastCollider2D {}
///
/// # impl FakeShapeCastCollider2D {
/// #     fn get_collider(&self, _idx: i32) -> Option<Gd<Node2D>> { Some(Node2D::new_alloc()) }
/// # }
///
/// trait Pushable { /* ... */ }
///
/// # let my_shapecast = FakeShapeCastCollider2D {};
/// # let idx = 1;
/// // We can try to convert `Gd<T>` into `DynGd<T, D>`.
/// let node: Option<DynGd<Node2D, dyn Pushable>> =
///     my_shapecast.get_collider(idx).and_then(
///         |obj| obj.try_dynify().ok()
///     );
///
/// // An object is returned after failed conversion, similarly to `Gd::try_cast()`.
/// # let some_node = Node::new_alloc();
/// match some_node.try_dynify::<dyn Pushable>() {
///     Ok(dyn_gd) => (),
///     Err(some_node) => godot_warn!("Failed to convert {some_node} into dyn Pushable!"),
/// }
/// ```
///
/// When converting from Godot back into `DynGd`, we say that the `dyn Health` trait object is _re-enriched_.
///
/// godot-rust achieves this thanks to the registration done by `#[godot_dyn]`: the library knows for which classes `Health` is implemented,
/// and it can query the dynamic type of the object. Based on that type, it can find the `impl Health` implementation matching the correct class.
/// Behind the scenes, everything is wired up correctly so that you can restore the original `DynGd` even after it has passed through Godot.
///
/// # Exporting
///
/// [Like `Gd<T>`](struct.Gd.html#exporting), using `#[export]` with `DynGd<T, D>` is possible only via [`OnEditor`] or [`Option`].
/// `DynGd<T, D>` can also be exported directly as an element of an array such as `Array<DynGd<T, D>>`.
///
/// When talking about "exporting", the following paragraphs assume that you wrap `DynGd` in one of those types.
///
/// In cases where `T: AsDyn<D>` (the trait is directly implemented on the user class, i.e. no upcasting), exporting `DynGd<T, D>` is
/// equivalent to exporting `Gd<T>` regarding Inspector UI.
///
/// ## Node-based classes
///
/// If `T` inherits `Node`, exporting `DynGd<T, D>` works identically to `Gd<T>`.
///
/// If you try to assign a class from the editor that does not implement trait `D`, Godot will report a conversion-failed error,
/// but it will only do so when accessing the given value.
///
/// ## Resource-based classes
///
/// If `T` inherits `Resource`, exporting `DynGd<T, D>>` will limit the available choices to known implementors of the trait `D`.
///
/// For example, let's say you have four Rust classes:
///
/// | Class        | Inherits   | Implements trait |
/// |--------------|------------|------------------|
/// | `Bullet`     | `Resource` | `Projectile`     |
/// | `Rocket`     | `Resource` | `Projectile`     |
/// | `BulletNode` | `Node`     | `Projectile`     |
/// | `Tower`      | `Resource` | (none)           |
///
/// Then, an exported `DynGd<Resource, dyn Projectile>` would be visible in Godot's Inspector UI with a drop-down field, i.e. users can assign
/// only objects of certain classes. **The available options for the drop-down are `Bullet` and `Rocket`.** The class `BulletNode` is not
/// available because it's not a `Resource`, and `Tower` is not because it doesn't implement the `Projectile` trait.
///
/// # Type inference
///
/// If a class implements more than one `AsDyn<D>` relation (usually via `#[godot_dyn]`), type inference will only work when the trait
/// used for `D` explicitly declares a `: 'static` bound.
/// Otherwise, if only one `impl AsDyn` is present for a given class, the type can always be inferred.
///
/// ```no_run
/// # use godot::prelude::*;
/// trait Health: 'static { /* ... */ }
///
/// // Exact equivalent to:
/// trait OtherHealth
/// where
///     Self: 'static
/// { /* ... */ }
///
/// trait NoInference { /* ... */ }
///
/// #[derive(GodotClass)]
/// # #[class(init)]
/// struct Monster { /* ... */ }
///
/// #[godot_dyn]
/// impl Health for Monster { /* ... */ }
///
/// #[godot_dyn]
/// impl NoInference for Monster { /* ... */ }
///
/// // Two example functions accepting trait object, to check type inference.
/// fn deal_damage(h: &mut dyn Health) { /* ... */ }
/// fn no_inference(i: &mut dyn NoInference) { /* ... */ }
///
/// // Type can be inferred since 'static bound is explicitly declared for Health trait.
/// let mut dyn_gd = Monster::new_gd().into_dyn();
/// deal_damage(&mut *dyn_gd.dyn_bind_mut());
///
/// // Otherwise type can't be properly inferred.
/// let mut dyn_gd = Monster::new_gd().into_dyn::<dyn NoInference>();
/// no_inference(&mut *dyn_gd.dyn_bind_mut());
/// ```
///
/// ```compile_fail
/// # use godot::prelude::*;
/// trait Health { /* ... */ }
///
/// trait OtherTrait { /* ... */ }
///
/// #[derive(GodotClass)]
/// # #[class(init)]
/// struct Monster { /* ... */ }
/// #[godot_dyn]
/// impl Health for Monster { /* ... */ }
/// #[godot_dyn]
/// impl OtherTrait for Monster { /* ... */ }
///
/// fn deal_damage(h: &mut dyn Health) { /* ... */ }
///
/// // Type can't be inferred.
/// // Would result in confusing compilation error
/// // since compiler would try to enforce 'static *lifetime* (&'static mut ...) on our reference.
/// let mut dyn_gd = Monster::new_gd().into_dyn();
/// deal_damage(&mut *dyn_gd.dyn_bind_mut());
/// ```
pub struct DynGd<T, D>
where
    // T does _not_ require AsDyn<D> here. Otherwise, it's impossible to upcast (without implementing the relation for all base classes).
    T: GodotClass,
    D: ?Sized + 'static,
{
    // Potential optimizations: use single Gd; use Rc/Arc instead of Box+clone; store a downcast fn from Gd<T>; ...
    obj: Gd<T>,
    erased_obj: Box<dyn ErasedGd<D>>,
}

impl<T, D> DynGd<T, D>
where
    T: AsDyn<D> + Bounds<Declarer = bounds::DeclUser>,
    D: ?Sized + 'static,
{
    pub(crate) fn from_gd(gd_instance: Gd<T>) -> Self {
        let erased_obj = Box::new(gd_instance.clone());

        Self {
            obj: gd_instance,
            erased_obj,
        }
    }
}

impl<T, D> DynGd<T, D>
where
    // Again, T deliberately does not require AsDyn<D> here. See above.
    T: GodotClass,
    D: ?Sized + 'static,
{
    /// Acquires a shared reference guard to the trait object `D`.
    ///
    /// The resulting guard implements `Deref<Target = D>`, allowing shared access to the trait's methods.
    ///
    /// See [`Gd::bind()`][Gd::bind] for borrow checking semantics and panics.
    pub fn dyn_bind(&self) -> DynGdRef<'_, D> {
        self.erased_obj.dyn_bind()
    }

    /// Acquires an exclusive reference guard to the trait object `D`.
    ///
    /// The resulting guard implements `DerefMut<Target = D>`, allowing exclusive mutable access to the trait's methods.
    ///
    /// See [`Gd::bind_mut()`][Gd::bind_mut] for borrow checking semantics and panics.
    pub fn dyn_bind_mut(&mut self) -> DynGdMut<'_, D> {
        self.erased_obj.dyn_bind_mut()
    }

    // Certain methods "overridden" from deref'ed Gd here, so they're more idiomatic to use.
    // Those taking self by value, like free(), must be overridden.

    /// **Upcast** to a Godot base, while retaining the `D` trait object.
    ///
    /// This is useful when you want to gather multiple objects under a common Godot base (e.g. `Node`), but still enable common functionality.
    /// The common functionality is still accessible through `D` even when upcasting.
    ///
    /// See also [`Gd::upcast()`].
    pub fn upcast<Base>(self) -> DynGd<Base, D>
    where
        Base: GodotClass,
        T: Inherits<Base>,
    {
        DynGd {
            obj: self.obj.upcast::<Base>(),
            erased_obj: self.erased_obj,
        }
    }

    /// **Downcast** to a more specific Godot class, while retaining the `D` trait object.
    ///
    /// If `T`'s dynamic type is not `Derived` or one of its subclasses, `Err(self)` is returned, meaning you can reuse the original
    /// object for further casts.
    ///
    /// See also [`Gd::try_cast()`].
    pub fn try_cast<Derived>(self) -> Result<DynGd<Derived, D>, Self>
    where
        Derived: Inherits<T>,
    {
        match self.obj.try_cast::<Derived>() {
            Ok(obj) => Ok(DynGd {
                obj,
                erased_obj: self.erased_obj,
            }),
            Err(obj) => Err(DynGd {
                obj,
                erased_obj: self.erased_obj,
            }),
        }
    }

    /// ⚠️ **Downcast:** to a more specific Godot class, while retaining the `D` trait object.
    ///
    /// See also [`Gd::cast()`].
    ///
    /// # Panics
    /// If the class' dynamic type is not `Derived` or one of its subclasses. Use [`Self::try_cast()`] if you want to check the result.
    pub fn cast<Derived>(self) -> DynGd<Derived, D>
    where
        Derived: Inherits<T>,
    {
        self.try_cast().unwrap_or_else(|from_obj| {
            panic!(
                "downcast from {from} to {to} failed; instance {from_obj:?}",
                from = T::class_id(),
                to = Derived::class_id(),
            )
        })
    }

    /// Unsafe fast downcasts, no trait bounds.
    ///
    /// # Safety
    /// The caller must ensure that the dynamic type of the object is `Derived` or a subclass of `Derived`.
    // Not intended for public use. The lack of bounds simplifies godot-rust implementation, but adds another unsafety layer.
    pub(crate) unsafe fn cast_unchecked<Derived>(self) -> DynGd<Derived, D>
    where
        Derived: GodotClass,
    {
        let cast_obj = self.obj.owned_cast::<Derived>();

        // SAFETY: ensured by safety invariant.
        let cast_obj = unsafe { cast_obj.unwrap_unchecked() };

        DynGd {
            obj: cast_obj,
            erased_obj: self.erased_obj,
        }
    }

    /// Downgrades to a `Gd<T>` pointer, abandoning the `D` abstraction.
    #[must_use]
    pub fn into_gd(self) -> Gd<T> {
        self.obj
    }

    /// Represents `null` when passing a dynamic object argument to Godot.
    ///
    /// See [`Gd::null_arg()`]
    pub fn null_arg() -> impl meta::AsArg<Option<DynGd<T, D>>> {
        meta::NullArg(std::marker::PhantomData)
    }

    /// Equivalent of [`Gd::run_deferred()`][crate::obj::Gd::run_deferred] for `DynGd`.
    pub fn run_deferred<F>(&mut self, mut_self_method: F)
    where
        F: FnOnce(&mut D) + 'static,
    {
        self.run_deferred_gd(|mut gd| {
            let mut guard = gd.dyn_bind_mut();
            mut_self_method(&mut *guard);
        });
    }

    /// Equivalent of [`Gd::run_deferred_gd()`][crate::obj::Gd::run_deferred_gd] for `DynGd`.
    pub fn run_deferred_gd<F>(&mut self, gd_function: F)
    where
        F: FnOnce(DynGd<T, D>) + 'static,
    {
        let obj = self.clone();
        assert!(
            is_main_thread(),
            "`run_deferred` must be called on the main thread"
        );

        let callable = Callable::from_once_fn("run_deferred", move |_| {
            gd_function(obj);
        });
        callable.call_deferred(&[]);
    }
}

impl<T, D> DynGd<T, D>
where
    T: GodotClass + Bounds<Memory = bounds::MemManual>,
    D: ?Sized + 'static,
{
    /// Destroy the manually-managed Godot object.
    ///
    /// See [`Gd::free()`] for semantics and panics.
    pub fn free(self) {
        self.obj.free()
    }
}

// Don't derive since that messes with bounds, and `.clone()` may silently fall back to deref'ed `Gd::clone()`.
impl<T, D> Clone for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized + 'static,
{
    fn clone(&self) -> Self {
        Self {
            obj: self.obj.clone(),
            erased_obj: self.erased_obj.clone_box(),
        }
    }
}

impl<T, D> PartialEq for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized,
{
    fn eq(&self, other: &Self) -> bool {
        self.obj == other.obj
    }
}

impl<T, D> Eq for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized,
{
}

impl<T, D> std::hash::Hash for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized,
{
    /// ⚠️ Hashes this object based on its instance ID.
    ///
    /// # Panics
    /// When `self` is dead.
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.obj.hash(state);
    }
}

impl<T, D> ops::Deref for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized + 'static,
{
    type Target = Gd<T>;

    fn deref(&self) -> &Self::Target {
        &self.obj
    }
}

impl<T, D> ops::DerefMut for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized + 'static,
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.obj
    }
}

impl<T, D> fmt::Debug for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let trt = sys::short_type_name::<D>();
        crate::classes::debug_string_with_trait::<T>(self, f, "DynGd", &trt)
    }
}

impl<T, D> fmt::Display for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        crate::classes::display_string(self, f)
    }
}

// ----------------------------------------------------------------------------------------------------------------------------------------------
// Type erasure

trait ErasedGd<D>
where
    D: ?Sized + 'static,
{
    fn dyn_bind(&self) -> DynGdRef<'_, D>;
    fn dyn_bind_mut(&mut self) -> DynGdMut<'_, D>;

    fn clone_box(&self) -> Box<dyn ErasedGd<D>>;
}

impl<T, D> ErasedGd<D> for Gd<T>
where
    T: AsDyn<D> + Bounds<Declarer = bounds::DeclUser>,
    D: ?Sized + 'static,
{
    fn dyn_bind(&self) -> DynGdRef<'_, D> {
        DynGdRef::from_guard::<T>(Gd::bind(self))
    }

    fn dyn_bind_mut(&mut self) -> DynGdMut<'_, D> {
        DynGdMut::from_guard::<T>(Gd::bind_mut(self))
    }

    fn clone_box(&self) -> Box<dyn ErasedGd<D>> {
        Box::new(Gd::clone(self))
    }
}

// ----------------------------------------------------------------------------------------------------------------------------------------------
// Integration with Godot traits -- most are directly delegated to Gd<T>.

impl<T, D> GodotConvert for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized + 'static,
{
    type Via = Gd<T>;

    fn godot_shape() -> GodotShape {
        use crate::classes;
        use crate::meta::shape::ClassHeritage;

        // Note: `get_dyn_implementor_class_ids` reads from a global registry populated during class registration.
        // If `godot_shape()` is ever called before registration completes, the implementor list may be incomplete.
        // Currently this is not an issue because godot_shape() is only called during or after registration.
        let heritage = if T::inherits::<classes::Resource>() {
            ClassHeritage::DynResource {
                implementors: get_dyn_implementor_class_ids::<T, D>(),
            }
        } else if T::inherits::<classes::Node>() {
            ClassHeritage::Node
        } else {
            ClassHeritage::Other
        };

        let class_id = T::class_id();
        GodotShape::Class {
            class_id,
            heritage,
            is_nullable: false,
        }
    }
}

impl<T, D> ToGodot for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized + 'static,
{
    // Delegate to Gd<T> passing strategy.
    type Pass = <Gd<T> as ToGodot>::Pass;

    fn to_godot(&self) -> &Self::Via {
        self.obj.to_godot()
    }

    fn to_variant(&self) -> Variant {
        self.obj.to_variant()
    }
}

impl<T, D> FromGodot for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized + 'static,
{
    fn try_from_godot(via: Self::Via) -> Result<Self, ConvertError> {
        match try_dynify_object(via) {
            Ok(dyn_gd) => Ok(dyn_gd),
            Err((from_godot_err, obj)) => Err(from_godot_err.into_error(obj)),
        }
    }
}

/*
// See `impl AsArg for Gd<T>` for why this isn't yet implemented.
impl<'r, T, TBase, D> meta::AsArg<DynGd<TBase, D>> for &'r DynGd<T, D>
where
    T: Inherits<TBase>,
    TBase: GodotClass,
    D: ?Sized + 'static,
{
    fn into_arg<'arg>(self) -> meta::CowArg<'arg, DynGd<TBase, D>>
    where
        'r: 'arg,
    {
        meta::CowArg::Owned(self.clone().upcast::<TBase>())
    }
}
*/

impl<T, D> meta::Element for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized + 'static,
{
}

impl<T, D> meta::Element for Option<DynGd<T, D>>
where
    T: GodotClass,
    D: ?Sized + 'static,
{
}

impl<T, D> Var for DynGd<T, D>
where
    T: GodotClass,
    D: ?Sized + 'static,
{
    type PubType = Self;

    fn var_get(field: &Self) -> Self::Via {
        <Gd<T> as Var>::var_get(&field.obj)
    }

    fn var_set(field: &mut Self, value: Self::Via) {
        // `var_set` can't be delegated to Gd<T>, since we have to set `erased_obj` as well.
        *field = <Self as FromGodot>::from_godot(value);
    }

    fn var_pub_get(field: &Self) -> Self::PubType {
        field.clone()
    }

    fn var_pub_set(field: &mut Self, value: Self::PubType) {
        *field = value;
    }
}

/// See [`DynGd` Exporting](struct.DynGd.html#exporting) section.
impl<T, D> Export for Option<DynGd<T, D>>
where
    T: GodotClass + Bounds<Exportable = bounds::Yes>,
    D: ?Sized + 'static,
{
    #[doc(hidden)]
    fn as_node_class() -> Option<ClassId> {
        PropertyHintInfo::object_as_node_class::<T>()
    }
}

impl<T, D> Default for OnEditor<DynGd<T, D>>
where
    T: GodotClass,
    D: ?Sized + 'static,
{
    fn default() -> Self {
        OnEditor::gd_invalid()
    }
}

impl<T, D> GodotConvert for OnEditor<DynGd<T, D>>
where
    T: GodotClass,
    D: ?Sized + 'static,
{
    type Via = Option<<DynGd<T, D> as GodotConvert>::Via>;

    fn godot_shape() -> GodotShape {
        DynGd::<T, D>::godot_shape()
    }
}

impl<T, D> Var for OnEditor<DynGd<T, D>>
where
    T: GodotClass,
    D: ?Sized + 'static,
{
    // Not Option<...> -- accessing from Rust through Var trait should not expose larger API than OnEditor itself.
    type PubType = <DynGd<T, D> as GodotConvert>::Via;

    fn var_get(field: &Self) -> Self::Via {
        Self::get_property_inner(field)
    }

    fn var_set(field: &mut Self, value: Self::Via) {
        // `var_set` can't be delegated to Gd<T>, since we have to set `erased_obj` as well.
        Self::set_property_inner(field, value);
    }

    fn var_pub_get(field: &Self) -> Self::PubType {
        Self::var_get(field)
            .expect("generated #[var(pub)] getter: uninitialized OnEditor<DynGd<T, D>>")
    }

    fn var_pub_set(field: &mut Self, value: Self::PubType) {
        Self::var_set(field, Some(value))
    }
}

/// See [`DynGd` Exporting](struct.DynGd.html#exporting) section.
impl<T, D> Export for OnEditor<DynGd<T, D>>
where
    Self: Var,
    T: GodotClass + Bounds<Exportable = bounds::Yes>,
    D: ?Sized + 'static,
{
    #[doc(hidden)]
    fn as_node_class() -> Option<ClassId> {
        PropertyHintInfo::object_as_node_class::<T>()
    }
}