5
5
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
6
*/
7
7
8
+ use std:: sync:: atomic:: { AtomicBool , Ordering :: Relaxed } ;
9
+
8
10
use godot_ffi as sys;
9
11
10
12
use sys:: GodotFfi ;
@@ -53,17 +55,38 @@ pub unsafe fn __gdext_load_library<E: ExtensionLibrary>(
53
55
is_success. unwrap_or ( 0 )
54
56
}
55
57
58
+ static LEVEL_SERVERS_CORE_LOADED : AtomicBool = AtomicBool :: new ( false ) ;
59
+
56
60
unsafe extern "C" fn ffi_initialize_layer < E : ExtensionLibrary > (
57
61
_userdata : * mut std:: ffi:: c_void ,
58
62
init_level : sys:: GDExtensionInitializationLevel ,
59
63
) {
60
64
let level = InitLevel :: from_sys ( init_level) ;
61
65
let ctx = || format ! ( "failed to initialize GDExtension level `{:?}`" , level) ;
62
66
63
- // Swallow panics. TODO consider crashing if gdext init fails.
64
- let _ = crate :: private:: handle_panic ( ctx, || {
67
+ fn try_load < E : ExtensionLibrary > ( level : InitLevel ) {
68
+ // Workaround for https://github.com/godot-rust/gdext/issues/629:
69
+ // When using editor plugins, Godot may unload all levels but only reload from Scene upward.
70
+ // Manually run initialization of lower levels.
71
+
72
+ // TODO: Remove this workaround once after the upstream issue is resolved.
73
+ if level == InitLevel :: Scene {
74
+ if !LEVEL_SERVERS_CORE_LOADED . load ( Relaxed ) {
75
+ try_load :: < E > ( InitLevel :: Core ) ;
76
+ try_load :: < E > ( InitLevel :: Servers ) ;
77
+ }
78
+ } else if level == InitLevel :: Core {
79
+ // When it's normal initialization, the `Servers` level is normally initialized.
80
+ LEVEL_SERVERS_CORE_LOADED . store ( true , Relaxed ) ;
81
+ }
82
+
65
83
gdext_on_level_init ( level) ;
66
84
E :: on_level_init ( level) ;
85
+ }
86
+
87
+ // Swallow panics. TODO consider crashing if gdext init fails.
88
+ let _ = crate :: private:: handle_panic ( ctx, || {
89
+ try_load :: < E > ( level) ;
67
90
} ) ;
68
91
}
69
92
@@ -76,6 +99,11 @@ unsafe extern "C" fn ffi_deinitialize_layer<E: ExtensionLibrary>(
76
99
77
100
// Swallow panics.
78
101
let _ = crate :: private:: handle_panic ( ctx, || {
102
+ if level == InitLevel :: Core {
103
+ // Once the CORE api is unloaded, reset the flag to initial state.
104
+ LEVEL_SERVERS_CORE_LOADED . store ( false , Relaxed ) ;
105
+ }
106
+
79
107
E :: on_level_deinit ( level) ;
80
108
gdext_on_level_deinit ( level) ;
81
109
} ) ;
0 commit comments