From 7a2100db55314129097b279f18d046125f997434 Mon Sep 17 00:00:00 2001 From: Guusggg Date: Mon, 16 Dec 2024 17:17:52 +0100 Subject: [PATCH] It runs...! For some reason iterating through all the class names made them "correct", as the runtime previously complained that it's trying to register classes with the same name. It runs with a ton of errors about double registering methods --- godot-core/src/init/mod.rs | 44 +++++++++++++++++++++++++++---- godot-core/src/meta/class_name.rs | 21 +++++++++++---- godot-ffi/src/binding/mod.rs | 8 ++++++ 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/godot-core/src/init/mod.rs b/godot-core/src/init/mod.rs index b268dda94..b080abb58 100644 --- a/godot-core/src/init/mod.rs +++ b/godot-core/src/init/mod.rs @@ -12,10 +12,14 @@ use godot_ffi as sys; use sys::GodotFfi; use crate::builtin::{GString, StringName}; +use crate::meta::ClassName; use crate::out; +use crate::private::ClassPlugin; pub use sys::GdextBuild; +static mut ENGINE_INITIALIZED: bool = false; + #[doc(hidden)] #[deny(unsafe_op_in_unsafe_fn)] pub unsafe fn __gdext_load_library( @@ -41,9 +45,21 @@ pub unsafe fn __gdext_load_library( let config = sys::GdextConfig::new(tool_only_in_editor); + out!("Is engine initialized? {}", unsafe { + if ENGINE_INITIALIZED { + "yes" + } else { + "nope" + } + }); + // SAFETY: no custom code has run yet + no other thread is accessing global handle. unsafe { - sys::initialize(get_proc_address, library, config); + if !ENGINE_INITIALIZED { + sys::initialize(get_proc_address, library, config); + } + + ENGINE_INITIALIZED = true; } // Currently no way to express failure; could be exposed to E if necessary. @@ -158,6 +174,24 @@ unsafe fn gdext_on_level_init(level: InitLevel) { _ => (), } + crate::private::iterate_plugins(|elem: &ClassPlugin| { + // Filter per ClassPlugin and not PluginItem, because all components of all classes are mixed together in one huge list. + if elem.init_level != level { + return; + } + + out!("Pre::auto_register_classes: {}", &elem.class_name); + + out!("All class names: "); + ClassName::iter_all(|entry| { + let string_name = entry + .godot_str + .get_or_init(|| entry.rust_str.to_string_name()); + + out!("\tClass name: {}", string_name); + }); + }); + crate::registry::class::auto_register_classes(level); } @@ -364,9 +398,9 @@ unsafe fn ensure_godot_features_compatible() { if godot_is_double != gdext_is_double { panic!( - "Godot runs with {} precision, but gdext was compiled with {} precision.\n\ - Cargo feature `double-precision` must be used if and only if Godot is compiled with `precision=double`.\n", - s(godot_is_double), s(gdext_is_double), - ); + "Godot runs with {} precision, but gdext was compiled with {} precision.\n\ + Cargo feature `double-precision` must be used if and only if Godot is compiled with `precision=double`.\n", + s(godot_is_double), s(gdext_is_double), + ); } } diff --git a/godot-core/src/meta/class_name.rs b/godot-core/src/meta/class_name.rs index ac122dbdb..04745031d 100644 --- a/godot-core/src/meta/class_name.rs +++ b/godot-core/src/meta/class_name.rs @@ -41,9 +41,9 @@ pub unsafe fn cleanup() { /// Entry in the class name cache. /// /// `StringName` needs to be lazy-initialized because the Godot binding may not be initialized yet. -struct ClassNameEntry { - rust_str: ClassNameSource, - godot_str: OnceCell, +pub struct ClassNameEntry { + pub rust_str: ClassNameSource, + pub godot_str: OnceCell, } impl ClassNameEntry { @@ -62,13 +62,13 @@ impl ClassNameEntry { // ---------------------------------------------------------------------------------------------------------------------------------------------- /// `Cow`-like enum for class names, but with C strings as the borrowed variant. -enum ClassNameSource { +pub enum ClassNameSource { Owned(String), Borrowed(&'static CStr), } impl ClassNameSource { - fn to_string_name(&self) -> StringName { + pub fn to_string_name(&self) -> StringName { match self { ClassNameSource::Owned(s) => StringName::from(s), @@ -107,6 +107,17 @@ pub struct ClassName { } impl ClassName { + pub fn iter_all(f: F) + where + F: Fn(&ClassNameEntry), + { + let guard = CLASS_NAMES.lock(); + + for name in guard.iter() { + f(name); + } + } + /// Construct a new class name. /// /// This is expensive the first time it called for a given `T`, but will be cached for subsequent calls. diff --git a/godot-ffi/src/binding/mod.rs b/godot-ffi/src/binding/mod.rs index a7676cb4f..5e723ef5a 100644 --- a/godot-ffi/src/binding/mod.rs +++ b/godot-ffi/src/binding/mod.rs @@ -11,6 +11,9 @@ use crate::{ GdextRuntimeMetadata, ManualInitCell, UtilityFunctionTable, }; +#[macro_use] +use crate::out; + #[cfg(feature = "experimental-threads")] mod multi_threaded; #[cfg(not(feature = "experimental-threads"))] @@ -84,6 +87,11 @@ unsafe impl Send for ClassLibraryPtr {} /// # Safety /// The table must not have been initialized yet. unsafe fn initialize_table(table: &ManualInitCell, value: T, what: &str) { + if table.is_initialized() { + out!("Table for {} is already initialized!", what); + return; + } + debug_assert!( !table.is_initialized(), "method table for {what} should only be initialized once"