7
7
8
8
//! Godot engine classes and methods.
9
9
10
- // Re-exports of generated symbols
11
10
use crate :: builtin:: { GString , NodePath } ;
12
11
use crate :: obj:: dom:: EngineDomain ;
13
12
use crate :: obj:: { Gd , GodotClass , Inherits , InstanceId } ;
13
+ use std:: collections:: HashSet ;
14
14
15
+ // Re-exports of generated symbols
15
16
pub use crate :: gen:: central:: global;
16
17
pub use crate :: gen:: classes:: * ;
17
18
pub use crate :: gen:: utilities;
@@ -246,15 +247,13 @@ pub(crate) fn ensure_object_alive(
246
247
247
248
#[ cfg( debug_assertions) ]
248
249
pub ( crate ) fn ensure_object_inherits (
249
- derived : & ClassName ,
250
- base : & ClassName ,
250
+ derived : ClassName ,
251
+ base : ClassName ,
251
252
instance_id : InstanceId ,
252
253
) -> bool {
253
- // TODO static cache.
254
-
255
254
if derived == base
256
- || base == & Object :: class_name ( ) // always true
257
- || ClassDb :: singleton ( ) . is_parent_class ( derived. to_string_name ( ) , base. to_string_name ( ) )
255
+ || base == Object :: class_name ( ) // for Object base, anything inherits by definition
256
+ || is_derived_base_cached ( derived, base)
258
257
{
259
258
return true ;
260
259
}
@@ -265,6 +264,30 @@ pub(crate) fn ensure_object_inherits(
265
264
)
266
265
}
267
266
267
+ /// Checks if `derived` inherits from `base`, using a cache for _successful_ queries.
268
+ #[ cfg( debug_assertions) ]
269
+ fn is_derived_base_cached ( derived : ClassName , base : ClassName ) -> bool {
270
+ use sys:: Global ;
271
+ static CACHE : Global < HashSet < ( ClassName , ClassName ) > > = Global :: default ( ) ;
272
+
273
+ let mut cache = CACHE . lock ( ) ;
274
+ let key = ( derived, base) ;
275
+ if cache. contains ( & key) {
276
+ return true ;
277
+ }
278
+
279
+ // Query Godot API (takes linear time in depth of inheritance tree).
280
+ let is_parent_class =
281
+ ClassDb :: singleton ( ) . is_parent_class ( derived. to_string_name ( ) , base. to_string_name ( ) ) ;
282
+
283
+ // Insert only successful queries. Those that fail are on the error path already and don't need to be fast.
284
+ if is_parent_class {
285
+ cache. insert ( key) ;
286
+ }
287
+
288
+ is_parent_class
289
+ }
290
+
268
291
// Separate function, to avoid constructing string twice
269
292
// Note that more optimizations than that likely make no sense, as loading is quite expensive
270
293
fn load_impl < T > ( path : & GString ) -> Option < Gd < T > >
0 commit comments