godot_core/obj/traits.rs
1/*
2 * Copyright (c) godot-rust; Bromeon and contributors.
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
6 */
7
8use crate::builder::ClassBuilder;
9use crate::builtin::GString;
10use crate::init::InitLevel;
11use crate::meta::ClassName;
12use crate::obj::{bounds, Base, BaseMut, BaseRef, Bounds, Gd};
13use crate::storage::Storage;
14
15use godot_ffi as sys;
16
17/// Makes `T` eligible to be managed by Godot and stored in [`Gd<T>`][crate::obj::Gd] pointers.
18///
19/// The behavior of types implementing this trait is influenced by the associated types; check their documentation for information.
20///
21/// Normally, you don't need to implement this trait yourself; use [`#[derive(GodotClass)]`](../register/derive.GodotClass.html) instead.
22// Above intra-doc link to the derive-macro only works as HTML, not as symbol link.
23#[diagnostic::on_unimplemented(
24 message = "Only classes registered with Godot are allowed in this context",
25 note = "you can use `#[derive(GodotClass)]` to register your own structs with Godot",
26 note = "see also: https://godot-rust.github.io/book/register/classes.html"
27)]
28pub trait GodotClass: Bounds + 'static
29where
30 Self: Sized,
31{
32 /// The immediate superclass of `T`. This is always a Godot engine class.
33 type Base: GodotClass; // not EngineClass because it can be ()
34
35 /// The name of the class, under which it is registered in Godot.
36 ///
37 /// This may deviate from the Rust struct name: `HttpRequest::class_name().as_str() == "HTTPRequest"`.
38 fn class_name() -> ClassName;
39
40 /// Initialization level, during which this class should be initialized with Godot.
41 ///
42 /// The default is a good choice in most cases; override only if you have very specific initialization requirements.
43 /// It must not be less than `Base::INIT_LEVEL`.
44 const INIT_LEVEL: InitLevel = <Self::Base as GodotClass>::INIT_LEVEL;
45
46 /// Returns whether `Self` inherits from `U`.
47 ///
48 /// This is reflexive, i.e `Self` inherits from itself.
49 ///
50 /// See also [`Inherits`] for a trait bound.
51 fn inherits<U: GodotClass>() -> bool {
52 if Self::class_name() == U::class_name() {
53 true
54 } else if Self::Base::class_name() == <NoBase>::class_name() {
55 false
56 } else {
57 Self::Base::inherits::<U>()
58 }
59 }
60}
61
62/// Type representing the absence of a base class, at the root of the hierarchy.
63///
64/// `NoBase` is used as the base class for exactly one class: [`Object`][crate::classes::Object].
65///
66/// This is an enum without any variants, as we should never construct an instance of this class.
67pub enum NoBase {}
68
69impl GodotClass for NoBase {
70 type Base = NoBase;
71
72 fn class_name() -> ClassName {
73 ClassName::none()
74 }
75
76 const INIT_LEVEL: InitLevel = InitLevel::Core; // arbitrary; never read.
77}
78
79unsafe impl Bounds for NoBase {
80 type Memory = bounds::MemManual;
81 type DynMemory = bounds::MemManual;
82 type Declarer = bounds::DeclEngine;
83 type Exportable = bounds::No;
84}
85
86/// Non-strict inheritance relationship in the Godot class hierarchy.
87///
88/// `Derived: Inherits<Base>` means that either `Derived` is a subclass of `Base`, or the class `Base` itself (hence "non-strict").
89///
90/// This trait is automatically implemented for all Godot engine classes and user-defined classes that derive [`GodotClass`].
91/// It has `GodotClass` as a supertrait, allowing your code to have bounds solely on `Derived: Inherits<Base>` rather than
92/// `Derived: Inherits<Base> + GodotClass`.
93///
94/// Inheritance is transitive across indirect base classes: `Node3D` implements `Inherits<Node>` and `Inherits<Object>`.
95///
96/// The trait is also reflexive: `T` always implements `Inherits<T>`.
97///
98/// # Usage
99///
100/// The primary use case for this trait is polymorphism: you write a function that accepts anything that derives from a certain class
101/// (including the class itself):
102/// ```no_run
103/// # use godot::prelude::*;
104/// fn print_node<T>(node: Gd<T>)
105/// where
106/// T: Inherits<Node>,
107/// {
108/// let up = node.upcast(); // type Gd<Node> inferred
109/// println!("Node #{} with name {}", up.instance_id(), up.get_name());
110/// up.free();
111/// }
112///
113/// // Call with different types
114/// print_node(Node::new_alloc()); // works on T=Node as well
115/// print_node(Node2D::new_alloc()); // or derived classes
116/// print_node(Node3D::new_alloc());
117/// ```
118///
119/// A variation of the above pattern works without `Inherits` or generics, if you move the `upcast()` into the call site:
120/// ```no_run
121/// # use godot::prelude::*;
122/// fn print_node(node: Gd<Node>) { /* ... */ }
123///
124/// // Call with different types
125/// print_node(Node::new_alloc()); // no upcast needed
126/// print_node(Node2D::new_alloc().upcast());
127/// print_node(Node3D::new_alloc().upcast());
128/// ```
129///
130/// # Safety
131///
132/// This trait must only be implemented for subclasses of `Base`.
133///
134/// Importantly, this means it is always safe to upcast a value of type `Gd<Self>` to `Gd<Base>`.
135pub unsafe trait Inherits<Base: GodotClass>: GodotClass {}
136
137// SAFETY: Every class is a subclass of itself.
138unsafe impl<T: GodotClass> Inherits<T> for T {}
139
140/// Trait that defines a `T` -> `dyn Trait` relation for use in [`DynGd`][crate::obj::DynGd].
141///
142/// You should typically not implement this manually, but use the [`#[godot_dyn]`](../register/attr.godot_dyn.html) macro.
143#[diagnostic::on_unimplemented(
144 message = "`{Trait}` needs to be a trait object linked with class `{Self}` in the library",
145 note = "you can use `#[godot_dyn]` on `impl Trait for Class` to auto-generate `impl Implements<dyn Trait> for Class`"
146)]
147// Note: technically, `Trait` doesn't _have to_ implement `Self`. The Rust type system provides no way to verify that a) D is a trait object,
148// and b) that the trait behind it is implemented for the class. Thus, users could any another reference type, such as `&str` pointing to a field.
149// This should be safe, since lifetimes are checked throughout and the class instance remains in place (pinned) inside a DynGd.
150pub trait AsDyn<Trait: ?Sized>: GodotClass {
151 fn dyn_upcast(&self) -> &Trait;
152 fn dyn_upcast_mut(&mut self) -> &mut Trait;
153}
154
155/// Implemented for all user-defined classes, providing extensions on the raw object to interact with `Gd`.
156#[doc(hidden)]
157pub trait UserClass: Bounds<Declarer = bounds::DeclUser> {
158 #[doc(hidden)]
159 fn __config() -> crate::private::ClassConfig;
160
161 #[doc(hidden)]
162 fn __before_ready(&mut self);
163
164 #[doc(hidden)]
165 fn __default_virtual_call(
166 _method_name: &str,
167 #[cfg(since_api = "4.4")] _hash: u32,
168 ) -> sys::GDExtensionClassCallVirtual {
169 None
170 }
171}
172
173/// Auto-implemented for all engine-provided enums.
174pub trait EngineEnum: Copy {
175 fn try_from_ord(ord: i32) -> Option<Self>;
176
177 /// Ordinal value of the enumerator, as specified in Godot.
178 /// This is not necessarily unique.
179 fn ord(self) -> i32;
180
181 fn from_ord(ord: i32) -> Self {
182 Self::try_from_ord(ord)
183 .unwrap_or_else(|| panic!("ordinal {ord} does not map to any enumerator"))
184 }
185
186 // The name of the enumerator, as it appears in Rust.
187 //
188 // If the value does not match one of the known enumerators, the empty string is returned.
189 fn as_str(&self) -> &'static str;
190
191 // The equivalent name of the enumerator, as specified in Godot.
192 //
193 // If the value does not match one of the known enumerators, the empty string is returned.
194 fn godot_name(&self) -> &'static str;
195}
196
197/// Auto-implemented for all engine-provided bitfields.
198pub trait EngineBitfield: Copy {
199 fn try_from_ord(ord: u64) -> Option<Self>;
200
201 /// Ordinal value of the bit flag, as specified in Godot.
202 fn ord(self) -> u64;
203
204 fn from_ord(ord: u64) -> Self {
205 Self::try_from_ord(ord)
206 .unwrap_or_else(|| panic!("ordinal {ord} does not map to any valid bit flag"))
207 }
208
209 // TODO consolidate API: named methods vs. | & ! etc.
210 fn is_set(self, flag: Self) -> bool {
211 self.ord() & flag.ord() != 0
212 }
213}
214
215/// Trait for enums that can be used as indices in arrays.
216///
217/// The conditions for a Godot enum to be "index-like" are:
218/// - Contains an enumerator ending in `_MAX`, which has the highest ordinal (denotes the size).
219/// - All other enumerators are consecutive integers inside `0..max` (no negative ordinals, no gaps).
220///
221/// Duplicates are explicitly allowed, to allow for renamings/deprecations. The order in which Godot exposes
222/// the enumerators in the JSON is irrelevant.
223pub trait IndexEnum: EngineEnum {
224 /// Number of **distinct** enumerators in the enum.
225 ///
226 /// All enumerators are guaranteed to be in the range `0..ENUMERATOR_COUNT`, so you can use them
227 /// as indices in an array of size `ENUMERATOR_COUNT`.
228 ///
229 /// Keep in mind that two enumerators with the same ordinal are only counted once.
230 const ENUMERATOR_COUNT: usize;
231
232 /// Converts the enumerator to `usize`, which can be used as an array index.
233 ///
234 /// Note that two enumerators may have the same index, if they have the same ordinal.
235 fn to_index(self) -> usize {
236 self.ord() as usize
237 }
238}
239
240/// Trait that is automatically implemented for user classes containing a `Base<T>` field.
241///
242/// Gives direct access to the containing `Gd<Self>` from `self`.
243///
244/// # Usage as a bound
245///
246/// In order to call `base()` or `base_mut()` within a function or on a type you define, you need a `WithBaseField<Base = T>` bound,
247/// where `T` is the base class of your type.
248///
249/// ```no_run
250/// # use godot::prelude::*;
251/// # use godot::obj::WithBaseField;
252/// fn some_fn<T>(value: &T)
253/// where
254/// T: WithBaseField<Base = Node3D>,
255/// {
256/// let base = value.base();
257/// let pos = base.get_position();
258/// }
259/// ```
260///
261// Possible alternative for builder APIs, although even less ergonomic: Base<T> could be Base<T, Self> and return Gd<Self>.
262#[diagnostic::on_unimplemented(
263 message = "Class `{Self}` requires a `Base<T>` field",
264 label = "missing field `_base: Base<...>`",
265 note = "A base field is required to access the base from within `self`, for script-virtual functions or #[rpc] methods",
266 note = "see also: https://godot-rust.github.io/book/register/classes.html#the-base-field"
267)]
268pub trait WithBaseField: GodotClass + Bounds<Declarer = bounds::DeclUser> {
269 /// Returns the `Gd` pointer containing this object.
270 ///
271 /// This is intended to be stored or passed to engine methods. You cannot call `bind()` or `bind_mut()` on it, while the method
272 /// calling `to_gd()` is still running; that would lead to a double borrow panic.
273 fn to_gd(&self) -> Gd<Self>;
274
275 /// Returns a reference to the `Base` stored by this object.
276 fn base_field(&self) -> &Base<Self::Base>;
277
278 /// Returns a shared reference suitable for calling engine methods on this object.
279 ///
280 /// Holding a shared guard prevents other code paths from obtaining a _mutable_ reference to `self`, as such it is recommended to drop the
281 /// guard as soon as you no longer need it.
282 ///
283 /// # Examples
284 ///
285 /// ```no_run
286 /// use godot::prelude::*;
287 ///
288 /// #[derive(GodotClass)]
289 /// #[class(init, base = Node)]
290 /// struct MyClass {
291 /// base: Base<Node>,
292 /// }
293 ///
294 /// #[godot_api]
295 /// impl INode for MyClass {
296 /// fn process(&mut self, _delta: f64) {
297 /// let name = self.base().get_name();
298 /// godot_print!("name is {name}");
299 /// }
300 /// }
301 ///
302 /// # pub struct Test;
303 ///
304 /// # #[gdextension]
305 /// # unsafe impl ExtensionLibrary for Test {}
306 /// ```
307 ///
308 /// However, we cannot call methods that require `&mut Base`, such as
309 /// [`Node::add_child()`](crate::classes::Node::add_child).
310 ///
311 /// ```compile_fail
312 /// use godot::prelude::*;
313 ///
314 /// #[derive(GodotClass)]
315 /// #[class(init, base = Node)]
316 /// struct MyClass {
317 /// /// base: Base<Node>,
318 /// }
319 ///
320 /// #[godot_api]
321 /// impl INode for MyClass {
322 /// fn process(&mut self, _delta: f64) {
323 /// let node = Node::new_alloc();
324 /// // fails because `add_child` requires a mutable reference.
325 /// self.base().add_child(&node);
326 /// }
327 /// }
328 ///
329 /// # pub struct Test;
330 ///
331 /// # #[gdextension]
332 /// # unsafe impl ExtensionLibrary for Test {}
333 /// ```
334 ///
335 /// For this, use [`base_mut()`](WithBaseField::base_mut()) instead.
336 fn base(&self) -> BaseRef<'_, Self> {
337 let gd = self.base_field().to_gd();
338
339 BaseRef::new(gd, self)
340 }
341
342 /// Returns a mutable reference suitable for calling engine methods on this object.
343 ///
344 /// This method will allow you to call back into the same object from Godot, unlike what would happen
345 /// if you used [`to_gd()`](WithBaseField::to_gd).
346 ///
347 /// Holding a mutable guard prevents other code paths from obtaining _any_ reference to `self`, as such it is recommended to drop the
348 /// guard as soon as you no longer need it.
349 ///
350 /// # Examples
351 ///
352 /// ```no_run
353 /// use godot::prelude::*;
354 ///
355 /// #[derive(GodotClass)]
356 /// #[class(init, base = Node)]
357 /// struct MyClass {
358 /// base: Base<Node>,
359 /// }
360 ///
361 /// #[godot_api]
362 /// impl INode for MyClass {
363 /// fn process(&mut self, _delta: f64) {
364 /// let node = Node::new_alloc();
365 /// self.base_mut().add_child(&node);
366 /// }
367 /// }
368 ///
369 /// # pub struct Test;
370 ///
371 /// # #[gdextension]
372 /// # unsafe impl ExtensionLibrary for Test {}
373 /// ```
374 ///
375 /// We can call back into `self` through Godot:
376 ///
377 /// ```
378 /// use godot::prelude::*;
379 ///
380 /// #[derive(GodotClass)]
381 /// #[class(init, base = Node)]
382 /// struct MyClass {
383 /// base: Base<Node>,
384 /// }
385 ///
386 /// #[godot_api]
387 /// impl INode for MyClass {
388 /// fn process(&mut self, _delta: f64) {
389 /// self.base_mut().call("other_method", &[]);
390 /// }
391 /// }
392 ///
393 /// #[godot_api]
394 /// impl MyClass {
395 /// #[func]
396 /// fn other_method(&mut self) {}
397 /// }
398 ///
399 /// # pub struct Test;
400 ///
401 /// # #[gdextension]
402 /// # unsafe impl ExtensionLibrary for Test {}
403 /// ```
404 #[allow(clippy::let_unit_value)]
405 fn base_mut(&mut self) -> BaseMut<'_, Self> {
406 let base_gd = self.base_field().to_gd();
407
408 let gd = self.to_gd();
409 // SAFETY:
410 // - We have a `Gd<Self>` so, provided that `storage_unbounded` succeeds, the associated instance
411 // storage has been created.
412 //
413 // - Since we can get a `&'a Base<Self::Base>` from `&'a self`, that must mean we have a Rust object
414 // somewhere that has this base object. The only way to have such a base object is by being the
415 // Rust object referenced by that base object. I.e. this storage's user-instance is that Rust
416 // object. That means this storage cannot be destroyed for the lifetime of that Rust object. And
417 // since we have a reference to the base object derived from that Rust object, then that Rust
418 // object must outlive `'a`. And so the storage cannot be destroyed during the lifetime `'a`.
419 let storage = unsafe {
420 gd.raw
421 .storage_unbounded()
422 .expect("we have a `Gd<Self>` so the raw should not be null")
423 };
424
425 let guard = storage.get_inaccessible(self);
426
427 BaseMut::new(base_gd, guard)
428 }
429}
430
431/// Extension trait for all reference-counted classes.
432pub trait NewGd: GodotClass {
433 /// Return a new, ref-counted `Gd` containing a default-constructed instance.
434 ///
435 /// `MyClass::new_gd()` is equivalent to `Gd::<MyClass>::default()`.
436 fn new_gd() -> Gd<Self>;
437}
438
439impl<T> NewGd for T
440where
441 T: cap::GodotDefault + Bounds<Memory = bounds::MemRefCounted>,
442{
443 fn new_gd() -> Gd<Self> {
444 Gd::default()
445 }
446}
447
448/// Extension trait for all manually managed classes.
449pub trait NewAlloc: GodotClass {
450 /// Return a new, manually-managed `Gd` containing a default-constructed instance.
451 ///
452 /// The result must be manually managed, e.g. by attaching it to the scene tree or calling `free()` after usage.
453 /// Failure to do so will result in memory leaks.
454 #[must_use]
455 fn new_alloc() -> Gd<Self>;
456}
457
458impl<T> NewAlloc for T
459where
460 T: cap::GodotDefault + Bounds<Memory = bounds::MemManual>,
461{
462 fn new_alloc() -> Gd<Self> {
463 use crate::obj::bounds::Declarer as _;
464
465 <Self as Bounds>::Declarer::create_gd()
466 }
467}
468
469// ----------------------------------------------------------------------------------------------------------------------------------------------
470
471/// Capability traits, providing dedicated functionalities for Godot classes
472pub mod cap {
473 use super::*;
474 use crate::builtin::{StringName, Variant};
475 use crate::meta::PropertyInfo;
476 use crate::obj::{Base, Bounds, Gd};
477 use std::any::Any;
478
479 /// Trait for all classes that are default-constructible from the Godot engine.
480 ///
481 /// Enables the `MyClass.new()` syntax in GDScript, and allows the type to be used by the editor, which often default-constructs objects.
482 ///
483 /// This trait is automatically implemented for the following classes:
484 /// - User defined classes if either:
485 /// - they override an `init()` method
486 /// - they have `#[class(init)]` attribute
487 /// - Engine classes if:
488 /// - they are reference-counted and constructible (i.e. provide a `new()` method).
489 ///
490 /// This trait is not manually implemented, and you cannot call any methods. You can use it as a bound, but typically you'd use
491 /// it indirectly through [`Gd::default()`][crate::obj::Gd::default()]. Note that `Gd::default()` has an additional requirement on
492 /// being reference-counted, meaning not every `GodotDefault` class can automatically be used with `Gd::default()`.
493 #[diagnostic::on_unimplemented(
494 message = "Class `{Self}` requires either an `init` constructor, or explicit opt-out",
495 label = "needs `init`",
496 note = "To provide a default constructor, use `#[class(init)]` or implement an `init` method",
497 note = "To opt out, use `#[class(no_init)]`",
498 note = "see also: https://godot-rust.github.io/book/register/constructors.html"
499 )]
500 pub trait GodotDefault: GodotClass {
501 /// Provides a default smart pointer instance.
502 ///
503 /// Semantics:
504 /// - For user-defined classes, this calls `T::init()` or the generated init-constructor.
505 /// - For engine classes, this calls `T::new()`.
506 #[doc(hidden)]
507 fn __godot_default() -> Gd<Self> {
508 // This is a bit hackish, but the alternatives are:
509 // 1. Separate trait `GodotUserDefault` for user classes, which then proliferates through all APIs and makes abstraction harder.
510 // 2. Repeatedly implementing __godot_default() that forwards to something like Gd::default_user_instance(). Possible, but this
511 // will make the step toward builder APIs more difficult, as users would need to re-implement this as well.
512 debug_assert_eq!(
513 std::any::TypeId::of::<<Self as Bounds>::Declarer>(),
514 std::any::TypeId::of::<bounds::DeclUser>(),
515 "__godot_default() called on engine class; must be overridden for engine classes"
516 );
517
518 Gd::default_instance()
519 }
520
521 /// Only provided for user classes.
522 #[doc(hidden)]
523 fn __godot_user_init(_base: Base<Self::Base>) -> Self {
524 unreachable!(
525 "__godot_user_init() called on engine class; must be overridden for user classes"
526 )
527 }
528 }
529
530 // TODO Evaluate whether we want this public or not
531 #[doc(hidden)]
532 pub trait GodotToString: GodotClass {
533 #[doc(hidden)]
534 fn __godot_to_string(&self) -> GString;
535 }
536
537 // TODO Evaluate whether we want this public or not
538 #[doc(hidden)]
539 pub trait GodotNotification: GodotClass {
540 #[doc(hidden)]
541 fn __godot_notification(&mut self, what: i32);
542 }
543
544 // TODO Evaluate whether we want this public or not
545 #[doc(hidden)]
546 pub trait GodotRegisterClass: GodotClass {
547 #[doc(hidden)]
548 fn __godot_register_class(builder: &mut ClassBuilder<Self>);
549 }
550
551 #[doc(hidden)]
552 pub trait GodotGet: GodotClass {
553 #[doc(hidden)]
554 fn __godot_get_property(&self, property: StringName) -> Option<Variant>;
555 }
556
557 #[doc(hidden)]
558 pub trait GodotSet: GodotClass {
559 #[doc(hidden)]
560 fn __godot_set_property(&mut self, property: StringName, value: Variant) -> bool;
561 }
562
563 #[doc(hidden)]
564 pub trait GodotGetPropertyList: GodotClass {
565 #[doc(hidden)]
566 fn __godot_get_property_list(&mut self) -> Vec<crate::meta::PropertyInfo>;
567 }
568
569 #[doc(hidden)]
570 pub trait GodotPropertyGetRevert: GodotClass {
571 #[doc(hidden)]
572 fn __godot_property_get_revert(&self, property: StringName) -> Option<Variant>;
573 }
574
575 #[doc(hidden)]
576 #[cfg(since_api = "4.2")]
577 pub trait GodotValidateProperty: GodotClass {
578 #[doc(hidden)]
579 fn __godot_validate_property(&self, property: &mut PropertyInfo);
580 }
581
582 /// Auto-implemented for `#[godot_api] impl MyClass` blocks
583 pub trait ImplementsGodotApi: GodotClass {
584 #[doc(hidden)]
585 fn __register_methods();
586 #[doc(hidden)]
587 fn __register_constants();
588 #[doc(hidden)]
589 fn __register_rpcs(_: &mut dyn Any) {}
590 }
591
592 pub trait ImplementsGodotExports: GodotClass {
593 #[doc(hidden)]
594 fn __register_exports();
595 }
596
597 /// Auto-implemented for `#[godot_api] impl XyVirtual for MyClass` blocks
598 pub trait ImplementsGodotVirtual: GodotClass {
599 #[doc(hidden)]
600 fn __virtual_call(
601 name: &str,
602 #[cfg(since_api = "4.4")] hash: u32,
603 ) -> sys::GDExtensionClassCallVirtual;
604 }
605}