Skip to content

Commit

Permalink
#434 Hot reload: recreate supplied at right places now.
Browse files Browse the repository at this point in the history
  • Loading branch information
kkolyan committed Oct 1, 2023
1 parent 08bfad5 commit 99d6c0d
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 26 deletions.
76 changes: 51 additions & 25 deletions godot-core/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ use crate::out;
use std::any::Any;
use std::collections::HashMap;
use std::{fmt, ptr};
use godot_ffi::GDExtensionBool;
use sys::GDExtensionClassInstancePtr;
use sys::GDExtensionObjectPtr;

// TODO(bromeon): some information coming from the proc-macro API is deferred through PluginComponent, while others is directly
// translated to code. Consider moving more code to the PluginComponent, which allows for more dynamic registration and will
Expand Down Expand Up @@ -66,6 +63,13 @@ pub enum PluginComponent {
) -> sys::GDExtensionObjectPtr,
>,

generated_recreate_fn: Option<
unsafe extern "C" fn(
p_class_userdata: *mut ::std::os::raw::c_void,
p_object: sys::GDExtensionObjectPtr,
) -> sys::GDExtensionClassInstancePtr
>,

free_fn: unsafe extern "C" fn(
_class_user_data: *mut std::ffi::c_void,
instance: sys::GDExtensionClassInstancePtr,
Expand All @@ -92,6 +96,13 @@ pub enum PluginComponent {
) -> sys::GDExtensionObjectPtr,
>,

user_recreate_fn: Option<
unsafe extern "C" fn(
p_class_userdata: *mut ::std::os::raw::c_void,
p_object: sys::GDExtensionObjectPtr,
) -> sys::GDExtensionClassInstancePtr
>,

/// User-defined `to_string` function
user_to_string_fn: Option<
unsafe extern "C" fn(
Expand All @@ -114,7 +125,7 @@ pub enum PluginComponent {
unsafe extern "C" fn(
p_instance: sys::GDExtensionClassInstancePtr, //
p_what: i32,
p_reversed: GDExtensionBool,
p_reversed: sys::GDExtensionBool,
),
>,

Expand Down Expand Up @@ -228,6 +239,7 @@ pub fn auto_register_classes(init_level: InitLevel) {
.or_insert_with(|| default_registration_info(name));

fill_class_info(elem.component.clone(), class_info);
// class_info.godot_params.recreate_instance_func = Some(callbacks::recreate::<T>)
});

//out!("Class-map: {map:#?}");
Expand All @@ -251,13 +263,18 @@ fn fill_class_info(component: PluginComponent, c: &mut ClassRegistrationInfo) {
PluginComponent::ClassDef {
base_class_name,
generated_create_fn,
generated_recreate_fn,
free_fn,
} => {
c.parent_class_name = Some(base_class_name);
fill_into(
&mut c.godot_params.create_instance_func,
generated_create_fn,
);
fill_into(
&mut c.godot_params.recreate_instance_func,
generated_recreate_fn,
);
c.godot_params.free_instance_func = Some(free_fn);
}

Expand All @@ -270,12 +287,14 @@ fn fill_class_info(component: PluginComponent, c: &mut ClassRegistrationInfo) {
PluginComponent::UserVirtuals {
user_register_fn,
user_create_fn,
user_recreate_fn,
user_to_string_fn,
user_on_notification_fn,
get_virtual_fn,
} => {
c.user_register_fn = user_register_fn;
fill_into(&mut c.godot_params.create_instance_func, user_create_fn);
fill_into(&mut c.godot_params.recreate_instance_func, user_recreate_fn);
c.godot_params.to_string_func = user_to_string_fn;
c.godot_params.notification_func = user_on_notification_fn;
c.godot_params.get_virtual_func = Some(get_virtual_fn);
Expand Down Expand Up @@ -311,15 +330,17 @@ fn register_class_raw(info: ClassRegistrationInfo) {
// Try to register class...

#[cfg(before_api = "4.2")]
#[allow(clippy::let_unit_value)] // notifies us if Godot API ever adds a return type.
#[allow(clippy::let_unit_value)]
// notifies us if Godot API ever adds a return type.
let _: () = interface_fn!(classdb_register_extension_class)(
sys::get_library(),
class_name.string_sys(),
parent_class_name.string_sys(),
ptr::addr_of!(info.godot_params),
);
#[cfg(since_api = "4.2")]
#[allow(clippy::let_unit_value)] // notifies us if Godot API ever adds a return type.
#[allow(clippy::let_unit_value)]
// notifies us if Godot API ever adds a return type.
let _: () = interface_fn!(classdb_register_extension_class2)(
sys::get_library(),
class_name.string_sys(),
Expand Down Expand Up @@ -369,19 +390,19 @@ pub mod callbacks {

pub unsafe extern "C" fn create<T: cap::GodotInit>(
_class_userdata: *mut std::ffi::c_void,
) -> GDExtensionObjectPtr {
) -> sys::GDExtensionObjectPtr {
create_custom(T::__godot_init)
}

#[cfg(since_api = "4.2")]
pub unsafe extern "C" fn recreate<T: cap::GodotInit>(
_class_userdata: *mut std::ffi::c_void,
object: GDExtensionObjectPtr,
) -> GDExtensionClassInstancePtr {
create_rust_counterpart(T::__godot_init, object)
object: sys::GDExtensionObjectPtr,
) -> sys::GDExtensionClassInstancePtr {
create_rust_part_for_existing_godot_part(T::__godot_init, object)
}

pub(crate) fn create_custom<T, F>(make_user_instance: F) -> GDExtensionObjectPtr
pub(crate) fn create_custom<T, F>(make_user_instance: F) -> godot_ffi::GDExtensionObjectPtr
where
T: GodotClass,
F: FnOnce(Base<T::Base>) -> T,
Expand All @@ -391,16 +412,19 @@ pub mod callbacks {
let base_ptr =
unsafe { interface_fn!(classdb_construct_object)(base_class_name.string_sys()) };

create_rust_counterpart(make_user_instance, base_ptr);
create_rust_part_for_existing_godot_part(make_user_instance, base_ptr);

// std::mem::forget(base_class_name);
base_ptr
}

fn create_rust_counterpart<T, F>(make_user_instance: F, base_ptr: GDExtensionObjectPtr) -> GDExtensionClassInstancePtr
where
T: GodotClass,
F: FnOnce(Base<T::Base>) -> T,
fn create_rust_part_for_existing_godot_part<T, F>(
make_user_instance: F,
base_ptr: sys::GDExtensionObjectPtr,
) -> sys::GDExtensionClassInstancePtr
where
T: GodotClass,
F: FnOnce(Base<T::Base>) -> T,
{
let class_name = T::class_name();

Expand All @@ -411,7 +435,7 @@ pub mod callbacks {

let instance = InstanceStorage::<T>::construct(user_instance);
let instance_ptr = instance.into_raw();
let instance_ptr = instance_ptr as GDExtensionClassInstancePtr;
let instance_ptr = instance_ptr as sys::GDExtensionClassInstancePtr;

let binding_data_callbacks = crate::storage::nop_instance_callbacks();
unsafe {
Expand All @@ -430,7 +454,7 @@ pub mod callbacks {

pub unsafe extern "C" fn free<T: GodotClass>(
_class_user_data: *mut std::ffi::c_void,
instance: GDExtensionClassInstancePtr,
instance: sys::GDExtensionClassInstancePtr,
) {
{
let storage = as_storage::<T>(instance);
Expand All @@ -453,7 +477,7 @@ pub mod callbacks {
}

pub unsafe extern "C" fn to_string<T: cap::GodotToString>(
instance: GDExtensionClassInstancePtr,
instance: sys::GDExtensionClassInstancePtr,
_is_valid: *mut sys::GDExtensionBool,
out_string: sys::GDExtensionStringPtr,
) {
Expand All @@ -470,7 +494,7 @@ pub mod callbacks {

#[cfg(before_api = "4.2")]
pub unsafe extern "C" fn on_notification<T: cap::GodotNotification>(
instance: GDExtensionClassInstancePtr,
instance: sys::GDExtensionClassInstancePtr,
what: i32,
) {
let storage = as_storage::<T>(instance);
Expand All @@ -481,23 +505,25 @@ pub mod callbacks {

#[cfg(since_api = "4.2")]
pub unsafe extern "C" fn on_notification<T: cap::GodotNotification>(
instance: GDExtensionClassInstancePtr,
instance: sys::GDExtensionClassInstancePtr,
what: i32,
_reversed: GDExtensionBool,
_reversed: sys::GDExtensionBool,
) {
let storage = as_storage::<T>(instance);
let mut instance = storage.get_mut();

T::__godot_notification(&mut *instance, what);
}

pub unsafe extern "C" fn reference<T: GodotClass>(instance: GDExtensionClassInstancePtr) {
pub unsafe extern "C" fn reference<T: GodotClass>(
instance: sys::GDExtensionClassInstancePtr,
) {
let storage = as_storage::<T>(instance);
storage.on_inc_ref();
}

pub unsafe extern "C" fn unreference<T: GodotClass>(
instance: GDExtensionClassInstancePtr,
instance: sys::GDExtensionClassInstancePtr,
) {
let storage = as_storage::<T>(instance);
storage.on_dec_ref();
Expand Down Expand Up @@ -605,6 +631,6 @@ fn default_creation_info() -> sys::GDExtensionClassCreationInfo2 {
call_virtual_with_data_func: None,
get_rid_func: None,
class_userdata: ptr::null_mut(),
is_exposed: false as u8
is_exposed: false as u8,
}
}
5 changes: 4 additions & 1 deletion godot-macros/src/class/derive_godot_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,15 @@ pub fn derive_godot_class(decl: Declaration) -> ParseResult<TokenStream> {
quote! {}
};

let (godot_init_impl, create_fn);
let (godot_init_impl, create_fn, recreate_fn);
if struct_cfg.has_generated_init {
godot_init_impl = make_godot_init_impl(class_name, fields);
create_fn = quote! { Some(#prv::callbacks::create::<#class_name>) };
recreate_fn = quote! { Some(#prv::callbacks::recreate::<#class_name>) };
} else {
godot_init_impl = TokenStream::new();
create_fn = quote! { None };
recreate_fn = quote! { None };
};

let config_impl = make_config_impl(class_name, struct_cfg.is_tool);
Expand All @@ -79,6 +81,7 @@ pub fn derive_godot_class(decl: Declaration) -> ParseResult<TokenStream> {
component: #prv::PluginComponent::ClassDef {
base_class_name: #base_class_name_obj,
generated_create_fn: #create_fn,
generated_recreate_fn: #recreate_fn,
free_fn: #prv::callbacks::free::<#class_name>,
},
init_level: <#class_name as ::godot::obj::GodotClass>::INIT_LEVEL,
Expand Down
3 changes: 3 additions & 0 deletions godot-macros/src/class/godot_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ fn transform_trait_impl(original_impl: Impl) -> Result<TokenStream, Error> {

let mut register_fn = quote! { None };
let mut create_fn = quote! { None };
let mut recreate_fn = quote! { None };
let mut to_string_fn = quote! { None };
let mut on_notification_fn = quote! { None };

Expand Down Expand Up @@ -412,6 +413,7 @@ fn transform_trait_impl(original_impl: Impl) -> Result<TokenStream, Error> {
}
};
create_fn = quote! { Some(#prv::callbacks::create::<#class_name>) };
recreate_fn = quote! { Some(#prv::callbacks::recreate::<#class_name>) };
}

"to_string" => {
Expand Down Expand Up @@ -502,6 +504,7 @@ fn transform_trait_impl(original_impl: Impl) -> Result<TokenStream, Error> {
component: #prv::PluginComponent::UserVirtuals {
user_register_fn: #register_fn,
user_create_fn: #create_fn,
user_recreate_fn: #recreate_fn,
user_to_string_fn: #to_string_fn,
user_on_notification_fn: #on_notification_fn,
get_virtual_fn: #prv::callbacks::get_virtual::<#class_name>,
Expand Down

0 comments on commit 99d6c0d

Please sign in to comment.